您的位置:首页 > 其它

通过call指令看静态IAT HOOK 实践EPO

2011-02-11 19:29 555 查看
Call的几种不同形式
序号
指令
反汇编
含义
1
FF D7
Call edi
Call reg/call [reg+xx]
2
E8 68F9FEFF
call
01001F51
Call 立即数
3
FF15 EC110001
call
dword ptr [10011EC]
Call dowrd ptr[立即数]
FF指令

01013FE6    FFD0            call    eax
01013FE8    FFD3            call    ebx
01013FEA    FFD1            call    ecx
01013FEC    FFD2            call    edx
01013FEE    FFD7            call    edi
01013FF0    FFD6            call    esi
01013FF2    FF10            call    dword ptr [eax]
01013FF4    FF93 10325476   call    dword ptr [ebx+76543210]
由此可见依FF为特征码的call都是于寄存器打交道的,而且其后缀部分长度不易确定



F8与FF15


01013FB0    E8 6C036486     call    87654321
01013FB5    E8 47C0FEFE     call    00000001
01013FBA    E8 53509081     call    82919012
01013FBF    90              nop
01013FC0    FF15 65769800   call    dword ptr [987665]
01013FC6    FF15 99999999   call    dword ptr [99999999]
01013FCC    FF15 00000000   call    dword ptr [0]
依F8与FF15为特征码的call 其后缀长度都是占sizeof(DWORD)大小



而由于PE调用的时候都是采用
Call dword ptr[xx00]
而xxoo在IAT中

所以
EPO
(EntryPoint Obscuring)
入口模糊技术的时候
我采用办法是
eop + xx()这里我从xx>=20开始搜索太小的话杀软扫描力度要大一些
我从一个偏值开始查找
FF 15
YYYY

然后判断YYYY是否在IAT返回内
如果是则表明该callcall
api

我们可以将YYY修改为我们的目标代码 ZZZ
执行完之后jmp 回到YYY

实践

通过搜索 call
dword ptr[立即数]


FF 15 XX XX XX XX

然后判断XXXXXXXX在IAT范围内以后开始修改
修改的流程如下
依call dword ptr [10011F4]为例
此处的代码如下
0101256B FF15 F4110001
call dword ptr [10011F4] ;
msvcrt.__getmainargs
01012571 8945 D0 mov dword ptr [ebp-30], eax
01012574 68 2C120001
push calc.0100122C
01012579 68 28120001 push
calc.01001228
修改为
0101256B E8 F0BF0000 call
0101E560
01012570 90 nop
01012571 8945 D0 mov dword ptr [ebp-30], eax
01012574 68 2C120001
push calc.0100122C
01012579 68 28120001 push
calc.01001228
关键点是将FF15 F4110001转换成了E8 F0BF0000
90
而0101E560处的代码为
0101E560 一段维持了堆栈平衡的shellcode
……
0101E564 - FF25 F4110001
jmp dword ptr [10011F4>;
msvcrt.__getmainargs
比如
0101E560 50 push eax
0101E561 58 pop eax
0101E562 53 push ebx
0101E563 5B pop ebx
0101E564 - FF25 F4110001
jmp dword ptr [10011F4>;
msvcrt.__getmainargs
这样程序的流程除了执行我们的代码意外 对原程序也不会有大的影响,如果我们替换的
指令不在循环范围呢 则也只执行一次,非常不错








今晚我对以上内容进行了实践 ,发现时可行的,准确率也很高,但是如果想达到高命中率需要巧妙的设定搜索范围,

而且最好不要局限于FF15 CALL 同样可以对FF25 jmp进行修改

但是发现这种方法有的函数HOOK 不杀 有的杀 所以还达不到我的要求

现在采用衍生方案

修改E8 CALL 然后判断E8后面的是否指向一个函数 如果是则进行修改

这种方案,比先前IAT静态HOOK的方案更加灵活多变

而如何判断E8后的立即数差值是否指向一个函数呢?



通过函数特征码
00401750 >  55              push    ebp
00401751    8BEC            mov     ebp, esp
这是一个最普通的函数的特征码
那么流程就是
1:搜索E8 CALL
2:通过CALL后的立即数差值与当前地址计算出目标函数基地址
3:判断基地址处的内容是否为55 8B EC
如果是则进行HOOK否则下一个
如果在搜索范围内找不到 则寻找下一个目标
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: