1
0
Fork 0

DBG: added assembleat function

DBG: added XEDParse (does not support all instructions yet)
BRIDGE: added function DbgAssembleAt
GUI: added assemble window
This commit is contained in:
mr.exodia 2014-02-22 16:14:36 +01:00
parent a3ec27853c
commit 53111a169d
15 changed files with 99 additions and 240 deletions

View File

@ -532,6 +532,13 @@ BRIDGE_IMPEXP void DbgSymbolEnum(duint base, CBSYMBOLENUM cbSymbolEnum, void* us
_dbg_sendmessage(DBG_SYMBOL_ENUM, &cbInfo, 0);
}
BRIDGE_IMPEXP bool DbgAssembleAt(duint addr, const char* instruction)
{
if(_dbg_sendmessage(DBG_ASSEMBLE_AT, (void*)addr, (void*)instruction))
return true;
return false;
}
//GUI
BRIDGE_IMPEXP void GuiDisasmAt(duint addr, duint cip)
{

View File

@ -111,7 +111,8 @@ enum DBGMSG
DBG_SCRIPT_ABORT, // param1=unused, param2=unused
DBG_SCRIPT_GETLINETYPE, // param1=int line, param2=unused
DBG_SCRIPT_SETIP, // param1=int line, param2=unused
DBG_SYMBOL_ENUM // param1=SYMBOLCBINFO* cbInfo, param2=unused
DBG_SYMBOL_ENUM, // param1=SYMBOLCBINFO* cbInfo, param2=unused
DBG_ASSEMBLE_AT // param1=duint addr, param2=const char* instruction
};
enum SCRIPTLINETYPE
@ -287,6 +288,7 @@ BRIDGE_IMPEXP SCRIPTLINETYPE DbgScriptGetLineType(int line);
BRIDGE_IMPEXP void DbgScriptSetIp(int line);
BRIDGE_IMPEXP void DbgSymbolEnum(duint base, CBSYMBOLENUM cbSymbolEnum, void* user);
BRIDGE_IMPEXP bool DbgAssembleAt(duint addr, const char* instruction);
//Gui enums
enum GUIMSG

View File

@ -0,0 +1,52 @@
#ifndef _XEDPARSE_H
#define _XEDPARSE_H
#include <windows.h>
//XEDParse defines
#ifdef XEDPARSE_BUILD
#define XEDPARSE_EXPORT __declspec(dllexport)
#else
#define XEDPARSE_EXPORT __declspec(dllimport)
#endif //XEDPARSE_BUILD
#define XEDPARSE_CALL //calling convention
#define XEDPARSE_MAXBUFSIZE 256
#define XEDPARSE_MAXASMSIZE 16
//typedefs
typedef bool (XEDPARSE_CALL *CBXEDPARSE_UNKNOWN)(const char* text, ULONG_PTR* value);
//XEDParse enums
enum XEDPARSE_STATUS
{
XEDPARSE_ERROR=0,
XEDPARSE_OK=1
};
//XEDParse structs
#pragma pack(push,8)
struct XEDPARSE
{
ULONG_PTR cip; //instruction pointer (for relative addressing)
unsigned int dest_size; //destination size (returned by XEDParse)
CBXEDPARSE_UNKNOWN cbUnknown; //unknown operand callback
unsigned char dest[XEDPARSE_MAXASMSIZE]; //destination buffer
char instr[XEDPARSE_MAXBUFSIZE]; //instruction text
char error[XEDPARSE_MAXBUFSIZE]; //error text (in case of an error)
};
#pragma pack(pop)
#ifdef __cplusplus
extern "C"
{
#endif
XEDPARSE_EXPORT XEDPARSE_STATUS XEDPARSE_CALL XEDParseAssemble(XEDPARSE* XEDParse);
#ifdef __cplusplus
}
#endif
#endif // _XEDPARSE_H

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -9,6 +9,7 @@
#include "disasm_helper.h"
#include "simplescript.h"
#include "symbolinfo.h"
#include "assemble.h"
extern "C" DLL_EXPORT duint _dbg_memfindbaseaddr(duint addr, duint* size)
{
@ -563,6 +564,12 @@ extern "C" DLL_EXPORT uint _dbg_sendmessage(DBGMSG type, void* param1, void* par
symbolenum(cbInfo->base, cbInfo->cbSymbolEnum, cbInfo->user);
}
break;
case DBG_ASSEMBLE_AT:
{
return assembleat((duint)param1, (const char*)param2);
}
break;
}
return 0;
}

View File

@ -1,193 +1,18 @@
#include "assemble.h"
#include "memory.h"
#include "debugger.h"
#include "XEDParse\XEDParse.h"
char nasmpath[deflen]="";
static bool issegment(const char* str)
bool assembleat(uint addr, const char* instruction)
{
if(!_strnicmp(str, "gs", 2))
return true;
if(!_strnicmp(str, "fs", 2))
return true;
if(!_strnicmp(str, "es", 2))
return true;
if(!_strnicmp(str, "ds", 2))
return true;
if(!_strnicmp(str, "cs", 2))
return true;
if(!_strnicmp(str, "ss", 2))
return true;
return false;
}
void intel2nasm(const char* intel, char* nasm)
{
char temp[256]="";
memset(temp, 0, sizeof(temp));
int len=strlen(intel);
for(int i=0,j=0; i<len; i++) //fix basic differences and problems
{
if(!_strnicmp(intel+i, "ptr", 3)) //remove "ptr"
{
i+=2;
if(intel[i+1]==' ')
i++;
continue;
}
else if(!_strnicmp(intel+i, " ", 2)) //remove double spaces
continue;
else if(intel[i]=='\t') //tab=space
{
j+=sprintf(temp+j, " ");
continue;
}
j+=sprintf(temp+j, "%c", intel[i]);
}
len=strlen(temp);
for(int i=0,j=0; i<len; i++)
{
if(temp[i]==' ' and temp[i+1]==',')
continue;
else if(temp[i]==',' and temp[i+1]==' ')
{
j+=sprintf(nasm+j, ",");
i++;
continue;
}
else if(issegment(temp+i) and temp[i+2]==' ')
{
j+=sprintf(nasm+j, "%c%c", temp[i], temp[i+1]);
i+=2;
continue;
}
else if(temp[i]==':' and temp[i+1]==' ')
{
j+=sprintf(nasm+j, ":");
i++;
continue;
}
j+=sprintf(nasm+j, "%c", temp[i]);
}
len=strlen(nasm);
for(int i=0,j=0; i<len; i++)
{
if(issegment(nasm+i) and nasm[i+2]==':' and nasm[i+3]=='[')
{
j+=sprintf(temp+j, "[%c%c:", nasm[i], nasm[i+1]);
i+=3;
continue;
}
j+=sprintf(temp+j, "%c", nasm[i]);
}
strcpy(nasm, temp);
}
bool assemble(const char* instruction, unsigned char** outdata, int* outsize, char* error, bool x64)
{
if(!instruction or !outsize)
return false;
char tmppath[MAX_PATH]="";
char tmpfile[MAX_PATH]="";
char outfile[MAX_PATH]="";
if(!GetTempPathA(MAX_PATH, tmppath) or !GetTempFileNameA(tmppath, "dbg", 0, tmpfile) or !GetTempFileNameA(tmppath, "dbg", 0, outfile))
{
DeleteFileA(outfile);
DeleteFileA(tmpfile);
return false;
}
char* asmfile=(char*)emalloc(strlen(instruction)+9);
if(x64)
strcpy(asmfile, "BITS 64d\n");
else
strcpy(asmfile, "BITS 32d\n");
strcat(asmfile, instruction);
HANDLE hFile=CreateFileA(tmpfile, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(hFile==INVALID_HANDLE_VALUE)
{
if(error)
strcpy(error, "Failed to create asmfile!");
efree(asmfile);
DeleteFileA(outfile);
DeleteFileA(tmpfile);
return false;
}
DWORD written=0;
if(!WriteFile(hFile, asmfile, strlen(asmfile), &written, 0))
{
if(error)
strcpy(error, "Failed to write asmfile!");
efree(asmfile);
CloseHandle(hFile);
DeleteFileA(outfile);
DeleteFileA(tmpfile);
return false;
}
efree(asmfile);
CloseHandle(hFile);
char cmdline[MAX_PATH*4]="";
sprintf(cmdline, "\"%s\" \"%s\" -o \"%s\"", nasmpath, tmpfile, outfile);
STARTUPINFO si;
memset(&si, 0, sizeof(si));
si.cb=sizeof(si);
PROCESS_INFORMATION pi;
if(!CreateProcessA(0, cmdline, 0, 0, false, CREATE_NO_WINDOW, 0, 0, &si, &pi))
{
if(error)
strcpy(error, "Failed to start NASM!");
DeleteFileA(outfile);
DeleteFileA(tmpfile);
return false;
}
DWORD exitCode=STILL_ACTIVE;
do
GetExitCodeProcess(pi.hProcess, &exitCode);
while(exitCode==STILL_ACTIVE);
CloseHandle(pi.hThread);
if(exitCode) //nasm failed
{
if(error)
strcpy(error, "NASM reported a failure!");
DeleteFileA(outfile);
DeleteFileA(tmpfile);
return false;
}
hFile=CreateFileA(outfile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if(hFile==INVALID_HANDLE_VALUE)
{
if(error)
strcpy(error, "Failed to open outfile!");
DeleteFileA(outfile);
DeleteFileA(tmpfile);
return false;
}
int filesize=GetFileSize(hFile, 0);
if(!filesize)
{
if(error)
strcpy(error, "No result in outfile!");
CloseHandle(hFile);
DeleteFileA(outfile);
DeleteFileA(tmpfile);
return false;
}
*outsize=filesize;
unsigned char* out=(unsigned char*)emalloc(filesize);
DWORD read=0;
if(!ReadFile(hFile, out, filesize, &read, 0))
{
if(error)
strcpy(error, "Failed to read outfile!");
efree(out);
CloseHandle(hFile);
DeleteFileA(outfile);
DeleteFileA(tmpfile);
return false;
}
if(outdata)
*outdata=out;
else
efree(out);
CloseHandle(hFile);
DeleteFileA(outfile);
DeleteFileA(tmpfile);
return true;
if(strlen(instruction)>=XEDPARSE_MAXBUFSIZE)
return false;
XEDPARSE parse;
memset(&parse, 0, sizeof(parse));
strcpy(parse.instr, instruction);
if(XEDParseAssemble(&parse)==XEDPARSE_ERROR)
return false;
bool ret=memwrite(fdProcessInfo->hProcess, (void*)addr, parse.dest, parse.dest_size, 0);
GuiUpdateAllViews();
return ret;
}

View File

@ -3,10 +3,6 @@
#include "_global.h"
//superglobal variables
extern char nasmpath[deflen];
bool assemble(const char* instruction, unsigned char** outdata, int* outsize, char* error, bool x64);
void intel2nasm(const char* intel, char* nasm);
bool assembleat(uint addr, const char* instruction);
#endif // _ASSEMBLE_H

View File

@ -375,45 +375,11 @@ CMDRESULT cbAssemble(int argc, char* argv[])
dprintf("invalid address: "fhex"!\n", addr);
return STATUS_ERROR;
}
char instruction[256]="";
intel2nasm(argv[2], instruction);
unsigned char* outdata=0;
int outsize=0;
char error[1024]="";
#ifdef _WIN64
bool ret=assemble(instruction, &outdata, &outsize, error, true);
#else
bool ret=assemble(instruction, &outdata, &outsize, error, false);
#endif // _WIN64
if(!ret)
if(!assembleat(addr, argv[2]))
{
dprintf("assemble error: %s\n", error);
dprintf("failed to assemble \"%s\"\n", argv[2]);
return STATUS_ERROR;
}
bool fillnop=false;
if(argc>=4) //fill with NOPs
fillnop=true;
if(!fillnop)
{
if(!memwrite(fdProcessInfo->hProcess, (void*)addr, outdata, outsize, 0))
{
efree(outdata);
dputs("failed to write memory!");
return STATUS_ERROR;
}
}
else
{
efree(outdata);
dputs("not yet implemented!");
return STATUS_ERROR;
}
varset("$result", outsize, false);
efree(outdata);
GuiUpdateAllViews();
return STATUS_CONTINUE;
}

View File

@ -190,8 +190,6 @@ extern "C" DLL_EXPORT const char* _dbg_dbginit()
char plugindir[deflen]="";
strcpy(plugindir, dir);
PathAppendA(plugindir, "plugins");
strcpy(nasmpath, dir);
PathAppendA(nasmpath, "nasm.exe");
pluginload(plugindir);
return 0;
}

View File

@ -27,6 +27,7 @@
<Add library=".\dbghelp\dbghelp_x86.a" />
<Add library=".\sqlite\libsqlite32.a" />
<Add library=".\BeaEngine\libBeaEngine.a" />
<Add library=".\XEDParse\XEDParse_x86.a" />
</Linker>
</Target>
<Target title="x64">
@ -49,6 +50,7 @@
<Add library=".\dbghelp\dbghelp_x64.a" />
<Add library=".\sqlite\libsqlite64.a" />
<Add library=".\BeaEngine\libBeaEngine_64.a" />
<Add library=".\XEDParse\XEDParse_x64.a" />
</Linker>
</Target>
</Build>
@ -68,6 +70,7 @@
<Unit filename="BeaEngine/export.h" />
<Unit filename="BeaEngine/macros.h" />
<Unit filename="TitanEngine/TitanEngine.h" />
<Unit filename="XEDParse/XEDParse.h" />
<Unit filename="_exports.cpp" />
<Unit filename="_exports.h" />
<Unit filename="_global.cpp" />

View File

@ -110,7 +110,7 @@
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>$(SolutionDir)bin\x32\x32_bridge.lib;dbghelp\dbghelp_x86.lib;TitanEngine\TitanEngine_x86.lib;sqlite\sqlite32.lib;BeaEngine\BeaEngine.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>XEDParse\XEDParse_x86.lib;$(SolutionDir)bin\x32\x32_bridge.lib;dbghelp\dbghelp_x86.lib;TitanEngine\TitanEngine_x86.lib;sqlite\sqlite32.lib;BeaEngine\BeaEngine.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -125,7 +125,7 @@
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>$(SolutionDir)bin\x64\x64_bridge.lib;dbghelp\dbghelp_x64.lib;TitanEngine\TitanEngine_x64.lib;sqlite\sqlite64.lib;BeaEngine\BeaEngine_64.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>XEDParse\XEDParse_x64.lib;$(SolutionDir)bin\x64\x64_bridge.lib;dbghelp\dbghelp_x64.lib;TitanEngine\TitanEngine_x64.lib;sqlite\sqlite64.lib;BeaEngine\BeaEngine_64.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -477,9 +477,12 @@ void CPUDisassembly::assembleAt()
if(mLineEdit.exec()!=QDialog::Accepted)
return;
QMessageBox msg(QMessageBox::Critical, "Error!", "Function not (yet) supported...");
msg.setWindowIcon(QIcon(":/icons/images/compile-error.png"));
msg.setParent(this, Qt::Dialog);
msg.setWindowFlags(msg.windowFlags()&(~Qt::WindowContextHelpButtonHint));
msg.exec();
if(!DbgAssembleAt(wVA, mLineEdit.editText.toUtf8().constData()))
{
QMessageBox msg(QMessageBox::Critical, "Error!", "Failed to assemble instruction \"" + mLineEdit.editText + QString("\""));
msg.setWindowIcon(QIcon(":/icons/images/compile-error.png"));
msg.setParent(this, Qt::Dialog);
msg.setWindowFlags(msg.windowFlags()&(~Qt::WindowContextHelpButtonHint));
msg.exec();
}
}