void main ( void ) { HMODULE ahMods[ 250 ] ; DWORD dwNumMods ; BOOL bRet ; // Get the loaded modules for this process. memset ( &ahMods , NULL , sizeof ( ahMods ) ) ; _tprintf ( _T ( "About to call GetLoadedModules - 1\n" ) ) ; _flushall ( ) ; bRet = GetLoadedModules ( GetCurrentProcessId ( ) , 250 , (HMODULE*)&ahMods , &dwNumMods ) ; if ( ( FALSE == bRet ) || ( 0 == dwNumMods ) ) { _tprintf ( _T ( "Failed getting loaded modules " ) _T ( "for this process!\n" ) ) ; return ; } _tprintf ( _T ( "Modules for this process - \n" ) ) ; _flushall ( ) ; TCHAR szBuff[ MAX_PATH ] ; for ( UINT i = 0 ; i < dwNumMods ; i++ ) { GetModuleFileName ( ahMods[ i ] , szBuff , sizeof ( szBuff ) ) ; _tprintf ( _T ( " 0x%08X - %s\n" ) , ahMods[ i ] , szBuff ) ; } // Now test passing in NULL values to get just the count. DWORD dwZeroTest = 0 ; _tprintf ( _T ( "About to call GetLoadedModules - 2\n" ) ) ; bRet = GetLoadedModules ( GetCurrentProcessId ( ) , 0 , NULL , &dwZeroTest ) ; if ( ( FALSE == bRet ) || ( dwZeroTest != dwNumMods ) ) { _tprintf ( _T ( "FAILED - test passing in NULL values to get " ) _T ( "just the count.\n" ) ) ; _flushall ( ) ; DebugBreak ( ) ; } // Pass in an invalid process handle. _tprintf ( _T ( "About to call GetLoadedModules - 3\n" ) ) ; DWORD dwBadPID = 0 ; bRet = GetLoadedModules ( 1 , 250 , (HMODULE*)&ahMods , &dwBadPID ); if ( ( TRUE == bRet ) || ( 0 != dwBadPID ) ) { _tprintf ( _T ( "FAILED - Pass in an invalid ) \ _T ( process handle.\n" ) ) ; _flushall ( ) ; DebugBreak ( ) ; }
std::string GetNtDllName() { if (!IsTarget64() && IsPtr64()) { // WOW64 std::vector<ModuleInfo> modules = GetLoadedModules(); for (std::vector<ModuleInfo>::iterator itr = modules.begin(); itr != modules.end(); ++itr) { CHAR *ptr = strrchr(itr->FullDllName, '\\'); if (ptr != NULL && strcmp(ptr + 1, "ntdll.dll") == 0) { CHAR name[] = "ntdll_01234567"; _snprintf_s(name, _TRUNCATE, "ntdll_%08x", (ULONG32)itr->DllBase); return name; } } } return "ntdll"; }
VOID EnumModulesLoadSatellites() { HMODULE hModules_PreAlloc[128]; HMODULE *p_hModules; DWORD RetCount = 0; p_hModules = GetLoadedModules(hModules_PreAlloc, _countof(hModules_PreAlloc), &RetCount); if (p_hModules) { DWORD i; for (i = 0; i < RetCount; i++) { CheckDllNameLoadSatellites(p_hModules[i]); CheckImportsLoadSatellites(p_hModules[i]); } if (p_hModules != hModules_PreAlloc) HeapFree(GetProcessHeap(), 0, p_hModules); } }
DWORD __stdcall BSUSymInitialize ( DWORD dwPID , HANDLE hProcess , PSTR UserSearchPath , BOOL fInvadeProcess ) { // If this is any flavor of NT or fInvadeProcess is FALSE, just call // SymInitialize itself if ( ( TRUE == IsNT ( ) ) || ( FALSE == fInvadeProcess ) ) { return ( ::SymInitialize ( hProcess , UserSearchPath , fInvadeProcess ) ) ; } else { // This is Win9x and the user wants to invade! // The first step is to initialize the symbol engine. If it // fails, there is not much I can do. BOOL bSymInit = ::SymInitialize ( hProcess , UserSearchPath , fInvadeProcess ) ; ASSERT ( FALSE != bSymInit ) ; if ( FALSE == bSymInit ) { return ( FALSE ) ; } DWORD dwCount ; // Find out how many modules there are. This is a BSU function. if ( FALSE == GetLoadedModules ( dwPID , 0 , NULL , &dwCount ) ) { ASSERT ( !"GetLoadedModules failed" ) ; // Clean up the symbol engine and leave. VERIFY ( ::SymCleanup ( hProcess ) ) ; return ( FALSE ) ; } // Allocate something big enough to hold the list. HMODULE * paMods = new HMODULE[ dwCount ] ; // Get the list for real. if ( FALSE == GetLoadedModules ( dwPID , dwCount , paMods , &dwCount ) ) { ASSERT ( !"GetLoadedModules failed" ) ; // Clean up the symbol engine and leave. VERIFY ( ::SymCleanup ( hProcess ) ) ; // Free the memory that I allocated earlier. delete [] paMods ; return ( FALSE ) ; } // The module filename. TCHAR szModName [ MAX_PATH ] ; for ( UINT uiCurr = 0 ; uiCurr < dwCount ; uiCurr++ ) { // Get the module's filename. if ( FALSE == GetModuleFileName ( paMods[ uiCurr ] , szModName , sizeof ( szModName ) ) ) { ASSERT ( !"GetModuleFileName failed!" ) ; // Clean up the symbol engine and leave. VERIFY ( ::SymCleanup ( hProcess ) ) ; // Free the memory that I allocated earlier. delete [] paMods ; return ( FALSE ) ; } // In order to get the symbol engine to work outside a // debugger, it needs a handle to the image. Yes, this // will leak but the OS will close it down when the process // ends. HANDLE hFile = CreateFile ( szModName , GENERIC_READ , FILE_SHARE_READ , NULL , OPEN_EXISTING , 0 , 0 ) ; // For whatever reason, SymLoadModule can return zero, but // it still loads the modules. Sheez. if ( FALSE == SymLoadModule ( hProcess , hFile , szModName , NULL , (DWORD)paMods[ uiCurr ] , 0 ) ) { // Check the last error value. If it is zero, then all // I can assume is that it worked. DWORD dwLastErr = GetLastError ( ) ; ASSERT ( ERROR_SUCCESS == dwLastErr ) ; if ( ERROR_SUCCESS != dwLastErr ) { // Clean up the symbol engine and leave. VERIFY ( ::SymCleanup ( hProcess ) ) ; // Free the memory that I allocated earlier. delete [] paMods ; return ( FALSE ) ; } } } delete [] paMods ; } return ( TRUE ) ; }
// ldr hook NTSTATUS NTAPI Hook_LdrLoadDll( IN PWCHAR PathToFile OPTIONAL, IN ULONG Flags OPTIONAL, IN PUNICODE_STRING ModuleFileName, OUT PHANDLE ModuleHandle) { NTSTATUS ntStatus; DWORD nModulesPre = 0, nModulesPost = 0; HMODULE ModulesPre[128]; HMODULE ModulesPost[128]; HMODULE* pModulesPre = NULL; HMODULE* pModulesPost = NULL; BOOL bNewDll; WCHAR wsModuleFileName[MAX_PATH]; DWORD Count = min(ModuleFileName->Length, sizeof(wsModuleFileName)-sizeof(WCHAR)); ULONG_PTR LdrLoadDllRecursion = 0L; InterlockedIncrement(&g_SysEnters); // DbPrint("r3hook64::Hook_LdrLoadDll - entering Hook_LdrLoadDll on thread %d\n", GetCurrentThreadId()); memcpy(wsModuleFileName, ModuleFileName->Buffer, Count); wsModuleFileName[Count/sizeof(WCHAR)] = 0; LdrLoadDllRecursion = (ULONG_PTR)TlsGetValue(g_tlsiLdrLoadDllRecursion); bNewDll = !LdrLoadDllRecursion /*&& !GetModuleHandleW(wsModuleFileName)*/; // fix bug if (bNewDll) pModulesPre = GetLoadedModules(ModulesPre, _countof(ModulesPre), &nModulesPre); TlsSetValue(g_tlsiLdrLoadDllRecursion, (PVOID)(LdrLoadDllRecursion+1)); ntStatus = ((fLdrLoadDll)g_pLdrLoadDll_Context->m_Thunk)(PathToFile, Flags, ModuleFileName, ModuleHandle); TlsSetValue(g_tlsiLdrLoadDllRecursion, (PVOID)LdrLoadDllRecursion); if (ntStatus == 0L) { if (pModulesPre) { pModulesPost = GetLoadedModules(ModulesPost, _countof(ModulesPost), &nModulesPost); if (pModulesPost) { DWORD i,j; for (i = 0; i < nModulesPost; i++) { if (i < nModulesPre && pModulesPre[i] == pModulesPost[i]) continue; for (j = 0; j < nModulesPre; j++) { if (pModulesPre[j] == pModulesPost[i]) break; } if (j == nModulesPre) // not found in pre modules - new dll { CheckDllNameLoadSatellites(pModulesPost[i]); CheckImportsLoadSatellites(pModulesPost[i]); } } } } } if (pModulesPre && pModulesPre != ModulesPre) HeapFree(GetProcessHeap(), 0, pModulesPre); if (pModulesPost && pModulesPost != ModulesPost) HeapFree(GetProcessHeap(), 0, pModulesPost); // DbPrint("r3hook64::Hook_LdrLoadDll - exiting Hook_LdrLoadDll on thread %d\n", GetCurrentThreadId()); InterlockedDecrement(&g_SysEnters); return ntStatus; }
HMODULE * __stdcall AllocAndFillProcessModuleList ( HANDLE hHeap , LPDWORD pdwCount ) { ASSERT ( FALSE == IsBadWritePtr ( pdwCount , sizeof ( LPDWORD ) ) ) ; if ( TRUE == IsBadWritePtr ( pdwCount , sizeof ( LPDWORD ) ) ) { SetLastError ( ERROR_INVALID_PARAMETER ) ; return ( NULL ) ; } ASSERT ( NULL != hHeap ) ; if ( NULL == hHeap ) { SetLastError ( ERROR_INVALID_PARAMETER ) ; return ( NULL ) ; } // First, ask how many modules are really loaded. DWORD dwQueryCount ; BOOL bRet = GetLoadedModules ( GetCurrentProcessId ( ) , 0 , NULL , &dwQueryCount ) ; ASSERT ( TRUE == bRet ) ; ASSERT ( 0 != dwQueryCount ) ; if ( ( FALSE == bRet ) || ( 0 == dwQueryCount ) ) { return ( NULL ) ; } // The HMODULE array. HMODULE * pModArray ; // Allocate the buffer to hold the returned array. pModArray = (HMODULE*)HeapAlloc ( hHeap , HEAP_ZERO_MEMORY , dwQueryCount * sizeof ( HMODULE ) ); ASSERT ( NULL != pModArray ) ; if ( NULL == pModArray ) { return ( NULL ) ; } // bRet holds BOOLEAN return values. bRet = GetLoadedModules ( GetCurrentProcessId ( ) , dwQueryCount , pModArray , pdwCount ) ; // Save off the last error so that the assert can still fire and // not change the value. DWORD dwLastError = GetLastError ( ) ; ASSERT ( TRUE == bRet ) ; if ( FALSE == bRet ) { // Get rid of the last buffer. free ( pModArray ) ; pModArray = NULL ; SetLastError ( dwLastError ) ; } else { SetLastError ( ERROR_SUCCESS ) ; } // All OK, Jumpmaster! return ( pModArray ) ; }
DWORD dwBadPID = 0 ; bRet = GetLoadedModules ( 1 , 250 , (HMODULE*)&ahMods , &dwBadPID ); if ( ( TRUE == bRet ) || ( 0 != dwBadPID ) ) { _tprintf ( _T ( "FAILED - Pass in an invalid ) \ _T ( process handle.\n" ) ) ; _flushall ( ) ; DebugBreak ( ) ; } // Check a bad parameter as the module array. DWORD dwBadParam = 0 ; _tprintf ( _T ( "About to call GetLoadedModules - 4\n" ) ) ; bRet = GetLoadedModules ( GetCurrentProcessId ( ) , 250 , NULL , &dwBadParam ) ; if ( ( TRUE == bRet ) || ( ERROR_INVALID_PARAMETER != GetLastError ( ) ) ) { _tprintf ( _T ( "FAILED - Check a bad parameter as " ) _T ( "the module array.\n" ) ) ; _flushall ( ) ; DebugBreak ( ) ; } // Pass in a bad real count value. dwBadParam = 0 ; _tprintf ( _T ( "About to call GetLoadedModules - 7\n" ) ) ; bRet = GetLoadedModules ( GetCurrentProcessId ( ) ,