为什么 mhook 无法钩住我的函数?

逆向工程 艾达 视窗 ollydbg C++
2021-07-09 18:17:49

所以我正在探索 mhook 2.3 并为此专门构建了一个示例可执行文件。我有一个注入器,可以将包含 mhook 的 dll 注入目标进程。

这一切正常,我可以通过检查我的日志文件来验证目标进程是否正在调用我的代码。

但是,当我去挂钩我的目标函数时,mhook 只是返回并说它未能挂钩该函数。我已经使用 OllyDBG 和 IDA 来验证我传递给 mhook 的目标函数的地址是否正确,并且蹦床的函数签名与目标函数完全相同,但它仍然失败。

我不知所措。有人可以告诉我我在这里做错了什么吗?

这是我构建的目标程序。这是一个简单的 Windows 控制台应用程序,每秒打印出一条随机消息。

// 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;
};

这是包含我注入该进程的 mhook 代码的 DLL。我想要做的就是钩住 blargFunction1,以便在调用时打印出额外的一行。

//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;
};

附录:我使用的是 Windows 32 位环境,因为最终我将在较旧的传统 32 位应用程序上尝试这种方法,除非它们在同一平台上,否则注入器似乎无法工作。

1个回答

这与其说是答案,不如说是评论(但评论很短且格式有限),因此我将其设为社区维基:

EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define GetCurrentModuleBase() ((HMODULE)&__ImageBase)

基本上,您可以完全节省您的实施工作,并使用上述内容作为替代。此外,仅 32 位 Windows 的时代已经结束。使用DWORD的内存地址现在是不正确的,绝对过时。