bool stackcommentget(duint addr, STACK_COMMENT* comment) { SHARED_ACQUIRE(LockSehCache); const auto found = SehCache.find(addr); if(found != SehCache.end()) { *comment = found->second; return true; } SHARED_RELEASE(); duint data = 0; memset(comment, 0, sizeof(STACK_COMMENT)); MemRead(addr, &data, sizeof(duint)); if(!MemIsValidReadPtr(data)) //the stack value is no pointer return false; duint size = 0; duint base = MemFindBaseAddr(data, &size); duint readStart = data - 16 * 4; if(readStart < base) readStart = base; unsigned char disasmData[256]; MemRead(readStart, disasmData, sizeof(disasmData)); duint prev = disasmback(disasmData, 0, sizeof(disasmData), data - readStart, 1); duint previousInstr = readStart + prev; BASIC_INSTRUCTION_INFO basicinfo; bool valid = disasmfast(disasmData + prev, previousInstr, &basicinfo); if(valid && basicinfo.call) //call { char label[MAX_LABEL_SIZE] = ""; ADDRINFO addrinfo; addrinfo.flags = flaglabel; if(_dbg_addrinfoget(data, SEG_DEFAULT, &addrinfo)) strcpy_s(label, addrinfo.label); char module[MAX_MODULE_SIZE] = ""; ModNameFromAddr(data, module, false); char returnToAddr[MAX_COMMENT_SIZE] = ""; if(*module) sprintf(returnToAddr, "%s.", module); if(!*label) sprintf_s(label, "%p", data); strcat(returnToAddr, label); data = basicinfo.addr; if(data) { *label = 0; addrinfo.flags = flaglabel; if(_dbg_addrinfoget(data, SEG_DEFAULT, &addrinfo)) strcpy_s(label, addrinfo.label); *module = 0; ModNameFromAddr(data, module, false); char returnFromAddr[MAX_COMMENT_SIZE] = ""; if(*module) sprintf_s(returnFromAddr, "%s.", module); if(!*label) sprintf_s(label, "%p", data); strcat_s(returnFromAddr, label); sprintf_s(comment->comment, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "return to %s from %s")), returnToAddr, returnFromAddr); } else sprintf_s(comment->comment, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "return to %s from ???")), returnToAddr); strcpy_s(comment->color, "!rtnclr"); // Special token for return address color; return true; } //string char string[MAX_STRING_SIZE] = ""; if(DbgGetStringAt(data, string)) { strncpy_s(comment->comment, string, _TRUNCATE); return true; } //label char label[MAX_LABEL_SIZE] = ""; ADDRINFO addrinfo; addrinfo.flags = flaglabel; if(_dbg_addrinfoget(data, SEG_DEFAULT, &addrinfo)) strcpy_s(label, addrinfo.label); char module[MAX_MODULE_SIZE] = ""; ModNameFromAddr(data, module, false); if(*module) //module { if(*label) //+label sprintf_s(comment->comment, "%s.%s", module, label); else //module only sprintf_s(comment->comment, "%s.%p", module, data); return true; } else if(*label) //label only { sprintf_s(comment->comment, "<%s>", label); return true; } return false; }
void stackgetcallstack(uint csp, CALLSTACK* callstack) { #if 1 callstack->total = 0; if(!DbgIsDebugging() || csp % sizeof(uint)) //alignment problem return; if(!MemIsValidReadPtr(csp)) return; std::vector<CALLSTACKENTRY> callstackVector; uint stacksize = 0; uint stackbase = MemFindBaseAddr(csp, &stacksize, false); if(!stackbase) //super-fail (invalid stack address) return; //walk up the stack uint i = csp; while(i != stackbase + stacksize) { uint data = 0; MemRead(i, &data, sizeof(uint)); if(MemIsValidReadPtr(data) && MemIsCodePage(data, false)) //the stack value is a pointer to an executable page { uint size = 0; uint base = MemFindBaseAddr(data, &size); uint readStart = data - 16 * 4; if(readStart < base) readStart = base; unsigned char disasmData[256]; MemRead(readStart, disasmData, sizeof(disasmData)); uint prev = disasmback(disasmData, 0, sizeof(disasmData), data - readStart, 1); uint previousInstr = readStart + prev; BASIC_INSTRUCTION_INFO basicinfo; bool valid = disasmfast(disasmData + prev, previousInstr, &basicinfo); if(valid && basicinfo.call) //call { CALLSTACKENTRY curEntry; memset(&curEntry, 0, sizeof(CALLSTACKENTRY)); StackEntryFromFrame(&curEntry, i, basicinfo.addr, data); callstackVector.push_back(curEntry); } } i += sizeof(uint); } callstack->total = (int)callstackVector.size(); if(callstack->total) { callstack->entries = (CALLSTACKENTRY*)BridgeAlloc(callstack->total * sizeof(CALLSTACKENTRY)); for(int i = 0; i < callstack->total; i++) { //CALLSTACKENTRY curEntry; //memcpy(&curEntry, &callstackVector.at(i), sizeof(CALLSTACKENTRY)); //dprintf(fhex":" fhex ":" fhex ":%s\n", curEntry.addr, curEntry.to, curEntry.from, curEntry.comment); memcpy(&callstack->entries[i], &callstackVector.at(i), sizeof(CALLSTACKENTRY)); } } #else // Gather context data CONTEXT context; memset(&context, 0, sizeof(CONTEXT)); context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; if(SuspendThread(hActiveThread) == -1) return; if(!GetThreadContext(hActiveThread, &context)) return; if(ResumeThread(hActiveThread) == -1) return; // Set up all frame data STACKFRAME64 frame; ZeroMemory(&frame, sizeof(STACKFRAME64)); #ifdef _M_IX86 DWORD machineType = IMAGE_FILE_MACHINE_I386; frame.AddrPC.Offset = context.Eip; frame.AddrPC.Mode = AddrModeFlat; frame.AddrFrame.Offset = context.Ebp; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrStack.Offset = csp; frame.AddrStack.Mode = AddrModeFlat; #elif _M_X64 DWORD machineType = IMAGE_FILE_MACHINE_AMD64; frame.AddrPC.Offset = context.Rip; frame.AddrPC.Mode = AddrModeFlat; frame.AddrFrame.Offset = context.Rsp; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrStack.Offset = csp; frame.AddrStack.Mode = AddrModeFlat; #endif // Container for each callstack entry std::vector<CALLSTACKENTRY> callstackVector; while(true) { if(!StackWalk64( machineType, fdProcessInfo->hProcess, hActiveThread, &frame, &context, StackReadProcessMemoryProc64, SymFunctionTableAccess64, StackGetModuleBaseProc64, StackTranslateAddressProc64)) { // Maybe it failed, maybe we have finished walking the stack break; } if(frame.AddrPC.Offset != 0) { // Valid frame CALLSTACKENTRY entry; memset(&entry, 0, sizeof(CALLSTACKENTRY)); StackEntryFromFrame(&entry, (uint)frame.AddrFrame.Offset, (uint)frame.AddrReturn.Offset, (uint)frame.AddrPC.Offset); callstackVector.push_back(entry); } else { // Base reached break; } } // Convert to a C data structure callstack->total = (int)callstackVector.size(); if(callstack->total > 0) { callstack->entries = (CALLSTACKENTRY*)BridgeAlloc(callstack->total * sizeof(CALLSTACKENTRY)); // Copy data directly from the vector memcpy(callstack->entries, callstackVector.data(), callstack->total * sizeof(CALLSTACKENTRY)); } #endif }
int RefFind(duint Address, duint Size, CBREF Callback, void* UserData, bool Silent, const char* Name, REFFINDTYPE type) { char fullName[deflen]; char moduleName[MAX_MODULE_SIZE]; duint scanStart, scanSize; REFINFO refInfo; if(type == CURRENT_REGION) // Search in current Region { duint regionSize = 0; duint regionBase = MemFindBaseAddr(Address, ®ionSize, true); // If the memory page wasn't found, fail if(!regionBase || !regionSize) { if(!Silent) dprintf("Invalid memory page 0x%p\n", Address); return 0; } // Assume the entire range is used scanStart = regionBase; scanSize = regionSize; // Otherwise use custom boundaries if size was supplied if(Size) { duint maxsize = Size - (Address - regionBase); // Make sure the size fits in one page scanStart = Address; scanSize = min(Size, maxsize); } // Determine the full module name if(ModNameFromAddr(scanStart, moduleName, true)) sprintf_s(fullName, "%s (Region %s)", Name, moduleName); else sprintf_s(fullName, "%s (Region %p)", Name, scanStart); // Initialize disassembler Capstone cp; // Allow an "initialization" notice refInfo.refcount = 0; refInfo.userinfo = UserData; refInfo.name = fullName; RefFindInRange(scanStart, scanSize, Callback, UserData, Silent, refInfo, cp, true, [](int percent) { GuiReferenceSetCurrentTaskProgress(percent, "Region Search"); GuiReferenceSetProgress(percent); }); } else if(type == CURRENT_MODULE) // Search in current Module { SHARED_ACQUIRE(LockModules); auto modInfo = ModInfoFromAddr(Address); if(!modInfo) { if(!Silent) dprintf("Couldn't locate module for 0x%p\n", Address); return 0; } duint modBase = modInfo->base; duint modSize = modInfo->size; SHARED_RELEASE(); scanStart = modBase; scanSize = modSize; // Determine the full module name if(ModNameFromAddr(scanStart, moduleName, true)) sprintf_s(fullName, "%s (%s)", Name, moduleName); else sprintf_s(fullName, "%s (%p)", Name, scanStart); // Initialize disassembler Capstone cp; // Allow an "initialization" notice refInfo.refcount = 0; refInfo.userinfo = UserData; refInfo.name = fullName; RefFindInRange(scanStart, scanSize, Callback, UserData, Silent, refInfo, cp, true, [](int percent) { GuiReferenceSetCurrentTaskProgress(percent, "Module Search"); GuiReferenceSetProgress(percent); }); } else if(type == ALL_MODULES) // Search in all Modules { bool initCallBack = true; std::vector<MODINFO> modList; ModGetList(modList); if(!modList.size()) { if(!Silent) dprintf("Couldn't get module list"); return 0; } // Initialize disassembler Capstone cp; // Determine the full module sprintf_s(fullName, "All Modules (%s)", Name); // Allow an "initialization" notice refInfo.refcount = 0; refInfo.userinfo = UserData; refInfo.name = fullName; for(duint i = 0; i < modList.size(); i++) { scanStart = modList[i].base; scanSize = modList[i].size; if(i != 0) initCallBack = false; RefFindInRange(scanStart, scanSize, Callback, UserData, Silent, refInfo, cp, initCallBack, [&i, &modList](int percent) { float fPercent = (float)percent / 100.f; float fTotalPercent = ((float)i + fPercent) / (float)modList.size(); int totalPercent = (int)floor(fTotalPercent * 100.f); char tst[256]; strcpy_s(tst, modList[i].name); GuiReferenceSetCurrentTaskProgress(percent, modList[i].name); GuiReferenceSetProgress(totalPercent); }); } } GuiReferenceSetProgress(100); GuiReferenceReloadData(); return refInfo.refcount; }
bool stackcommentget(uint addr, STACK_COMMENT* comment) { uint data = 0; memset(comment, 0, sizeof(STACK_COMMENT)); MemRead(addr, &data, sizeof(uint)); if(!MemIsValidReadPtr(data)) //the stack value is no pointer return false; uint size = 0; uint base = MemFindBaseAddr(data, &size); uint readStart = data - 16 * 4; if(readStart < base) readStart = base; unsigned char disasmData[256]; MemRead(readStart, disasmData, sizeof(disasmData)); uint prev = disasmback(disasmData, 0, sizeof(disasmData), data - readStart, 1); uint previousInstr = readStart + prev; BASIC_INSTRUCTION_INFO basicinfo; bool valid = disasmfast(disasmData + prev, previousInstr, &basicinfo); if(valid && basicinfo.call) //call { char label[MAX_LABEL_SIZE] = ""; ADDRINFO addrinfo; addrinfo.flags = flaglabel; if(_dbg_addrinfoget(data, SEG_DEFAULT, &addrinfo)) strcpy_s(label, addrinfo.label); char module[MAX_MODULE_SIZE] = ""; ModNameFromAddr(data, module, false); char returnToAddr[MAX_COMMENT_SIZE] = ""; if(*module) sprintf(returnToAddr, "%s.", module); if(!*label) sprintf(label, fhex, data); strcat(returnToAddr, label); data = basicinfo.addr; if(data) { *label = 0; addrinfo.flags = flaglabel; if(_dbg_addrinfoget(data, SEG_DEFAULT, &addrinfo)) strcpy_s(label, addrinfo.label); *module = 0; ModNameFromAddr(data, module, false); char returnFromAddr[MAX_COMMENT_SIZE] = ""; if(*module) sprintf(returnFromAddr, "%s.", module); if(!*label) sprintf(label, fhex, data); strcat_s(returnFromAddr, label); sprintf_s(comment->comment, "return to %s from %s", returnToAddr, returnFromAddr); } else sprintf_s(comment->comment, "return to %s from ???", returnToAddr); strcpy_s(comment->color, "#ff0000"); return true; } //string STRING_TYPE strtype; char string[512] = ""; if(disasmgetstringat(data, &strtype, string, string, 500)) { if(strtype == str_ascii) sprintf(comment->comment, "\"%s\"", string); else //unicode sprintf(comment->comment, "L\"%s\"", string); return true; } //label char label[MAX_LABEL_SIZE] = ""; ADDRINFO addrinfo; addrinfo.flags = flaglabel; if(_dbg_addrinfoget(data, SEG_DEFAULT, &addrinfo)) strcpy_s(label, addrinfo.label); char module[MAX_MODULE_SIZE] = ""; ModNameFromAddr(data, module, false); if(*module) //module { if(*label) //+label sprintf(comment->comment, "%s.%s", module, label); else //module only sprintf(comment->comment, "%s." fhex, module, data); return true; } else if(*label) //label only { sprintf(comment->comment, "<%s>", label); return true; } return false; }
extern "C" DLL_EXPORT duint _dbg_memfindbaseaddr(duint addr, duint* size) { return MemFindBaseAddr(addr, size); }