So I'm exploring mhook 2.3 and have build a sample executable specifically for this purpose. I have an injector that injects a dll containing mhook into the target process.
This all works correctly and I can verify that my code is being called by the target process by checking my log file.
However, when I go to hook my target function mhook simply returns and says that it failed to hook the function. I've used OllyDBG and IDA to verify that the address for the target function that I'm passing in to mhook is correct and the function signature for the trampoline is exactly the same as the target function but it still fails.
I'm at my wits end. Can someone please tell me what I'm doing wrong here?
Here is the target program that I've built. It's a simple Windows console application that prints out a random message every second.
// reverse me.cpp : This is the program that I will be attempting to hook into.
//
#include "stdafx.h"
#include <stdlib.h>
#include <Windows.h>
#include <Psapi.h>
#include <string>
class blargClass1
{
public:
blargClass1();
void WINAPI blargFunction1(void);
};
__declspec(noinline) blargClass1::blargClass1()
{
printf("blargClass1::blargClass1\n");
};
__declspec(noinline) void WINAPI blargClass1::blargFunction1( void )
{
switch( rand() % 10 + 1 )
{
case 1:
printf("blargFunction1 - case 1\n");
break;
case 2:
printf("blargFunction1 - case 2\n");
break;
case 3:
printf("blargFunction1 - case 3\n");
break;
case 4:
printf("blargFunction1 - case 4\n");
break;
case 5:
printf("blargFunction1 - case 5\n");
break;
default:
printf("blargFunction1 - default\n");
}
};
#pragma comment( lib, "psapi.lib")
DWORD GetCurrentModuleBase( LPWSTR targetModule )
{
HMODULE hMods[1024];
HANDLE hProcess;
DWORD cbNeeded;
DWORD baseAddress = -1;
unsigned int i;
// Get the current process id.
DWORD processID = GetCurrentProcessId();
printf( "GetCurrentProcessId = %u\n", processID );
// Get a handle to the process.
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
// Sanity checking on process handle.
if( hProcess == NULL )
{
printf( "hProcess is NULL.\n" );
return 1;
}
// Get a list of all the modules in this process.
if( EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
// Iterate through each module
for ( i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
{
WCHAR szModName[MAX_PATH];
// Get the full path to the module's file.
if ( GetModuleFileNameEx( hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
{
// Print the module name and handle value.
//wprintf( L"\t%s (0x%08X)\n", szModName, hMods[i] );
// Is this the module that we're looking for?
std::wstring moduleName = szModName;
if( moduleName.find( targetModule ) != std::wstring::npos )
{
baseAddress = (DWORD)hMods[i];
}
}
}
}
// Release the handle to the process.
CloseHandle( hProcess );
return baseAddress;
}
int _tmain(int argc, _TCHAR* argv[])
{
blargClass1 blarg_class_1;
printf( "GetCurrentModuleBase = 0x%08X\n", GetCurrentModuleBase( L"reverse me.exe" ) );
while( true )
{
// Call the target function
blarg_class_1.blargFunction1();
Sleep(1000);
}
return 0;
};
And here is the DLL containing the mhook code that I inject into that process. All I'm trying to do is hook blargFunction1 so that it prints out an additional line when it's called.
//SimpleDLL.cpp
#include "Stdafx.h"
#include "SimpleDLL.h"
#include "mhook-lib/mhook.h"
#include <Psapi.h>
#include <string>
#include <wchar.h>
// Open the log file.
FILE *file;
//=========================================================================
// Define the target functions so we can dynamically bind to the function
//
typedef void (WINAPI *_blargFunction1)( void );
//=========================================================================
// Get the current (original) address to the functions to be hooked
//
_blargFunction1 TrueBlargFunction1 = (_blargFunction1)(0x1770);
//=========================================================================
// This is the function that will replace the target function once the hook
// is in place
//
void WINAPI blargFunction1(void)
{
fprintf( file, "***** Call to blargFunction1 from mhook sample.\n");
return TrueBlargFunction1();
}
#pragma comment(lib, "psapi.lib")
DWORD GetCurrentModuleBase( LPWSTR targetModule )
{
HMODULE hMods[1024];
HANDLE hProcess;
DWORD cbNeeded;
DWORD baseAddress = -1;
unsigned int i;
// Get the current process id.
DWORD processID = GetCurrentProcessId();
fprintf( file, "Process ID: %u\n", processID );
// Get a handle to the process.
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID );
// Sanity checking on process handle.
if( hProcess == NULL )
{
fprintf( file, "hProcess is NULL.\n" );
return 1;
}
// Get a list of all the modules in this process.
if( EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
// Iterate through each module
for ( i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
{
WCHAR szModName[MAX_PATH];
// Get the full path to the module's file.
if ( GetModuleFileNameEx( hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
{
// Print the module name and handle value.
//fwprintf( file, L"\t%s (0x%08X)\n", szModName, hMods[i] );
// Is this the module that we're looking for?
std::wstring moduleName = szModName;
if( moduleName.find( targetModule ) != std::wstring::npos )
{
//fprintf( file, "Found it.\n");
baseAddress = (DWORD)hMods[i];
}
}
}
}
// Release the handle to the process.
CloseHandle( hProcess );
return baseAddress;
}
extern "C" int WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) {
time_t now = time(NULL);
struct tm nowTM;
char datetime[32];
DWORD baseAddress = 0;
localtime_s( &nowTM, &now );
// Generate a date/time string.
strftime(datetime, 32, "%Y%m%d %H:%M:%S", &nowTM);
fopen_s( &file, "simpledll.log", "a+");
// Perform different actions based on why this function is being called.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
fprintf(file, "----------------------------------\n");
fprintf(file, "%s SimpleDll - DLL_PROCESS_ATTACH.\n", datetime);
// Determine the base address of this process.
baseAddress = GetCurrentModuleBase( L"reverse me.exe" );
strftime(datetime, 32, "%Y%m%d %H:%M:%S", &nowTM);
fprintf( file, "%s SimpleDll - GetCurrentModuleBase = 0x%08X\n", datetime, baseAddress );
// Determine the memory address of the target function.
TrueBlargFunction1 = (_blargFunction1)( (DWORD)TrueBlargFunction1 + baseAddress);
strftime( datetime, 32, "%Y%m%d %H:%M:%S", &nowTM );
fprintf( file, "%s SimpleDll - TrueBlargFunction1 = 0x%08X.\n", datetime, TrueBlargFunction1 );
//strftime(datetime, 32, "%Y%m%d %H:%M:%S", &nowTM);
//fprintf(file, "%s SimpleDll - Before Mhook_SetHook.\n", datetime);
// Set the hook
if( Mhook_SetHook( (PVOID*)&TrueBlargFunction1, blargFunction1) )
{
strftime(datetime, 32, "%Y%m%d %H:%M:%S", &nowTM);
fprintf(file, "%s SimpleDll - Successfully set hook.\n", datetime);
// Remove the hook
//Mhook_Unhook((PVOID*)&TrueBlargFunction1);
//strftime(datetime, 32, "%Y%m%d %H:%M:%S", &nowTM);
//fprintf(file, "%s SimpleDll - Unset hook.\n", datetime);
}
else
{
strftime(datetime, 32, "%Y%m%d %H:%M:%S", &nowTM);
fprintf(file, "%s SimpleDll - Failed to set hook.\n", datetime);
}
strftime(datetime, 32, "%Y%m%d %H:%M:%S", &nowTM);
fprintf(file, "%s SimpleDll - After Mhook_SetHook.\n", datetime);
break;
case DLL_PROCESS_DETACH:
strftime(datetime, 32, "%Y%m%d %H:%M:%S", &nowTM);
fprintf(file, "%s SimpleDll - DLL_PROCESS_DETACH.\n", datetime);
break;
case DLL_THREAD_ATTACH:
strftime(datetime, 32, "%Y%m%d %H:%M:%S", &nowTM);
fprintf(file, "%s SimpleDll - DLL_THREAD_ATTACH.\n", datetime);
break;
case DLL_THREAD_DETACH:
strftime(datetime, 32, "%Y%m%d %H:%M:%S", &nowTM);
fprintf(file, "%s SimpleDll - DLL_THREAD_DETACH.\n", datetime);
break;
}
fclose( file );
return TRUE;
};
Addendum: I'm using a Windows 32 bit environment because ultimately I'll be trying this approach on an older legacy 32 bit application and the injector doesn't seem to work unless they're on the same platform.
TrueBlargFunction1
and don't follow the example given on the project's website and useGetProcAddress
?_blargFunction1 TrueBlargFunction1 = (_blargFunction1)(0x1770);
... that address is likely not even in the address range of the module anyway.