《逆向工程核心原理》——API HOOK

编写dll处理hook逻辑,注入到目标进程,实现api hook。

Windows10 notepad,通过hook kernel32.dll.WriteFile,实现小写字母转大写保存到文件。

hook前kernel32.dll.WriteFile入口:

《逆向工程核心原理》——API HOOK

 

 

kernel32.dll.WriteFile在调用时入口是条jmp指令

跳转后

《逆向工程核心原理》——API HOOK

 

 hook时通过GetProcAddress得到的是jmp处的地址,在jmp指令周边有一些int 3指令,这些空间可以用来做一些跳转操作。

#include "pch.h"
#include <tchar.h>
#define DLLNAME "kernel32.dll"
#define WRITEFILE "WriteFile"
BYTE g_pOrgBytes[6] = { 0 };
FARPROC g_writefile = GetProcAddress(GetModuleHandleA(DLLNAME), WRITEFILE);

//此函数用来将api前5个字节改为jmp xxxx 
BOOL hook_by_code(FARPROC pfnOrg, PROC pfnNew, PBYTE pOrgBytes) {
    DWORD dwOldProtect, dwAddress;
    BYTE pBuf[6] = { 0xE9,0,0,0,0, 0x90};
    PBYTE pByte;
    pByte = (PBYTE)pfnOrg;
    if (pByte[0] == 0xE9)//若已被勾取,则返回False
        return FALSE;
    VirtualProtect((LPVOID)pfnOrg, 12, PAGE_EXECUTE_READWRITE, &dwOldProtect);//为了修改字节,先向内存添加“写”的属性
    memcpy(pOrgBytes, pfnOrg, 6);//备份原有代码
    dwAddress = (DWORD64)pfnNew - (DWORD64)pfnOrg - 5;//计算JMP地址   => XXXX = pfnNew - pfnOrg - 5
    memcpy(&pBuf[1], &dwAddress, 4);//E9,剩下后面4个字节为跳转的地址
    memcpy(pfnOrg, pBuf, 6);//复制指令,跳转到hook逻辑
    
    memcpy(&pByte[6], pOrgBytes, 6);//后面的int 3指令进行修改,跳转到原api逻辑
    pByte[8] -= 6;//修正跳转偏移

    VirtualProtect((LPVOID)pfnOrg, 12, dwOldProtect, &dwOldProtect);//恢复内存属性
    return TRUE;
}

BOOL unhook_by_code(FARPROC pFunc, PBYTE pOrgBytes) {
    
    DWORD dwOldProtect;
    PBYTE pByte;
    pByte = (PBYTE)pFunc;
    if (pByte[0] != 0xE9)//若已脱钩,则返回False
        return FALSE;
    VirtualProtect((LPVOID)pFunc, 6, PAGE_EXECUTE_READWRITE, &dwOldProtect);//向内存添加“写”的属性,为恢复原代码做准备
    memcpy(pFunc, pOrgBytes, 6);//脱钩
    VirtualProtect((LPVOID)pFunc, 6, dwOldProtect, &dwOldProtect);//恢复内存属性
    return TRUE;
}
//WINBASEAPI
//BOOL
//WINAPI
//WriteFile(
//    _In_ HANDLE hFile,
//    _In_reads_bytes_opt_(nNumberOfBytesToWrite) LPCVOID lpBuffer,
//    _In_ DWORD nNumberOfBytesToWrite,
//    _Out_opt_ LPDWORD lpNumberOfBytesWritten,
//    _Inout_opt_ LPOVERLAPPED lpOverlapped
//);
typedef BOOL(WINAPI* PFWriteFile)(
    _In_ HANDLE hFile,
    _In_reads_bytes_opt_(nNumberOfBytesToWrite) LPCVOID lpBuffer,
    _In_ DWORD nNumberOfBytesToWrite,
    _Out_opt_ LPDWORD lpNumberOfBytesWritten,
    _Inout_opt_ LPOVERLAPPED lpOverlapped
    );
BOOL WINAPI  MyWriteFile(
    _In_ HANDLE hFile,
    _In_reads_bytes_opt_(nNumberOfBytesToWrite) LPCVOID lpBuffer,
    _In_ DWORD nNumberOfBytesToWrite,
    _Out_opt_ LPDWORD lpNumberOfBytesWritten,
    _Inout_opt_ LPOVERLAPPED lpOverlapped) {
    PBYTE ptr = (PBYTE)g_writefile;
    //unhook_by_code(g_writefile, g_pOrgBytes);
    BOOL ret = TRUE;
    char* pc = (char*)lpBuffer;
    while (*pc)
    {
        if (*pc >= a && *pc <= z) {
            *pc -= 0x20;
        }
        pc++;
    }
    ret = ((PFWriteFile)(ptr+6))(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);//原入口偏移+6处是修正的原jmp指令
    //hook_by_code(g_writefile, (PROC)MyWriteFile, g_pOrgBytes);
    return ret;
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        hook_by_code(g_writefile,(PROC)MyWriteFile, g_pOrgBytes);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        unhook_by_code(g_writefile,g_pOrgBytes);
        break;
    }
    return TRUE;
}

 

hook效果:

《逆向工程核心原理》——API HOOK

 

《逆向工程核心原理》——API HOOK

上一篇:AnyCAD C#开发-BrepTools::Extrude创建拉伸


下一篇:restful api 设计原则