首页
社区
课程
招聘
接着讲和DLL与代码插入有关的几点看法
发表于: 2006-8-5 18:40 10383

接着讲和DLL与代码插入有关的几点看法

2006-8-5 18:40
10383

?微软的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都未必看得出来。
*****

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


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (9)
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
2
讲的很专业,继续学习
2006-8-5 19:06
0
雪    币: 415
活跃值: (34)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
关注device driver
2006-8-5 20:42
0
雪    币: 248
活跃值: (1096)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
精辟!
以前看到别人用FlushInstructionCache(),不知为何?现在了解了一点。
有几点不明白:

1. MS用下材料添充API:
;        lea     esp,[esp+0]        ; 8DA42400000000 ; 7 bytes
;        lea     ebx,[ebx+0]        ; 8D9B00000000 ; 6 bytes
;        add     eax,0                   ; 0500000000 ; 5 bytes
;        lea     esp,[esp]        ; 8D642400 ; 4 bytes
;        lea     ecx,[ecx]        ; 8D4900 ; 3 bytes
;        mov     edi,edi                ; 8BFF ; 2 bytes
;        nop                                 ; 90 ; 1 byte
为什么不用全NOP?

2. 有小于5BYTES的API吗?

3. 热补有三个功能:
   3.1 修改输入参数,执行原API;
   3.2 执行原API,修改输出参数;
   3.3 执行新功能,不执行原API。
为何第三条路不可行?
2006-8-5 22:04
0
雪    币: 139
活跃值: (126)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
5
1。你用debugger看过你的detours过的程序吗?我没有注意到微软的程序用这些指令来“填充”API。我看到的就是一个JUMP,干嘛要填这些指令?不明白你的问题。

2。Win32 API是没有,但是记住API patching是不仅仅局限于Windows的API的,如果你有dbghelp.dll和你的程序的pdb符号文件,你可以甚至调试你自己的内部函数。小于5 bytes的函数是一个极端情况

3。你可以做呀,只是这样你想达到什么效果?让该API完全失效?
2006-8-6 01:12
0
雪    币: 139
活跃值: (126)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
6
我感觉不能patch一些和同步有关的API,比如WaitForSingleObject(Ex) / WaitForMultipleObjects(Ex),否则会死锁的可能原因是:

在我们的thread要patch那些API时,系统会自动产生一个锁来保证对内存的写访问是线性化的(serializable),而这个锁本身就会调用比如说WaitForSingleObject(Ex),从而造成死锁。毕竟看不到Windows的源程序,只能猜了。
2006-8-6 01:29
0
雪    币: 248
活跃值: (1096)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
iterasm MACRO n
    lea   edx, [eax+(1 SHL n)]
    lea   ebx, [eax+(2 SHL n)]
    shl   edx, n
    mov   esi, ecx
    sub   ecx, edx
    cmovnc eax, ebx
    cmovc ecx, esi
ENDM

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

align 4
;============================
isqrt proc arg:DWORD
    mov   ecx, [esp+4]          ; arg
    push  ebx                   ; save as per calling convention
    push  esi                   ; save as per calling convention
    xor   eax, eax              ; 2*root
    ; iteration 15
    mov   ebx, 2 SHL 15
    mov   esi, ecx
    sub   ecx, 1 SHL 30
    cmovnc eax, ebx
    cmovc ecx, esi
    iterasm 14
    iterasm 13
    iterasm 12
    iterasm 11
    iterasm 10
    iterasm 9
    iterasm 8
    iterasm 7
    iterasm 6
    iterasm 5
    iterasm 4
    iterasm 3
    iterasm 2
    iterasm 1
    ; iteration 0
    mov   edx, 1
    mov   ebx, 2
    add   edx, eax
    add   ebx, eax
    sub   ecx, edx
    cmovnc eax, ebx
    shr   eax, 1
    mov   esi, [esp]            ; restore as per calling convention
    mov   ebx, [esp+4]          ; restore as per calling convention
    add   esp, 8                ; remove temp variables
    ret   4                     ; pop one DWORD arg and return
isqrt endp
;======================================
我看到的就是一个JUMP,干嘛要填这些指令?不明白你的问题。

再追,你会看到上述指令。至于为什么,这是align产生的效果,我猜东西放整齐、规则,总是好取好放。
至于为什么这样替换,这是老外的回答:
"Interesting that they chose an instruction like "mov edi, edi" instead of just
two NOPs. Then again, you need a two-byte instruction to make sure no thread is
about to execute NOP#2 when the jump-destination is written."
我没搞懂。

只是这样你想达到什么效果?让该API完全失效?

当你看到许多VIRUS SOURCE CODE中的shit_it PROC,其效果恰如其分。
如:当谁在调试、中断、修改、删除等操作时。
2006-8-6 09:08
0
雪    币: 249
活跃值: (10)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
8
楼主好赖皮亚, 呵呵
2006-8-6 15:15
0
雪    币: 217
活跃值: (99)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
最初由 sixL 发布
"Interesting that they chose an instruction like "mov edi, edi" instead of just
two NOPs. Then again, you need a two-byte instruction to make sure no thread is
about to execute NOP#2 when the jump-destination is written."
我没搞懂。

嗯,意思就是线程恰好suspend在第2个nop指令的时候patch那2个字节就会导致crash,而单指令就不会出现这个问题.
2006-8-6 23:31
0
雪    币: 248
活跃值: (1096)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
意思就是线程恰好suspend在第2个nop指令的时候patch那2个字节就会导致crash,而单指令就不会出现这个问题.

谢。
2006-8-6 23:43
0
游客
登录 | 注册 方可回帖
返回
//