【Detours】DLL 注入式 hook

Detours Hook API 调用拦截技术

0x00 介绍

Detours 是 Microsoft Corporation 出品的应用程序 API 调用拦截技术项目,采用 MIT 开源协议。

Detours Github,请选中 Release 并下载源代码(好像 Release 停在 2018 不更新了,不过源代码还在更新,可以 Clone 仓库并找到需要的文件)。

0x01 找到需要的文件

克隆(Clone) 仓库,并使用终端软件例如 cmdWindows 终端 来切换到目录,并使用 cmake 将项目转为源代码和解决方案文件,打开 .sln 文件进行编译(将在目录下产生几个文件夹,其中 LIB.X<编译平台类型> 是我们所需的文件)。

将 LIB.X* 中的所有文件复制到您需要编写的项目的目录中,并在代码头部加入以下文本:

#include "detours.h" // 您也可以将这行代码写到 "pch.h" 中。
 
#pragma comment(lib, "detours.lib") // 链接到 detours.lib。

0x02 开始编写代码!

0. 了解函数结构

请创建一个 Windows 动态链接库 (DLL)项目。首先您需要了解需要拦截的 API 的调用方法,比如 MessageBoxA (HWND, LPCSTR, LPCSTR, UINT)。

本文将使用 MessageBoxA 函数演示,拦截其他函数的方法大同小异(((

1. 定义结构体

了解后在代码中定义一个结构体:

// 定义原始的MessageBox函数类型
typedef int (WINAPI* MessageBoxA_t)(HWND, LPCSTR, LPCSTR, UINT);
MessageBoxA_t OriginalMessageBoxA = NULL;

其中 MessageBoxA_t 是原始的 API 函数,使用它定义一个 OriginalMessageBoxA(原始的 MessageBoxA 函数)

2. 获取原函数地址并替换为自己的函数地址

在 DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 函数中,如果 ul_reason_for_call == DLL_PROCESS_ATTACH,那么执行以下代码:

OriginalMessageBoxA = (MessageBoxA_t)GetProcAddress(GetModuleHandle(L"user32.dll"), "MessageBoxA");

if (OriginalMessageBoxA) {
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourAttach(&(PVOID&)OriginalMessageBoxA, MyMessageBoxA);
    DetourTransactionCommit();
}

代码解析:

使用 GetProcAddress 获取到 MessageBoxA 的函数地址,将其备份到 OriginalMessageBoxA 中。注意需要使用“(MessageBoxA_t)”将其强制转换为 MessageBoxA_t 类型。

使用 DetourTransactionBegin()DetourUpdateThread(GetCurrentThread()) 让 Detours 初始化并附着在当前线程。其中 MyMessageBoxA 是您替换的 MessageBoxA 的代码。

使用 DetourAttach(PVOID *ppPointer, PVOID pDetour) 替换掉需要的函数。之后调用 DetourTransactionCommit() 是让 Detour 函数起作用并检查函数的返回值判断是正确还是错误。

您可以参照以下的 MyMessageBoxA 代码:

int WINAPI MyMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {
    if (strstr(lpText, "运行时出错!") != nullptr)
        if (OriginalMessageBoxA(hWnd, "很抱歉,程序运行时出现错误,需要终止进程。对您造成的不便,我们深感抱歉。\n\n是否跳转到产品官网?", "运行时出现错误", MB_ICONERROR | MB_YESNO) == IDYES)
        {
            system("start https://cnstlapy.cn/");
        }
        return 0;
    }
    return OriginalMessageBoxA(hWnd, lpText, lpCaption, uType);
}

代码解析:

当被注入应用程序调用 MessageBoxA(弹出信息框) 时,将会取消执行原来的 MessageBoxA 并调用我们的 MyMessageBoxA,并传入调用原函数的参数。

很显然,这是一个判断某个易语言是否运行时出错的函数代码。如果应用程序调用了 MessageBoxA(尝试弹出信息框)时,会先检查信息框的内容(lpText)是否包含“运行时出错!”的文本(代码使用的是查找文本,索引如果不是空指针的话就是找到了文本)。如果是,则弹出自己的信息框,询问用户是否跳转到官网反馈问题。如果用户点击了 是按钮(IDYES),则运行“start https://cnstlapy.cn/”,让系统调用默认浏览器打开网址。返回 0 后,易语言程序将会退出。

如果不包含“运行时出错”的文本,将会调用原始的 MessageBoxA 函数,将会正常地弹出信息框。

3. 编译 DLL

如图,在 Visual Studio 右上角选择发布类型和发布平台(发布类型选 Release),如果您需要将 DLL 注入到 32 位应用程序,那么请选择平台:x86,否则请选择 x64。

选择“▶ 本地 Windows 调试器”运行编译,编译成功后,可在文件夹中找到编译的 DLL。使用 VirtualAlloc,WriteProcessMemory 注入到进程中。此时 API 拦截程序 应当正常工作。(您可以试图触发易语言运行时错误,看看有没有弹出您的自定义信息框)

效果如下:

但是,API 拦截技术 基于用户态,某些应用程序总有办法绕过。如果需要严格的限制,可以考虑一下使用 Windows 驱动程序(((

感谢您的阅读(新人发帖,大佬轻喷www\)

lib.X86.zip 不会编译 Detours 的可以下载这个((

下载地址
本地下载
密码:无

评论

  1. 博主
    2 月前
    2025-3-09 22:56:51

    没有人发评论嘛www

  2. 2 月前
    2025-3-10 23:51:04

    打卡

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇