Detour安装及简单使用实例

Detours是微软开发的一个函数库,可用于捕获系统API。在用其进行程序开发之前,得做一些准备工作:

一.下载Detours
http://research.microsoft.com/sn/detours 可免费下载Detours
二.安装Detours
一路NEXT
三.生成Detours库
在安装后的文件夹下找不到直接可以拿来用的LIB文件,但是却有SRC文件(在**\Microsoft Research\Detours Express 2.1\src下)。该文件夹下还有Makefile,可以直接用来生成库。
将Detours路径下的SCR文件夹拷贝到**\Microsoft Visual Studio 9.0\VC路径下,注意是整个文件夹(其它版本VC自己照着复制)
运行cmd,(win7需要在system32目录找到cmd右键以管理员身份运行),切换至 c:\Program Files\Microsoft Visual Studio 9.0\VC\bin目录运行vcvars32.bat
切换到\Microsoft Visual Studio9.0\VC\SRC,然后输入..\bin\nmake指令,编译成功后在\Microsoft Visual Studio9.0\VC\Lib文件下就能找到detoured.lib与detours.lib文件了。

来看几个关键函数:

在Detours库中,驱动detours执行的是函数

LONG DetourAttach( PVOID * ppPointer, PVOID pDetour );


这个函数的职责是挂接目标API,函数的第一个参数是一个指向将要被挂接函数地址的函数指针,第二个参数是指向实际运行的函数的指针,一般来说是我们定义的替代函数的地址。但是,在挂接开始之前,还有以下几件事需要完成:
需要对detours进行初始化. DetourTransactionBegin()
需要更新进行detours的线程. DetourUpdateThread(GetCurrentThread())
在这两件事做完以后,detour函数才是真正地附着到目标函数上。
在此之后,调用DetourTransactionCommit()是detour函数起作用并检查函数的返回值判断是正确还是错误。

想把HOOK的函数改回來则可以使用

LONG WINAPI DetourDetach( PVOID *ppPointer, PVOID pDetour)

参数与DetourAttach相同

付使用简单例子:HOOK MessageBoxW函数

#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; }

还有一個DetourCreateProcessWithDll函数,该函数是在以DLL注入方式拦截API时使用的,它其实就是封装“CreateProcess”,以“CREATE_SUSPEND”方式创建进程,然后修改IAT,把Detoured.dll和您的*.dll插入到它的导入表,然后再启动进程。所以它的参数就是在普通的CreateProcess基础上增加了两个DLL的路径参数,最后一个参数为创建进程的函数指针,默认为CreateProcessA,简单的说就是可以在创建进程的時候加载一個dll吧

示例代码:

#undef UNICODE #include <cstdio> #include <windows.h> #include <detours\detours.h> int main() { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(STARTUPINFO)); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); si.cb = sizeof(STARTUPINFO); char* DirPath = new char[MAX_PATH]; char* DLLPath = new char[MAX_PATH]; //testdll.dll char* DetourPath = new char[MAX_PATH]; //detoured.dll GetCurrentDirectory(MAX_PATH, DirPath); sprintf_s(DLLPath, MAX_PATH, "%s\\testdll.dll", DirPath); sprintf_s(DetourPath, MAX_PATH, "%s\\detoured.dll", DirPath); DetourCreateProcessWithDll(NULL, "C:\\windows\\notepad.exe", NULL,NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL,&si, &pi, DetourPath, DLLPath, NULL); delete [] DirPath; delete [] DLLPath; delete [] DetourPath; return 0; }


当我们需要hook的函数既不是一个标准的WIN32 API,也不是导出函数。这时我们需要把我们的程序和被所要注入的程序同时编译,或者,把函数的地址硬编码:

#undef UNICODE #include <cstdio> #include <windows.h> #include <detours\detours.h> typedef void (WINAPI *pFunc)(DWORD); void WINAPI MyFunc(DWORD); pFunc FuncToDetour = (pFunc)(0x0100347C); //Set it at address to detour in //the process INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) { switch(Reason) { case DLL_PROCESS_ATTACH: { DisableThreadLibraryCalls(hDLL); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourAttach(&(PVOID&)FuncToDetour, MyFunc); DetourTransactionCommit(); } break; case DLL_PROCESS_DETACH: DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&(PVOID&)FuncToDetour, MyFunc); DetourTransactionCommit(); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break; } return TRUE; } void WINAPI MyFunc(DWORD someParameter) { //Some magic can happen here }
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名,pszFun
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值