-
-
如何阻击“ESP定律”?
-
发表于:
2005-1-21 15:43
9823
-
如何阻击“ESP定律”?
作者:jney2
喜欢Crack,也关注加密手段。
首先,感谢kanxue终于推出了我苦苦等待的看雪学院论坛精华6,惊喜中居然还是五周年纪念收藏版。粗略了一下,精华6是分量足,精华多呀!
个人感觉Crack界变化较大的有三:1、Cracker队伍不断壮大,高手不断涌现;2、脱壳日益成为Cracker的必修功课;3、OllyDbg日益成为Cracker的首选调试工具。
OllyDbg,我一直用它!OllyDbg我选择,我喜欢!
其次,我来说一下“ESP定律”。
在五周年纪念收藏版中搜索“ESP定律”即可找到25篇文章,要了解“ESP定律”有3篇文章必看:
1、fly的(论坛里fly的印象给我最深了)《ESP定律 + 壹锅端――另类ACProtect V1.20壳的简便脱壳And修复方法》(2004年2月19日 03:46)。这篇文章首提“ESP定律”,相信老鸟一看就懂。我看了是有一种豁然开朗的感觉,我怎么没想到在我心爱的OllyDbg中可以这样下断呢?2、Lenus的《寻找真正的入口(OEP)--广义ESP定律》(不知由哪位仁兄转帖2004-09-14,15:43)。这篇文章具有释疑、解惑之功效,我等菜鸟是一看就懂,也更加明白什么是“堆栈平衡”原理。3、cater的《ESP 脱壳 个人小节》(2004-08-31,09:09)。这篇文章简直就是Cracker的众多加密软件的“ESP定律”应用宝典。在这里,无论Cracker还是软件加密者都可以看到“ESP定律”的存在已是众多加密软件的致命伤之一。
第三、如何阻击“ESP定律”?
“ESP定律”之所以存在,就是因为“堆栈平衡”原理。要是违反了这一原理,程序就无法正常运行。然尔学过汇编的人都应当知道以下几点的:1、堆栈是可以改变的;2、堆栈指针是可以改变的;3、堆栈内容是可以复制的;4、堆栈内容也是可以加密的;5、操作堆栈更是极其危险的。你也许会说,堆栈内容复制还要访问原始堆栈地址,还是要断下的,但我可在保护现场之后马上进行,然后再解壳,再改变堆栈指针。并且刚开始的堆栈内容不多,可以连续复制若干份,恢复时随机取一份,防止Cracker在新的位置下断。对堆栈内容加密也是可取的。这样“ESP定律”即使应用了也收效不大,有效的防止了快速脱壳。
还有,我做过试验,有些壳不恢复现场也还能正常运行,可见刚开始的堆栈平衡”并不十分重要。当然,这样的危险系数还是蛮大的。
第四、我的实例简单实现。
1、 UPX加壳记事本,这是大家最熟悉的壳了。
原始壳:
01014FE0 > 60 PUSHAD
01014FE1 BE 00100101 MOV ESI,notepad.01011000
01014FE6 8DBE 0000FFFF LEA EDI,DWORD PTR DS:[ESI+FFFF0000]
01014FEC 57 PUSH EDI
01014FED 83CD FF OR EBP,FFFFFFFF
01014FF0 EB 10 JMP SHORT notepad.01015002
01014FF2 90 NOP
01014FF3 90 NOP
01014FF4 90 NOP
01014FF5 90 NOP
01014FF6 90 NOP
01014FF7 90 NOP
刚好这里有6个90字节,可加入如下调用指令:
01014FF0 E8 75010000 CALL notepad .0101516A
01014FF5 90 NOP
01014FF6 EB 0A JMP SHORT notepad.01015002
0101516a处是连续的0字节:
01015168 0000 ADD BYTE PTR DS:[EAX],AL //用来保持复制后的指针位置;
以下复制堆栈内容到新置;
0101516A 60 PUSHAD
0101516B 8BFC MOV EDI,ESP
0101516D 81EF 00000100 SUB EDI,10000 ; UNICODE "=::=::\"
01015173 8BF4 MOV ESI,ESP
01015175 B9 40000000 MOV ECX,40
0101517A 893D 68510101 MOV DWORD PTR DS:[1015168],EDI
01015180 36:8B06 MOV EAX,DWORD PTR SS:[ESI]
01015183 36:8907 MOV DWORD PTR SS:[EDI],EAX
01015186 83C7 04 ADD EDI,4
01015189 83C6 04 ADD ESI,4
0101518C ^ E2 F2 LOOPD SHORT notepad.01015180
0101518E 61 POPAD
0101518F C3 RETN
原壳转到OEP处的代码:
0101512E 61 POPAD
0101512F - E9 AC19FFFF JMP notepad.01006AE0
01015134 0000 ADD BYTE PTR DS:[EAX],AL
01015136 0000 ADD BYTE PTR DS:[EAX],AL
01015138 0000 ADD BYTE PTR DS:[EAX],AL
修改为:
0101512E 8BF4 MOV ESI,ESP
01015130 81EE 00010000 SUB ESI,100
01015136 8B3D 68510101 MOV EDI,DWORD PTR DS:[1015168]
0101513C B9 40000000 MOV ECX,40
01015141 36:8B07 MOV EAX,DWORD PTR SS:[EDI]
01015144 36:8906 MOV DWORD PTR SS:[ESI],EAX
01015147 83C6 04 ADD ESI,4
0101514A 83C7 04 ADD EDI,4
0101514D ^ E2 F2 LOOPD SHORT notepad.01015141
0101514F 8BD4 MOV EDX,ESP
01015151 81EA 00010000 SUB EDX,100
01015157 83C2 28 ADD EDX,28
0101515A 8BE2 MOV ESP,EDX
0101515C 61 POPAD
0101515D 68 E06A0001 PUSH notepad1.01006AE0
01015162 C3 RETN
以上代码完成堆栈内容转移,指针调整,转到OEP处的功能。
第五、完成如上修改只是对我的构想最简单的实现,其实还有很多需要改进和注意的地方,在此只不过抛砖引玉,希望高手也来谈谈自己的感想和经验。
附修改后的Notepad
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)