API挂钩使用JMP指令失败

时间:2014-01-17 19:38:51

标签: c windows winapi hook detours

我正在使用JMP interception

中给出的JMP指令拦截Win32函数调用

我能够成功地将DLL注入进程地址空间但无法使用新函数拦截调用。这是DLL代码,它被注入到调用win32函数的进程中。它在“VirtualProtect2 failed”时失败,错误代码为998(无效访问)。我是否在拦截电话时遇到任何错误?

// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"

#define SIZE 6  
typedef HANDLE (WINAPI *pFindFirstFileA)(LPCSTR,LPWIN32_FIND_DATAA);  // Messagebox protoype
HANDLE WINAPI MyFindFirstFileA(LPCSTR,LPWIN32_FIND_DATAA);            // Our detour
 void BeginRedirect(LPVOID);                                        
 pFindFirstFileA pOrigMBAddress = NULL;                                // address of original
 BYTE oldBytes[SIZE] = {0};                                         // backup
 BYTE JMP[SIZE] = {0};                                              // 6 byte JMP instruction
 DWORD oldProtect, myProtect = PAGE_EXECUTE_READWRITE; 

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        OutputDebugStringA("dll attach");
                 pOrigMBAddress = (pFindFirstFileA)                      
                 GetProcAddress(GetModuleHandleA("Kernel32.dll"),               // get address of original 
                       "FindFirstFileA");  
                 if(pOrigMBAddress != NULL) 
                 {
                    OutputDebugStringA("dll attach orig address is not null");
                   BeginRedirect(MyFindFirstFileA); 
                 }
                 else
                    OutputDebugStringA("dll attach orig address is null");
                 // start detouring
                 break;  
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
                memcpy(pOrigMBAddress, oldBytes, SIZE);                       // restore backup
        break;
    }
    return TRUE;
}

void BeginRedirect(LPVOID newFunction)  
{  
    OutputDebugStringA("dll beginredirect");
    BYTE tempJMP[SIZE] = {0xE9, 0x90, 0x90, 0x90, 0x90, 0xC3};         // 0xE9 = JMP 0x90 = NOP oxC3 = RET
    memcpy(JMP, tempJMP, SIZE);                                        // store jmp instruction to JMP
    DWORD JMPSize = ((DWORD)newFunction - (DWORD)pOrigMBAddress - 5);  // calculate jump distance
    bool ret = VirtualProtect((LPVOID)pOrigMBAddress, SIZE,                       // assign read write protection
           PAGE_EXECUTE_READWRITE, &oldProtect);  
    if(!ret)
        OutputDebugStringA("VirtualProtect1 failed");
    memcpy(oldBytes, pOrigMBAddress, SIZE);                            // make backup
    memcpy(&JMP[1], &JMPSize, 4);                              // fill the nop's with the jump distance (JMP,distance(4bytes),RET)
    memcpy(pOrigMBAddress, JMP, SIZE);                                 // set jump instruction at the beginning of the original function
    ret = VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL);
    if(!ret)
    {
        char str[200];
        sprintf(str,"VirtualProtect2 failed %d",GetLastError());
        OutputDebugStringA(str);
    }
    // reset protection
}

HANDLE WINAPI MyFindFirstFileA(LPCSTR lpFileName,LPWIN32_FIND_DATAA lpFindFileData) 
{  
    OutputDebugStringA("success hook");
    VirtualProtect((LPVOID)pOrigMBAddress, SIZE, myProtect, NULL);     // assign read write protection
    memcpy(pOrigMBAddress, oldBytes, SIZE);                            // restore backup
    HANDLE retValue = FindFirstFileA(lpFileName,lpFindFileData);       // get return value of original function
    memcpy(pOrigMBAddress, JMP, SIZE);                                 // set the jump instruction again
    VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL);    // reset protection
    return retValue;                                                   // return original return value
} 

1 个答案:

答案 0 :(得分:0)

下面链接中的VirtualProtect的msdn描述表明,如果lpfOldProtect参数为NULL并且看起来你正在使用NULL,则VirtualProtect会失败。

http://msdn.microsoft.com/en-us/library/windows/desktop/aa366898(v=vs.85).aspx

“lpflOldProtect [out] 指向变量的指针,该变量接收指定页面区域中第一页的先前访问保护值。 如果此参数为NULL或未指向有效变量,则函数将失败。