Detours3.0 文档翻译
http://blog.csdn.net/buck84/article/details/8289991
拦截二进制函数
Detours库能够在执行过程中动态拦截函数调用。detours将目标函数前几个指令替换为一个无条件跳转,跳转到用户定义的detour函数。被拦截的函数保存在trampoline函数中。trampoline保存了目标函数移除的指令和一个无条件跳转,能够跳转到目标函数的执行体部分(未被移除的部分)。
当运行到目标函数的时候,直接跳转到用户提供的detours拦截函数。拦截函数開始运行自己的代码。
detour函数能够直接返回或调用trampoline函数,将流程返回到拦截前。当目标函数运行完以后,再将控制交给detour函数。detour函数运行适当的代码返回。下图分别表示没有拦截和拦截以后的运行流程:
detours库通过在目标进程二进制映像中写入指令进行拦截。
对于目标函数。detours实际上写入两个函数。目标函数和trampoline函数,以及一个函数指针pointer(怀疑文档中有错误)。trampoline函数由detours动态分配。拦截之前,trampoline仅仅包括一条跳转到目标函数的语句。拦截以后。trampoline包括目标函数的初始几条语句和跳转到目标函数剩余内容的跳转指令。
目标指针最初被初始化为指向目标函数。
用detour依附(attach)到目标函数以后。目标指针就被改动为指向trampoline函数。当detour从目标函数分离(detach)以后,目标指针像開始一样指向目标函数。
上图展示了detours拦截过程。为了拦截目标函数,首先为动态trampoline函数分配内存(假设没有静态的trampoline),然后改动目标函数和trampoline为可写。
拦截的第一步,detours从目标函数中复制至少5字节指令到trampoline(足够一条无条件跳转指令)。假设目标函数小于5字节,detours退出并返回一个错误码
复制指令的过程中,detours採用了一种简单的表格驱动反汇编器。detours在trampoline最后加入一条跳转命令,跳转到目标函数第一条没有被复制的指令处。detours在目标函数的第一条指令处写入一条无条件跳转指令,跳转到detour函数中。最后,detours将目标函数和trampoline函数恢复为原始状态,然后通过调用借口FlushInstructionCache刷新cpu指令缓存。
使用Detours
为了detour目标函数,须要一个指向目标函数的指针和一个detour函数。为了可以正确拦截目标函数,detour函数和目标指针的调用规则须要一致,包含參数和调用规则。调用规则一致确保寄存器能正确保存。detour和目标函数的栈可以合理分配。
以下的代码描写叙述了detours库的用法,用户必须包括头文件detours.h,连接过程包括库detours.lib
- #include <windows.h>
- #include <detours.h>
- static LONG dwSlept = 0;
- // Target pointer for the uninstrumented Sleep API.
- //
- static VOID (WINAPI * TrueSleep)(DWORD dwMilliseconds) = Sleep;
- // Detour function that replaces the Sleep API.
- //
- VOID WINAPI TimedSleep(DWORD dwMilliseconds)
- {
- // Save the before and after times around calling the Sleep API.
- DWORD dwBeg = GetTickCount();
- TrueSleep(dwMilliseconds);
- DWORD dwEnd = GetTickCount();
- InterlockedExchangeAdd(&dwSlept, dwEnd - dwBeg);
- }
- // DllMain function attaches and detaches the TimedSleep detour to the
- // Sleep target function. The Sleep target function is referred to
- // through the TrueSleep target pointer.
- //
- BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
- {
- if (DetourIsHelperProcess()) {
- return TRUE;
- }
- if (dwReason == DLL_PROCESS_ATTACH) {
- DetourRestoreAfterWith();
- DetourTransactionBegin();
- DetourUpdateThread(GetCurrentThread());
- DetourAttach(&(PVOID&)TrueSleep, TimedSleep);
- DetourTransactionCommit();
- }
- else if (dwReason == DLL_PROCESS_DETACH) {
- DetourTransactionBegin();
- DetourUpdateThread(GetCurrentThread());
- DetourDetach(&(PVOID&)TrueSleep, TimedSleep);
- DetourTransactionCommit();
- }
- return TRUE;
- }
拦截目标函数通过与detour交互,调用DetourAttach实现。与detour的交互通过调用DetourTransactionBegin和DetourTransactionCommit实现。
DetourAttach包括2个參数:目标函数指针的地址和detour函数地址。
目标函数不能直接作为參数传入。由于须要传入一个目标指针。
交互过程中DetourUpdateThread更新全部线程。确保全部拦截点都能正确更新。
DetourAttach为调用目标函数分配并准备好一个trampoline。
detour执行以后,目标函数和trampoline会被重写。目标指针被更新。指向trampoline函数。
一旦目标函数被detour,目标函数的调用会被转到detour函数。目标函数通过trampoline被运行的时候。detour函数将參数复制过来,由于如今目标函数变成了detour函数的一个子程序。
要想移除拦截。能够调用detoursDetach。与DetourAttach类似,DetourDetach包括两个參数:目标函数指针地址和detour函数指针。函数运行以后。目标函数被重写为其原来的状态。trampoline函数被删除,目标函数指针恢复为原来的目标函数。
假设须要拦截的程序没有源码。detour函数须要打包为一个dll。
将dll载入到一个新的进程中。进程启动的时候调用DetourCreateProcessWithDllEx载入dll。
假设通过调用DetourCreateProcessWithDllEx插入dll,DllMain函数必须调用DetourRestoreAfterWith函数。假设希望dll可以在32位和64为机器上使用,DllMain必须调用DetourIsHelperProcess函数。
Dll必须导出DetourFinishHelperProcess函数.
注意:微软不保证或支持不论什么被改动的微软或第三方的代码,无论是採用detour改动还是其他方式改动。
detours自带样例withdll採用DetourCreateProcesswithDllEx函数启动一个新进程加载一个命名dll
Payloads和DLL导入编辑
除了连接和分离detours函数,detours包还提供了注入其它数据段的API,如二进制文件,或改动dll导入表,叫做payloads。Detours中的二进制改动API是全然可逆的,Detours在二进制中保存了恢复信息。使得全部的改动都能够还原。
windowsPE格式的二进制文件结构如上图所看到的。PE格式的windows二进制文件时COFF格式(通用文件格式)的一个扩展。
windows二进制文件包括一个DOS兼容的头,PE头。包括代码的text段,包括初始化数据的data段,包括导入的dll和函数的导入表,包括代码导出函数的导出表,调试信息。二进制文件必须包括两个头,其他的段都是可选的。
为了改动windows二进制文件,Detours创建了一个.detours段,在导出表和调试符号中间,如上图所看到的。windows二进制文件必须把调试符号放在最后。
新的段包括一个detours头。和原始PE头的一份拷贝,假设改动导入表,detours创建一个新的导入表,将其放在复制的PE头后面,然后改动原始的PE头,将其指向新的导入表。最后,Detours在.detours段的最后写入用户的payloads,然后加上调试信息完毕文件。
改动后的windows二进制文件能够非常easy恢复:从.detours段中恢复PE头。移除.detours段。上图表示的是Detours改动过的windows二进制文件格式。
创建一个导入表有2个目的。首先是保持原始的导入表不变,以便以后恢复文件,其次,新建的导入表包括重命名的导入DLL和函数,或者是整个dll和函数。比如。detours保的样例中setdll.exe这个程序。讲一个用户dll插入到目标二进制程序中。因为新的导入表在应用程序中第一个位置。所以用户的dll在程序中会首先被运行。
Detours提供了非常多实用接口。包含编辑导入表(DetourBinaryEditImports)。加入payloads(DetourBinarySetPayload)。枚举payloads(DetourBinaryEnumeratePayloads),移除payloads(DetourBinaryPurgePayloads)。DetourEnumerateModules能够枚举一个地址空间中的二进制文件。DetourFindPayload能够定位二进制文件里映射的payloads。每个payload通过一个128位的guid表示。
payloads能够将程序配置数据注入到二进制程序中。
DetourCopyPayloadToProcess能够直接将Payloads拷贝到目标进程
Detour 32位和64位进程
注意:仅仅有专业版的Detours支持64位程序。非商业版,express版本号仅仅支持32位x86系统
detours最常见的使用情况是在不改动原始二进制程序的情况下的改变函数运行情况。这时。用户提供的detour函数打包到一个dll中,在程序运行開始的时候调用DetourCreateProcesswithDll载入该dll。父进程调用DetourCreateProcesswithDll,通过插入一个导入表来改变程序内存中的拷贝。新的插入表使得系统在程序開始的时候,程序逻辑代码还没有运行的时候载入dll。这样deoturDLL就能够hook目标进程中的目标函数。
在64位的处理器上。windows支持32位或64位的应用程序。
为了支持32位或64位程序。须要创建32位和64位的detourDLL。
调用DetourCreateProcessWithDll的地方须要改为DetourCreateProcessWithDllEx。DetourCreateProcessWithDllEx会依据系统选择合适的Dll来注入目标程序。
须要这样做:
为了在一个系统上支持32位和64位程序,须要创建2个DLL。一个包括32位代码,还有一个包括64位代码。
两个DLL放在同一个文件夹中而且起同样的名字。并加上对应的后缀“32”和“64”,比方foo32.dll和foo64.dll。
调用DetourCreateProcessWithDllEx来启动一个包括对应DLL的进程。另外,你的DLL须要:
1.导出DetourFinishHelperProcess
2.在DllMain中调用DetourIsHelperProcess。假设DetourIsHelperProcess返回TRUE。则立即返回TRUE。
3.通过调用DetourCreateProcessWithDllEx而不是DetourCreateProcessWithDll来创建新的进程。
工作原理
假设目标进程跟dll的父进程同为32位或同为64位,DetourCreateProcessWithDllEx执行过程类似DetourCreateProcessWithDll。
假设父进程与目标进程不同,一个是32位,一个是64位,DetourCreateProcessWithDllEx会创建一个辅助进程。将DLL载入到rundll32.exe进程,然后调用DetourFinishHelperProcess。这个API通过使用正确的32位或64位代码来修补导入表。
应用演示样例
以下測试辅助进程,首先在32位环境中编译Detours样例。然后在64位环境中编译64位样例。然后进入样例中\tryman文件夹,在64位环境中输入"nmake size64",这样能够递归执行进程。包含32位和64位进程。
附注
关于rundll32.exe,请參考http://support.microsoft.com/kb/164787
Detours3.0 文档翻译的更多相关文章
- detours3.0文档翻译
拦截二进制函数 Detours库可以在运行过程中动态拦截函数调用.detours将目标函数前几个指令替换为一个无条件跳转,跳转到用户定义的detour函数.被拦截的函数保存在trampoline函数中 ...
- WIN7下VS2008生成Detours3.0
Detours是微软开发的一个函数库,可用于捕获系统API.在用其进行程序开发之前,得做一些准备工作: 一.下载Detours 在http://research.microsoft.com ...
- 使用detours实现劫持
第一步:下载detours3.0,安装detours 第二步:构建库文件,nmake编译 第三步:包含库文件和头文件 #include "detours.h" //载入头文件 #p ...
- Detours信息泄漏漏洞
v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...
- Detours修改段属性漏洞
v:* { } o:* { } w:* { } .shape { }p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-botto ...
- Detours改动段属性漏洞
v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...
- detours编译与windows下makefile学习
1.编译 windows环境命令行编译很少用,detours需要使用命令行编译,刚好试试,过程如下: 1.为了能够在所有目录中使用nmake命令,需要设置环境变量Path D:\Program Fil ...
- detours学习
最近学习detours3.0,总结下学习过程,给后来学习者一点参考,也便于自己以后复习 首先应该知道detours可以干什么,学习之前最好看一下detours文档,这个文档很简单,只有4篇文章,相对比 ...
- ZAM 3D 制作简单的3D字幕 流程(二)
原地址:http://www.cnblogs.com/yk250/p/5663907.html 文中表述仅为本人理解,若有偏差和错误请指正! 接着 ZAM 3D 制作简单的3D字幕 流程(一) .本篇 ...
随机推荐
- 24深入理解C指针之---指针和数组
一.指针和数组 #include <stdio.h> int main(int argc, char **argv) { ] = {, , , , ,}; int *ptrVector = ...
- XOCDE5开发
一.XCODE5以后,file's owner取消,那么table view的数据源和委托应该指向哪里呢,答案是指向view control那里,当然了,view control必须与相应继承了数据源 ...
- Java原来如此-随机数
在Java中,生成随机数有两种方法.1是使用Random类.2是使用Math类中的random方法. 我们现在做个例子,比如生成20个0到10之间的随机数. 1.使用Random类的nextInt(n ...
- TCP11种状态
2.全部11种状态 2.1.客户端独有的:(1)SYN_SENT (2)FIN_WAIT1 (3)FIN_WAIT2 (4)CLOSING (5)TIME_WAIT . 2.2.服务器独有的:(1)L ...
- REBXOR
题面 Description 给定一个含N个元素的数组A,下标从1开始.请找出下面式子的最大值. (A[l1]xorA[l2+1]xor-xorA[r1])+(A[l2]xorA[l2+1]xor-x ...
- 电影TS/TC/SCR/R5/BD/HD/HC版本意思收集(转)
一.版本说明: 1.CAM(枪版) CAM通常是用数码摄像机从电影院盗录.有时会使用小三角架,但大多数时候不可能使用,所以摄像机会抖动.因此我们看到画面通常偏暗人物常常会失真,下方的 字幕时常会出现倾 ...
- JRoll 2 使用文档(史上最强大的下拉刷新,滚动,无限加载插件)
概述 说明 JRoll,一款能滚起上万条数据,具有滑动加速.回弹.缩放.滚动条.滑动事件等功能,兼容CommonJS/AMD/CMD模块规范,开源,免费的轻量级html5滚动插件. JRoll第二版是 ...
- objective-c 类目(Category)和延展(Extension)
类目的基本概念: 如果有封装好的一个类,随着程序功能的增加,需要在类中增加一个方法,那我们就不必在那个类中做修改或者再定义一个子类,只需要在用到那个方法时添加一个该类的类目即可. 1.在类目定义的方法 ...
- 【mac IntelliJ Idea】mac上 idea快速重写父类方法 快捷键
windows上快捷键: Ctrl+O Mac上快捷键: command+O 在要重写父类方法的位置 ,按下快捷键,然后选择要重写的方法即可.
- word中更改图片和标题之间的垂直距离
word中插入图片后.往往须要给图片加上标题. 你插入图片和给图片插入标题时,word用的是默认的格式给你插入的图片和标题. 假如原来的paragraph是2倍行距.你的图片和标题之间的距离也是2倍行 ...