From 5634206e85c0d1613f4bb4aebc810d34af3ca0d4 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Tue, 14 Jul 2015 14:03:20 +0200 Subject: [PATCH] DBG: resolved issue #78 (added virtual module support) --- x64_dbg_dbg/debugger.cpp | 2 +- x64_dbg_dbg/debugger.h | 1 + x64_dbg_dbg/instruction.cpp | 42 ++++++++++++++++++++++ x64_dbg_dbg/instruction.h | 1 + x64_dbg_dbg/module.cpp | 71 ++++++++++++++++++++++++++----------- x64_dbg_dbg/x64_dbg.cpp | 1 + 6 files changed, 96 insertions(+), 22 deletions(-) diff --git a/x64_dbg_dbg/debugger.cpp b/x64_dbg_dbg/debugger.cpp index 88610553..eef90527 100644 --- a/x64_dbg_dbg/debugger.cpp +++ b/x64_dbg_dbg/debugger.cpp @@ -478,7 +478,7 @@ static BOOL CALLBACK SymRegisterCallbackProc64(HANDLE hProcess, ULONG ActionCode return TRUE; } -static bool cbSetModuleBreakpoints(const BREAKPOINT* bp) +bool cbSetModuleBreakpoints(const BREAKPOINT* bp) { if(!bp->enabled) return true; diff --git a/x64_dbg_dbg/debugger.h b/x64_dbg_dbg/debugger.h index 07a293c5..3e3dcb98 100644 --- a/x64_dbg_dbg/debugger.h +++ b/x64_dbg_dbg/debugger.h @@ -126,6 +126,7 @@ bool cbDeleteAllMemoryBreakpoints(const BREAKPOINT* bp); bool cbDeleteAllHardwareBreakpoints(const BREAKPOINT* bp); DWORD WINAPI threadAttachLoop(void* lpParameter); void cbDetach(); +bool cbSetModuleBreakpoints(const BREAKPOINT* bp); //variables extern PROCESS_INFORMATION* fdProcessInfo; diff --git a/x64_dbg_dbg/instruction.cpp b/x64_dbg_dbg/instruction.cpp index c724d608..a06aa56b 100644 --- a/x64_dbg_dbg/instruction.cpp +++ b/x64_dbg_dbg/instruction.cpp @@ -1953,6 +1953,48 @@ CMDRESULT cbInstrExanalyse(int argc, char* argv[]) return STATUS_CONTINUE; } +CMDRESULT cbInstrVirtualmod(int argc, char* argv[]) +{ + if(argc < 3) + { + dputs("Not enough arguments!"); + return STATUS_ERROR; + } + uint base; + if(!valfromstring(argv[2], &base)) + { + dputs("Invalid parameter [base]!"); + return STATUS_ERROR; + } + if(!MemIsValidReadPtr(base)) + { + dputs("Invalid memory address!"); + return STATUS_ERROR; + } + uint size; + if(argc < 4) + base = MemFindBaseAddr(base, &size); + else if(!valfromstring(argv[3], &size)) + { + dputs("Invalid parameter [size]"); + return STATUS_ERROR; + } + auto name = String("virtual:\\") + (argv[1]); + if(!ModLoad(base, size, name.c_str())) + { + dputs("Failed to load module (ModLoad)..."); + return STATUS_ERROR; + } + + char modname[256] = ""; + if(ModNameFromAddr(base, modname, true)) + BpEnumAll(cbSetModuleBreakpoints, modname); + + dprintf("Virtual module \"%s\" loaded on %p[%p]!\n", argv[1], base, size); + GuiUpdateAllViews(); + return STATUS_CONTINUE; +} + CMDRESULT cbInstrVisualize(int argc, char* argv[]) { if(argc < 3) diff --git a/x64_dbg_dbg/instruction.h b/x64_dbg_dbg/instruction.h index 035547fd..3def8375 100644 --- a/x64_dbg_dbg/instruction.h +++ b/x64_dbg_dbg/instruction.h @@ -73,5 +73,6 @@ CMDRESULT cbInstrVisualize(int argc, char* argv[]); CMDRESULT cbInstrMeminfo(int argc, char* argv[]); CMDRESULT cbInstrCfanalyse(int argc, char* argv[]); CMDRESULT cbInstrExanalyse(int argc, char* argv[]); +CMDRESULT cbInstrVirtualmod(int argc, char* argv[]); #endif // _INSTRUCTIONS_H diff --git a/x64_dbg_dbg/module.cpp b/x64_dbg_dbg/module.cpp index f218ffda..9cfb95e5 100644 --- a/x64_dbg_dbg/module.cpp +++ b/x64_dbg_dbg/module.cpp @@ -3,9 +3,36 @@ #include "threading.h" #include "symbolinfo.h" #include "murmurhash.h" +#include "memory.h" +#include "console.h" +#include "label.h" std::map modinfo; +static void getModuleInfo(MODINFO & info, ULONG_PTR FileMapVA) +{ + // Get the entry point + info.entry = GetPE32DataFromMappedFile(FileMapVA, 0, UE_OEP) + info.base; + + // Enumerate all PE sections + int sectionCount = (int)GetPE32DataFromMappedFile(FileMapVA, 0, UE_SECTIONNUMBER); + + for(int i = 0; i < sectionCount; i++) + { + MODSECTIONINFO curSection; + + curSection.addr = GetPE32DataFromMappedFile(FileMapVA, i, UE_SECTIONVIRTUALOFFSET) + info.base; + curSection.size = GetPE32DataFromMappedFile(FileMapVA, i, UE_SECTIONVIRTUALSIZE); + const char* sectionName = (const char*)GetPE32DataFromMappedFile(FileMapVA, i, UE_SECTIONNAME); + + // Escape section name when needed + strcpy_s(curSection.name, StringUtils::Escape(sectionName).c_str()); + + // Add entry to the vector + info.sections.push_back(curSection); + } +} + bool ModLoad(uint Base, uint Size, const char* FullPath) { // Handle a new module being loaded @@ -30,6 +57,8 @@ bool ModLoad(uint Base, uint Size, const char* FullPath) strcpy_s(file, fileStart + 1); fileStart[0] = '\0'; } + else + strcpy_s(file, FullPath); } // Calculate module hash from full file name @@ -59,28 +88,17 @@ bool ModLoad(uint Base, uint Size, const char* FullPath) HANDLE FileMap; ULONG_PTR FileMapVA; WString wszFullPath = StringUtils::Utf8ToUtf16(FullPath); - if(StaticFileLoadW(wszFullPath.c_str(), UE_ACCESS_READ, false, &FileHandle, &LoadedSize, &FileMap, &FileMapVA)) + + bool bVirtual = strstr(FullPath, "virtual:\\") == FullPath; + Memory data(Size); + MemRead(Base, data(), data.size()); + if(bVirtual) //virtual module { - // Get the entry point - info.entry = GetPE32DataFromMappedFile(FileMapVA, 0, UE_OEP) + info.base; - - // Enumerate all PE sections - int sectionCount = (int)GetPE32DataFromMappedFile(FileMapVA, 0, UE_SECTIONNUMBER); - - for(int i = 0; i < sectionCount; i++) - { - MODSECTIONINFO curSection; - - curSection.addr = GetPE32DataFromMappedFile(FileMapVA, i, UE_SECTIONVIRTUALOFFSET) + info.base; - curSection.size = GetPE32DataFromMappedFile(FileMapVA, i, UE_SECTIONVIRTUALSIZE); - const char* sectionName = (const char*)GetPE32DataFromMappedFile(FileMapVA, i, UE_SECTIONNAME); - - // Escape section name when needed - strcpy_s(curSection.name, StringUtils::Escape(sectionName).c_str()); - - // Add entry to the vector - info.sections.push_back(curSection); - } + getModuleInfo(info, (ULONG_PTR)data()); + } + else if(StaticFileLoadW(wszFullPath.c_str(), UE_ACCESS_READ, false, &FileHandle, &LoadedSize, &FileMap, &FileMapVA)) //physical module + { + getModuleInfo(info, FileMapVA); StaticFileUnloadW(wszFullPath.c_str(), false, FileHandle, LoadedSize, FileMap, FileMapVA); } @@ -89,6 +107,17 @@ bool ModLoad(uint Base, uint Size, const char* FullPath) modinfo.insert(std::make_pair(Range(Base, Base + Size - 1), info)); EXCLUSIVE_RELEASE(); + // Put labels for virtual module exports + if(bVirtual) + { + if(info.entry >= Base && info.entry < Base + Size) + LabelSet(info.entry, "EntryPoint", false); + apienumexports(Base, [](uint base, const char* mod, const char* name, uint addr) + { + LabelSet(addr, name, false); + }); + } + SymUpdateModuleList(); return true; } diff --git a/x64_dbg_dbg/x64_dbg.cpp b/x64_dbg_dbg/x64_dbg.cpp index f46a9bca..4e88a4bb 100644 --- a/x64_dbg_dbg/x64_dbg.cpp +++ b/x64_dbg_dbg/x64_dbg.cpp @@ -205,6 +205,7 @@ static void registercommands() dbgcmdnew("cfanal\1cfanalyse\1cfanalyze", cbInstrCfanalyse, true); //control flow analysis 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 } static bool cbCommandProvider(char* cmd, int maxlen)