////////////////////////////////////////////////////////////////////////////// // // Detour Test Program (symtest.cpp of symtest.exe) // // Microsoft Research Detours Package // // Copyright (c) Microsoft Corporation. All rights reserved. // #include #include #pragma warning(push) #if _MSC_VER > 1400 #pragma warning(disable:6102 6103) // /analyze warnings #endif #include #pragma warning(pop) #include #include "target.h" #if (_MSC_VER < 1299) #include typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64; typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64; typedef IMAGEHLP_SYMBOL SYMBOL_INFO; typedef PIMAGEHLP_SYMBOL PSYMBOL_INFO; #else #pragma warning(push) #pragma warning(disable:4091) // empty typedef #include #pragma warning(pop) #endif ////////////////////////////////////////////////////////////////////////////// // typedef LPAPI_VERSION (NTAPI *PF_ImagehlpApiVersionEx)(LPAPI_VERSION AppVersion); typedef BOOL (NTAPI *PF_SymInitialize)(IN HANDLE hProcess, IN LPCSTR UserSearchPath, IN BOOL fInvadeProcess); typedef DWORD (NTAPI *PF_SymSetOptions)(IN DWORD SymOptions); typedef DWORD (NTAPI *PF_SymGetOptions)(VOID); typedef DWORD64 (NTAPI *PF_SymLoadModule64)(IN HANDLE hProcess, IN HANDLE hFile, IN PSTR ImageName, IN PSTR ModuleName, IN DWORD64 BaseOfDll, IN DWORD SizeOfDll); typedef BOOL (NTAPI *PF_SymGetModuleInfo64)(IN HANDLE hProcess, IN DWORD64 qwAddr, OUT PIMAGEHLP_MODULE64 ModuleInfo); typedef BOOL (NTAPI *PF_SymFromName)(IN HANDLE hProcess, IN LPSTR Name, OUT PSYMBOL_INFO Symbol); #if (_MSC_VER < 1299) typedef BOOL (NTAPI *PF_SymRegisterCallback64)(); typedef BOOL (NTAPI *PF_SymEnumerateModules64)(); typedef BOOL (NTAPI *PF_SymEnumSymbols)(); #else typedef BOOL (NTAPI *PF_SymRegisterCallback64)(IN HANDLE hProcess, IN PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction, IN ULONG64 UserContext); typedef BOOL (NTAPI *PF_SymEnumerateModules64)(IN HANDLE hProcess, IN PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback, IN PVOID UserContext); typedef BOOL (NTAPI *PF_SymEnumSymbols)(IN HANDLE hProcess, IN ULONG64 BaseOfDll, IN PCSTR Mask, IN PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, IN PVOID UserContext); #endif PF_ImagehlpApiVersionEx pfImagehlpApiVersionEx = NULL; PF_SymInitialize pfSymInitialize = NULL; PF_SymSetOptions pfSymSetOptions = NULL; PF_SymGetOptions pfSymGetOptions = NULL; PF_SymLoadModule64 pfSymLoadModule64 = NULL; PF_SymGetModuleInfo64 pfSymGetModuleInfo64 = NULL; PF_SymFromName pfSymFromName = NULL; PF_SymRegisterCallback64 pfSymRegisterCallback64 = NULL; PF_SymEnumerateModules64 pfSymEnumerateModules64 = NULL; PF_SymEnumSymbols pfSymEnumSymbols = NULL; ////////////////////////////////////////////////////////////////////////////// // #if (_MSC_VER > 1299) static BOOL WINAPI SymEnumerateCallback( PCSTR pszModule, DWORD64 base, PVOID pvUserContext) { (void)pvUserContext; printf(" %p: %s\n", (PVOID)base, pszModule); return TRUE; } static int nSymbolCount = 0; static BOOL WINAPI SymEnumerateSymbols(PSYMBOL_INFO pSym, ULONG size, PVOID pvUserContext) { (void)size; (void)pvUserContext; if (strstr(pSym->Name, "Target") != NULL || strstr(pSym->Name, "Hidden") != NULL) { printf(" %p: %s\n", (PVOID)pSym->Address, pSym->Name); nSymbolCount++; } else if (nSymbolCount < 5) { printf(" %p: %s\n", (PVOID)pSym->Address, pSym->Name); nSymbolCount++; } return TRUE; } static void truncate(PCHAR data) { size_t len = strlen(data); if (len > 0 && data[len-1] == '\r') { data[--len] = '\0'; } if (len > 0 && data[len-1] == '\n') { data[--len] = '\0'; } } BOOL WINAPI CallbackFunction(HANDLE hProcess, ULONG action, ULONG64 data, ULONG64 context) { (void)context; switch (action) { case CBA_DEBUG_INFO: truncate((PCHAR)data); printf("::> %s\n", (PCHAR)data); return TRUE; case CBA_DEFERRED_SYMBOL_LOAD_CANCEL: printf("::> proc=%p action=%08lx data=%p\n", (PVOID)hProcess, action, (PVOID)data); { PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 pi = (PIMAGEHLP_DEFERRED_SYMBOL_LOAD64)data; printf("pi->SizeOfStruct = %ld\n", pi->SizeOfStruct); printf("pi->BaseOfImage = %p\n", (PVOID)(size_t)pi->BaseOfImage); printf("pi->CheckSum = %8lx\n", pi->CheckSum); printf("pi->FileName = %p [%s]\n", pi->FileName, pi->FileName); printf("pi->Reparse = %d\n", pi->Reparse); } return FALSE; default: printf("::> proc=%p action=%08lx data=%p\n", (PVOID)hProcess, action, (PVOID)data); return FALSE; } } #endif int __cdecl main(void) { printf("symtest.exe: Starting.\n"); fflush(stdout); //////////////////////////////////////////////////////// Get the functions. // HMODULE hDbgHelp = LoadLibraryA("dbghelp.dll"); if (hDbgHelp == NULL) { printf("Couldn't load dbghelp.dll"); return 1; } pfImagehlpApiVersionEx = (PF_ImagehlpApiVersionEx)GetProcAddress(hDbgHelp, "ImagehlpApiVersionEx"); pfSymInitialize = (PF_SymInitialize)GetProcAddress(hDbgHelp, "SymInitialize"); pfSymSetOptions = (PF_SymSetOptions)GetProcAddress(hDbgHelp, "SymSetOptions"); pfSymGetOptions = (PF_SymGetOptions)GetProcAddress(hDbgHelp, "SymGetOptions"); pfSymLoadModule64 = (PF_SymLoadModule64)GetProcAddress(hDbgHelp, "SymLoadModule64"); pfSymGetModuleInfo64 = (PF_SymGetModuleInfo64)GetProcAddress(hDbgHelp, "SymGetModuleInfo64"); pfSymFromName = (PF_SymFromName)GetProcAddress(hDbgHelp, "SymFromName"); pfSymRegisterCallback64 = (PF_SymRegisterCallback64)GetProcAddress(hDbgHelp, "SymRegisterCallback64"); pfSymEnumerateModules64 = (PF_SymEnumerateModules64)GetProcAddress(hDbgHelp, "SymEnumerateModules64"); pfSymEnumSymbols = (PF_SymEnumSymbols)GetProcAddress(hDbgHelp, "SymEnumSymbols"); ////////////////////////////////////////////////////////////////////////////// // HANDLE hProcess = GetCurrentProcess(); API_VERSION av; ZeroMemory(&av, sizeof(av)); av.MajorVersion = API_VERSION_NUMBER; pfImagehlpApiVersionEx(&av); printf(" Version: %d.%d (%d)\n", av.MajorVersion, av.MinorVersion, API_VERSION_NUMBER); if (!pfSymInitialize(hProcess, NULL, FALSE)) { printf("SymInitialize failed: %ld\n", GetLastError()); return 1; } #if (_MSC_VER > 1299) pfSymRegisterCallback64(hProcess, CallbackFunction, NULL); #endif DWORD dw = pfSymGetOptions(); printf("GetOptions = %08lx\n", dw); dw &= ~(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | 0); dw |= ( #if defined(SYMOPT_EXACT_SYMBOLS) SYMOPT_EXACT_SYMBOLS | #endif #if defined(SYMOPT_DEBUG) SYMOPT_DEBUG | #endif #if defined(SYMOPT_NO_UNQUALIFIED_LOADS) SYMOPT_NO_UNQUALIFIED_LOADS | #endif #if defined(SYMOPT_FAIL_CRITICAL_ERRORS) SYMOPT_FAIL_CRITICAL_ERRORS | #endif #if defined(SYMOPT_INCLUDE_32BIT_MODULES) SYMOPT_INCLUDE_32BIT_MODULES | #endif 0); printf("SetOptions = %08lx\n", dw); pfSymSetOptions(dw); /////////////////////////////////////////////// First, try GetProcAddress. // PCHAR pszFile = "target" DETOURS_STRINGIFY(DETOURS_BITS) ".dll"; HMODULE hModule = LoadLibraryA(pszFile); if (hModule == NULL) { printf("LoadLibraryA(%s) failed: %ld\n", pszFile, GetLastError()); return 2; } ////////////////////////////////////////////////////// Then try ImageHelp. // #if (_MSC_VER > 1299) //CHAR szFull[MAX_PATH]; //GetModuleFileNameA(hModule, szFull, sizeof(szFull)); printf("SymLoadModule64(%s) will be called.\n", pszFile /*szFull*/); DWORD64 loaded = pfSymLoadModule64(hProcess, NULL, (PCHAR)pszFile/*szFull*/, NULL, (DWORD64)hModule, 0); if (loaded == 0) { printf("SymLoadModule64(%p) failed: %ld\n", hProcess, GetLastError()); printf("\n"); } else { printf("SymLoadModule64(%p) succeeded: 0x%p\n", hProcess, (PVOID)loaded); } CHAR szModName[512]; printf("Modules:\n"); // The first parameter of PSYM_ENUMMODULES_CALLBACK64 changed from PSTR to PCSTR // between Windows 2003 and Windows 7. Cast here to work with either. pfSymEnumerateModules64(hProcess, (PSYM_ENUMMODULES_CALLBACK64)SymEnumerateCallback, NULL); printf("\n"); IMAGEHLP_MODULE64 modinfo; ZeroMemory(&modinfo, sizeof(modinfo)); modinfo.SizeOfStruct = sizeof(modinfo); if (!pfSymGetModuleInfo64(hProcess, (DWORD64)hModule, &modinfo)) { printf("SymGetModuleInfo64(%p, %p) [64] failed: %ld\n", hProcess, hModule, GetLastError()); } else { printf("SymGetModuleInfo64(%p, %p) [64] succeeded: %ld\n", hProcess, hModule, GetLastError()); StringCchCopyA(szModName, ARRAYSIZE(szModName), modinfo.ModuleName); StringCchCatA(szModName, ARRAYSIZE(szModName), "!"); printf("NumSyms: %ld\n", modinfo.NumSyms); printf("SymType: %d\n", modinfo.SymType); printf("ModuleName: %s\n", modinfo.ModuleName); printf("ImageName: %s\n", modinfo.ImageName); printf("LoadedImageName: %s\n", modinfo.LoadedImageName); } printf("\n"); fflush(stdout); printf("DLLs:\n"); for (hModule = NULL; (hModule = DetourEnumerateModules(hModule)) != NULL;) { CHAR szName[MAX_PATH]; GetModuleFileNameA(hModule, szName, sizeof(szName)); printf(" %p: %s\n", hModule, szName); } if (pfSymEnumSymbols == NULL) { printf("Couldn't find SymEnumSymbols.\n"); } else { printf("===Enum===\n"); SetLastError(0); nSymbolCount = 0; if (!pfSymEnumSymbols(hProcess, loaded, NULL, SymEnumerateSymbols, NULL)) { printf("SymEnumSymbols() failed: %ld\n", GetLastError()); } } // Look for specific symbols. struct CFullSymbol : SYMBOL_INFO { CHAR szRestOfName[MAX_SYM_NAME]; } symbol; CHAR szFullName[512]; // Look for Target StringCchCopyA(szFullName, ARRAYSIZE(szFullName), szModName); StringCchCatA(szFullName, ARRAYSIZE(szFullName), "Target"); printf("Symbol: [%s]\n", szFullName); ZeroMemory(&symbol, sizeof(symbol)); symbol.SizeOfStruct = sizeof(SYMBOL_INFO); #ifdef DBHLPAPI symbol.MaxNameLen = MAX_SYM_NAME; #else symbol.MaxNameLength = MAX_SYM_NAME; #endif SetLastError(0); if (!pfSymFromName(hProcess, szFullName, &symbol)) { printf("--SymFromName(%s) failed: %ld\n", szFullName, GetLastError()); } if (symbol.Address != 0) { printf("--SymFromName(%s) succeeded\n", szFullName); } printf("%s => %p\n\n", szFullName, (PBYTE)symbol.Address); // Look for Hidden StringCchCopyA(szFullName, ARRAYSIZE(szFullName), szModName); StringCchCatA(szFullName, ARRAYSIZE(szFullName), "Hidden"); printf("Symbol: [%s]\n", szFullName); ZeroMemory(&symbol, sizeof(symbol)); symbol.SizeOfStruct = sizeof(SYMBOL_INFO); #ifdef DBHLPAPI symbol.MaxNameLen = MAX_SYM_NAME; #else symbol.MaxNameLength = MAX_SYM_NAME; #endif SetLastError(0); if (!pfSymFromName(hProcess, szFullName, &symbol)) { printf("--SymFromName(%s) failed: %ld\n", szFullName, GetLastError()); } if (symbol.Address != 0) { printf("--SymFromName(%s) succeeded\n", szFullName); } printf("%s => %p\n\n", szFullName, (PBYTE)symbol.Address); #endif // We call Target once to insure it is loaded. Target(0); return 0; } // ///////////////////////////////////////////////////////////////// End of File.