c++----detours2.1

本文详细介绍了使用Detours库时遇到的链接错误及其解决方法,并提供了在不同情况下如何编译和使用Detours库的指导。包括在VC6中解决链接错误、在dll动态链接库工程中解决语法错误以及在不同环境下正确编译Detours库的步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.遇见的问题

项目detours使用2.1版本


project->settings->general     设置为use mfc in a library


在win32 console application建项目可能用到了mfc东西,自然要加点东西

1

Linking...
nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in libcpmtd.lib(delop.obj)
Debug/detours.exe : fatal error LNK1169: one or more multiply defined symbols found
Error executing link.exe.


detours.exe - 2 error(s), 0 warning(s)

解决方法:

如果是vc
alt+f7打开工程设置
在link下第二行添加MSVCRT.LIB

2.

VC6 各link错误解决

错误1:
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
在project-setting-link里找到project options 去掉里面的/subsystem:console

错误2:
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endt...
将工程设置为Using MFC in a static library

错误3:
libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
在project-setting-link里找到project options 将里面的/subsystem:console 改为/subsystem:windows


3..如果是 dll的动态链接库工程报

e:\学习\c++程序\hd\detours.h(20) : error C2146: syntax error : missing ';' before identifier 'ULONG_PTR'
e:\学习\c++程序\hd\detours.h(20) : fatal error C1004: unexpected end of file found

解决:在#include "detours.h" 前加上一句#include <windows.h> 或 "#include <afxwin.h>


二  编译连接,编译detours

vc2003编译的lib不能用于vc6

你要在vc6中使用可以在vc6的命令行下编译
开一个cmd,执行c:\...vc98\bin\vcvars32.bat

再cd到你的Detours的src目录执行nmake即可。



例子代码

#include "stdafx.h"
#include "DetourHook.h"
#include <detours.h>

#pragma comment(lib, "detours.lib") 
#pragma comment(lib, "detoured.lib")



static int (WINAPI* OLD_MessageBoxW)(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType)=MessageBoxW;
int WINAPI NEW_MessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType)
{
                
        //修改输入参数,调用原函数
        int ret=OLD_MessageBoxW(hWnd,L"输入参数已修改",L"[测试]",uType);
        return ret;
}

VOID Hook()
{
        DetourRestoreAfterWith();
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());

        //这里可以连续多次调用DetourAttach,表明HOOK多个函数
        DetourAttach(&(PVOID&)OLD_MessageBoxW,NEW_MessageBoxW);

        DetourTransactionCommit();
}

VOID UnHook()
{
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        
        //这里可以连续多次调用DetourDetach,表明撤销多个函数HOOK
        DetourDetach(&(PVOID&)OLD_MessageBoxW,NEW_MessageBoxW);

        DetourTransactionCommit();

}
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
        MessageBoxW(0,L"正常消息框",L"测试",0);
        Hook();
        MessageBoxW(0,L"正常消息框",L"测试",0);
        UnHook();
        return 0;
        
}



补充连接

http://www.cnitblog.com/cc682/archive/2009/05/28/58883.html

http://blog.youkuaiyun.com/zhsp1029/article/details/4195139

补充:全局拦截函数

main.cpp

#include <Windows.h>

void main(){
	HMODULE hDll = NULL;
	if (hDll==NULL)
	{
		hDll=LoadLibrary("DLL.dll");
	}

	MessageBox(0,"testhook","測試start",0);
}

dll.dll


#include "stdafx.h"
#include "detours.h"
#include <Winsock2.h>

#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "detours.lib") 
#pragma comment(lib, "detoured.lib")

VOID UnHook();
HANDLE m_hModule=0;

//static int (WINAPI* OLD_MessageBoxW)(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType)=MessageBoxW;
static SOCKET (WINAPI* OLD_MessageBox)(int af,int type,int protocol)=socket;
//static int (WINAPI* pSend)(SOCKET s, const char* buf, int len, int flags)=send;
//int WINAPI NEW_MessageBox(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType)
int WINAPI NEW_MessageBox(int af,int type,int protocol)
{	
	//修改?入参数,?用原函数
	int ret=MessageBoxW(NULL,L"輸入参数已修改",L"[測試]",MB_OK);
	UnHook();
	return ret;
}

VOID Hook()
{
	DetourRestoreAfterWith();
	DetourTransactionBegin();
	DetourUpdateThread(GetCurrentThread());
	
	//?里可以??多次?用DetourAttach,表明HOOK多个函数
	DetourAttach(&(PVOID&)OLD_MessageBox,NEW_MessageBox);
	
	DetourTransactionCommit();
}

VOID UnHook()
{
	DetourTransactionBegin();
	DetourUpdateThread(GetCurrentThread());
	
	//?里可以??多次?用DetourDetach,表明撤?多个函数HOOK
	DetourDetach(&(PVOID&)OLD_MessageBox,NEW_MessageBox);
	
	DetourTransactionCommit();
	
}

LRESULT CALLBACK CBTProc(
						 int nCode,      // hook code
						 WPARAM wParam,  // depends on hook code
						 LPARAM lParam   // depends on hook code
						 ){
	//MessageBox(0,"進入鉤子","測試",0);
	return CallNextHookEx((HHOOK)m_hModule,nCode,wParam,lParam);
}

// int APIENTRY _tWinMain(HINSTANCE hInstance,
// 					   HINSTANCE hPrevInstance,
// 					   LPTSTR    lpCmdLine,
// 					   int       nCmdShow)
// {
// // 	MessageBoxW(0,L"正常消息框",L"測試",0);
// 	Hook();
// // 	MessageBoxW(0,L"正常消息框",L"測試",0);
// // 	UnHook();
// // 	MessageBoxW(0,L"正常消息框",L"測試",0);
// 	//send(socket())
// 	//HHOOK hhk=SetWindowsHookEx(WH_CBT,CBTProc,0,0);
// 	//CallNextHookEx(hhk,WH_CBT,0,0);
// 	int i=0;
// // 	while (true)
// // 	{
// // 		if (i==300)
// // 		{
// // 			MessageBoxW(0,L"準備進入鉤子",L"測試",0);
// // 		}
// // 		i++;
// // 	}
// 	return 0;
// 	
// }

BOOL APIENTRY DllMain( HANDLE hModule, 
					  DWORD  ul_reason_for_call, 
					  LPVOID lpReserved
					  )
{
    switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:	
		
		m_hModule=hModule;  
		SetWindowsHookEx(WH_CBT,(HOOKPROC)CBTProc,(HINSTANCE)m_hModule,0);
		Hook();	
		break;
	case DLL_THREAD_ATTACH:		
		
		break;
	case DLL_THREAD_DETACH:		

		break;
	case DLL_PROCESS_DETACH:			

		//UnhookWindowsHookEx((HHOOK)m_hModule);
		UnHook();
		break;
    }
    return TRUE;
}

SetWindowsHookEx(WH_CBT,(HOOKPROC)CBTProc,(HINSTANCE)m_hModule,0);

UnhookWindowsHookEx((HHOOK)m_hModule);最好写在main函数中








                
Detours是微软开发的一个函数库, 用于修改运行中的程序在内存中的影像,从而即使没有源代码也能改变程序的行为。具体用途是: 拦截WIN32 API调用,将其引导到自己的子程序,从而实现WIN32 API的定制。 为一个已在运行的进程创建一新线程,装入自己的代码并运行。 ---- 本文将简介Detours的原理,Detours库函数的用法, 并利用Detours库函数在Windows NT上编写了一个程序,该程序能使有“调试程序”的用户权限的用户成为系统管理员,附录利用Detours库函数修改该程序使普通用户即可成为系统管理员 (在NT4 SP3上)。 一. Detours的原理 ---- 1. WIN32进程的内存管理 ---- 总所周知,WINDOWS NT实现了虚拟存储器,每一WIN32进程拥有4GB的虚存空间, 关于WIN32进程的虚存结构及其操作的具体细节请参阅WIN32 API手册, 以下仅指出与Detours相关的几点: ---- (1) 进程要执行的指令也放在虚存空间中 ---- (2) 可以使用QueryProtectEx函数把存放指令的页面的权限更改为可读可写可执行,再改写其内容,从而修改正在运行的程序 ---- (3) 可以使用VirtualAllocEx从一个进程为另一正运行的进程分配虚存,再使用 QueryProtectEx函数把页面的权限更改为可读可写可执行,并把要执行的指令以二进制机器码的形式写入,从而为一个正在运行的进程注入任意的代码 ---- 2. 拦截WIN32 API的原理 ---- Detours定义了三个概念: ---- (1) Target函数:要拦截的函数,通常为Windows的API。 ---- (2) Trampoline函数:Target函数的复制品。因为Detours将会改写Target函数,所以先把Target函数复制保存好,一方面仍然保存Target函数的过程调用语义,另一方面便于以后的恢复。 ---- (3) Detour 函数:用来替代Target函数的函数。 ---- Detours在Target函数的开头加入JMP Address_of_ Detour_ Function指令(共5个字节)把对Target函数的调用引导到自己的Detour函数, 把Target函数的开头的5个字节加上JMP Address_of_ Target _ Function+5作为Trampoline函数。例子如下: 拦截前:Target _ Function: ;Target函数入口,以下为假想的常见的子程序入口代码 push ebp mov ebp, esp push eax push ebx Trampoline: ;以下是Target函数的继续部分 …… 拦截后: Target _ Function: jmp Detour_Function Trampoline: ;以下是Target函数的继续部分 …… Trampoline_Function: ; Trampoline函数入口, 开头的5个字节与Target函数相同 push ebp mov ebp, esp push eax push ebx ;跳回去继续执行Target函数 jmp Target_Function+5 ---- 3. 为一个已在运行的进程装入一个DLL ---- 以下是其步骤: ---- (1) 创建一个ThreadFuction,内容仅是调用LoadLibrary。 ---- (2) 用VirtualAllocEx为一个已在运行的进程分配一片虚存,并把权限更改为可读可写可执行。 ---- (3) 把ThreadFuction的二进制机器码写入这片虚存。 ---- (4) 用CreateRemoteThread在该进程上创建一个线程,传入前面分配的虚存的起始地址作为线程函数的地址,即可为一个已在运行的进程装入一个DLL。通过DllMain 即可在一个已在运行的进程中运行自己的代码。 二. Detours库函数的用法 ---- 因为Detours软件包并没有附带帮助文件,以下接口仅从剖析源代码得出。 ---- 1. PBYTE WINAPI DetourFindFunction(PCHAR pszModule, PCHAR pszFunction) ---- 功能:从一DLL中找出一函数的入口地址 ---- 参数:pszModule是DLL名,pszFunction是函数名。 ---- 返回:名为pszModule的DLL的名为pszFunction的函数的入口地址 ---- 说明:DetourFindFunctio
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值