小能豆

inline hook 系统messagebox函数 异常

javascript

请问一下各位大佬,我在windows 10环境下,使用shellcode来hook系统messagebox函数。
用驱动修改EDT过写拷贝,将shellcode写入USER32.dll中,修改messagebox函数跳入shellcode中。运行完成跳回messagebox。

程序使用X64dbg跟踪运行发现,在修改messageboxa函数的头部5个字节跳转时,
第一次报C00000005异常 EXCEPUTION_ACCESS_VOILATION,
接着第二次报C0000041D,STATUS_USER_CALLBACK.之后通过运行。
程序正常运行。能达到HOOK的目标。

但如果不使用X64dbg则无法运行。我想肯定就是那两次异常的问题,请问是什么原因哦,有没有办法可以处理


阅读 50

收藏
2024-06-24

共1个答案

小能豆

在 Windows 10 环境下使用 Shellcode 来 Hook 系统的 MessageBox 函数,并出现 C00000005C0000041D 异常时,问题可能与以下几个因素有关:

  1. 地址空间布局随机化(ASLR):Windows 10 上启用了 ASLR,这可能导致代码段和数据段的位置不固定,导致跳转目标地址不可预测。

  2. 数据执行保护(DEP):Windows 10 上默认启用 DEP,这可能阻止你的 Shellcode 执行。

  3. 线程间消息处理和回调机制:Windows 中 MessageBox 是一种复杂的函数,它涉及到许多内部的回调和消息处理机制。Hook MessageBox 函数可能会干扰这些机制。

  4. 调试器的影响:使用 X64dbg 进行调试可能会改变程序的执行路径、执行时间和内存布局,从而掩盖了一些问题。

解决方案和建议

1. 禁用 DEP 或标记 Shellcode 可执行

如果你的 Shellcode 位于非可执行的内存区域,DEP 会阻止其执行。你需要确保 Shellcode 位于可执行的内存区域。

void *execMem = VirtualAlloc(nullptr, shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (execMem != nullptr) {
    memcpy(execMem, shellcode, shellcodeSize);
    // Use execMem as the target for your hook
}

2. 禁用 ASLR(仅用于测试)

可以暂时禁用 ASLR 来排除其影响,但不建议在生产环境中这样做。

3. 正确处理线程间消息和回调

MessageBox 可能涉及到线程间消息处理和用户模式回调。你需要确保你的 Hook 代码正确处理这些情况。

4. 检查内存写入权限

确保你有权限修改 USER32.dll 中的内存。使用以下方法来修改内存保护属性:

DWORD oldProtect;
VirtualProtect(targetAddress, size, PAGE_EXECUTE_READWRITE, &oldProtect);
// Write your hook
VirtualProtect(targetAddress, size, oldProtect, &oldProtect);

5. 避免干扰系统调用

为了避免对系统调用的干扰,建议使用安全的 Hook 框架,如 Microsoft DetoursMinHook,这些框架提供了更稳定和可靠的 Hook 机制。

示例代码

以下是一个使用 MinHook 的示例代码,用于 Hook MessageBox

#include <Windows.h>
#include "MinHook.h"

typedef int (WINAPI *MessageBoxW_t)(HWND, LPCWSTR, LPCWSTR, UINT);
MessageBoxW_t originalMessageBoxW = nullptr;

int WINAPI HookedMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) {
    // 修改消息内容
    return originalMessageBoxW(hWnd, L"Hooked!", lpCaption, uType);
}

void HookMessageBox() {
    // 初始化 MinHook
    if (MH_Initialize() != MH_OK) {
        return;
    }

    // 创建 Hook
    if (MH_CreateHook(&MessageBoxW, &HookedMessageBoxW, reinterpret_cast<void**>(&originalMessageBoxW)) != MH_OK) {
        return;
    }

    // 启用 Hook
    if (MH_EnableHook(&MessageBoxW) != MH_OK) {
        return;
    }
}

void UnhookMessageBox() {
    // 禁用 Hook
    MH_DisableHook(&MessageBoxW);

    // 取消初始化 MinHook
    MH_Uninitialize();
}

int main() {
    HookMessageBox();

    MessageBoxW(nullptr, L"Original", L"Title", MB_OK);

    UnhookMessageBox();

    return 0;
}

这个示例使用 MinHook 框架来 Hook MessageBoxW 函数,并确保在程序退出时解除 Hook。这种方法比直接修改函数头部字节更加可靠和安全。

总结

直接修改系统 DLL 中的函数头部字节进行 Hook 是一种高风险操作,容易导致异常和不可预期的行为。建议使用可靠的 Hook 框架,并确保正确处理内存保护和线程间消息。

2024-06-24