本教程非常初级,适合新手食用
开发环境,WIN10 64bit, VS2022
点击右侧
下载后解压到例如 E:\Detours-4.0.1
然后打开VS2022的自带命令行工具(如果要注入的目标为64请选择x64)
在这里我需要对32位程序进行注入,所以我选择x86的命令提示工具
通过命令提示进入到E:\Detours-4.0.1
输入nmake
等待编译完成
编译完成后在E:\Detours-4.0.1会得到3个文件夹
bin.X86里面是所有sample的编译后的文件。其中还有一个重要的setdll.exe工具
include是自己创建钩子dll时需要引用的头文件
lib.X86是Detours的本体静态链接库detours.lib
自此编译就OK了。
然后我们新建一个winform程序。
我习惯用C#作为win视图程序的语言,可以根据自己爱好选择例如MFC或者其他语言。
这里先用C#作为演示
创建好项目后在窗体上拖入一个button 控件,然后双击button进入到点击事件的代码逻辑
在中间写一个弹出窗口的代码即可。
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("窗口文字随便写");
}
准备生成EXE文件,这里要注意,32位和64位不能混用,不然会注入失败。
我们上面选了32位,那么这个应用程序也必须是32位(x86)
按F5如果弹出一个框,选择
禁用仅我的代码并继续
点击按钮测试下弹窗是否正常。
然后到 我们项目的\bin\x86\Release\net6.0-windows
会看到我们生成的exe程序
=============================分割线==============================
然后重点来了,我们要开始做钩子DLL了。
此时偷懒的话,可以直接在刚才创建的项目里,在解决方案管理器树状目录的顶层右键
添加-新建项目选择C++动态链接库
注意这两个项目代码没有任何关联,只是我为了方便把两个项目放到一个解决方案里了。
默认生成的项目里有两个文件
1个是dllmain.cpp(DLL入口)
1个是pch.cpp(预编译头)
我们添加一个新的myhook.cpp文件到项目,内容如下
#include <Windows.h>
#include "detours.h"
//真实的调用函数,函数原型必须和真实API一致。部分类型如果无法声明可以用void *替代
static int (WINAPI* REALMessageBox) (HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) = MessageBox;
//伪造的调用函数,也就是我们的钩子,参数类型和返回值必须和真实的一样,
static int WINAPI MYMessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
//在这里可以任意发挥~~~
//在函数末尾调用真正的API来返回
return REALMessageBox(NULL, L"MyHook!! MessageBoxCRACK!!", L"Please", MB_OK);
}
void StartHook()
{
long err;
DetourRestoreAfterWith();
//开始事务
DetourTransactionBegin();
//更新线程信息
DetourUpdateThread(GetCurrentThread());
//将拦截的函数附加到原函数的地址上
DetourAttach(&(PVOID&)REALMessageBox, MYMessageBox);
//结束事务
err = DetourTransactionCommit();
}
//解除钩子
void EndHook()
{
//开始事务
DetourTransactionBegin();
//更新线程信息
DetourUpdateThread(GetCurrentThread());
//将拦截的函数从原函数的地址上解除
DetourDetach(&(PVOID&)REALMessageBox, MYMessageBox);
//结束事务
DetourTransactionCommit();
}
此时提示一堆错误,因为我们没有把头文件导入进来。
去我们刚才生成的E:\Detours-4.0.1\include里将detours.h放到到项目根目录。
然后在解决方案资源管理器点击显示所有文件按钮,找到detours.h (有个红色的减号很明显)
右键——包括在项目。再点一下显示所有文件按钮。
此时错误全部消失。
这时我们还差一步: 在dllmain.cpp里调用StartHook函数
extern void StartHook();//新增
//新增一个导出函数,这个可以随便写,但必须至少有一个导出函数才能使用setdll远程注入
VOID __declspec(dllexport) test()
{
OutputDebugString(L"__declspec(dllexport) test() \r\n");
}
{StartHook();} //新增
dllmain代码看起来应该是这样的。
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "framework.h"
extern void StartHook();//新增
//新增一个导出函数,这个可以随便写,但必须至少有一个导出函数才能使用setdll远程注入
VOID __declspec(dllexport) test()
{
OutputDebugString(L"__declspec(dllexport) test() \r\n");
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{StartHook();} //新增
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
右键项目——生成。
如果出现 C1010 在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include "pch.h"”?
将这个头文件添加到相应CPP的文件头部即可
或者右键项目——属性——C/C++——预编译头——使用(/Yu)改为不使用预编译头
是不是非常简单!!!~
此时再生成,会出现一堆无法解析的外部符号。
是因为我们没有导入我们刚才nmake生成的detours.lib
将E:\Detours-4.0.1\lib.X86\detours.lib拷贝到项目根目录
右键项目添加现有项选择detours.lib。
再次生成。
生成OK
在输出控制台要记住我们生成的dll文件位置,因为我们下面要用到
===========================分割线又来了==================================
所有代码都编写完成后,我们需要将DLL注入到目标程序。
打开cmd进入到E:\Detours-4.0.1\bin.X86目录
setdll /?
会打印出注入工具的帮助命令
开始注入:
在命令提示符里输入格式如下的命令
setdll /d:【自己的DLL】 【目标exe程序】
setdll /d:C:\Users\g\source\repos\LotTest\Release\lotDll.dll C:\Users\g\source\repos\LotTest\bin\x86\Release\net6.0-windows\LotTest.exe
应该会得到以下输出
再去执行窗口程序。
如果想要撤销注入
setdll /r C:\Users\g\source\repos\LotTest\bin\x86\Release\net6.0-windows\LotTest.exe
写于2022年3月26日,CSDN博客。