<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[一米阳光【莫名奇妙】]]></title> 
<link>http://www.ymyg.net/blog/index.php</link> 
<description><![CDATA[源于一个没前途的程序员的懒散生活日志]]></description> 
<language>en-US</language> 
<copyright><![CDATA[一米阳光【莫名奇妙】]]></copyright>
<item>
<link>http://www.ymyg.net/blog/post/ESP-da-ding-lv-yuan-li.php</link>
<title><![CDATA[ESP大定律原理]]></title> 
<author>CEO &lt;ceo@ymyg.net&gt;</author>
<category><![CDATA[Cracker]]></category>
<pubDate>Wed, 07 Oct 2009 17:41:45 +0000</pubDate> 
<guid>http://www.ymyg.net/blog/post/ESP-da-ding-lv-yuan-li.php</guid> 
<description>
<![CDATA[ 
	<p><span style="color: #ff0000">1.call</span> <br />
这个命令是访问子程序的一个汇编基本指令。也许你说，这个我早就知道了！别急请继续看完。call真正的意义是什么呢？我们可以这样来理解： <br />
<br />
<br />
1.向堆栈中压入下一行程序的地址； <br />
<br />
2.JMP到call的子程序地址处。 <br />
例如： <br />
00401029.E8 DA240A00 call 004A3508 <br />
0040102E.5A pop edx <br />
在执行了00401029以后，程序会将0040102E压入堆栈，然后JMP到004A3508地址处！ <br />
<br />
<br />
<span style="color: #ff0000">2.RETN</span> <br />
与call对应的就是RETN了。对于RETN我们可以这样来理解： <br />
<br />
1.将当前的ESP中指向的地址出栈； <br />
<br />
2.JMP到这个地址。 <br />
这个就完成了一次调用子程序的过程。在这里关键的地方是：如果我们要返回父程序，则当我们在堆栈中进行堆栈的操作的时候，一定要保证在RETN这条指令之前，ESP指向的是我们压入栈中的地址。这也就是著名的&ldquo;堆栈平衡&rdquo;原理！ <br />
<br />
<br />
<span style="color: #cc00ff">3.狭义ESP定律</span> <br />
ESP定律的原理就是&ldquo;堆栈平衡&rdquo;原理。 <br />
<br />
<br />
<span style="color: #ff0033">让我们来到程序的入口处看看吧！ <br />
</span><br />
1.这个是加了ASPACK壳的入口时各个寄存器的值！ <br />
EAX 00000000 ECX 0012FFB0 EDX 7FFE0304 //堆栈值<br />
EBX 7FFDF000 //堆栈值 <br />
ESP 0012FFC4 <br />
EBP 0012FFF0 <br />
ESI 77F57D70 ntdll.77F57D70 <br />
EDI 77F944A8 ntdll.77F944A8 <br />
EIP 0040D000 ASPACK.<br />
<br />
2.这个是ASPACK壳JMP到OEP后的寄存器的值！ <br />
EAX 004010CC ASPACK.004010CC <br />
ECX 0012FFB0 <br />
EDX 7FFE0304 //堆栈值 <br />
EBX 7FFDF000 //堆栈值 <br />
ESP 0012FFC4 <br />
EBP 0012FFF0 <br />
ESI 77F57D70 ntdll.77F57D70 <br />
EDI 77F944A8 ntdll.77F944A8 <br />
EIP 004010CC ASPACK.004010CC <br />
呵呵~是不是除了EIP不同以外，eax保存当前OEP值，其他都一模一样啊！ <br />
为什么会这样呢？我们来看看 <br />
<br />
0040D000 A&gt; 60 pushad //注意这里ESP=0012FFC4 <br />
0040D001 E8 00000000 call ASPACK.0040D006 //ESP=0012FFA4 <br />
<br />
PUSHAD就是把所有寄存器压栈！我们在到壳的最后看看： <br />
<br />
0040D558 61 popad //ESP=0012FFA4 <br />
0040D559 75 08 jnz short ASPACK.0040D563 //注意这里ESP=0012FFC4 <br />
<br />
也就是说当我们对ESP的0012FFA4下硬件访问断点之后。当程序要通过堆栈访问这些值 <br />
，从而恢复原来寄存器的值，准备跳向苦苦寻觅的OEP的时候，OD帮助我们中断下来。 <br />
<br />
<br />
<span style="color: #ff0000">小结：</span>我们可以把壳假设为一个子程序，当壳把代码解压前和解压后，他必须要做的是遵循堆栈平衡的原理。 <br />
<br />
因为大家对ESP理解各有异同，但是，大同小异！一般理解可以为： <br />
<br />
1、在命令行下断hr esp-4（此时的ESP就是OD载入后当前显示的值） <br />
<br />
2、hr ESP(关键标志下一行代码所指示的ESP值(单步通过)) <br />
<br />
<br />
5.总结 <br />
<br />
现在我们可以轻松的回答一些问题了。 <br />
<br />
<br />
1.ESP定律的原理是什么？ <br />
堆栈平衡原理。 <br />
<br />
<br />
2.ESP定律的适用范围是什么？ <br />
几乎全部的压缩壳，部分加密壳。只要是在JMP到OEP后，ESP=0012FFC4的壳，理论上我们都可以使用。但是在何时下断点避开校验，何时下断OD才能断下来，这还需要多多总结和多多积累。 <br />
<br />
<br />
3.是不是只能下断12FFA4的访问断点？ <br />
<br />
当然不是，那只是ESP定律的一个体现，我们运用的是ESP定律的原理，而不应该是他的具体数值，不能说12FFA4，或者12FFC0就是ESP定律，他们只是ESP定律的一个应用罢了</p><br/>Tags - <a href="http://www.ymyg.net/blog/go.php/tags/esp%25E5%25A4%25A7%25E5%25AE%259A%25E5%25BE%258B%25E5%258E%259F%25E7%2590%2586/" rel="tag">esp大定律原理</a> , <a href="http://www.ymyg.net/blog/go.php/tags/esp%25E5%25AE%259A%25E5%25BE%258B/" rel="tag">esp定律</a> , <a href="http://www.ymyg.net/blog/go.php/tags/%25E8%2584%25B1%25E5%25A3%25B3/" rel="tag">脱壳</a>
]]>
</description>
</item><item>
<link>http://www.ymyg.net/blog/post/ESP-da-ding-lv-yuan-li.php#blogcomment</link>
<title><![CDATA[[Comments] ESP大定律原理]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[Comments]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://www.ymyg.net/blog/post/ESP-da-ding-lv-yuan-li.php#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>