From 6bb96406b33324b3a44aa30aed49b87013f13b87 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Tue, 13 Oct 2015 22:51:23 +0200 Subject: [PATCH] DBG: find pattern in the memory map (findallmem startAddr, "1? 24 ?6 78") --- x64_dbg_dbg/instruction.cpp | 131 +++++++++++++++++++++++++++++++++++- x64_dbg_dbg/instruction.h | 2 + x64_dbg_dbg/memory.cpp | 39 +++++++++++ x64_dbg_dbg/memory.h | 17 ++++- x64_dbg_dbg/x64_dbg.cpp | 2 + 5 files changed, 189 insertions(+), 2 deletions(-) diff --git a/x64_dbg_dbg/instruction.cpp b/x64_dbg_dbg/instruction.cpp index f05503d9..8d9c9a77 100644 --- a/x64_dbg_dbg/instruction.cpp +++ b/x64_dbg_dbg/instruction.cpp @@ -31,8 +31,10 @@ #include "analysis_nukem.h" #include "exceptiondirectoryanalysis.h" #include "_scriptapi_stack.h" +#include "threading.h" static bool bRefinit = false; +static int maxFindResults = 5000; CMDRESULT cbBadCmd(int argc, char* argv[]) { @@ -1240,7 +1242,7 @@ CMDRESULT cbInstrFindAll(int argc, char* argv[]) dputs("failed to transform pattern!"); return STATUS_ERROR; } - while(refCount < 5000) + while(refCount < maxFindResults) { uint foundoffset = patternfind(data() + start + i, find_size - i, searchpattern); if(foundoffset == -1) @@ -1277,6 +1279,116 @@ CMDRESULT cbInstrFindAll(int argc, char* argv[]) return STATUS_CONTINUE; } +CMDRESULT cbInstrFindMemAll(int argc, char* argv[]) +{ + dprintf("argc: %d\n", argc); + for(int i = 0; i < argc; i++) + { + dprintf("%d:\"%s\"\n", i, argv[i]); + } + if(argc < 3) + { + dputs("not enough arguments!"); + return STATUS_ERROR; + } + uint addr = 0; + if(!valfromstring(argv[1], &addr, false)) + return STATUS_ERROR; + + char pattern[deflen] = ""; + //remove # from the start and end of the pattern (ODBGScript support) + if(argv[2][0] == '#') + strcpy_s(pattern, argv[2] + 1); + else + strcpy_s(pattern, argv[2]); + int len = (int)strlen(pattern); + if(pattern[len - 1] == '#') + pattern[len - 1] = '\0'; + std::vector searchpattern; + if(!patterntransform(pattern, searchpattern)) + { + dputs("failed to transform pattern!"); + return STATUS_ERROR; + } + + uint endAddr = -1; + bool findData = false; + if(argc >= 4) + { + if(!_stricmp(argv[3], "&data&")) + findData = true; + else if(!valfromstring(argv[3], &endAddr)) + findData = false; + } + + SHARED_ACQUIRE(LockMemoryPages); + std::vector searchPages; + for(auto & itr : memoryPages) + { + SimplePage page(uint(itr.second.mbi.BaseAddress), itr.second.mbi.RegionSize); + if(page.address >= addr && page.address + page.size <= endAddr) + searchPages.push_back(page); + } + SHARED_RELEASE(); + + DWORD ticks = GetTickCount(); + + std::vector results; + if(!MemFindInMap(searchPages, searchpattern, results, maxFindResults)) + { + dputs("MemFindInMap failed!"); + return STATUS_ERROR; + } + + //setup reference view + char patternshort[256] = ""; + strncpy_s(patternshort, pattern, min(16, len)); + if(len > 16) + strcat_s(patternshort, "..."); + char patterntitle[256] = ""; + sprintf_s(patterntitle, "Pattern: %s", patternshort); + GuiReferenceInitialize(patterntitle); + GuiReferenceAddColumn(2 * sizeof(uint), "Address"); + if(findData) + GuiReferenceAddColumn(0, "&Data&"); + else + GuiReferenceAddColumn(0, "Disassembly"); + GuiReferenceReloadData(); + + int refCount = 0; + for(uint result : results) + { + char msg[deflen] = ""; + sprintf(msg, fhex, result); + GuiReferenceSetRowCount(refCount + 1); + GuiReferenceSetCellContent(refCount, 0, msg); + if(findData) + { + Memory printData(searchpattern.size(), "cbInstrFindAll:printData"); + MemRead(result, printData(), printData.size()); + for(size_t j = 0, k = 0; j < printData.size(); j++) + { + if(j) + k += sprintf(msg + k, " "); + k += sprintf(msg + k, "%.2X", printData()[j]); + } + } + else + { + if(!GuiGetDisassembly(result, msg)) + strcpy_s(msg, "[Error disassembling]"); + } + GuiReferenceSetCellContent(refCount, 1, msg); + refCount++; + } + + GuiReferenceReloadData(); + dprintf("%d occurrences found in %ums\n", refCount, GetTickCount() - ticks); + varset("$result", refCount, false); + + return STATUS_CONTINUE; +} + static bool cbModCallFind(Capstone* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFINFO* refinfo) { if(!disasm || !basicinfo) //initialize @@ -2159,4 +2271,21 @@ CMDRESULT cbInstrMeminfo(int argc, char* argv[]) dputs("memory map updated!"); } return STATUS_CONTINUE; +} + +CMDRESULT cbInstrSetMaxFindResult(int argc, char* argv[]) +{ + if(argc < 2) + { + dputs("Not enough arguments!"); + return STATUS_ERROR; + } + uint num; + if(!valfromstring(argv[1], &num)) + { + dprintf("Invalid expression: \"%s\"", argv[1]); + return STATUS_ERROR; + } + maxFindResults = num; + return STATUS_CONTINUE; } \ No newline at end of file diff --git a/x64_dbg_dbg/instruction.h b/x64_dbg_dbg/instruction.h index 1166a07c..48f69688 100644 --- a/x64_dbg_dbg/instruction.h +++ b/x64_dbg_dbg/instruction.h @@ -55,6 +55,7 @@ CMDRESULT cbInstrCopystr(int argc, char* argv[]); CMDRESULT cbInstrFind(int argc, char* argv[]); CMDRESULT cbInstrFindAll(int argc, char* argv[]); +CMDRESULT cbInstrFindMemAll(int argc, char* argv[]); CMDRESULT cbInstrModCallFind(int argc, char* argv[]); CMDRESULT cbInstrCommentList(int argc, char* argv[]); CMDRESULT cbInstrLabelList(int argc, char* argv[]); @@ -75,5 +76,6 @@ CMDRESULT cbInstrMeminfo(int argc, char* argv[]); CMDRESULT cbInstrCfanalyse(int argc, char* argv[]); CMDRESULT cbInstrExanalyse(int argc, char* argv[]); CMDRESULT cbInstrVirtualmod(int argc, char* argv[]); +CMDRESULT cbInstrSetMaxFindResult(int argc, char* argv[]); #endif // _INSTRUCTIONS_H diff --git a/x64_dbg_dbg/memory.cpp b/x64_dbg_dbg/memory.cpp index a04012c6..4830f81e 100644 --- a/x64_dbg_dbg/memory.cpp +++ b/x64_dbg_dbg/memory.cpp @@ -471,3 +471,42 @@ bool MemPageRightsFromString(DWORD* Protect, const char* Rights) return (*Protect != 0); } + +bool MemFindInPage(SimplePage page, uint startoffset, const std::vector & pattern, std::vector & results, uint maxresults) +{ + if(startoffset >= page.size || results.size() >= maxresults) + return false; + + //TODO: memory read limit + Memory data(page.size); + if(!MemRead(page.address, data(), data.size())) + return false; + + uint maxFind = maxresults; + uint foundCount = results.size(); + uint i = 0; + uint findSize = data.size() - startoffset; + while(foundCount < maxFind) + { + uint foundoffset = patternfind(data() + startoffset + i, findSize - i, pattern); + if(foundoffset == -1) + break; + i += foundoffset + 1; + uint result = page.address + startoffset + i - 1; + results.push_back(result); + foundCount++; + } + return true; +} + +bool MemFindInMap(const std::vector & pages, const std::vector & pattern, std::vector & results, uint maxresults) +{ + for(const auto page : pages) + { + if(!MemFindInPage(page, 0, pattern, results, maxresults)) + return false; + if(results.size() >= maxresults) + break; + } + return true; +} \ No newline at end of file diff --git a/x64_dbg_dbg/memory.h b/x64_dbg_dbg/memory.h index d4fdcb4b..30d0842e 100644 --- a/x64_dbg_dbg/memory.h +++ b/x64_dbg_dbg/memory.h @@ -2,10 +2,23 @@ #include "_global.h" #include "addrinfo.h" +#include "patternfind.h" extern std::map memoryPages; extern bool bListAllPages; +struct SimplePage +{ + uint address; + uint size; + + SimplePage(uint address, uint size) + { + this->address = address; + this->size = size; + } +}; + void MemUpdateMap(); uint MemFindBaseAddr(uint Address, uint* Size, bool Refresh = false); bool MemRead(uint BaseAddress, void* Buffer, uint Size, uint* NumberOfBytesRead = nullptr); @@ -21,4 +34,6 @@ bool MemGetPageInfo(uint Address, MEMPAGE* PageInfo, bool Refresh = false); bool MemSetPageRights(uint Address, const char* Rights); bool MemGetPageRights(uint Address, char* Rights); bool MemPageRightsToString(DWORD Protect, char* Rights); -bool MemPageRightsFromString(DWORD* Protect, const char* Rights); \ No newline at end of file +bool MemPageRightsFromString(DWORD* Protect, const char* Rights); +bool MemFindInPage(SimplePage page, uint startoffset, const std::vector & pattern, std::vector & results, uint maxresults); +bool MemFindInMap(const std::vector & pages, const std::vector & pattern, std::vector & results, uint maxresults); \ No newline at end of file diff --git a/x64_dbg_dbg/x64_dbg.cpp b/x64_dbg_dbg/x64_dbg.cpp index 489828db..78f1e29b 100644 --- a/x64_dbg_dbg/x64_dbg.cpp +++ b/x64_dbg_dbg/x64_dbg.cpp @@ -210,6 +210,8 @@ static void registercommands() dbgcmdnew("analyse_nukem\1analyze_nukem\1anal_nukem", cbInstrAnalyseNukem, true); //secret analysis command #2 dbgcmdnew("exanal\1exanalyse\1exanalyze", cbInstrExanalyse, true); //exception directory analysis dbgcmdnew("virtualmod", cbInstrVirtualmod, true); //virtual module + dbgcmdnew("findallmem\1findmemall", cbInstrFindMemAll, true); //memory map pattern find + dbgcmdnew("setmaxfindresult\1findsetmaxresult", cbInstrSetMaxFindResult, false); //set the maximum number of occurences found } static bool cbCommandProvider(char* cmd, int maxlen)