您现在的位置是:首页 >其他 >Detours HOOK网站首页其他

Detours HOOK

辰霖心 2023-07-22 10:42:17
简介Detours HOOK

参考文本

如何使用Detours库进行DLL注入,拦截API - 知乎 (zhihu.com)

解决‘nmake‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。_nmake' 不是内部或外部命令,也不是可运行的程序 或批处理文件。_AI浩的博客-CSDN博客

Detours使用方法,简单明了_再学5分钟的博客-CSDN博客

Detours注入DLL钩子入门教程detours 注入SoulRed的博客-CSDN博客

detours介绍与使用_顺其自然~的博客-CSDN博客

https://www.cnblogs.com/dayw/p/3289443.html

Detours版HOOK 未导出的API函数CreateProcessInternalW_detours hook未导出的函数_侠客软件开发的博客-CSDN博客

(205条消息) Detours框架实现原理探究_microsoft detours_Leen的博客-CSDN博客

安装Detours

首先下载detours的资源,地址:GitHub - microsoft/Detours: Detours is a software package for monitoring and instrumenting API calls on Windows. It is distributed in source code form.

  • 下载到本地后解压至任意文件夹;

  • 打开cmd终端,注该cmd需要是下载VS2022一起下载的终端,进到这个文件夹下,键入nmake;下图为正常结果

  •  

  • 否则会出现”nmake‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件“

    这里分享一个我踩到的坑,就是在nmake的时候出现了

    'sn' 不是内部或外部命令,也不是可运行的程序
    或批处理文件。

    面对上述问题,是因为.NET Framework没有安装,修改安装后即可,但似乎即便没有安装,生成的lib文件也是可用的

  • 编译完成后:

  • 新建一个工程,将include中的detours.h移动至工程文件下;

  • 将lib.X64(X86也有对应目录)下的detours.lib移动至工程文件下;

编写目标程序

示例一

创建一个目标程序,内容随意,需要能够编译成exe文件,并且调用了Messagebox,越简单越好,生成exe文件,这里要注意,32位和64位不能混用,不然会注入失败,这里选择了64位

#include<windows.h>
#include<cstdio>
int main() {
	MessageBox(GetForegroundWindow(),L"这是正常的弹窗",L"正常的",1);
}

示例二:

#include<windows.h>
#include<cstdio>

int main() {
	SYSTEMTIME time, time2;
	GetLocalTime(&time);
	printf("%d::%d", time.wHour, time.wMinute);
}

示例三

#include<windows.h>
#include<cstdio>

int main() {
	
	//MessageBox(GetForegroundWindow(),L"这是正常的弹窗",L"正常的",1);
	system("notepad");

}

动态链接库

此时新建一个项目,选择动态链接库

默认生成的项目里有两个文件

1个是dllmain.cpp(DLL入口)

1个是pch.cpp(预编译头)

我们添加一个新的myhook.cpp文件到项目,内容如下,并且通过上方的方法,配置好detours库

示例一:

#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 (WINAPI* OldGetLocalTime)(LPSYSTEMTIME) = GetLocalTime;
void NewGetLocalTime(LPSYSTEMTIME lpSystemTime) {
	OldGetLocalTime(lpSystemTime);
	lpSystemTime->wMinute = 59;
}
*/
void StartHook()
{
	long err;
	DetourRestoreAfterWith();
	//开始事务
	DetourTransactionBegin();
	//更新线程信息  
	DetourUpdateThread(GetCurrentThread());
	//将拦截的函数附加到原函数的地址上
	DetourAttach(&(PVOID&)REALMessageBox, MYMessageBox);
    //DetourAttach(&(PVOID&)OldGetLocalTime, NewGetLocalTime);
	//结束事务
	err = DetourTransactionCommit();
}

//解除钩子
void EndHook()
{
	//开始事务
	DetourTransactionBegin();
	//更新线程信息 
	DetourUpdateThread(GetCurrentThread());
	//将拦截的函数从原函数的地址上解除
	DetourDetach(&(PVOID&)REALMessageBox, MYMessageBox);
    //DetourDetach(&(PVOID&)OldGetLocalTime, NewGetLocalTime);
	//结束事务
	DetourTransactionCommit();
}

在dllmain.cpp里调用StartHook函数

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "framework.h"
 
extern void StartHook();//新增
 
//新增一个导出函数,这个可以随便写,但必须至少有一个导出函数才能使用setdll远程注入
VOID __declspec(dllexport) test()
{
	OutputDebugString(L"__declspec(dllexport) test() 
");
}
 
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;
}

示例二:

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


void (WINAPI* OldGetLocalTime)(LPSYSTEMTIME) = GetLocalTime;
void NewGetLocalTime(LPSYSTEMTIME lpSystemTime) {
	OldGetLocalTime(lpSystemTime);
	lpSystemTime->wMinute = 59;
}

void StartHook()
{
	long err;
	DetourRestoreAfterWith();
	//开始事务
	DetourTransactionBegin();
	//更新线程信息  
	DetourUpdateThread(GetCurrentThread());
	//将拦截的函数附加到原函数的地址上
	//DetourAttach(&(PVOID&)REALMessageBox, MYMessageBox);
    DetourAttach(&(PVOID&)OldGetLocalTime, NewGetLocalTime);
	//结束事务
	err = DetourTransactionCommit();
}

//解除钩子
void EndHook()
{
	//开始事务
	DetourTransactionBegin();
	//更新线程信息 
	DetourUpdateThread(GetCurrentThread());
	//将拦截的函数从原函数的地址上解除
	//DetourDetach(&(PVOID&)REALMessageBox, MYMessageBox);
    DetourDetach(&(PVOID&)OldGetLocalTime, NewGetLocalTime);
	//结束事务
	DetourTransactionCommit();
}

示例三

#include <Windows.h>
#include "detours.h"
#include <iostream>
#include <Windows.h>
//#include"pch.h"
using namespace std;


int (*Oldsystem)(char const*) = system;
#pragma comment(lib, "detours.lib")

void Newsystem(char const* command) {
	Oldsystem("explorer");
}

void StartHook()
{
	long err;
	DetourRestoreAfterWith();
	//开始事务
	DetourTransactionBegin();
	//更新线程信息  
	DetourUpdateThread(GetCurrentThread());
	//将拦截的函数附加到原函数的地址上
	//DetourAttach(&(PVOID&)REALMessageBox, MYMessageBox);
	//etourAttach(&(PVOID&)OldGetLocalTime, NewGetLocalTime);
	DetourAttach(&(PVOID&)Oldsystem, Newsystem);
	//结束事务
	err = DetourTransactionCommit();
}

//解除钩子
void EndHook()
{
	//开始事务
	DetourTransactionBegin();
	//更新线程信息 
	DetourUpdateThread(GetCurrentThread());
	//将拦截的函数从原函数的地址上解除
	DetourDetach(&(PVOID&)Oldsystem, Newsystem);
	//结束事务
	DetourTransactionCommit();
}

右键项目--生成

如果出现 C1010 在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include "pch.h"”?

将这个头文件添加到相应CPP的文件头部即可

或者右键项目——属性——C/C++——预编译头——使用(/Yu)改为不使用预编译头

tip:这里还有一个坑,添加预编译头文件到项目中后,我出现了即便导入lib库,依旧无法识别外部符号的问题,不知道原理,但是建议改为不使用预编译头,而不是添加文件

如果出现无法解析的外部符号。

是因为我们没有导入我们刚才nmake生成的detours.lib

将E:Detours-4.0.1lib.X64detours.lib拷贝到项目根目录

tip:这里有一个小细节,如果你将两个项目放置在同一个解决方案之下,需要注意上方的项目调试配置默认的是先创建的项目,想要配置后创建的项目,需要在解决方案窗口选中再进行调试配置

成功生成项目以后,存在于该项目的release文件中

DLL文件注入

打开cmd进入到E:Detours-4.0.1in.X86目录,如果是64位的,则进入bin.X64

etdll /? 会打印出注入工具的帮助命令

开始注入:

在命令提示符里输入格式如下的命令

setdll /d:【自己的DLL】 【目标exe程序】

>setdll /d:C:Users27824source
eposDll3ReleaseDll3.dll C:Users27824source
epos	argetRelease	arget.exe

一般会出现以下界面,则证明注入成功了

然后重新打开exe文件 :

示例一:

 

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。