逆向工程實驗(拆炸彈bomb實驗)(深大計系2實驗3) 6題答案+解法

上一篇【爲拆炸彈實驗做的預習與準備】講述了一些必須的知識

這個實驗是給出可執行文件,要求用gdb反編譯出彙編代碼,一共有6個關卡,要求玩家輸入6個輸入,要通過分析彙編代碼來找到何種輸入不會觸發炸彈,然後輸入正確的輸入信息以拆解炸彈

第一關 字符串比對

彙編原碼及個人註釋

在這裏插入圖片描述

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則跳轉成功,不會觸發<explode_bomb>,然後關注到它將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?

第二關:數組與循環

彙編源碼及個人註釋

在這裏插入圖片描述

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] 是否相等!

在這裏插入圖片描述
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

彙編源碼及個人註釋
在這裏插入圖片描述

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時跳轉的目的地址

在這裏插入圖片描述
如圖,從上到下對應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項)

彙編源碼及個人註釋
在這裏插入圖片描述

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:

在這裏插入圖片描述

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

第五關:跳轉數組

彙編源碼及個人註釋
在這裏插入圖片描述

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,所以畫跳轉路徑:

在這裏插入圖片描述
要想跳轉12次纔到15,這裏需要從15反推路徑,推出了是從7下標開始,跳轉12次即可到達15,而將他們加和起來,累加和是

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

答案

7 93

第六關:

這題我沒看懂,但是最後有一個比較,如果不等則bomb,我是通過gdb讀取cmp的比較值,來猜輸入是哪個數字的,屬於投機取巧法

彙編源碼及個人註釋

在這裏插入圖片描述

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代碼:

在這裏插入圖片描述

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]<esi則跳轉,否則break
  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<M[rcx]則跳轉到40108d
  4010d5:	eb cb                	jmp    4010a2 <fun6+0x33>
  4010d7:	f3 c3                	repz retq 

看到fun6彙編的瞬間我雙手離開鍵盤,我發現寫完註釋我還是看不懂,於是打算還是從判斷語句反推

我通過在cmp語句設置斷點(如下圖),然後查看rdx 和 M[rax] 的值,發現rdx是我的輸入(1234567),M[rax]是673,站在上帝視角,我猜測要想避免炸彈,輸入必須等於673
在這裏插入圖片描述
於是直接投機取巧輸入673 。。。。。。過了

答案:

673

在這裏插入圖片描述

總結

複習到了很多知識,比如寄存器的功能,尋址方式,指令,gdb的使用等

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

在這裏插入圖片描述
還了解了調用者保存和被調用者保存,知了曉遞歸調用時如何保存狀態,比如調用者保存就是父函數自己想辦法保存數據,而被調用者保存則是子函數幫忙保存父函數的數據

尋址方式(同樣借用書上圖片)

其中最常用的就是 imm(rb) 這種,翻譯過來就是 M[imm + R(rb)]
在這裏插入圖片描述

指令

還複習了各種指令,用的最多的當屬mov和add,jump指令
在這裏插入圖片描述

技巧總結:

  • 在彙編中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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章