作 者: FlyToTheSpace
说明:第一步设置符号表路径.比如 E:/WINDOWS/system32/Symbols/
第二步指定系统动态库,比如user32.dll
第三步指定系统库函数名比如ValidateHwnd.
如果调用成功的话,返回值就为未导出的库函数地址.
例外说明.使用ollydbg设置好了符号表路径,好像是没有效果.
只有把符号文件放到系统目录/system32/symbols/里面才能加载.
class ProcedureAddrRetrieve
{
public:
ProcedureAddrRetrieve(TCHAR *PdbSearchPath,DWORD _Options = NULL);
~ProcedureAddrRetrieve();
BOOL LoadSymbol(TCHAR *DllName);
BOOL EnumSymbol(TCHAR *pSearchMask = NULL);
DWORD64 RetrieveAddr(TCHAR *_szProcedureName);
protected:
private:
BOOL GetFileSize( const TCHAR* pFileName, DWORD& FileSize );
static BOOL CALLBACK EnumSymbolsCallback( SYMBOL_INFO* pSymInfo, ULONG SymbolSize, PVOID UserContext );
DWORD64 ModBase64;
char szProcedureName[MAX_PATH];
DWORD64 Address;
};
void test();
#include <windows.h>
#include <tchar.h>
#include <io.h>
#include <stdio.h>
#include <dbghelp.h>
#include <stdio.h>
#include "lib.h"
#pragma comment( lib, "dbghelp.lib" )
void test()
{
ProcedureAddrRetrieve par("E://WINDOWS//system32//Symbols//");
par.LoadSymbol("User32.dll");
par.RetrieveAddr("ValidateHwnd");
}
ProcedureAddrRetrieve::ProcedureAddrRetrieve(TCHAR *PdbSearchPath,DWORD _Options )
{
BOOL bRet = FALSE;
ZeroMemory(this,sizeof(ProcedureAddrRetrieve));
// Set options
DWORD Options = SymGetOptions();
// SYMOPT_DEBUG option asks DbgHelp to print additional troubleshooting
// messages to debug output - use the debugger's Debug Output window
// to view the messages
Options =Options | SYMOPT_DEBUG | _Options/*|SYMOPT_ALLOW_ABSOLUTE_SYMBOLS*/;
SymSetOptions( Options );
// Initialize DbgHelp and load symbols for all modules of the current process
bRet = SymInitialize (
GetCurrentProcess(), // Process handle of the current process
PdbSearchPath, // user-defined search path -> use default
FALSE // Do not load symbols for modules in the current process
);
if( !bRet )
{
_tprintf(_T("Error: SymInitialize() failed. Error code: %u /n"), ::GetLastError());
return ;
}
}
BOOL ProcedureAddrRetrieve::LoadSymbol(TCHAR *DllName)
{
HMODULE ModBase;
TCHAR DllFullPath[MAX_PATH];
DWORD FileSize = 0;
//Get DLL full path.
ModBase = GetModuleHandle(DllName);
if(ModBase == NULL)
{
ModBase = LoadLibrary(DllName);
if(ModBase == NULL)
return FALSE;
}
GetModuleFileName(ModBase,DllFullPath,MAX_PATH);
GetFileSize(DllFullPath,FileSize);
if(ModBase64)
{
// Unload symbols for the module
if(!SymUnloadModule64( GetCurrentProcess(), ModBase64 ))
{
_tprintf( _T("Error: SymUnloadModule64() failed. Error code: %u /n"), ::GetLastError() );
return FALSE;
}
}
// Load symbols for the module
_tprintf( _T("Loading symbols for: %s ... /n"), DllFullPath );
ModBase64 = SymLoadModule64 (
GetCurrentProcess(), // Process handle of the current process
NULL, // Handle to the module's image file (not needed)
DllFullPath, // Path/name of the file
NULL, // User-defined short name of the module (it can be NULL)
(DWORD64)ModBase, // Base address of the module (cannot be NULL if .PDB file is used, otherwise it can be NULL)
FileSize // Size of the file (cannot be NULL if .PDB file is used, otherwise it can be NULL)
);
if( ModBase == 0 )
{
_tprintf(_T("Error: SymLoadModule64() failed. Error code: %u /n"), ::GetLastError());
return FALSE;
}
return TRUE;
}
BOOL ProcedureAddrRetrieve::GetFileSize( const TCHAR* pFileName, DWORD& FileSize )
{
// Check parameters
if( pFileName == 0 )
{
return FALSE;
}
// Open the file
HANDLE hFile = CreateFile( pFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL );
if( hFile == INVALID_HANDLE_VALUE )
{
_tprintf( _T("CreateFile() failed. Error: %u /n"), ::GetLastError() );
return FALSE;
}
// Obtain the size of the file
FileSize = ::GetFileSize( hFile, NULL );
if( FileSize == INVALID_FILE_SIZE )
{
_tprintf( _T("GetFileSize() failed. Error: %u /n"), ::GetLastError() );
// and continue ...
}
// Close the file
if( !CloseHandle( hFile ) )
{
_tprintf( _T("CloseHandle() failed. Error: %u /n"), ::GetLastError() );
// and continue ...
}
// Complete
return ( FileSize != INVALID_FILE_SIZE );
}
ProcedureAddrRetrieve::~ProcedureAddrRetrieve()
{
if(ModBase64)
{
// Unload symbols for the module
if(!SymUnloadModule64( GetCurrentProcess(), ModBase64 ))
{
_tprintf( _T("Error: SymUnloadModule64() failed. Error code: %u /n"), ::GetLastError() );
}
}
}
BOOL ProcedureAddrRetrieve::EnumSymbol(TCHAR *pSearchMask)
{
BOOL bRet = TRUE;
// Enumerate symbols and display information about them
if( pSearchMask != NULL )
_tprintf( _T("Search mask: %s /n"), pSearchMask );
_tprintf( _T("Symbols: /n") );
bRet = ::SymEnumSymbols(
GetCurrentProcess(), // Process handle of the current process
ModBase64, // Base address of the module
pSearchMask, // Mask (NULL -> all symbols)
EnumSymbolsCallback, // The callback function
this // A used-defined context can be passed here, if necessary
);
if( !bRet )
{
_tprintf( _T("Error: SymEnumSymbols() failed. Error code: %u /n"), ::GetLastError() );
}
return TRUE;
}
BOOL CALLBACK ProcedureAddrRetrieve::EnumSymbolsCallback( SYMBOL_INFO* pSymInfo, ULONG SymbolSize, PVOID UserContext )
{
ProcedureAddrRetrieve *pPar = (ProcedureAddrRetrieve *)UserContext;
if( pSymInfo != 0 )
{
if(*pPar->szProcedureName)
{
if(strcmp(pPar->szProcedureName,pSymInfo->Name)==0)
{
pPar->Address = pSymInfo->Address;
return FALSE;
}
}
else
{
_tprintf(pSymInfo->Name);
_tprintf("/n");
}
}
return TRUE;
}
DWORD64 ProcedureAddrRetrieve::RetrieveAddr(TCHAR *_szProcedureName)
{
strncpy(szProcedureName,_szProcedureName,MAX_PATH);
Address = 0;
if(!EnumSymbol(""))
return NULL;
return Address;
}