作业续集_二进制炸弹_手把手教学

前情回顾

上回说到了前4题,接下来说phase_4

phase_4递归

本来以为网上的很多教程都有讲解,实在不行看看别人的教程,可是、、、看了好久也没有和我的一样的题型,本题我认为是最难的一个,没有之一。好了,回顾一下心酸的历程。

08049660 <func4>:
 8049660:	55                   	push   %ebp
 8049661:	89 e5                	mov    %esp,%ebp
 8049663:	83 ec 18             	sub    $0x18,%esp
 8049666:	8b 55 0c             	mov    0xc(%ebp),%edx
 8049669:	8b 45 10             	mov    0x10(%ebp),%eax
 804966c:	01 d0                	add    %edx,%eax
 804966e:	89 c2                	mov    %eax,%edx
 8049670:	c1 ea 1f             	shr    $0x1f,%edx
 8049673:	01 d0                	add    %edx,%eax
 8049675:	d1 f8                	sar    %eax
 8049677:	89 45 f4             	mov    %eax,-0xc(%ebp)
 804967a:	8b 45 0c             	mov    0xc(%ebp),%eax
 804967d:	3b 45 10             	cmp    0x10(%ebp),%eax
 8049680:	7c 13                	jl     8049695 <func4+0x35>
 8049682:	8b 45 10             	mov    0x10(%ebp),%eax
 8049685:	8d 14 85 00 00 00 00 	lea    0x0(,%eax,4),%edx
 804968c:	8b 45 08             	mov    0x8(%ebp),%eax
 804968f:	01 d0                	add    %edx,%eax
 8049691:	8b 00                	mov    (%eax),%eax
 8049693:	eb 3c                	jmp    80496d1 <func4+0x71>
 8049695:	83 ec 04             	sub    $0x4,%esp
 8049698:	ff 75 f4             	pushl  -0xc(%ebp)
 804969b:	ff 75 0c             	pushl  0xc(%ebp)
 804969e:	ff 75 08             	pushl  0x8(%ebp)
 80496a1:	e8 ba ff ff ff       	call   8049660 <func4>
 80496a6:	83 c4 10             	add    $0x10,%esp
 80496a9:	89 45 f0             	mov    %eax,-0x10(%ebp)
 80496ac:	8b 45 f4             	mov    -0xc(%ebp),%eax
 80496af:	83 c0 01             	add    $0x1,%eax
 80496b2:	83 ec 04             	sub    $0x4,%esp
 80496b5:	ff 75 10             	pushl  0x10(%ebp)
 80496b8:	50                   	push   %eax
 80496b9:	ff 75 08             	pushl  0x8(%ebp)
 80496bc:	e8 9f ff ff ff       	call   8049660 <func4>
 80496c1:	83 c4 10             	add    $0x10,%esp
 80496c4:	89 45 ec             	mov    %eax,-0x14(%ebp)
 80496c7:	8b 45 ec             	mov    -0x14(%ebp),%eax
 80496ca:	39 45 f0             	cmp    %eax,-0x10(%ebp)
 80496cd:	0f 4d 45 f0          	cmovge -0x10(%ebp),%eax
 80496d1:	c9                   	leave  
 80496d2:	c3                   	ret    

080496d3 <phase_4>:
 80496d3:	55                   	push   %ebp
 80496d4:	89 e5                	mov    %esp,%ebp
 80496d6:	57                   	push   %edi
 80496d7:	56                   	push   %esi
 80496d8:	53                   	push   %ebx
 80496d9:	81 ec bc 00 00 00    	sub    $0xbc,%esp
 80496df:	8d 85 40 ff ff ff    	lea    -0xc0(%ebp),%eax
 80496e5:	bb 40 b2 04 08       	mov    $0x804b240,%ebx
 80496ea:	ba 29 00 00 00       	mov    $0x29,%edx
 80496ef:	89 c7                	mov    %eax,%edi
 80496f1:	89 de                	mov    %ebx,%esi
 80496f3:	89 d1                	mov    %edx,%ecx
 80496f5:	f3 a5                	rep movsl %ds:(%esi),%es:(%edi)
 80496f7:	8d 85 38 ff ff ff    	lea    -0xc8(%ebp),%eax
 80496fd:	50                   	push   %eax
 80496fe:	8d 85 3c ff ff ff    	lea    -0xc4(%ebp),%eax
 8049704:	50                   	push   %eax
 8049705:	68 ff b1 04 08       	push   $0x804b1ff
 804970a:	ff 75 08             	pushl  0x8(%ebp)
 804970d:	e8 be f9 ff ff       	call   80490d0 <__isoc99_sscanf@plt>
 8049712:	83 c4 10             	add    $0x10,%esp
 8049715:	89 45 e4             	mov    %eax,-0x1c(%ebp)
 8049718:	83 7d e4 02          	cmpl   $0x2,-0x1c(%ebp)
 804971c:	74 0f                	je     804972d <phase_4+0x5a>
 804971e:	e8 c5 07 00 00       	call   8049ee8 <explode_bomb>
 8049723:	b8 00 00 00 00       	mov    $0x0,%eax
 8049728:	e9 bc 00 00 00       	jmp    80497e9 <phase_4+0x116>
 804972d:	8b 95 38 ff ff ff    	mov    -0xc8(%ebp),%edx
 8049733:	8b 85 3c ff ff ff    	mov    -0xc4(%ebp),%eax
 8049739:	83 ec 04             	sub    $0x4,%esp
 804973c:	52                   	push   %edx
 804973d:	50                   	push   %eax
 804973e:	8d 85 40 ff ff ff    	lea    -0xc0(%ebp),%eax
 8049744:	50                   	push   %eax
 8049745:	e8 16 ff ff ff       	call   8049660 <func4>
 804974a:	83 c4 10             	add    $0x10,%esp
 804974d:	3d e9 01 00 00       	cmp    $0x1e9,%eax
 8049752:	74 0f                	je     8049763 <phase_4+0x90>
 8049754:	e8 8f 07 00 00       	call   8049ee8 <explode_bomb>
 8049759:	b8 00 00 00 00       	mov    $0x0,%eax
 804975e:	e9 86 00 00 00       	jmp    80497e9 <phase_4+0x116>
 8049763:	8b 85 3c ff ff ff    	mov    -0xc4(%ebp),%eax
 8049769:	85 c0                	test   %eax,%eax
 804976b:	7e 36                	jle    80497a3 <phase_4+0xd0>
 804976d:	8b 85 38 ff ff ff    	mov    -0xc8(%ebp),%eax
 8049773:	8b 95 3c ff ff ff    	mov    -0xc4(%ebp),%edx
 8049779:	83 ea 01             	sub    $0x1,%edx
 804977c:	83 ec 04             	sub    $0x4,%esp
 804977f:	50                   	push   %eax
 8049780:	52                   	push   %edx
 8049781:	8d 85 40 ff ff ff    	lea    -0xc0(%ebp),%eax
 8049787:	50                   	push   %eax
 8049788:	e8 d3 fe ff ff       	call   8049660 <func4>
 804978d:	83 c4 10             	add    $0x10,%esp
 8049790:	3d e9 01 00 00       	cmp    $0x1e9,%eax
 8049795:	75 0c                	jne    80497a3 <phase_4+0xd0>
 8049797:	e8 4c 07 00 00       	call   8049ee8 <explode_bomb>
 804979c:	b8 00 00 00 00       	mov    $0x0,%eax
 80497a1:	eb 46                	jmp    80497e9 <phase_4+0x116>
 80497a3:	8b 85 38 ff ff ff    	mov    -0xc8(%ebp),%eax
 80497a9:	83 f8 27             	cmp    $0x27,%eax
 80497ac:	7f 36                	jg     80497e4 <phase_4+0x111>
 80497ae:	8b 85 38 ff ff ff    	mov    -0xc8(%ebp),%eax
 80497b4:	8d 50 01             	lea    0x1(%eax),%edx
 80497b7:	8b 85 3c ff ff ff    	mov    -0xc4(%ebp),%eax
 80497bd:	83 ec 04             	sub    $0x4,%esp
 80497c0:	52                   	push   %edx
 80497c1:	50                   	push   %eax
 80497c2:	8d 85 40 ff ff ff    	lea    -0xc0(%ebp),%eax
 80497c8:	50                   	push   %eax
 80497c9:	e8 92 fe ff ff       	call   8049660 <func4>
 80497ce:	83 c4 10             	add    $0x10,%esp
 80497d1:	3d e9 01 00 00       	cmp    $0x1e9,%eax
 80497d6:	75 0c                	jne    80497e4 <phase_4+0x111>
 80497d8:	e8 0b 07 00 00       	call   8049ee8 <explode_bomb>
 80497dd:	b8 00 00 00 00       	mov    $0x0,%eax
 80497e2:	eb 05                	jmp    80497e9 <phase_4+0x116>
 80497e4:	b8 01 00 00 00       	mov    $0x1,%eax
 80497e9:	8d 65 f4             	lea    -0xc(%ebp),%esp
 80497ec:	5b                   	pop    %ebx
 80497ed:	5e                   	pop    %esi
 80497ee:	5f                   	pop    %edi
 80497ef:	5d                   	pop    %ebp
 80497f0:	c3                   	ret    

当时看完发现这么长的代码已经做好了心理准备。可是没想到还是让人崩溃,哭辽。。。

80496e5:	bb 40 b2 04 08       	mov    $0x804b240,%ebx

发现明码地址先看看情况。
在这里插入图片描述
啥也不是
还有一个明码地址,有点熟悉,前面几个题出现过

8049705:	68 ff b1 04 08       	push   $0x804b1ff

在这里插入图片描述
也就是说,这一题需要输入两个整数,然后调用fun4,fun4是一个递归函数,功能是需要这两个数之间满足某种联系才可以,所以需要仔细分析fun4才可以。

后来发现fun4真TMD难。
看代码我没能完整写出来,万般无奈打开了IDA,来吧一起看看
在这里插入图片描述
打开以后按F5调试伪代码。
于是有一下内容
在这里插入图片描述
首先可以确定的是,v5是判断是不是两个数,然后进行下一步操作。可以看到有三个if语句,每一个判断条件都是一个递归函数,仔细看看能看懂嘛。

好了,不能,这才是最伤心的。有伪代码都看不懂。。。。
主要是这三个参数分别是什么呢,&v4,v2 v3
再来看看fun4
在这里插入图片描述
看起来没有那么难啊,可是仔细一看却无从下手。
现在的目的是找到这三个参数的来源,然后看看能不能调试的时候查看一下。

答案很简单,不能

 80496e5:	bb 40 b2 04 08       	mov    $0x804b240,%ebx
 80496ea:	ba 29 00 00 00       	mov    $0x29,%edx

这两行是什么意思呢,就是说,先开辟了一段空间,然后放一个数组进去,长度是0x29也就是41.
调试看一下
在这里插入图片描述
这里发现ecx从41递减一直到0
然后一直调试41行才可以完成这一步
在这里插入图片描述
气人的是还看不到数组是什么。。。悲伤
继续往后看吧。发现有两个比较,0和39
有什么用呢?

要不胸口碎大石吧,从0和39一个一个尝试,hhhh加油,看好你(我试过了。。。。。)
好了,别想有一点的侥幸。老实的分析吧。
很容易看出

804974d:	3d e9 01 00 00       	cmp    $0x1e9,%eax
 8049752:	74 0f                	je     8049763 <phase_4+0x90>

返回值要和489比较,
然后运行调试
这里我使用的第一个数是1 第二个39
在这里插入图片描述
有点小惊喜,第一个比较通过了,难道这就好了吗???
并没有,第二个还是会boom
在这里插入图片描述
至此,思路全无,洗洗睡吧,晚安

怎么说呢,这么一个一个尝试这么也不是办法,分析思路才是正道。
于是分析fun4的功能,最后写c++程序

#include<iostream>
using namespace std;

int func4(int num[], int first, int last)
{
    
    
	int max_f, max_l;

    int mid = (first + last) / 2;

    if (first >= last)
		return num[last];
	
    //if ((first+1) == last)
	//	return (num[first] >= num[last])? num[first] : num[last];
	
	max_f = func4(num, first, mid);
	max_l = func4(num, mid+1, last);
	return (max_f >= max_l)? max_f : max_l;
}
  

int main(){
    
    
int num[] = {
    
    1,2,3,4,5,6,7,8,2,3,4,5,6,7,8,2,3,4,5,6,7,8,2,3,4,5,6,7,8,2,3,4,5,6,7,8,1,2,1,1,1};
//int phase_4(char *input) {
    
    
 int first, last;
    int temp;
	
   for (int i=1;i<40;i++){
    
    
       temp=i;
       num[i-1]=1;
       num[i]=489;
for (int k=0;k<40;k++){
    
    
    first =k;
    for(int j=0;j<40;j++){
    
    
        last=j;
while (first>0 && func4(num,first-1,temp)==489)
		first = first - 1;

	last = temp;
    while (last<40 && func4(num,temp,last+1)==489)
		last = last + 1;
		
	cout<<first<<"_"<<last<<"\t";
   }
}
   }

    return 0;
}

简单介绍一下,代码里也设置了一个数组,不过是随便设置的,因为不知道那个特定的489的位置,所以用了一个for循环,一个一个暴力拆解。
然后按照题目的两个数的范围,再用两个for一个一个找。
最后程序直接输出两个答案。
总的来说,这题的功能是递归求数组最值。
答案0 40
在这里插入图片描述
非常艰难的解决了这一题。好了我们继续。

phase_5

080497f1 <phase_5>:
 80497f1:	55                   	push   %ebp
 80497f2:	89 e5                	mov    %esp,%ebp
 80497f4:	83 ec 18             	sub    $0x18,%esp
 80497f7:	83 ec 0c             	sub    $0xc,%esp
 80497fa:	ff 75 08             	pushl  0x8(%ebp)
 80497fd:	e8 52 04 00 00       	call   8049c54 <string_length>
 8049802:	83 c4 10             	add    $0x10,%esp
 8049805:	89 45 ec             	mov    %eax,-0x14(%ebp)
 8049808:	83 7d ec 06          	cmpl   $0x6,-0x14(%ebp)
//比较是不是6个字符长度
 804980c:	74 0c                	je     804981a <phase_5+0x29>
//相等跳转
 804980e:	e8 d5 06 00 00       	call   8049ee8 <explode_bomb>
 8049813:	b8 00 00 00 00       	mov    $0x0,%eax
 8049818:	eb 4c                	jmp    8049866 <phase_5+0x75>
 804981a:	c7 45 f0 00 00 00 00 	movl   $0x0,-0x10(%ebp)
 8049821:	c7 45 f4 00 00 00 00 	movl   $0x0,-0xc(%ebp)
 8049828:	eb 1f                	jmp    8049849 <phase_5+0x58>
 804982a:	8b 55 f4             	mov    -0xc(%ebp),%edx
 804982d:	8b 45 08             	mov    0x8(%ebp),%eax
 8049830:	01 d0                	add    %edx,%eax
 8049832:	0f b6 00             	movzbl (%eax),%eax
 8049835:	0f be c0             	movsbl %al,%eax
 8049838:	83 e0 0f             	and    $0xf,%eax
//按位与操作,只取最低位
 804983b:	8b 04 85 40 d2 04 08 	mov    0x804d240(,%eax,4),%eax
 8049842:	01 45 f0             	add    %eax,-0x10(%ebp)
 8049845:	83 45 f4 01          	addl   $0x1,-0xc(%ebp)
 8049849:	83 7d f4 05          	cmpl   $0x5,-0xc(%ebp)
//将结果与5进行比较
 804984d:	7e db                	jle    804982a <phase_5+0x39>
//小于跳转
 804984f:	83 7d f0 27          	cmpl   $0x27,-0x10(%ebp)
 8049853:	74 0c                	je     8049861 <phase_5+0x70>
//相等跳转
 8049855:	e8 8e 06 00 00       	call   8049ee8 <explode_bomb>
 804985a:	b8 00 00 00 00       	mov    $0x0,%eax
 804985f:	eb 05                	jmp    8049866 <phase_5+0x75>
 8049861:	b8 01 00 00 00       	mov    $0x1,%eax
 8049866:	c9                   	leave  
 8049867:	c3                   	ret    
}

这一题是字符串破解。
很有意思,但是不难。

这部分程序的功能是指针考察。该阶段使用输入字符串中字符作为数组索引进行计算,要求输入字符串满足计算结果要求。对本阶段函数的反汇编结果进行总体分析。分析针对输入字符串的处理过程。相应构造输入字符串。
重新打开终端,这次断点打在phase_5 。
在这里插入图片描述
本题类似于密码解密,要求输入6个字符每一个字符对应密码以后,得到满足题意的结果。movzbl (%eax),%eax对于这样的指令格式遇到不止一次了,x86/x64 寻址方式众多,什么直接寻址、间接寻址、基址寻址、基址变址寻址等等让人眼花缭乱,而 AT&T 语法对内存寻址方式做了一个很好的统一,其格式为section:displacement(base, index, scale),其中section 是段地址,displacement 是位移,base 是基址寄存器,index是索引,scale 是缩放因子,其计算方式为线性地址=section + displacement + base + index*scale,最重要的是,可以省略以上格式中的一个或多个部分,比如 movw 4, %ax 就是把内存地址 4 中的值移动到 ax 寄存器中,movw 4(%esp), %ax 就是把 esp+4 指向的地址中的值移动到 ax 寄存器中,依此类推。
解题关键是这一行

8049838:	83 e0 0f             	and    $0xf,%eax

//按位与操作,只取最低位
要熟悉理解按位操作,才可解决这一题的核心算法。
也就是说,输入的6个字符串的每个字母的ASCII码对应的应该是一个特定的数字,然后加在一起是5.
继续进行分析以后查询ASCII表,可知第一个英文字母的小写a是97,然后进行按位与操作,只取最低位,变成1,同理bcd…等等可以分别分析出对应的数字。然后经过以下操作

804983b:	8b 04 85 40 d2 04 08 	mov    0x804d240(,%eax,4),%eax
 8049842:	01 45 f0             	add    %eax,-0x10(%ebp)
 8049845:	83 45 f4 01          	addl   $0x1,-0xc(%ebp)
发现a对应6,c对应7,从而为了满足最后的条件,
 804984f:	83 7d f0 27          	cmpl   $0x27,-0x10(%ebp)

即相加为39,只需要3个a,3个c即可
可以取aaaccc,并且不要求顺序。而且答案不唯一

phase_6

这部分程序的功能是考察链表/指针/结构。该阶段要求输入一串数字用以调整一个链表中各结构的顺序,使其满足特定顺序要求。对本阶段函数的反汇编结果进行总体分析。分析程序的链表处理逻辑和内置链表数据进行分析。相应构造输入数串。
重新打开终端,这次断点打在phase_6 。

// Code Block
08049868 <phase_6>:
 8049868:	55                   	push   %ebp
 8049869:	89 e5                	mov    %esp,%ebp
 804986b:	83 ec 58             	sub    $0x58,%esp//内存开辟
 804986e:	c7 45 e8 78 d1 04 08 	movl   $0x804d178,-0x18(%ebp)
 8049875:	83 ec 04             	sub    $0x4,%esp
 8049878:	6a 08                	push   $0x8//入栈
 804987a:	8d 45 c8             	lea    -0x38(%ebp),%eax
 804987d:	50                   	push   %eax
 804987e:	ff 75 08             	pushl  0x8(%ebp)//入栈
 8049881:	e8 40 03 00 00       	call   8049bc6 <read_n_numbers>
//调用函数,读取n个数字
 8049886:	83 c4 10             	add    $0x10,%esp
 8049889:	85 c0                	test   %eax,%eax
//判断每一个数字是不是大于0
 804988b:	75 0a                	jne    8049897 <phase_6+0x2f>
//不满足跳转
 804988d:	b8 00 00 00 00       	mov    $0x0,%eax
 8049892:	e9 5f 01 00 00       	jmp    80499f6 <phase_6+0x18e>
 8049897:	c7 45 f0 00 00 00 00 	movl   $0x0,-0x10(%ebp)
 804989e:	eb 60                	jmp    8049900 <phase_6+0x98>
 80498a0:	8b 45 f0             	mov    -0x10(%ebp),%eax
 80498a3:	8b 44 85 c8          	mov    -0x38(%ebp,%eax,4),%eax
 80498a7:	85 c0                	test   %eax,%eax
//判断每一个数字是不是大于0
 80498a9:	7e 0c                	jle    80498b7 <phase_6+0x4f>//跳转
 80498ab:	8b 45 f0             	mov    -0x10(%ebp),%eax
 80498ae:	8b 44 85 c8          	mov    -0x38(%ebp,%eax,4),%eax
 80498b2:	83 f8 08             	cmp    $0x8,%eax
//从这里看看可以分析到是要读取8个数字。
 80498b5:	7e 0f                	jle    80498c6 <phase_6+0x5e>
 80498b7:	e8 2c 06 00 00       	call   8049ee8 <explode_bomb>
 80498bc:	b8 00 00 00 00       	mov    $0x0,%eax
 80498c1:	e9 30 01 00 00       	jmp    80499f6 <phase_6+0x18e>
 80498c6:	8b 45 f0             	mov    -0x10(%ebp),%eax
 80498c9:	83 c0 01             	add    $0x1,%eax
 80498cc:	89 45 ec             	mov    %eax,-0x14(%ebp)
 80498cf:	eb 25                	jmp    80498f6 <phase_6+0x8e>
 80498d1:	8b 45 f0             	mov    -0x10(%ebp),%eax
 80498d4:	8b 54 85 c8          	mov    -0x38(%ebp,%eax,4),%edx
 80498d8:	8b 45 ec             	mov    -0x14(%ebp),%eax
 80498db:	8b 44 85 c8          	mov    -0x38(%ebp,%eax,4),%eax
 80498df:	39 c2                	cmp    %eax,%edx
//比较两个数
 80498e1:	75 0f                	jne    80498f2 <phase_6+0x8a>
 80498e3:	e8 00 06 00 00       	call   8049ee8 <explode_bomb>
 80498e8:	b8 00 00 00 00       	mov    $0x0,%eax
 80498ed:	e9 04 01 00 00       	jmp    80499f6 <phase_6+0x18e>
 80498f2:	83 45 ec 01          	addl   $0x1,-0x14(%ebp)
 80498f6:	83 7d ec 07          	cmpl   $0x7,-0x14(%ebp)
//循环的判断
 80498fa:	7e d5                	jle    80498d1 <phase_6+0x69>
 80498fc:	83 45 f0 01          	addl   $0x1,-0x10(%ebp)
 8049900:	83 7d f0 07          	cmpl   $0x7,-0x10(%ebp)
 8049904:	7e 9a                	jle    80498a0 <phase_6+0x38>
 8049906:	c7 45 f0 00 00 00 00 	movl   $0x0,-0x10(%ebp)
 804990d:	eb 19                	jmp    8049928 <phase_6+0xc0>
 804990f:	8b 45 f0             	mov    -0x10(%ebp),%eax
 8049912:	8b 44 85 c8          	mov    -0x38(%ebp,%eax,4),%eax
 8049916:	ba 09 00 00 00       	mov    $0x9,%edx
 804991b:	29 c2                	sub    %eax,%edx?//减法操作
 804991d:	8b 45 f0             	mov    -0x10(%ebp),%eax
 8049920:	89 54 85 c8          	mov    %edx,-0x38(%ebp,%eax,4)
 8049924:	83 45 f0 01          	addl   $0x1,-0x10(%ebp)
 8049928:	83 7d f0 07          	cmpl   $0x7,-0x10(%ebp)
 804992c:	7e e1                	jle    804990f <phase_6+0xa7>
 804992e:	c7 45 f0 00 00 00 00 	movl   $0x0,-0x10(%ebp)
 8049935:	eb 36                	jmp    804996d <phase_6+0x105>
 8049937:	8b 45 e8             	mov    -0x18(%ebp),%eax
 804993a:	89 45 f4             	mov    %eax,-0xc(%ebp)
 804993d:	c7 45 ec 01 00 00 00 	movl   $0x1,-0x14(%ebp)
 8049944:	eb 0d                	jmp    8049953 <phase_6+0xeb>
 8049946:	8b 45 f4             	mov    -0xc(%ebp),%eax
 8049949:	8b 40 08             	mov    0x8(%eax),%eax
 804994c:	89 45 f4             	mov    %eax,-0xc(%ebp)
 804994f:	83 45 ec 01          	addl   $0x1,-0x14(%ebp)
 8049953:	8b 45 f0             	mov    -0x10(%ebp),%eax
 8049956:	8b 44 85 c8          	mov    -0x38(%ebp,%eax,4),%eax
 804995a:	39 45 ec             	cmp    %eax,-0x14(%ebp)//比较
 804995d:	7c e7                	jl     8049946 <phase_6+0xde>
 804995f:	8b 45 f0             	mov    -0x10(%ebp),%eax
 8049962:	8b 55 f4             	mov    -0xc(%ebp),%edx
 8049965:	89 54 85 a8          	mov    %edx,-0x58(%ebp,%eax,4)
 8049969:	83 45 f0 01          	addl   $0x1,-0x10(%ebp)
 804996d:	83 7d f0 07          	cmpl   $0x7,-0x10(%ebp)
 8049971:	7e c4                	jle    8049937 <phase_6+0xcf>
 8049973:	8b 45 a8             	mov    -0x58(%ebp),%eax
 8049976:	89 45 e8             	mov    %eax,-0x18(%ebp)
 8049979:	8b 45 e8             	mov    -0x18(%ebp),%eax
 804997c:	89 45 f4             	mov    %eax,-0xc(%ebp)
 804997f:	c7 45 f0 01 00 00 00 	movl   $0x1,-0x10(%ebp)
 8049986:	eb 1a                	jmp    80499a2 <phase_6+0x13a>
 8049988:	8b 45 f0             	mov    -0x10(%ebp),%eax
 804998b:	8b 54 85 a8          	mov    -0x58(%ebp,%eax,4),%edx
 804998f:	8b 45 f4             	mov    -0xc(%ebp),%eax
 8049992:	89 50 08             	mov    %edx,0x8(%eax)
 8049995:	8b 45 f4             	mov    -0xc(%ebp),%eax
 8049998:	8b 40 08             	mov    0x8(%eax),%eax
//以上有多步内存操作
 804999b:	89 45 f4             	mov    %eax,-0xc(%ebp)
 804999e:	83 45 f0 01          	addl   $0x1,-0x10(%ebp)
 80499a2:	83 7d f0 07          	cmpl   $0x7,-0x10(%ebp)
 80499a6:	7e e0                	jle    8049988 <phase_6+0x120>
 80499a8:	8b 45 f4             	mov    -0xc(%ebp),%eax
 80499ab:	c7 40 08 00 00 00 00 	movl   $0x0,0x8(%eax)
 80499b2:	8b 45 e8             	mov    -0x18(%ebp),%eax
 80499b5:	89 45 f4             	mov    %eax,-0xc(%ebp)
 80499b8:	c7 45 f0 00 00 00 00 	movl   $0x0,-0x10(%ebp)
 80499bf:	eb 2a                	jmp    80499eb <phase_6+0x183>
 80499c1:	8b 45 f4             	mov    -0xc(%ebp),%eax
 80499c4:	8b 10                	mov    (%eax),%edx
 80499c6:	8b 45 f4             	mov    -0xc(%ebp),%eax
 80499c9:	8b 40 08             	mov    0x8(%eax),%eax
 80499cc:	8b 00                	mov    (%eax),%eax
 80499ce:	39 c2                	cmp    %eax,%edx
//比较两个数
 80499d0:	7d 0c                	jge    80499de <phase_6+0x176>
 80499d2:	e8 11 05 00 00       	call   8049ee8 <explode_bomb>
 80499d7:	b8 00 00 00 00       	mov    $0x0,%eax
 80499dc:	eb 18                	jmp    80499f6 <phase_6+0x18e>
 80499de:	8b 45 f4             	mov    -0xc(%ebp),%eax
 80499e1:	8b 40 08             	mov    0x8(%eax),%eax
 80499e4:	89 45 f4             	mov    %eax,-0xc(%ebp)
 80499e7:	83 45 f0 01          	addl   $0x1,-0x10(%ebp)
 80499eb:	83 7d f0 06          	cmpl   $0x6,-0x10(%ebp)
 80499ef:	7e d0                	jle    80499c1 <phase_6+0x159>
 80499f1:	b8 01 00 00 00       	mov    $0x1,%eax
//还原内存,保护数据,离开
 80499f6:	c9                   	leave  
 80499f7:	c3                   	ret    



这一部分的汇编语言经过以上的分析以后,可以写出程序如下;



```c
// Code Block

int __cdecl phase_6(char *s)
{
  int v2[8]; // [esp+0h] [ebp-58h]
  int v3[8]; // [esp+20h] [ebp-38h]
  _DWORD *v4; // [esp+40h] [ebp-18h]
  int j; // [esp+44h] [ebp-14h]
  int i; // [esp+48h] [ebp-10h]
  _DWORD *v7; // [esp+4Ch] [ebp-Ch]

  v4 = &node1;
  if ( !read_n_numbers(s, (int)v3, 8) )
    return 0;
  for ( i = 0; i <= 7; ++i )
  {
    if ( v3[i] <= 0 || v3[i] > 8 )
    {
      explode_bomb();
      return 0;
    }
    for ( j = i + 1; j <= 7; ++j )
    {
      if ( v3[i] == v3[j] )
      {
        explode_bomb();
        return 0;
      }
    }
  }
  for ( i = 0; i <= 7; ++i )
    v3[i] = 9 - v3[i];
  for ( i = 0; i <= 7; ++i )
  {
    v7 = v4;
    for ( j = 1; j < v3[i]; ++j )
      v7 = v7[2];
    v2[i] = (int)v7;
  }
  v4 = v2[0];
  v7 = v2[0];
  for ( i = 1; i <= 7; ++i )
  {
    v7[2] = v2[i];
    v7 = v7[2];
  }
  v7[2] = 0;
  v7 = v4;
  for ( i = 0; i <= 6; ++i )
  {
    if ( *v7 < v7[2] )
    {
      explode_bomb();
      return 0;
    }
    v7 = v7[2];
  }
  return 1;
}

然后可以看出,不同链表的指向;使用一下方式更加直接了当:

(


```bash
gdb) x/3x 0x804d178
0x804d178 <node1>:	0x00000005	0x00000001	0x0804d16c
(gdb) x/3x 0x0804d16c
0x804d16c <node2>:	0x00000002	0x00000002	0x0804d160
(gdb) x/3x 0x0804d160
0x804d160 <node3>:	0x00000001	0x00000003	0x0804d154
(gdb) x/3x 0x0804d154
0x804d154 <node4>:	0x00000009	0x00000004	0x0804d148
(gdb) x/3x 0x0804d148
0x804d148 <node5>:	0x00000007	0x00000005	0x0804d13c
(gdb) x/3x 0x0804d13c
0x804d13c <node6>:	0x00000006	0x00000006	0x0804d130
(gdb) x/3x 0x0804d130
0x804d130 <node7>:	0x00000008	0x00000007	0x0804d124
(gdb) x/3x 0x0804d130
0x804d130 <node7>:	0x00000008	0x00000007	0x0804d124
(gdb) x/3x 0x0804d124
0x804d124 <node8>:	0x00000004	0x00000008	0x00000000

然后根据第一个0x数字的大小,将链表元素按value值由大到小排序,但是并不是最后结果因为还要用9减去每一个数字才可。结果是5 2 4 3 8 1 7 6。

Phase secret:

这部分程序的功能是综合功能。
重新打开终端,这次断点打在secret_phase。

// Code Block
08049a5b <secret_phase>:
 8049a5b:	55                   	push   %ebp
 8049a5c:	89 e5                	mov    %esp,%ebp
 8049a5e:	83 ec 18             	sub    $0x18,%esp// Integer Subtraction
 8049a61:	e8 3f 03 00 00       	call   8049da5 <read_line>
//Call Procedure
 8049a66:	89 45 f4             	mov    %eax,-0xc(%ebp)
 8049a69:	83 ec 0c             	sub    $0xc,%esp
 8049a6c:	ff 75 f4             	pushl  -0xc(%ebp)
 8049a6f:	e8 8c f6 ff ff       	call   8049100 <atoi@plt>
 8049a74:	83 c4 10             	add    $0x10,%esp//加法操作
 8049a77:	89 45 f0             	mov    %eax,-0x10(%ebp)
 8049a7a:	83 7d f0 00          	cmpl   $0x0,-0x10(%ebp)//比较两个数
 8049a7e:	7e 09                	jle    8049a89 <secret_phase+0x2e>
 8049a80:	81 7d f0 e9 03 00 00 	cmpl   $0x3e9,-0x10(%ebp)
 8049a87:	7e 0c                	jle    8049a95 <secret_phase+0x3a>
 8049a89:	e8 5a 04 00 00       	call   8049ee8 <explode_bomb>
 8049a8e:	b8 00 00 00 00       	mov    $0x0,%eax//内存操作
 8049a93:	eb 42                	jmp    8049ad7 <secret_phase+0x7c>
 8049a95:	83 ec 08             	sub    $0x8,%esp//减法操作
 8049a98:	ff 75 f0             	pushl  -0x10(%ebp)
 8049a9b:	68 2c d2 04 08       	push   $0x804d22c
 8049aa0:	e8 53 ff ff ff       	call   80499f8 <fun7>
 8049aa5:	83 c4 10             	add    $0x10,%esp
 8049aa8:	89 45 ec             	mov    %eax,-0x14(%ebp)
 8049aab:	83 7d ec 02          	cmpl   $0x2,-0x14(%ebp)
 8049aaf:	74 0c                	je     8049abd <secret_phase+0x62>
//判断是否相等
 8049ab1:	e8 32 04 00 00       	call   8049ee8 <explode_bomb>
 8049ab6:	b8 00 00 00 00       	mov    $0x0,%eax
 8049abb:	eb 1a                	jmp    8049ad7 <secret_phase+0x7c>
 8049abd:	83 ec 0c             	sub    $0xc,%esp//减法操作
 8049ac0:	68 e4 b2 04 08       	push   $0x804b2e4
 8049ac5:	e8 c6 f5 ff ff       	call   8049090 <puts@plt>
 8049aca:	83 c4 10             	add    $0x10,%esp
 8049acd:	e8 3f 04 00 00       	call   8049f11 <phase_defused>
 8049ad2:	b8 01 00 00 00       	mov    $0x1,%eax
 8049ad7:	c9                   	leave  
 8049ad8:	c3                   	ret    //Return Near from Procedure

}

代码很多,先看明码地址。发现很多有意思的事情。但是要进入secret phase呢就要再输入一个austinpower的字符串。那我在拆炸弹的时候,在拆phase4的时候多输入一个austinpower,然后就成功进入了secret phase。
在这一关我使用了IDA进行分析
得到以下伪代码

 int __cdecl fun7(_DWORD *a1, int a2)
{
    
    
  if ( !a1 )
    return -1;
  if ( a2 < *a1 )
    return 2 * fun7(a1[1], a2);
  if ( a2 == *a1 )
    return 0;
  return 2 * fun7(a1[2], a2) + 1;
}
  
ret  signed int secret_phase()
{
    
    
  char *nptr; // ST1C_4
  signed int result; // eax
  int v2; // [esp+8h] [ebp-10h]

  nptr = (char *)read_line();
  v2 = atoi(nptr);
  if ( v2 > 0 && v2 <= 1001 )
  {
    
    
    if ( fun7(&n1, v2) == 2 )
    {
    
    
      puts("Wow! You've defused the secret stage!");
      phase_defused();
      result = 1;
    }
    else
    {
    
    
      explode_bomb();
      result = 0;
    }
  }
  else
  {
    
    
    explode_bomb();
    result = 0;
  }
  return result;
}  

通过明码地址可以一步一步摸索到这一字符串。然后分析fun7的作用。有了以上代码,思路清晰但是比较繁琐最后经过手动计算得到答案是20.

在这里插入图片描述

作业小总结

可能因为比较笨,所以花的时间比较长才解决。
总之,加油鸭!

猜你喜欢

转载自blog.csdn.net/cena1001/article/details/109596141