我在分析某程序时经常会看到这段代码被调用,而据我分析这段代码只是在堆上分配了一些内存,并将该内存提供给上一调用者使用
120077F0 /$ 51 push ecx
120077F1 |. 8D4C24 04 lea ecx,dword ptr ss:[esp+4]
120077F5 |. 2BC8 sub ecx,eax
120077F7 |. 1BC0 sbb eax,eax
120077F9 |. F7D0 not eax
120077FB |. 23C8 and ecx,eax
120077FD |. 8BC4 mov eax,esp
##[1]## 这里不解,与0xfffff000与之后,我原以为是对齐到4KB字节的边界但
120077FF |. 25 00F0FFFF and eax,FFFFF000
12007804 |> 3BC8 /cmp ecx,eax
12007806 |. 72 0A |jb short yb_mem.12007812
这里将ecx值放入eax后直接与esp交换,好像和4KB边界没什么关系
所以这个循环很奇怪,搞不懂为啥这样写
12007808 |. 8BC1 |mov eax,ecx
1200780A |. 59 |pop ecx
1200780B |. 94 |xchg eax,esp
1200780C |. 8B00 |mov eax,dword ptr ds:[eax]
1200780E |. 890424 |mov dword ptr ss:[esp],eax
12007811 |. C3 |retn
12007812 |> 2D 00100000 |sub eax,1000
12007817 |. 8500 |test dword ptr ds:[eax],eax
12007819 \.^ EB E9 \jmp short yb_mem.12007804
另一个函数,调用上面的函数
12002040 <>/$ 6A FF push -1
12002042 |. 68 67650112 push yb_mem.12016567
12002047 |. 64:A1 00000000 mov eax,dword ptr fs:[0]
1200204D |. 50 push eax
1200204E |. B8 44280000 mov eax,2844
以上的函数在这里被调用,通过寄存器EAX 传值
12002053 |. E8 98570000 call yb_mem.120077F0
g_StackKey1是在初始化时生成的某随机值,之后不变
##2## 还有这里也很奇怪
12002058 |. A1 78C10112 mov eax,dword ptr ds:[<g_StackKey1>]
1200205D |. 33C4 xor eax,esp
1200205F |. 898424 40280000 mov dword ptr ss:[esp+2840],eax
...
...
...
上面2号位置的值最终在这里取出,再次异或esp,再与g_StackKey1比较
1200230B |. 8B8C24 40280000 mov ecx,dword ptr ss:[esp+2840]
12002312 |. 33CC xor ecx,esp
xxxxxxxx 3B0D 78C10112 cmp ecx,dword ptr ds:[<g_StackKey1>]
xxxxxxxx . 75 02 jnz short yb_mem.12006A60
...
函数结束
问题: ##1##位置为什么要与0xfffff000异或?是为了4KB字节边界对齐吗?
但eax小于ecx后,又将esp指向ecx,循环似乎没什么用啊?
##2##位置与esp异或,结束后再异或得到原来值,再比较是否确实为原值。我觉得肯定会是原值啊,不然堆栈没有正确释放会影响下一个函数执行。但如果和原值不同,将跳到另一个地方去执行,那里的代码调用了IsDebuggerPresent,不过返回值不重要,只要跳过去,最终调用了TerminateProcess. 能帮忙解释下这样做的用途吗?
小弟刚接触这方面半年,盼有朋友指点一二,谢谢!!
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课