const bool Symbols::SymbolFromName(const char * const pName, const SymbolInfo **pFullSymbolInfo) { char pBuffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(char) + sizeof(ULONG64) - 1 / sizeof(ULONG64)] = { 0 }; PSYMBOL_INFO pSymInfo = (PSYMBOL_INFO)pBuffer; pSymInfo->SizeOfStruct = sizeof(SYMBOL_INFO); pSymInfo->MaxNameLen = MAX_SYM_NAME; const bool bSuccess = BOOLIFY(SymFromName(m_hProcess, pName, pSymInfo)); if (!bSuccess) { fprintf(stderr, "Could not retrieve symbol for name %s. Error = %X.\n", pName, GetLastError()); return false; } fprintf(stderr, "Symbol found for %s. Name: %.*s. Address: %p. Base address of module: %p\n", pName, pSymInfo->NameLen, pSymInfo->Name, (DWORD_PTR)pSymInfo->Address, (DWORD_PTR)pSymInfo->ModBase); *pFullSymbolInfo = FindSymbolByAddress((DWORD_PTR)pSymInfo->Address); return bSuccess; }
// private //------------------------------------------------------------------------- Bool Injector::_GetFunctionAddress( UHuge& address, const CHAR* name ) { SYMBOL_INFO symbol = {0}; // init parameters symbol.SizeOfStruct = sizeof(symbol); // get address of function if( !SymFromName(_process, name, &symbol) || symbol.Address == 0 ) return false; // store address address = symbol.Address; return true; }
static int find_pe_symbol_by_name(Context * ctx, int frame, ContextAddress ip, char * name, Symbol * sym) { HANDLE process = get_context_handle(ctx->parent == NULL ? ctx : ctx->parent); ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; SYMBOL_INFO * info = (SYMBOL_INFO *)buffer; IMAGEHLP_STACK_FRAME stack_frame; DWORD err; if (set_pe_context(ctx, frame, ip, process, &stack_frame) < 0) return -1; memset(info, 0, sizeof(SYMBOL_INFO)); info->SizeOfStruct = sizeof(SYMBOL_INFO); info->MaxNameLen = MAX_SYM_NAME; if (find_cache_symbol(ctx, frame, stack_frame.InstructionOffset, name, sym)) return errno ? -1 : 0; /* TODO: SymFromName() searches only main executable, need to search DLLs too */ if (SymFromName(process, name, info) && info->Tag != SymTagPublicSymbol) { syminfo2symbol(ctx, frame, info, sym); add_cache_symbol(ctx, stack_frame.InstructionOffset, name, sym, 0); return 0; } if (stack_frame.InstructionOffset != 0) { DWORD64 module = SymGetModuleBase64(process, stack_frame.InstructionOffset); if (module != 0 && SymGetTypeFromName(process, module, name, info)) { syminfo2symbol(ctx, frame, info, sym); add_cache_symbol(ctx, stack_frame.InstructionOffset, name, sym, 0); return 0; } } set_win32_errno(err = GetLastError()); if (err == 0 || err == ERROR_MOD_NOT_FOUND) { add_cache_symbol(ctx, stack_frame.InstructionOffset, name, NULL, ERR_SYM_NOT_FOUND); errno = ERR_SYM_NOT_FOUND; } return -1; }
int main(int argc, char* argv[]) { if (argc != 2) { printf("\n *** OffsetToSource by Sasha Goldshtein (blog.sashag.net), (C) 2013 ***\n\n"); printf(" Usage: OffsetToSource module[.exe|.dll][!function]+0x<offset>\n\n"); printf(" Example: OffsetToSource myapp!main+0xd0\n"); printf(" Example: OffsetToSource myapp+0x441d0\n"); return 2; } const HANDLE hProcess = GetCurrentProcess(); SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES); if (FALSE == SymInitialize(hProcess, NULL, FALSE)) { printf("*** Error initializing symbol engine: 0x%x\n", GetLastError()); return 1; } CHAR symbolPath[2048], path[2048]; GetEnvironmentVariableA("PATH", path, ARRAYSIZE(symbolPath)); GetEnvironmentVariableA("_NT_SYMBOL_PATH", symbolPath, ARRAYSIZE(symbolPath)); strcat_s(path, ";.;"); strcat_s(path, symbolPath); SymSetSearchPath(hProcess, path); //Parse argv[1] to obtain the module name, symbol name, and offset // Example format: module!Class::Method+0x40 // Another option: module+0x1000 BOOL symbolNameSpecified; CHAR moduleName[200], symName[200]; DWORD offset = 0; CHAR* bang = strchr(argv[1], '!'); if (bang != NULL) { strncpy_s(moduleName, argv[1], bang - argv[1]); CHAR* plus = strchr(bang, '+'); if (plus != NULL) { strncpy_s(symName, bang + 1, plus - bang - 1); sscanf_s(plus + 1, "0x%x", &offset); } else { strcpy_s(symName, bang + 1); } symbolNameSpecified = TRUE; } else { CHAR* plus = strchr(argv[1], '+'); if (plus == NULL) { printf("*** Invalid input: %s\n", argv[1]); return 1; } strncpy_s(moduleName, argv[1], plus - argv[1]); sscanf_s(plus + 1, "0x%x", &offset); symbolNameSpecified = FALSE; } BOOL nakedName = strstr(moduleName, ".dll") == NULL && strstr(moduleName, ".exe") == NULL; if (nakedName) { strcat_s(moduleName, ".dll"); } DWORD64 moduleBase; while (0 == (moduleBase = SymLoadModule64(hProcess, NULL, moduleName, NULL, 0, 0))) { if (nakedName) { strcpy(strstr(moduleName, ".dll"), ".exe"); nakedName = FALSE; continue; } printf("*** Error loading symbols: 0x%x\n", GetLastError()); return 1; } DWORD64 symbolAddress; if (symbolNameSpecified) { ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); pSymbol->MaxNameLen = MAX_SYM_NAME; if (FALSE == SymFromName(hProcess, symName, pSymbol)) { printf("*** Error retrieving symbol information for symbol %s: 0x%x\n", argv[1], GetLastError()); return 1; } symbolAddress = pSymbol->Address + offset; } else { symbolAddress = moduleBase + offset; } DWORD displacement; IMAGEHLP_LINE64 line; RtlZeroMemory(&line, sizeof(line)); line.SizeOfStruct = sizeof(line); if (FALSE == SymGetLineFromAddr64(hProcess, symbolAddress, &displacement, &line)) { printf("*** Error retrieving source line for %s: 0x%x\n", argv[1], GetLastError()); return 1; } printf("%s [0x%I64x] = %s line %d (+0x%x)\n", argv[1], symbolAddress, line.FileName, line.LineNumber, displacement); SymCleanup(hProcess); return 0; }