如何在WinAPI挂钩中创建一个挂钩和蹦床函数 [英] How to make a Hook and Trampoline function in one for WinAPI hooking

查看:112
本文介绍了如何在WinAPI挂钩中创建一个挂钩和蹦床函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我一直在学习挂钩和使用蹦床的概念,以绕过/执行WinAPI挂钩函数中的数据(在另一个可执行文件中,使用DLL注入).到目前为止,我知道如何使用程序集和C的混合物来制作它(蹦床和挂钩),但是我似乎不能仅使用C来做到这一点,因为我似乎缺少了一些东西.如果有人能告诉我我做错了什么以及如何解决它,我将不胜感激.

So I have been learning about the concept of hooking and using trampolines in order to bypass/execute data in a WinAPI hook function (In a different executable file, using DLL injection). So far I know how to make it (the trampoline and hook) using a mixture of assembly and C, but I can't seem to do it with just using C, as I seem to be missing something. I'd appreciate if someone could tell me what I'm doing wrong and how to fix it up.

现在我的代码:

#include <Windows.h>

unsigned char* address = 0;

__declspec(naked) int __stdcall MessageBoxAHookTrampoline(HWND Window, char* Message, char* Title, int Type) {
    __asm
    {
        push ebp
        mov ebp, esp
        mov eax, address
        add eax, 5
        jmp eax
    }
}

int __stdcall MessageBoxAHook(HWND Window, char* Message, char* Title, int Type) {
    wchar_t* WMessage = L"Hooked!";
    wchar_t* WTitle = L"Success!";
    MessageBoxW(0, WMessage, WTitle, 0);
    return MessageBoxAHookTrampoline(Window, Message, Title, Type);
}

unsigned long __stdcall Thread(void* Context) {
    address = (unsigned char*)GetProcAddress(LoadLibraryA("user32"), "MessageBoxA");
    ULONG OP = 0;
    if (VirtualProtect(address, 1, PAGE_EXECUTE_READWRITE, &OP)) {
        memset(address, 0x90, 5);
        *address = 0xE9;
        *(unsigned long*)(address + 1) = (unsigned long)MessageBoxAHook - (unsigned long)address - 5;
    }
    else {
        MessageBoxA(0, "Failed to change protection", "RIP", 0);
    }
    return 1;
}

// Entry point.
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
    if (fdwReason == DLL_PROCESS_ATTACH) {
        CreateThread(0, 0, Thread, 0, 0, 0);
    }
    else if (fdwReason == DLL_PROCESS_DETACH) {

    }
    return true;
}

所以问题是:我将如何使一个函数说成InstallHook,该函数将安装钩子并返回蹦床,以便我可以轻松地使用它? 函数原型可能是:void* InstallHook(void* originalFunc, void* targetFunc, int jumpsize),或者据我所知,可以在线阅读,但是不确定jumpsize用于什么目的.

So question is: How would I make a function say InstallHook that will install the hook and return a trampoline so I can use it easily? Function prototype probably would be: void* InstallHook(void* originalFunc, void* targetFunc, int jumpsize), or so I've understood reading online, but unsure what jumpsize would be used for.

到目前为止,我知道必须保留和恢复前5个字节,然后跳转到原始挂钩函数的地址.因此,我不得不使用malloc分配内存,使用memcpy复制字节,0xE9是跳转指令的值,等等,但是我只是不知道如何仅使用纯C来实现它. href ="https://stackoverflow.com/questions/8099660/writing-a-trampoline-function">我认为这类似于该问题中的代码.那么我该如何编写一个钩子函数可以使用纯C语言的WinAPI函数返回蹦床吗?

So far I know that the first 5 bytes must be preserved and restored, and then there's a jump to the address of the original hooked function. So I'd have to use malloc to allocate memory, memcpy to copy bytes over, the 0xE9 is the value of a jump instruction and such, but I just don't know how to implement it using just pure C. I figure it would be something similar to the code in this question. So how can I write a hook function that returns a trampoline using pure C for WinAPI functions?

推荐答案

如果我正确地理解了这个问题,则想避免在汇编中对蹦床功能进行硬编码",大概是这样,您可能会在使用多个蹦床同时不重复代码.您可以使用VirtualAlloc来实现此目的(由于返回的内存将不可执行,因此malloc将不起作用).

If I understood the question correctly, you want to avoid "hard-coding" the trampoline function in assembly, presumably so you could have multiple trampolines in use at the same time without duplicating the code. You can achieve this using VirtualAlloc (malloc won't work since the returned memory won't be executable).

我是从内存中编写此代码的,而没有访问编译器的权限,因此它可能存在一些小错误,但是一般的想法就在这里.通常,一旦完成修改,您还可以使用VirtualProtect将页面权限更改为r-x而不是rwx,但是为了简单起见,我将其省略了:

I wrote this from memory without access to a compiler so it might have some minor bugs, but the general idea is here. Normally you would also use VirtualProtect to change the page permissions to r-x instead of rwx once you're done modifying it, but I've left that out for the sake of simplicity:

void *CreateTrampoline(void *originalFunc)
{
    /* Allocate the trampoline function */
    uint8_t *trampoline = VirtualAlloc(
        NULL,
        5 + 5, /* 5 for the prologue, 5 for the JMP */
        MEM_COMMIT | MEM_RESERVE,
        PAGE_EXECUTE_READWRITE); /* Make trampoline executable */

    /* Copy the original function's prologue */
    memcpy(trampoline, originalFunc, 5);

    /* JMP rel/32 opcode */
    trampoline[5] = 0xE9;

    /* JMP rel/32 operand */
    uint32_t jmpDest = (uint32_t)originalFunc + 5; /* Skip original prologue */
    uint32_t jmpSrc = (uint32_t)trampoline + 10; /* Starting after the JMP */
    uint32_t delta = jmpDest - jmpSrc;
    memcpy(trampoline + 6, &delta, 4);

    return trampoline;
}

然后,您的InstallHook函数将仅调用CreateTrampoline创建一个蹦床,然后使用JMP rel/32将原始函数的前5个字节修补到钩子上.

Your InstallHook function would then just call CreateTrampoline to create a trampoline, then patch the first 5 bytes of the original function with a JMP rel/32 to your hook.

请注意,这仅适用于WinAPI函数,因为Microsoft要求它们具有5字节的序言以启用热修补程序(这就是您在此处所做的事情).普通函数没有此要求-通常它们仅以push ebp; mov ebp, esp开头,该字节只有3个字节(如果编译器决定对其进行优化,则有时甚至没有).

Be warned, this only works on WinAPI functions, because Microsoft requires that they have a 5-byte prologue to enable hot-patching (which is what you're doing here). Normal functions do not have this requirement -- usually they only start with push ebp; mov ebp, esp which is only 3 bytes (and sometimes not even that, if the compiler decides to optimize it out).

这是数学的工作原理:

                          _______________delta______________
                         |                                  |
trampoline               |                  originalFunc    |
    |                    |                        |         |
    v                    |                        v         v
    [prologue][jmp delta]                         [prologue][rest of func]
    |________||_________|                         |________|
         5    +    5                                   5

这篇关于如何在WinAPI挂钩中创建一个挂钩和蹦床函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆