From bdecbc6458545561cc88f57986ccfb7a90f24a61 Mon Sep 17 00:00:00 2001 From: "mr.exodia" Date: Fri, 27 Dec 2013 20:54:10 +0100 Subject: [PATCH] PROJECT: updated todo list BRIDGE: added FUNCTION structure to the ADDRINFO structure DBG: fixed some potential buffer overflows in modname variables DBG: added 'functions' to the database (functionfromaddr, functionoverlaps, functionadd) DBG: added 'functionadd' command ("functionadd startAddr,endAddr") DBG: FINALLY fixed this non-silent bug in mathfromstring GUI: re-enabled Function_single drawing --- todo_dbg.txt | 3 +- x64_dbg_bridge/bridgemain.cpp | 22 ++-- x64_dbg_bridge/bridgemain.h | 12 +- x64_dbg_bridge/x64_dbg_bridge.cbp | 2 +- x64_dbg_dbg/_exports.cpp | 5 + x64_dbg_dbg/addrinfo.cpp | 114 ++++++++++++++++-- x64_dbg_dbg/addrinfo.h | 3 + x64_dbg_dbg/instruction.cpp | 18 +++ x64_dbg_dbg/instruction.h | 1 + x64_dbg_dbg/math.cpp | 4 +- x64_dbg_dbg/x64_dbg.cpp | 1 + .../Project/Src/BasicView/Disassembly.cpp | 14 +++ .../Project/Src/BasicView/Disassembly.h | 1 + 13 files changed, 174 insertions(+), 26 deletions(-) diff --git a/todo_dbg.txt b/todo_dbg.txt index 1b438d9a..bfdfdefd 100644 --- a/todo_dbg.txt +++ b/todo_dbg.txt @@ -1,4 +1,4 @@ -- attach/detach debugger +- detach debugger - asm command - memcpy - pe data access @@ -69,7 +69,6 @@ - find all intermodular calls - highlight register changes (only when CIP changed also) - PAGE UP + PAGE DOWN keys in disasm -- function lines database for analysis - 'dead' bytes custom analysis - loops lines database for analysis - enable/disable hw+mem breakpoint \ No newline at end of file diff --git a/x64_dbg_bridge/bridgemain.cpp b/x64_dbg_bridge/bridgemain.cpp index e661ca98..810da818 100644 --- a/x64_dbg_bridge/bridgemain.cpp +++ b/x64_dbg_bridge/bridgemain.cpp @@ -378,16 +378,20 @@ BRIDGE_IMPEXP bool DbgCmdExecDirect(const char* cmd) BRIDGE_IMPEXP FUNCTYPE DbgGetFunctionTypeAt(duint addr) { - //NOTE: test code for 'function.exe' - if(addr==0x0040132A) - return FUNC_BEGIN; - else if(addr>0x0040132A && addr<0x004013BA) - return FUNC_MIDDLE; - else if(addr==0x004013BA) - return FUNC_END; - else if(addr==0x004013BB) + ADDRINFO info; + memset(&info, 0, sizeof(info)); + info.flags=flagfunction; + if(!_dbg_addrinfoget(addr, SEG_DEFAULT, &info)) + return FUNC_NONE; + duint start=info.function.start; + duint end=info.function.end; + if(start==end) return FUNC_SINGLE; - return FUNC_NONE; + else if(addr==start) + return FUNC_BEGIN; + else if(addr==end) + return FUNC_END; + return FUNC_MIDDLE; } BRIDGE_IMPEXP LOOPTYPE DbgGetLoopTypeAt(duint addr, int depth) diff --git a/x64_dbg_bridge/bridgemain.h b/x64_dbg_bridge/bridgemain.h index 841aaa3e..199da555 100644 --- a/x64_dbg_bridge/bridgemain.h +++ b/x64_dbg_bridge/bridgemain.h @@ -84,7 +84,8 @@ enum ADDRINFOFLAGS flagmodule=1, flaglabel=2, flagcomment=4, - flagbookmark=8 + flagbookmark=8, + flagfunction=16 }; enum BPXTYPE @@ -144,13 +145,20 @@ struct BPMAP BRIDGEBP* bp; }; +struct FUNCTION +{ + duint start; + duint end; +}; + struct ADDRINFO { + int flags; //ADDRINFOFLAGS char module[MAX_MODULE_SIZE]; //module the address is in char label[MAX_LABEL_SIZE]; char comment[MAX_COMMENT_SIZE]; bool isbookmark; - int flags; //ADDRINFOFLAGS + FUNCTION function; }; struct FLAGS diff --git a/x64_dbg_bridge/x64_dbg_bridge.cbp b/x64_dbg_bridge/x64_dbg_bridge.cbp index 1e1e1101..2b583ed1 100644 --- a/x64_dbg_bridge/x64_dbg_bridge.cbp +++ b/x64_dbg_bridge/x64_dbg_bridge.cbp @@ -39,7 +39,7 @@ - + diff --git a/x64_dbg_dbg/_exports.cpp b/x64_dbg_dbg/_exports.cpp index b53a9920..04030839 100644 --- a/x64_dbg_dbg/_exports.cpp +++ b/x64_dbg_dbg/_exports.cpp @@ -213,6 +213,11 @@ extern "C" DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, ADDR addrinfo->isbookmark=bookmarkget(addr); retval=true; } + if(addrinfo->flags&flagfunction) + { + if(functionfromaddr(addr, &addrinfo->function.start, &addrinfo->function.end)) + retval=true; + } return retval; } diff --git a/x64_dbg_dbg/addrinfo.cpp b/x64_dbg_dbg/addrinfo.cpp index 435bad3f..ab1d217c 100644 --- a/x64_dbg_dbg/addrinfo.cpp +++ b/x64_dbg_dbg/addrinfo.cpp @@ -26,6 +26,8 @@ void dbinit() dprintf("SQL Error: %s\n", sqllasterror()); if(!sqlexec(userdb, "CREATE TABLE IF NOT EXISTS breakpoints (id INTEGER PRIMARY KEY AUTOINCREMENT, addr INT64 NOT NULL, enabled INT NOT NULL, singleshoot INT NOT NULL, oldbytes INT NOT NULL, type INT NOT NULL, titantype INT NOT NULL, mod TEXT, name TEXT)")) dprintf("SQL Error: %s\n", sqllasterror()); + if(!sqlexec(userdb, "CREATE TABLE IF NOT EXISTS functions (id INTEGER PRIMARY KEY AUTOINCREMENT, mod TEXT, start INT64 NOT NULL, end INT64 NOT NULL, manual BOOL NOT NULL)")) + dprintf("SQL Error: %s\n", sqllasterror()); dbsave(); bpenumall(0); //update breakpoint list GuiUpdateBreakpointsView(); @@ -185,7 +187,7 @@ bool apienumexports(uint base, EXPORTENUMCALLBACK cbEnum) unsigned int NumberOfNames=export_dir.NumberOfNames; if(!export_dir.NumberOfFunctions or !NumberOfNames) //no named exports return false; - char modname[256]=""; + char modname[MAX_MODULE_SIZE]=""; modnamefromaddr(base, modname, true); uint original_name_va=export_dir.Name+base; char original_name[deflen]=""; @@ -248,7 +250,7 @@ bool commentset(uint addr, const char* text) return commentdel(addr); char commenttext[MAX_COMMENT_SIZE]=""; sqlstringescape(text, commenttext); - char modname[35]=""; + char modname[MAX_MODULE_SIZE]=""; char sql[deflen]=""; if(!modnamefromaddr(addr, modname, true)) //comments without module { @@ -282,7 +284,7 @@ bool commentget(uint addr, char* text) { if(!IsFileBeingDebugged() or !memisvalidreadptr(fdProcessInfo->hProcess, addr) or !text) return false; - char modname[35]=""; + char modname[MAX_MODULE_SIZE]=""; char sql[deflen]=""; if(!modnamefromaddr(addr, modname, true)) //comments without module sprintf(sql, "SELECT text FROM comments WHERE mod IS NULL AND addr=%"fext"d", addr); @@ -295,7 +297,7 @@ bool commentdel(uint addr) { if(!IsFileBeingDebugged() or !memisvalidreadptr(fdProcessInfo->hProcess, addr)) return false; - char modname[35]=""; + char modname[MAX_MODULE_SIZE]=""; char sql[deflen]=""; if(!modnamefromaddr(addr, modname, true)) //comments without module sprintf(sql, "SELECT id FROM comments WHERE mod IS NULL AND addr=%"fext"d", addr); @@ -328,7 +330,7 @@ bool labelset(uint addr, const char* text) return labeldel(addr); char labeltext[MAX_LABEL_SIZE]=""; sqlstringescape(text, labeltext); - char modname[35]=""; + char modname[MAX_MODULE_SIZE]=""; char sql[deflen]=""; if(!modnamefromaddr(addr, modname, true)) //labels without module { @@ -398,7 +400,7 @@ bool labelget(uint addr, char* text) { if(!IsFileBeingDebugged() or !memisvalidreadptr(fdProcessInfo->hProcess, addr) or !text) return false; - char modname[35]=""; + char modname[MAX_MODULE_SIZE]=""; char sql[deflen]=""; if(!modnamefromaddr(addr, modname, true)) //labels without module sprintf(sql, "SELECT text FROM labels WHERE mod IS NULL AND addr=%"fext"d", addr); @@ -411,7 +413,7 @@ bool labeldel(uint addr) { if(!IsFileBeingDebugged() or !memisvalidreadptr(fdProcessInfo->hProcess, addr)) return false; - char modname[35]=""; + char modname[MAX_MODULE_SIZE]=""; char sql[deflen]=""; if(!modnamefromaddr(addr, modname, true)) //labels without module sprintf(sql, "SELECT id FROM labels WHERE mod IS NULL AND addr=%"fext"d", addr); @@ -440,7 +442,7 @@ bool bookmarkset(uint addr) { if(!IsFileBeingDebugged() or !memisvalidreadptr(fdProcessInfo->hProcess, addr)) return false; - char modname[35]=""; + char modname[MAX_MODULE_SIZE]=""; char sql[deflen]=""; if(!modnamefromaddr(addr, modname, true)) //bookmarks without module { @@ -474,7 +476,7 @@ bool bookmarkget(uint addr) { if(!IsFileBeingDebugged() or !memisvalidreadptr(fdProcessInfo->hProcess, addr)) return false; - char modname[35]=""; + char modname[MAX_MODULE_SIZE]=""; char sql[deflen]=""; if(!modnamefromaddr(addr, modname, true)) //bookmarks without module sprintf(sql, "SELECT * FROM bookmarks WHERE mod IS NULL AND addr=%"fext"d", addr); @@ -487,7 +489,7 @@ bool bookmarkdel(uint addr) { if(!IsFileBeingDebugged() or !memisvalidreadptr(fdProcessInfo->hProcess, addr)) return false; - char modname[35]=""; + char modname[MAX_MODULE_SIZE]=""; char sql[deflen]=""; if(!modnamefromaddr(addr, modname, true)) //bookmarks without module sprintf(sql, "SELECT id FROM bookmarks WHERE mod IS NULL AND addr=%"fext"d", addr); @@ -525,3 +527,95 @@ bool symfromname(const char* name, uint* addr) *addr=(uint)pSymbol->Address; return true; } + +///function functions :D +bool functionfromaddr(duint addr, duint* start, duint* end) +{ + if(!IsFileBeingDebugged() or !memisvalidreadptr(fdProcessInfo->hProcess, addr)) + return false; + char modname[MAX_MODULE_SIZE]=""; + char sql[deflen]=""; + uint modbase=0; + if(!modnamefromaddr(addr, modname, true)) + sprintf(sql, "SELECT start,end FROM functions WHERE mod IS NULL AND start<=%"fext"d AND end>=%"fext"d", addr, addr); + else + { + modbase=modbasefromaddr(addr); + uint rva=addr-modbase; + sprintf(sql, "SELECT start,end FROM functions WHERE mod='%s' AND start<=%"fext"d AND end>=%"fext"d", modname, rva, rva); + } + if(addr==0x7758100F) + puts(sql); + sqlite3_stmt* stmt; + if(sqlite3_prepare_v2(userdb, sql, -1, &stmt, 0)!=SQLITE_OK) + { + sqlite3_finalize(stmt); + return false; + } + if(sqlite3_step(stmt)!=SQLITE_ROW) + { + sqlite3_finalize(stmt); + return false; + } +#ifdef _WIN64 + uint dbstart=sqlite3_column_int64(stmt, 0)+modbase; //start + uint dbend=sqlite3_column_int64(stmt, 1)+modbase; //end +#else + uint dbstart=sqlite3_column_int(stmt, 0)+modbase; //addr + uint dbend=sqlite3_column_int(stmt, 1)+modbase; //end +#endif // _WIN64 + sqlite3_finalize(stmt); + if(start) + *start=dbstart; + if(end) + *end=dbend; + return true; +} + +bool functionoverlaps(uint start, uint end) +{ + char sql[deflen]=""; + char modname[MAX_MODULE_SIZE]=""; + //check for function overlaps + if(!modnamefromaddr(start, modname, true)) + sprintf(sql, "SELECT manual FROM functions WHERE mod IS NULL AND start<=%"fext"d AND end>=%"fext"d", end, start); + else + { + uint modbase=modbasefromaddr(start); + sprintf(sql, "SELECT manual FROM functions WHERE mod='%s' AND start<=%"fext"d AND end>=%"fext"d", modname, end-modbase, start-modbase); + } + if(sqlhasresult(userdb, sql)) //functions overlap + return true; + return false; +} + +bool functionadd(uint start, uint end, bool manual) +{ + if(!IsFileBeingDebugged() or endhProcess, start, 0)!=memfindbaseaddr(fdProcessInfo->hProcess, end, 0)) //the function boundaries are not in the same mem page + return false; + char sql[deflen]=""; + char modname[MAX_MODULE_SIZE]=""; + uint modbase=0; + //check for function overlaps + if(!modnamefromaddr(start, modname, true)) + sprintf(sql, "SELECT manual FROM functions WHERE mod IS NULL AND start<=%"fext"d AND end>=%"fext"d", end, start); + else + { + modbase=modbasefromaddr(start); + sprintf(sql, "SELECT manual FROM functions WHERE mod='%s' AND start<=%"fext"d AND end>=%"fext"d", modname, end-modbase, start-modbase); + } + if(sqlhasresult(userdb, sql)) //functions overlap + return false; + if(modbase) + sprintf(sql, "INSERT INTO functions (mod,start,end,manual) VALUES('%s',%"fext"d,%"fext"d,%d)", modname, start-modbase, end-modbase, manual); + else + sprintf(sql, "INSERT INTO functions (start,end,manual) VALUES(%"fext"d,%"fext"d,%d)", start, end, manual); + if(!sqlexec(userdb, sql)) + { + dprintf("SQL Error: %s\nSQL Query: %s\n", sqllasterror(), sql); + return false; + } + GuiUpdateAllViews(); + dbsave(); + return true; +} diff --git a/x64_dbg_dbg/addrinfo.h b/x64_dbg_dbg/addrinfo.h index 97eb2ff7..43cc1355 100644 --- a/x64_dbg_dbg/addrinfo.h +++ b/x64_dbg_dbg/addrinfo.h @@ -40,5 +40,8 @@ bool bookmarkset(uint addr); bool bookmarkget(uint addr); bool bookmarkdel(uint addr); bool symfromname(const char* name, uint* addr); +bool functionfromaddr(duint addr, duint* start, duint* end); +bool functionoverlaps(uint start, uint end); +bool functionadd(uint start, uint end, bool manual); #endif // _ADDRINFO_H diff --git a/x64_dbg_dbg/instruction.cpp b/x64_dbg_dbg/instruction.cpp index 299a9947..69c601fe 100644 --- a/x64_dbg_dbg/instruction.cpp +++ b/x64_dbg_dbg/instruction.cpp @@ -417,3 +417,21 @@ CMDRESULT cbAssemble(int argc, char* argv[]) GuiUpdateAllViews(); return STATUS_CONTINUE; } + +CMDRESULT cbFunction(int argc, char* argv[]) +{ + if(argc<3) + { + dputs("not enough arguments!"); + return STATUS_ERROR; + } + uint start=0; + uint end=0; + if(!valfromstring(argv[1], &start, 0, 0, false, 0) or !valfromstring(argv[2], &end, 0, 0, false, 0)) + return STATUS_ERROR; + if(functionadd(start, end, true)) + dputs("function added!"); + else + dputs("function NOT added..."); + return STATUS_CONTINUE; +} diff --git a/x64_dbg_dbg/instruction.h b/x64_dbg_dbg/instruction.h index 3dc3c23d..9fd1b932 100644 --- a/x64_dbg_dbg/instruction.h +++ b/x64_dbg_dbg/instruction.h @@ -20,5 +20,6 @@ CMDRESULT cbInstrBookmarkDel(int argc, char* argv[]); CMDRESULT cbLoaddb(int argc, char* argv[]); CMDRESULT cbSavedb(int argc, char* argv[]); CMDRESULT cbAssemble(int argc, char* argv[]); +CMDRESULT cbFunction(int argc, char* argv[]); #endif // _INSTRUCTIONS_H diff --git a/x64_dbg_dbg/math.cpp b/x64_dbg_dbg/math.cpp index b2a5ba30..176049a5 100644 --- a/x64_dbg_dbg/math.cpp +++ b/x64_dbg_dbg/math.cpp @@ -374,7 +374,7 @@ bool mathfromstring(const char* string, uint* value, int* value_size, bool* isva } if(!highestop) { - if(!valfromstring(string, value, value_size, isvar, false, 0)) + if(!valfromstring(string, value, value_size, isvar, silent, 0)) return false; return true; } @@ -392,7 +392,7 @@ bool mathfromstring(const char* string, uint* value, int* value_size, bool* isva return false; } uint right=0; - if(!valfromstring(strright, &right, 0, 0, false, 0)) + if(!valfromstring(strright, &right, 0, 0, silent, 0)) { efree(strleft, "mathfromstring:strleft"); efree(strright, "mathfromstring:strright"); diff --git a/x64_dbg_dbg/x64_dbg.cpp b/x64_dbg_dbg/x64_dbg.cpp index 5ebcb827..80ff2f82 100644 --- a/x64_dbg_dbg/x64_dbg.cpp +++ b/x64_dbg_dbg/x64_dbg.cpp @@ -80,6 +80,7 @@ static void registercommands() cmdnew(cmd, "asm", cbAssemble, true); //assemble instruction cmdnew(cmd, "AttachDebugger\1attach", cbDebugAttach, false); //attach //cmdnew(cmd, "DetachDebugger\1detach", cbDebugDetach, true); //detach + cmdnew(cmd, "functionadd\1function\1func", cbFunction, true); //function } static bool cbCommandProvider(char* cmd, int maxlen) diff --git a/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp b/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp index f8f3a781..db7c09d8 100644 --- a/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp +++ b/x64_dbg_gui/Project/Src/BasicView/Disassembly.cpp @@ -218,6 +218,8 @@ QString Disassembly::paintContent(QPainter* painter, int_t rowBase, int rowOffse switch(DbgGetFunctionTypeAt(cur_addr)) { case FUNC_SINGLE: + funcType=Function_single; + break; case FUNC_NONE: funcType=Function_none; break; @@ -670,6 +672,18 @@ int Disassembly::paintFunctionGraphic(QPainter* painter, int x, int y, Function_ } switch(funcType) { + case Function_single: + { + if(loop) + y_add=height/2+1; + painter->drawLine(x+x_add+line_width, y+y_add, x+x_add, y+y_add); + painter->drawLine(x+x_add, y+y_add, x+x_add, y+height-y_add-1); + if(loop) + y_add=height/2-1; + painter->drawLine(x+x_add, y+height-y_add, x+x_add+line_width, y+height-y_add); + } + break; + case Function_start: { if(loop) diff --git a/x64_dbg_gui/Project/Src/BasicView/Disassembly.h b/x64_dbg_gui/Project/Src/BasicView/Disassembly.h index 15d74b46..e81f03bb 100644 --- a/x64_dbg_gui/Project/Src/BasicView/Disassembly.h +++ b/x64_dbg_gui/Project/Src/BasicView/Disassembly.h @@ -40,6 +40,7 @@ public: enum Function_t { Function_none, + Function_single, Function_start, Function_middle, Function_loop_entry,