逆向工程——二进制炸弹(第6关补完版)
2011-06-27 17:01
211 查看
最近收到THU的同学回复:第6关似乎应该是链表。我之前也很奇怪怎么最后一关会这么简单。于是找来最高难度的phase_6版本挑战一下。
phase_6的反汇编也确实够长了(差不多两页A4)。刚开始,真有点不知从何下手。先大致浏览一遍,唯一的印象是这段代码中跳转语句达到了12个,仅仅是这一条就会晕头转向了。
根据以往的经验,首先就是选出那些不该执行的语句(explode_bomb)。如图所示,黄线标出了引爆点。另外,既然跳转这么多,那就先来看看跳转,理出个大体结构。可以看到代码中跳转分成了两大类:1)条件跳转。2)直接跳转。而进一步分析,有些条件跳转是和callexplode_bomb相关的,而这条指令不该被执行,所以就又可以确定了某些条件跳转的方向。于是,红色箭头标出了确定的跳转方向,蓝色箭头标出5个条件跳转的不确定方向。
标出了跳转方向后,程序的大致结构就比较清晰了。根据这些跳转,可以把phase_6分成两大主要语句块(红色和绿色)。这时发现红色块执行到绿色块唯一的途径是蓝色跳转语句(1)(蓝1)。大致的结构分析完了,就深入程序看看吧。
首先由call8049112<read_six_numbers>可以知道要读入6个数。那问题就是怎样的6个数?
红色代码块:
由红色的代码块,我得出结论:这6个数<=6,且均不相等。
为什么这么说呢?由蓝2和最后一条jmp8048c77的大跳转,能想到什么,是不是有点像一个大循环嵌套了一个小循环呢?那为什么大跳转是用jmp而不是条件跳转。这时,想到了唯一跳转出红色大块的蓝1,可以猜想到了语句中用到了类似goto的语句(可见goto确实很会搅局,连分析起反汇编后的代码都很晦涩)。看到红色大块的前两条,感觉和输入数据有关,于是查看-0x24(%ebp)后知道是输入的第一个数据data[0],所以之后data[i]就存在了-0x24(%ebp,i,4)=-0x24(%ebp)+4i。由此可以推断%ebx应该是索引变量,而每次%eax=data[i]。再由代码块(a)得知data[i]<=6才行,否则就爆炸了。
再往下就是%edi=%ebx+1,%edi就是下一个索引,当到了索引5时就执行蓝1跳转。由此,可以先写个外层循环的大致框架:
[code]{
[/code]
之后的lea-0x24(%ebp,%ebx,4),%esi则是把当前数据的地址赋给%esi,即%esi=&data[i]。
[code]lea-0x24(%ebp),%eax//%eax=&data[0]
[/code]
往下读,jne8048cb1可知这两个数不能相等,否则就爆炸了。
最后看到代码块(b),每次%ebx+1,%esi+4,同时以%ebx<=5作为循环条件。根据蓝2的跳转,知道每次mov-0x4(%edx,%edi,4),%eax中的%edx和%edi是不变的,所以%eax==&data[0]+4(%edi–1),而%edi为外循环初始时的%ebx+1(因为内循环%ebx每次都在累加),所以%eax==&data[0]+4%ebx==&data[i]。
而每次%esi+4,而初始%esi=-0x24(%ebp,%ebx,4)=&data[i],所以cmp0x4(%esi),%eax依次遍历data[i]后面的数据。根据这些线索,我们可以写出内循环的框架:
[code]for(intj=i+1;;j<=5)
[/code]
最后的那条mov%edi,%ebx是把外层的循环变量复原,在此就在内外层用不同的两个变量了,最后写成C代码如下:
[code]{
[/code]
于是,根据以上的分析,我们就得出了最初的结论:这6个数<=6,且均不相等。
绿色代码:
这段代码很长,初看很没头绪。那怎么办呢?依然根据跳转语句来理出一些思路,希望能够分成更小的块,分而治之。于是我们有了四个更小的代码块c,d,e,f。
代码c:
可以知道,%ecx保存的是地址值,而%eax是一个循环变量。cmp-0x24(%ebp,%edx,4),%eax可知要取地址的次数为我们输入的数据。
代码d:
由-0x24(%ebp,%edx,4)可知%edx是索引变量。再由mov%ecx,-0x3c(%ebp,%edx,4)可知相应的地址(-0x3c(%ebp),-0x38(%ebp),-0x34(%ebp),-0x30(%ebp),-0x2c(%ebp),-0x28(%ebp))将被赋值(与代码e中的取地址对应)
根据对代码块d的理解,可以写出一个大致的c代码框架:
[code]{
[/code]
代码e:
举例来说:
[code]mov-0x38(%ebp),%eax
[/code]
可知,-0x38(%ebp)中的地址被放入了*(-0x3c(%ebp))+0x8中,而后的各步与此相似。相当于在做一个链表的链接功能。
代码f:
[code]mov(%ebx),%eax
[/code]
这三条语句可知这是当前节点的值(*%ebx)和下一个节点的值(*0x8(%ebx))在进行比较,而且当前节点的值必须大于等于下一个节点的值。由此可以写出一个c的代码框架:
[code]{
[/code]
由此,我们可以知道检查0x804a5fc及其之后0x8为步长的地址是关键。
由gdb查看得知:
*0x804a5fc=0x3b7
*(0x804a5fc+8)=0x804a5f0,*0x804a5f0=0x3c6
*(0x804a5f0+8)=0x804a5e4,*0x804a5e4=0x112
*(0x804a5e4+8)=0x804a5d8,*0x804a5d8=0x3a4
*(0x804a5d8+8)=0x804a5cc,*0x804a5cc=0x5a
*(0x804a5cc+8)=0x804a5c0,*0x804a5c0=0xfe
根据这个内存的检测,我们把值进行排序,以期符合代码f中的要求,得到(括号中为所属序号):
0x3c6(2)>0x3b7(1)>0x3a4(4)>0x112(3)>0xfe(6)>0x5a(5),根据其序号得出最后的答案:214365
phase_6的反汇编也确实够长了(差不多两页A4)。刚开始,真有点不知从何下手。先大致浏览一遍,唯一的印象是这段代码中跳转语句达到了12个,仅仅是这一条就会晕头转向了。
根据以往的经验,首先就是选出那些不该执行的语句(explode_bomb)。如图所示,黄线标出了引爆点。另外,既然跳转这么多,那就先来看看跳转,理出个大体结构。可以看到代码中跳转分成了两大类:1)条件跳转。2)直接跳转。而进一步分析,有些条件跳转是和callexplode_bomb相关的,而这条指令不该被执行,所以就又可以确定了某些条件跳转的方向。于是,红色箭头标出了确定的跳转方向,蓝色箭头标出5个条件跳转的不确定方向。
标出了跳转方向后,程序的大致结构就比较清晰了。根据这些跳转,可以把phase_6分成两大主要语句块(红色和绿色)。这时发现红色块执行到绿色块唯一的途径是蓝色跳转语句(1)(蓝1)。大致的结构分析完了,就深入程序看看吧。
首先由call8049112<read_six_numbers>可以知道要读入6个数。那问题就是怎样的6个数?
红色代码块:
由红色的代码块,我得出结论:这6个数<=6,且均不相等。
为什么这么说呢?由蓝2和最后一条jmp8048c77的大跳转,能想到什么,是不是有点像一个大循环嵌套了一个小循环呢?那为什么大跳转是用jmp而不是条件跳转。这时,想到了唯一跳转出红色大块的蓝1,可以猜想到了语句中用到了类似goto的语句(可见goto确实很会搅局,连分析起反汇编后的代码都很晦涩)。看到红色大块的前两条,感觉和输入数据有关,于是查看-0x24(%ebp)后知道是输入的第一个数据data[0],所以之后data[i]就存在了-0x24(%ebp,i,4)=-0x24(%ebp)+4i。由此可以推断%ebx应该是索引变量,而每次%eax=data[i]。再由代码块(a)得知data[i]<=6才行,否则就爆炸了。
再往下就是%edi=%ebx+1,%edi就是下一个索引,当到了索引5时就执行蓝1跳转。由此,可以先写个外层循环的大致框架:
for(inti=0;;i++)
[code]{
%eax=data[i]
%edi=i+1
if(%edi==6)
gotoblueblock;
}
[/code]
之后的lea-0x24(%ebp,%ebx,4),%esi则是把当前数据的地址赋给%esi,即%esi=&data[i]。
mov%edi,%ebx//%ebx=%ebx+1
[code]lea-0x24(%ebp),%eax//%eax=&data[0]
%edx=&data[0]
mov-0x4(%edx,%edi,4),%eax//%eax=%edx+4%edi–4=&data[0]+4(%edi–1)。
cmp0x4(%esi),%eax//比较*(&data[i]+0x4),*(&data[0]+4(%edi–1))从这条可以隐约看出是在比较两个输入的数据,那么这两个输入的数据关系是什么呢?
[/code]
往下读,jne8048cb1可知这两个数不能相等,否则就爆炸了。
最后看到代码块(b),每次%ebx+1,%esi+4,同时以%ebx<=5作为循环条件。根据蓝2的跳转,知道每次mov-0x4(%edx,%edi,4),%eax中的%edx和%edi是不变的,所以%eax==&data[0]+4(%edi–1),而%edi为外循环初始时的%ebx+1(因为内循环%ebx每次都在累加),所以%eax==&data[0]+4%ebx==&data[i]。
而每次%esi+4,而初始%esi=-0x24(%ebp,%ebx,4)=&data[i],所以cmp0x4(%esi),%eax依次遍历data[i]后面的数据。根据这些线索,我们可以写出内循环的框架:
%esi=&data[i];
[code]for(intj=i+1;;j<=5)
{
if(data[j]!=data[i])
j++;
else
explode_bomb();
}
[/code]
最后的那条mov%edi,%ebx是把外层的循环变量复原,在此就在内外层用不同的两个变量了,最后写成C代码如下:
for(inti=0;;i++)
[code]{
if(data[i]>6)
explode_bomb();
if(i+1==6)
gotoblueblock;
for(intj=i+1;j<=5;j++)
{
if(data[j]==data[i])
explode_bomb();
}
}
[/code]
于是,根据以上的分析,我们就得出了最初的结论:这6个数<=6,且均不相等。
绿色代码:
这段代码很长,初看很没头绪。那怎么办呢?依然根据跳转语句来理出一些思路,希望能够分成更小的块,分而治之。于是我们有了四个更小的代码块c,d,e,f。
代码c:
可以知道,%ecx保存的是地址值,而%eax是一个循环变量。cmp-0x24(%ebp,%edx,4),%eax可知要取地址的次数为我们输入的数据。
代码d:
由-0x24(%ebp,%edx,4)可知%edx是索引变量。再由mov%ecx,-0x3c(%ebp,%edx,4)可知相应的地址(-0x3c(%ebp),-0x38(%ebp),-0x34(%ebp),-0x30(%ebp),-0x2c(%ebp),-0x28(%ebp))将被赋值(与代码e中的取地址对应)
根据对代码块d的理解,可以写出一个大致的c代码框架:
for(inti=0;i<6;i++)
[code]{
addr=0x804a5fc;
for(intj=0;j<data[i];j++)
addr=*(addr+0x8);
-0x3c(%ebp)+4*i=addr;
}
[/code]
代码e:
举例来说:
mov-0x3c(%ebp),%ecx
[code]mov-0x38(%ebp),%eax
mov%eax,0x8(%ecx)
[/code]
可知,-0x38(%ebp)中的地址被放入了*(-0x3c(%ebp))+0x8中,而后的各步与此相似。相当于在做一个链表的链接功能。
代码f:
mov0x8(%ebx),%edx
[code]mov(%ebx),%eax
cmp(%edx),%eax
[/code]
这三条语句可知这是当前节点的值(*%ebx)和下一个节点的值(*0x8(%ebx))在进行比较,而且当前节点的值必须大于等于下一个节点的值。由此可以写出一个c的代码框架:
structnode
[code]{
intx,y;
node*next;
};
nodea=firstNode;
for(inti=0;i<5;i++)
{
nodeb=a->next;
if(a->x>=b->x)
a=b;
else
explode_bomb();
}
[/code]
由此,我们可以知道检查0x804a5fc及其之后0x8为步长的地址是关键。
由gdb查看得知:
*0x804a5fc=0x3b7
*(0x804a5fc+8)=0x804a5f0,*0x804a5f0=0x3c6
*(0x804a5f0+8)=0x804a5e4,*0x804a5e4=0x112
*(0x804a5e4+8)=0x804a5d8,*0x804a5d8=0x3a4
*(0x804a5d8+8)=0x804a5cc,*0x804a5cc=0x5a
*(0x804a5cc+8)=0x804a5c0,*0x804a5c0=0xfe
根据这个内存的检测,我们把值进行排序,以期符合代码f中的要求,得到(括号中为所属序号):
0x3c6(2)>0x3b7(1)>0x3a4(4)>0x112(3)>0xfe(6)>0x5a(5),根据其序号得出最后的答案:214365
相关文章推荐
- 逆向工程——二进制炸弹(CSAPP Project)
- 逆向工程——二进制炸弹(CSAPP Project)
- 逆向工程——二进制炸弹(CSAPP Project)
- 逆向工程实验---二进制炸弹(CSAPP Project)
- [PD]使用PowerDesign进行逆向工程
- mybatis-generator逆向工程生成model dao mapping
- 智能一代云平台(三十):逆向工程生成mybatis
- 几个开发工具的java逆向工程(java reverse engineering)功能比较
- os x下 apk逆向工程利器 AndroidCrackTool for Mac 最新版
- 关于PowerDesigner Reverse Engineer from database-mysql的逆向工程
- 9. PD逆向工程--由数据库转为模型(ER图)
- mybatis--逆向工程
- 用Maven中实现MyBatis逆向工程(IDEA版)
- 逆向工程-第一次修改.exe
- SSM+Bootstrap场地管理系统第一天----数据库的建立和mybatis的逆向工程
- eclipse下使用hibernate tools实现hibernate逆向工程
- Enterprise Architect 数据库逆向工程(导入已经存在的数据表结构)
- MyBatis逆向工程
- Powerdesigner逆向工程从现有数据库生成PDM
- powerdesigner连接mysql 数据库逆向工程