?微软的detours本质上和一些trojan的方法是一样的,只不过它的本意是用来帮助调试程序。如果你的程序调用一些API后并不判断返回的结果和一些可能的出错情况,就可能会crash。他的目的就是帮助你的程序多崩溃几次,让你别太得意。

进程内的API hooking一般有两种:patch Import Table,将主程序的输入函数的入口地址改成你自己的,几年前的病毒和木马爱用,相对简单一些;一种就是detours和不少木马的direct function entry point patching,通过查找对应DLL的输出函数表得到API的起始点,然后简单地反汇编和判断一下,一般保留开始的5个byte(也可能更多),然后从起始点改成JUMP(E9 xxxx xxxx)到你的函数点去执行。所以如果原来的API还不到5个字节,你是没法改它的,否则你如何JUMP?

在你的函数里,可以有两条执行路径:

1。在你的函数执行完的RET之前,先执行你前面保留的原来的函数的入口点的指令,然后JUMP回原来的被patch的函数的后面一条指令继续执行。

2。先CALL原来的函数的指令继续执行,等到它返回后,在你的函数里做你想做的逻辑判断和运算,比如可能修改函数的返回值和error code,或者buffer里的内容等等,然后RET。


Direct function entry point patching(detours只是里面的一种)有它的先天缺陷,不能patch一些和同步有关的API,比如WaitForSingleObject(Ex) / WaitForMultipleObjects(Ex),否则会死锁。不信?你试试。原因?不知道

===================================

看看detours( http://research.microsoft.com/sn/detours/ )的例子程序就会明白,想把你的DLL放到目标程序的进程中去,可以有3种方法:

1。直接修改目标程序的磁盘文件,改动它的import table,把你的DLL放进去。一个例子就是detours的setdll示范程序。好处是快,你不用修改你的源程序;坏处是如果你的目标程序有相关的保护机制,比如加了数字签名(digital signature)或者各种hash,你只要改了一个byte,就会破坏它,程序里只要调用crypto API或者重新hash验证一把就会发现,让你的修改穿帮。

2。运行你的目标程序,CreateProcess(...,CREATE_SUSPENDED,...),然后修改你的目标进程的里的import table,把要插入的DLL放进去,然后ResumeThread。这和系统的PE Loader关系很大,对它更熟悉的大牛可以继续补充。前提条件是你要有足够的权限调用ReadProcessMemory/WriteProcessMemory察看和修改别的进程空间里的PE Image header,比如local administrator。detours的例子是withdll。更多的细节你可以在windbg或者ollydbg里慢慢看。

3。就是很多trojian爱用的,CreateRemoteThread。细节可参考MSDN,那里的说明最准确和详细。微软也不是傻瓜,XP SP2和windows2003 SP1就已经改进了不少,还在不停地打补丁。漏洞肯定还有很多,但长远看肯定是越补越少,和我们维护改进自己的程序是一个道理。不知道Vista上面还能不能用,等它正式出来后再看吧。这也就是为什么很多hacker开始打rootkit的注意,从kernel和device driver下手。user mode下的这些方法已经不太好使了。不少调试和测试软件用的手法和病毒木马是差不多的,只是目的不同而已。

方法3的主要缺点是不安全,因为是在别的进程的空间里,俩眼一抹黑,真是摸着石头过河。为什么呢?因为第一你不知道目标进程是不是多线程的(当然有办法,比如一些未公开的API,但肯定麻烦和不可靠),第二你不知道你创建的remote thread在patch某个API的时候,是不是有某个倒霉的thread正好执行到这个入口点上或者已经在函数里面(这是我的考虑,可能不对)。

*****
有一点是我到目前为止在google上所有能看得到的CreateRemoteThread方法的疏忽。就是你改动了某个API的入口点,但这仅仅是改动了内存里的代码,而现在计算机的CPU里一般至少有Level 1和Level 2 的多级指令缓存cache,cache里可能就有该函数的旧的入口点代码,可能就要被某个thread执行。指令的不一致性肯定不安全,最好在调用WriteProcessMemory()修改之前先CALL一把FlushInstructionCache()。否则在单CPU的机器上可能还不明显,在多核(multi-core)的机器上是早晚会撞到鬼的,崩溃了还不知道是怎么回事,查crash dump都未必看得出来。
*****

我这里主要是从程序设计和调试的角度谈问题,你想怎么用全看你自己。和扑克牌一样,我们既可以用来消遣,也可以来赌博。