逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法

上一篇【为拆炸弹实验做的预习与准备】讲述了一些必须的知识

这个实验是给出可执行文件,要求用gdb反编译出汇编代码,一共有6个关卡,要求玩家输入6个输入,要通过分析汇编代码来找到何种输入不会触发炸弹,然后输入正确的输入信息以拆解炸弹

第一关 字符串比对

汇编原码及个人注释

逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第1张图片

0000000000400e70 <phase_1>:
  400e70:	48 83 ec 08          	sub    $0x8,%rsp					// 开栈
  400e74:	be f8 1a 40 00       	mov    $0x401af8,%esi				// 函数的第二个参数是$0x401af8,猜测是常量字符串
  400e79:	e8 bf 03 00 00       	callq  40123d <strings_not_equal>	
  400e7e:	85 c0                	test   %eax,%eax					// 返回值等于0,即两个字符串相等,则结束否则bomb
  400e80:	74 05                	je     400e87 <phase_1+0x17>
  400e82:	e8 b6 07 00 00       	callq  40163d <explode_bomb>
  400e87:	48 83 c4 08          	add    $0x8,%rsp					// 退栈
  400e8b:	c3      

前三句是压栈,调用一个strings_not_equal函数,根据英文阅读理解,判断这个函数是输入和一常量字符串比较判断是否相同,如果不同则返回true(1),如果相同则返回false(0)

然后根据返回值,用je进行跳转,如果eax即函数返回值为0则跳转成功,不会触发,然后关注到它将0x401af8赋值给esi,函数string_not_equal的第二个参数,而第一个参数仍然是phase1调用的第一个参数,应该是输入值,所以我猜测这第二个参数是一个常量字符串的地址,于是gdb试一下,gdb查看对应内存地址的字符串

在这里插入图片描述
发现这个常量字符串是Science isn’t about why, it’s about why not? 结合上面的分析不难看出,输入串必须与其相等,方可通关!

答案:

Science isn't about why, it's about why not?

第二关:数组与循环

汇编源码及个人注释

逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第2张图片

0000000000400e8c <phase_2>:
  400e8c:	48 89 5c 24 e0       	mov    %rbx,-0x20(%rsp)				// 保存父函数数据,压栈
  400e91:	48 89 6c 24 e8       	mov    %rbp,-0x18(%rsp)
  400e96:	4c 89 64 24 f0       	mov    %r12,-0x10(%rsp)
  400e9b:	4c 89 6c 24 f8       	mov    %r13,-0x8(%rsp)				
  400ea0:	48 83 ec 48          	sub    $0x48,%rsp					// 开栈
  400ea4:	48 89 e6             	mov    %rsp,%rsi					// 栈顶指针给到第二个参数
  400ea7:	e8 97 08 00 00       	callq  401743 <read_six_numbers>	// 调用函数读数据
  400eac:	48 89 e5             	mov    %rsp,%rbp					// 保存栈指针到rbp
  400eaf:	4c 8d 6c 24 0c       	lea    0xc(%rsp),%r13				// 栈指针+12保存到r13
  400eb4:	41 bc 00 00 00 00    	mov    $0x0,%r12d					// r12低32位清零
  // ----------------------------------------------------- 循环 -------------------------------------------- //
  400eba:	48 89 eb             	mov    %rbp,%rbx					// rbp的值保存到rbx,【下文跳转到这】
  400ebd:	8b 45 0c             	mov    0xc(%rbp),%eax				// M[rbp+12]保存到eax
  400ec0:	39 45 00             	cmp    %eax,0x0(%rbp)				// 看 M[rbp] 和 M[rbp+12] 是否相等
  400ec3:	74 05                	je     400eca <phase_2+0x3e>		// 如果M[rbp]和M[rbp+12]不等则bomb
  400ec5:	e8 73 07 00 00       	callq  40163d <explode_bomb>		
  400eca:	44 03 23             	add    (%rbx),%r12d					// r12 += M[rbx]
  400ecd:	48 83 c5 04          	add    $0x4,%rbp					// rbp += 4,rbp为迭代指针
  400ed1:	4c 39 ed             	cmp    %r13,%rbp					// r13和rbp如果不等则跳转
  400ed4:	75 e4                	jne    400eba <phase_2+0x2e>
  // ---------------------------------------------------- 循环结束 ------------------------------------------ //
  400ed6:	45 85 e4             	test   %r12d,%r12d					// r12d是累加值,累加值为0则bomb
  400ed9:	75 05                	jne    400ee0 <phase_2+0x54>
  400edb:	e8 5d 07 00 00       	callq  40163d <explode_bomb>
  400ee0:	48 8b 5c 24 28       	mov    0x28(%rsp),%rbx				// 退栈
  400ee5:	48 8b 6c 24 30       	mov    0x30(%rsp),%rbp
  400eea:	4c 8b 64 24 38       	mov    0x38(%rsp),%r12
  400eef:	4c 8b 6c 24 40       	mov    0x40(%rsp),%r13
  400ef4:	48 83 c4 48          	add    $0x48,%rsp
  400ef8:	c3                   	retq   

可以清晰的看到,一开始先读取6个数(英文阅读理解可知),然后使用rbp作为迭代指针,rbp+12为迭代终点,一共迭代三次,而每次我们都将M[rbp] 和 M[rbp+12] 处的数据比对,如果不等则bomb,而且一个int刚好是4字节,三个就是12!结合刚刚的读取6个数字,可以大胆的猜测,这是在判断 a[i] 和 a[i+3] 是否相等!

逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第3张图片
r12之前清零,但是每次又 += M[rbx],猜测 是在计算累加和,根据后文的test $r12d $r12d,可以知道,如果三个数累加起来是0,即使a[i] = a[i+3] 也会炸,所以可以拆弹了!

因为1145141919810是好数字,不妨输入 114 514 1919810 114 514 1919810,可以满足条件!

答案:

114 514 1919810 114 514 1919810
a b c a b c 且 (a+b+c)!=0 即可

第三关switch

汇编源码及个人注释
逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第4张图片

0000000000400ef9 <phase_3>:
  400ef9:	48 83 ec 18          	sub    $0x18,%rsp					// 开栈
  400efd:	48 8d 4c 24 08       	lea    0x8(%rsp),%rcx				// rcx = rsp+8  第四个参数
  400f02:	48 8d 54 24 0c       	lea    0xc(%rsp),%rdx				// rdx = rsp+12 第三个参数
  400f07:	be be 1e 40 00       	mov    $0x401ebe,%esi				// 第二个参数 gdb查找这个字符串的值是 "%d %d"
  400f0c:	b8 00 00 00 00       	mov    $0x0,%eax					// 返回值低32字节置0
  400f11:	e8 9a fb ff ff       	callq  400ab0 <__isoc99_sscanf@plt>	// 读数据
  400f16:	83 f8 01             	cmp    $0x1,%eax					// scanf返回不为1则bomb
  400f19:	7f 05                	jg     400f20 <phase_3+0x27>
  400f1b:	e8 1d 07 00 00       	callq  40163d <explode_bomb>
  400f20:	83 7c 24 0c 07       	cmpl   $0x7,0xc(%rsp)				// 7 < M[rsp+12](第一个%d) 则跳转到bomb
  400f25:	77 3c                	ja     400f63 <phase_3+0x6a>
  400f27:	8b 44 24 0c          	mov    0xc(%rsp),%eax				// M[rsp+12](第一个%d)存到eax
  400f2b:	ff 24 c5 60 1b 40 00 	jmpq   *0x401b60(,%rax,8)			// 跳转到 M[0x401b60+ 8*rax] 地址
  400f32:	b8 17 02 00 00       	mov    $0x217,%eax					// if rax=0则到这里,eax=535
  400f37:	eb 3b                	jmp    400f74 <phase_3+0x7b>
  400f39:	b8 d6 00 00 00       	mov    $0xd6,%eax					// if rax=2则到这里,eax=214
  400f3e:	eb 34                	jmp    400f74 <phase_3+0x7b>		
  400f40:	b8 53 01 00 00       	mov    $0x153,%eax					// if rax=3则到这里,eax=339
  400f45:	eb 2d                	jmp    400f74 <phase_3+0x7b>		
  400f47:	b8 77 00 00 00       	mov    $0x77,%eax					// if rax=4则到这里,eax=119
  400f4c:	eb 26                	jmp    400f74 <phase_3+0x7b>		
  400f4e:	b8 60 01 00 00       	mov    $0x160,%eax					// if rax=5则到这里,eax=352
  400f53:	eb 1f                	jmp    400f74 <phase_3+0x7b>		
  400f55:	b8 97 03 00 00       	mov    $0x397,%eax					// if rax=6则到这里,eax=919
  400f5a:	eb 18                	jmp    400f74 <phase_3+0x7b>		
  400f5c:	b8 9c 01 00 00       	mov    $0x19c,%eax					// if rax=7则到这里,eax=412
  400f61:	eb 11                	jmp    400f74 <phase_3+0x7b>
  400f63:	e8 d5 06 00 00       	callq  40163d <explode_bomb>		// bomb
  400f68:	b8 00 00 00 00       	mov    $0x0,%eax					
  400f6d:	eb 05                	jmp    400f74 <phase_3+0x7b>
  400f6f:	b8 9e 03 00 00       	mov    $0x39e,%eax					// if rax=1则到这里,eax=926
  400f74:	3b 44 24 08          	cmp    0x8(%rsp),%eax				// switch转到这里,如果第二个%d不等于eax,则bomb
  400f78:	74 05                	je     400f7f <phase_3+0x86>
  400f7a:	e8 be 06 00 00       	callq  40163d <explode_bomb>
  400f7f:	48 83 c4 18          	add    $0x18,%rsp					// 退栈
  400f83:	c3                   	retq  

先关注scanf调用前,传入第三第四个参数了,他们存在rsp+8和rsp+12位置,从间距来看应该是int(4字节嘛),然后又向esi传入常量,推测是scanf格式确定的字符串,查看,果然,是“%d %d”,基本可以确定输入的是两个整数

在这里插入图片描述
然后注意到返回后判断了第一个数是否大于7,如果是则bomb,那么可以确定第一个数取值为0~7

然后有一个变址跳转,目的地址是M[0x401b60 + rax*8],rax是第一个%d,然后看看跳转之后的地址,在gdb中打印,分别对应第一个输入为0~7时跳转的目的地址

逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第5张图片
如图,从上到下对应0~7的跳转,见上面注释部分

跳转之后,为第一个输入的变量赋新值,然后判断第二个%d输入(rsp+8)和他是否相等,不等则bomb,那么思路很明确了,就是第一个值决定switch,然后判断第二个值是否对应,观察switch可知,这里有8个答案

答案(选一即可)

0 	535
1 	926
2 	214
3 	339
4 	119
5 	352
6 	919
7 	412

第四关递归(斐波那契第n项)

汇编源码及个人注释
逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第6张图片

0000000000400fc1 <phase_4>:
  400fc1:	48 83 ec 18          	sub    $0x18,%rsp					// 开栈
  400fc5:	48 8d 54 24 0c       	lea    0xc(%rsp),%rdx				// rdx=rsp+12,设置第三个参数为rsp+12,即存放输入
  400fca:	be c1 1e 40 00       	mov    $0x401ec1,%esi				// 根据上面几题的经验应该是scanf的格式字串,为%d
  400fcf:	b8 00 00 00 00       	mov    $0x0,%eax					// eax置零
  400fd4:	e8 d7 fa ff ff       	callq  400ab0 <__isoc99_sscanf@plt>	
  400fd9:	83 f8 01             	cmp    $0x1,%eax					// scanf返回值是否为1?不为1则bomb	
  400fdc:	75 07                	jne    400fe5 <phase_4+0x24>
  400fde:	83 7c 24 0c 00       	cmpl   $0x0,0xc(%rsp)				// 进一步比较输入的int是否大于0
  400fe3:	7f 05                	jg     400fea <phase_4+0x29>
  400fe5:	e8 53 06 00 00       	callq  40163d <explode_bomb>		// 输入的int为0也bomb
  400fea:	8b 7c 24 0c          	mov    0xc(%rsp),%edi				// 如果输入int大于0则到这里,设置fun4第一个参数为输入的int
  400fee:	e8 91 ff ff ff       	callq  400f84 <func4>
  400ff3:	83 f8 37             	cmp    $0x37,%eax					// 返回值是否为55?
  400ff6:	74 05                	je     400ffd <phase_4+0x3c>
  400ff8:	e8 40 06 00 00       	callq  40163d <explode_bomb>		// 返回值不为55则bomb
  400ffd:	48 83 c4 18          	add    $0x18,%rsp					// 返回值为55则退栈
  401001:	c3                   	retq   

同样观察参数,发现这次scanf只读一个参数,根据前面的经验不难看出,0x401ec1存储的是scanf的常字符串,那么gdb查看他,发现是一个int

在这里插入图片描述

然后往下看,读取的int必须大于0,再看,使用我们输入的int做了一个函数fun4的参数,如果fun4的返回值为55则退栈,否则bomb,看来问题聚焦在fun4上了,查看fun4:

逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第7张图片

0000000000400f84 <func4>:
  400f84:	48 89 5c 24 f0       	mov    %rbx,-0x10(%rsp)
  400f89:	48 89 6c 24 f8       	mov    %rbp,-0x8(%rsp)
  400f8e:	48 83 ec 18          	sub    $0x18,%rsp			// 开栈
  400f92:	89 fb                	mov    %edi,%ebx			
  400f94:	b8 01 00 00 00       	mov    $0x1,%eax			// 返回值置1
  400f99:	83 ff 01             	cmp    $0x1,%edi			// 如果第一个参数为1,直接返回(此时返回值是1)
  400f9c:	7e 14                	jle    400fb2 <func4+0x2e>	
  400f9e:	8d 7b ff             	lea    -0x1(%rbx),%edi		// 设置第一个参数 edi = rbx -1,再递归调用fun4
  400fa1:	e8 de ff ff ff       	callq  400f84 <func4>		
  400fa6:	89 c5                	mov    %eax,%ebp			// 返回值保存到 ebp
  400fa8:	8d 7b fe             	lea    -0x2(%rbx),%edi		// 设置第一个参数 edi = rbx -2,再递归调用fun4
  400fab:	e8 d4 ff ff ff       	callq  400f84 <func4>
  400fb0:	01 e8                	add    %ebp,%eax			// ebp += 返回值
  400fb2:	48 8b 5c 24 08       	mov    0x8(%rsp),%rbx		// 退栈
  400fb7:	48 8b 6c 24 10       	mov    0x10(%rsp),%rbp
  400fbc:	48 83 c4 18          	add    $0x18,%rsp
  400fc0:	c3                   	retq   

Fun4一进来判断输入,如果是1返回1,如果不是,返回fun4(x-1)+fun4(x-2),显然这是斐波那契数列,那么fib的第几项等于55呢?应该是9,看:[1,1,2,3,5,8,13,21,55]

答案:

9

第五关:跳转数组

汇编源码及个人注释
逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第8张图片

0000000000401002 <phase_5>:
  401002:	48 83 ec 18          	sub    $0x18,%rsp						// 开栈
  401006:	48 8d 4c 24 08       	lea    0x8(%rsp),%rcx					// 第四个参数 += M[rsp+8]
  40100b:	48 8d 54 24 0c       	lea    0xc(%rsp),%rdx					// 第三个参数 += M[rsp+12]
  401010:	be be 1e 40 00       	mov    $0x401ebe,%esi					// 第二个参数,gdb查看内容为"%d %d"
  401015:	b8 00 00 00 00       	mov    $0x0,%eax						// eax清零
  40101a:	e8 91 fa ff ff       	callq  400ab0 <__isoc99_sscanf@plt>	
  40101f:	83 f8 01             	cmp    $0x1,%eax						// 如果eax<=1那么bomb
  401022:	7f 05                	jg     401029 <phase_5+0x27>
  401024:	e8 14 06 00 00       	callq  40163d <explode_bomb>
  401029:	8b 44 24 0c          	mov    0xc(%rsp),%eax					// eax = M[rsp+12],即输入的第一个int
  40102d:	83 e0 0f             	and    $0xf,%eax						// eax &= f,即保留低4位
  401030:	89 44 24 0c          	mov    %eax,0xc(%rsp)					// M[rsp+12] = eax ,即保留eax的低4位
  401034:	83 f8 0f             	cmp    $0xf,%eax						// 如果eax = 15那么bomb
  401037:	74 2c                	je     401065 <phase_5+0x63>
  401039:	b9 00 00 00 00       	mov    $0x0,%ecx						// ecx清零
  40103e:	ba 00 00 00 00       	mov    $0x0,%edx						// edx清零
  // -------------------------------------------------- 循环 ---------------------------------------------------------//
  401043:	83 c2 01             	add    $0x1,%edx						// edx += 1 ,记录循环次数
  401046:	48 98                	cltq									// 拓展字节
  401048:	8b 04 85 a0 1b 40 00 	mov    0x401ba0(,%rax,4),%eax			// eax = M[0x401ba0+rax*4] (eax rax是一个寄存器)
  40104f:	01 c1                	add    %eax,%ecx						// ecx += eax,记录累加值
  401051:	83 f8 0f             	cmp    $0xf,%eax						// 如果eax不等于15则继续
  401054:	75 ed                	jne    401043 <phase_5+0x41>
  // ------------------------------------------------ 循环结束 -------------------------------------------------------//
  401056:	89 44 24 0c          	mov    %eax,0xc(%rsp)					// M[rsp+12] = eax,即=15
  40105a:	83 fa 0c             	cmp    $0xc,%edx						// 如果edx(循环次数)不等于12则bomb
  40105d:	75 06                	jne    401065 <phase_5+0x63>
  40105f:	3b 4c 24 08          	cmp    0x8(%rsp),%ecx					// M[rsp+8]即输入的第二个int,不等于ecx则bomb
  401063:	74 05                	je     40106a <phase_5+0x68>
  401065:	e8 d3 05 00 00       	callq  40163d <explode_bomb>			
  40106a:	48 83 c4 18          	add    $0x18,%rsp						// 退栈
  40106e:	c3                   	retq   

一开始还是观察scanf的输入,两个lea语句将scanf的第三第四个参数确定,gdb esi的地址查看输入格式,发现是%d%d两个int

在这里插入图片描述
然后发现第一个输出是会被截断到0~15的,如果第一个输入等于15那么直接炸

关注之后的语句,发现有一个循环,edx每次++,eax每次指向内存中的一个地址,因为eax和rax是同一个,相当于 k = next[k] 这种数组跳转语句,而且偏移的单位是4字节,刚好是一个int,这更加坚定了这里出现数组跳转语句的判断了,gdb查看这个数组,果然

在这里插入图片描述

那么知道了跳转数组之后,发现跳转次数只能是12,而且,第二个输入的int必须等于每次跳转的目标下标的累加和,而且最后一次跳转的结果是15,所以画跳转路径:

逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第9张图片
要想跳转12次才到15,这里需要从15反推路径,推出了是从7下标开始,跳转12次即可到达15,而将他们加和起来,累加和是

11+13+9+4+8+0+10+1+2+14+6+15 = 93

答案

7 93

第六关:

这题我没看懂,但是最后有一个比较,如果不等则bomb,我是通过gdb读取cmp的比较值,来猜输入是哪个数字的,属于投机取巧法

汇编源码及个人注释

逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第10张图片

00000000004010d9 <phase_6>:
  4010d9:	48 83 ec 08          	sub    $0x8,%rsp									// 开栈
  4010dd:	ba 0a 00 00 00       	mov    $0xa,%edx									// 第三个参数=10,strtol转换基数为10
  4010e2:	be 00 00 00 00       	mov    $0x0,%esi									// 第二个参数=0
  4010e7:	e8 94 fa ff ff       	callq  400b80 <strtol@plt>							// 将字符串根据基数转换为长整型数
  4010ec:	89 05 8e 16 20 00    	mov    %eax,0x20168e(%rip)        # 602780 <node0>	// M[20168e+rip] = eax(返回值)
  4010f2:	bf 80 27 60 00       	mov    $0x602780,%edi								// edi为第一个参数,这个位置应该是输入的字符串
  4010f7:	e8 73 ff ff ff       	callq  40106f <fun6>
  4010fc:	48 8b 40 08          	mov    0x8(%rax),%rax								// rax = M[rax+8] rax:返回值
  401100:	48 8b 40 08          	mov    0x8(%rax),%rax								// rax = M[rax+8] 
  401104:	48 8b 40 08          	mov    0x8(%rax),%rax								// rax = M[rax+8] 
  401108:	8b 15 72 16 20 00    	mov    0x201672(%rip),%edx        # 602780 <node0>	// edx = M[201672+rip]
  40110e:	39 10                	cmp    %edx,(%rax)									// 如果edx 不等于 rax则bomb
  401110:	74 05                	je     401117 <phase_6+0x3e>
  401112:	e8 26 05 00 00       	callq  40163d <explode_bomb>
  401117:	48 83 c4 08          	add    $0x8,%rsp									// 退栈
  40111b:	c3                   	retq   

这里一开始调用strtol,同时传入一个字符串,这个字符串的位置是0x602780

推测是让我们输入一个字符串,然后转换为long,然后这个long会传入fun6,一顿操作之后,附带几次寻址,比较 rdx 和M[rax] 的值,如果不相等则炸,那么关键点就在fun6了,查看fun6代码:

逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第11张图片

000000000040106f <fun6>:
  40106f:	4c 8b 47 08          	mov    0x8(%rdi),%r8		// 第五个参数 = M[rdi(第一个参数)+8] 
  401073:	48 c7 47 08 00 00 00 	movq   $0x0,0x8(%rdi)		// M[rdi+8] = 0
  40107a:	00 
  40107b:	48 89 f8             	mov    %rdi,%rax			// rax = rdi
  40107e:	48 89 f9             	mov    %rdi,%rcx			// rcx = rdi
  401081:	4d 85 c0             	test   %r8,%r8				// 第五个参数不等于0则跳转
  401084:	75 40                	jne    4010c6 <fun6+0x57>
  401086:	48 89 f8             	mov    %rdi,%rax			// rax = rdi(第一个参数)
  401089:	c3                   	retq						// 退栈
  // -------------------------------------------------- 循环 ---------------------------------------------------------//
  40108a:	48 89 d1             	mov    %rdx,%rcx			// rcx = rdx
  40108d:	48 8b 51 08          	mov    0x8(%rcx),%rdx		// rdx = M[rcx+8],即rdx=M[rdx+8]
  401091:	48 85 d2             	test   %rdx,%rdx			// 如果rdx=0则跳转
  401094:	74 09                	je     40109f <fun6+0x30>
  401096:	39 32                	cmp    %esi,(%rdx)			// M[rdx]
  401098:	7f f0                	jg     40108a <fun6+0x1b>
  // ------------------------------------------------ 循环结束 -------------------------------------------------------//
  40109a:	48 89 cf             	mov    %rcx,%rdi			// rdi = rcx
  40109d:	eb 03                	jmp    4010a2 <fun6+0x33>
  40109f:	48 89 cf             	mov    %rcx,%rdi			// 如果rdx=0则到这rdi = rcx
  // -------------------------------------------------- 循环 ---------------------------------------------------------//
  4010a2:	48 39 d7             	cmp    %rdx,%rdi			// 如果rdi = rdx
  4010a5:	74 06                	je     4010ad <fun6+0x3e>
  4010a7:	4c 89 47 08          	mov    %r8,0x8(%rdi)
  4010ab:	eb 03                	jmp    4010b0 <fun6+0x41>
  4010ad:	4c 89 c0             	mov    %r8,%rax				// 如果rdi=rdx则到这,rax=第五个参数
  4010b0:	49 8b 48 08          	mov    0x8(%r8),%rcx		// rcx = M[r8+8]
  4010b4:	49 89 50 08          	mov    %rdx,0x8(%r8)		// M[r8+8] = rdx
  4010b8:	48 85 c9             	test   %rcx,%rcx			// 如果rcx=0则跳至结束
  4010bb:	74 1a                	je     4010d7 <fun6+0x68>	
  4010bd:	49 89 c8             	mov    %rcx,%r8				// r8 = cax
  4010c0:	48 89 c1             	mov    %rax,%rcx			// rcx = rax
  4010c3:	48 89 c7             	mov    %rax,%rdi			// rdi = rax
  4010c6:	48 89 ca             	mov    %rcx,%rdx			// 如果第五个参数不等于0那么到这 rdx=rcx
  4010c9:	48 85 c9             	test   %rcx,%rcx			
  4010cc:	74 d4                	je     4010a2 <fun6+0x33>	// 如果rcx=0那么跳转到4010a2
  // ------------------------------------------------ 循环结束 -------------------------------------------------------//
  4010ce:	41 8b 30             	mov    (%r8),%esi			// esi = M[r8]
  4010d1:	39 31                	cmp    %esi,(%rcx)
  4010d3:	7f b8                	jg     40108d <fun6+0x1e>	// 如果esi
  4010d5:	eb cb                	jmp    4010a2 <fun6+0x33>
  4010d7:	f3 c3                	repz retq 

看到fun6汇编的瞬间我双手离开键盘,我发现写完注释我还是看不懂,于是打算还是从判断语句反推

我通过在cmp语句设置断点(如下图),然后查看rdx 和 M[rax] 的值,发现rdx是我的输入(1234567),M[rax]是673,站在上帝视角,我猜测要想避免炸弹,输入必须等于673
逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第12张图片
于是直接投机取巧输入673 。。。。。。过了

答案:

673

逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第13张图片

总结

复习到了很多知识,比如寄存器的功能,寻址方式,指令,gdb的使用等

X86 64位寄存器的功能:(借用书上图片)

逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第14张图片
还了解了调用者保存和被调用者保存,知了晓递归调用时如何保存状态,比如调用者保存就是父函数自己想办法保存数据,而被调用者保存则是子函数帮忙保存父函数的数据

寻址方式(同样借用书上图片)

其中最常用的就是 imm(rb) 这种,翻译过来就是 M[imm + R(rb)]
逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第15张图片

指令

还复习了各种指令,用的最多的当属mov和add,jump指令
逆向工程实验(拆炸弹bomb实验)(深大计系2实验3) 6题答案+解法_第16张图片

技巧总结:

  • 在汇编中esi常常用作scanf格式常字符串存放的地方,而rax是返回值,通过观察scanf的参数可以很快确定输入的格式是啥,这样才能做题
  • 汇编中选择语句的使用:使用cmp或者test判断,然后jump
  • 汇编中循环语句的使用:使用某个寄存器作为迭代指针,然后不到一定条件,就一直跳转到循环起始点,否则break。int数组迭代的循环有一个明显的特征,那就是每次指针前进4字节,刚好一个int,这个技巧使得我很快看出来第二题的循环结构
  • 如果一个指针自己寻址自己,即 k = a[k] 这种,要很快想到是数组跳转,在上学期数据结构课程,kmp算法也有类似语句 k = next[k],这使得我很快发现第五题的跳转结构

Gdb使用技巧:

run 执行
si 单步执行

b 设置断点,可以在函数调用时中断,即 
b  func1
或者在指定地址处中断,比如
b  *0x12f3de
在指定位置设置断点可以更好的判断触发bomb的条件,可以打印对应的寄存器看看值是多少,这样能够有效避免bomb,第六题我就是用这个技巧投机取巧

p 查看数据
p (char*)0x123fed 查看对应地址的字符串,在分析scanf的输入格式时很有效
还可以查看某个地址对应的数组,比如
p *0x30fed4@7,查看0x30fed4往后对应7个数字,查看数组在第五题尤其重要
查看寄存器
p $rdx
查看寻址结果
p *(0x3014fd) 或者 p *($rdx)

你可能感兴趣的:(计算机系统,汇编,反汇编,gdb,逆向工程,c语言)