二进制炸弹Lab
Lab 采用的是 coursera 上華盛頓大學的The Hardware/Software Interface. 與CSAPP書上的不同,這里的lab采用的是64位機器。
Lab2 要求拆除6個炸彈加一個secret bomb。
?
phase_1
0000000000400e70 <phase_1>:400e70: 48 83 ec 08 sub $0x8,%rsp400e74: be f8 1a 40 00 mov $0x401af8,%esi400e79: e8 bf 03 00 00 callq 40123d <strings_not_equal>400e7e: 85 c0 test %eax,%eax400e80: 74 05 je 400e87 <phase_1+0x17>400e82: e8 b6 07 00 00 callq 40163d <explode_bomb>400e87: 48 83 c4 08 add $0x8,%rsp400e8b: c3 retq 000000000040123d <strings_not_equal>:40123d: 48 89 5c 24 e8 mov %rbx,-0x18(%rsp)401242: 48 89 6c 24 f0 mov %rbp,-0x10(%rsp)401247: 4c 89 64 24 f8 mov %r12,-0x8(%rsp)40124c: 48 83 ec 18 sub $0x18,%rsp401250: 48 89 fb mov %rdi,%rbx401253: 48 89 f5 mov %rsi,%rbp401256: e8 c6 ff ff ff callq 401221 <string_length>40125b: 41 89 c4 mov %eax,%r12d40125e: 48 89 ef mov %rbp,%rdi401261: e8 bb ff ff ff callq 401221 <string_length>401266: ba 01 00 00 00 mov $0x1,%edx40126b: 41 39 c4 cmp %eax,%r12d40126e: 75 36 jne 4012a6 <strings_not_equal+0x69> 0000000000401221 <string_length>:401221: b8 00 00 00 00 mov $0x0,%eax401226: 80 3f 00 cmpb $0x0,(%rdi)401229: 74 10 je 40123b <string_length+0x1a>40122b: 48 89 fa mov %rdi,%rdx40122e: 48 83 c2 01 add $0x1,%rdx401232: 89 d0 mov %edx,%eax401234: 29 f8 sub %edi,%eax401236: 80 3a 00 cmpb $0x0,(%rdx)401239: 75 f3 jne 40122e <string_length+0xd>40123b: f3 c3 repz retq?
string_length 中的代碼比較好懂,是以%rdi中的內容為地址,然后與0比較(0即是字符串的終結符號)。所以字符串起始地址應該藏在%rdi中!再看?strings_not_equal,分別有兩次 string_length 調用,再結合函數名?strings_not_equal,可以想見是我們輸入的字符串與藏在程序中的字符串進行比較!所以只要在?401256,401261兩處設置斷點,打印出以%rdi中內容為起始地址的字符串。其中一個是我們輸入的字符串,而另一個就是我們尋找的字符串。
?
phase_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,%rsp400ea4: 48 89 e6 mov %rsp,%rsi400ea7: e8 97 08 00 00 callq 401743 <read_six_numbers>400eac: 48 89 e5 mov %rsp,%rbp400eaf: 4c 8d 6c 24 0c lea 0xc(%rsp),%r13400eb4: 41 bc 00 00 00 00 mov $0x0,%r12d400eba: 48 89 eb mov %rbp,%rbx400ebd: 8b 45 0c mov 0xc(%rbp),%eax400ec0: 39 45 00 cmp %eax,0x0(%rbp)400ec3: 74 05 je 400eca <phase_2+0x3e>400ec5: e8 73 07 00 00 callq 40163d <explode_bomb>400eca: 44 03 23 add (%rbx),%r12d400ecd: 48 83 c5 04 add $0x4,%rbp400ed1: 4c 39 ed cmp %r13,%rbp400ed4: 75 e4 jne 400eba <phase_2+0x2e>400ed6: 45 85 e4 test %r12d,%r12d400ed9: 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),%rbx400ee5: 48 8b 6c 24 30 mov 0x30(%rsp),%rbp400eea: 4c 8b 64 24 38 mov 0x38(%rsp),%r12400eef: 4c 8b 6c 24 40 mov 0x40(%rsp),%r13400ef4: 48 83 c4 48 add $0x48,%rsp400ef8: c3 retq?
phase_2 會調用?read_six_numbers,所以我們要輸入的應該是6個數字。
這段匯編代碼比較好懂,是讓我們比較 0x0(%rbp) 與 0xc(%rbp) ,0x4(%rbp) 與 0x10(%rbp),0x8(%rbp) 與 0x14(%rbp)的內容,一旦有一個不符就引爆炸彈,同時還會檢測?0x0(%rbp) +?0x4(%rbp) +?0x8(%rbp) 的和是否為0,為0則引爆炸彈。
那么上面這些與我們輸入的數字又有什么關系呢?只要在gdb中打印出來看看就行了。
啊哈,表示的就是我們輸入進去的數字嘛。所以我們只要保證后三位與前三位相同同時前三位之和不為0就ok了。 比如 1 2 3 1 2 3
?
phase_3
0000000000400ef9 <phase_3>:400ef9: 48 83 ec 18 sub $0x18,%rsp400efd: 48 8d 4c 24 08 lea 0x8(%rsp),%rcx400f02: 48 8d 54 24 0c lea 0xc(%rsp),%rdx400f07: be be 1e 40 00 mov $0x401ebe,%esi400f0c: b8 00 00 00 00 mov $0x0,%eax400f11: e8 9a fb ff ff callq 400ab0 <__isoc99_sscanf@plt>400f16: 83 f8 01 cmp $0x1,%eax400f19: 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)400f25: 77 3c ja 400f63 <phase_3+0x6a>400f27: 8b 44 24 0c mov 0xc(%rsp),%eax400f2b: ff 24 c5 60 1b 40 00 jmpq *0x401b60(,%rax,8)400f32: b8 17 02 00 00 mov $0x217,%eax400f37: eb 3b jmp 400f74 <phase_3+0x7b>400f39: b8 d6 00 00 00 mov $0xd6,%eax400f3e: eb 34 jmp 400f74 <phase_3+0x7b>400f40: b8 53 01 00 00 mov $0x153,%eax400f45: eb 2d jmp 400f74 <phase_3+0x7b>400f47: b8 77 00 00 00 mov $0x77,%eax400f4c: eb 26 jmp 400f74 <phase_3+0x7b>400f4e: b8 60 01 00 00 mov $0x160,%eax400f53: eb 1f jmp 400f74 <phase_3+0x7b>400f55: b8 97 03 00 00 mov $0x397,%eax400f5a: eb 18 jmp 400f74 <phase_3+0x7b>400f5c: b8 9c 01 00 00 mov $0x19c,%eax400f61: eb 11 jmp 400f74 <phase_3+0x7b>400f63: e8 d5 06 00 00 callq 40163d <explode_bomb>400f68: b8 00 00 00 00 mov $0x0,%eax400f6d: eb 05 jmp 400f74 <phase_3+0x7b>400f6f: b8 9e 03 00 00 mov $0x39e,%eax400f74: 3b 44 24 08 cmp 0x8(%rsp),%eax400f78: 74 05 je 400f7f <phase_3+0x86>400f7a: e8 be 06 00 00 callq 40163d <explode_bomb>400f7f: 48 83 c4 18 add $0x18,%rsp400f83: c3 retq?
?400ab0 <__isoc99_sscanf@plt> 指明了 sscanf 是標準庫函數,經查文檔,得到該函數的 signature 為?int sscanf(const char *buffer,const char *format,[argument ]...);
與gets函數一樣都要有buffer,結合前面將?0x8(%rsp),0xc(%rsp) 的地址壓入寄存器,以及后面會取出0x8(%rsp),0xc(%rsp)進行其他操作,所以猜測應該是輸入的內容放入棧中這兩個位置(作為buffer)。而且該函數的返回值(返回值為參數數目)要求大于1才不會爆炸,所以結合buffer的大小為2輸入的應該是兩個字符。%esi 對應的是參數?const char *forma,經打印為
更加確定輸入的是兩個字符,而且是兩個數字。
后面部分就很簡單,要求輸入的第一個數字小于等于7,且跳轉到 *(0x401b60 + 8 * args[1] ) 處。
這是一個switch結構,分別對eax賦值,然后與我們輸入的第二個數字比較,相等才過關。
所以相應的這里的答案也有8組。其中一組為 0 535 。
?
phase_4
0000000000400fc1 <phase_4>:400fc1: 48 83 ec 18 sub $0x18,%rsp400fc5: 48 8d 54 24 0c lea 0xc(%rsp),%rdx400fca: be c1 1e 40 00 mov $0x401ec1,%esi400fcf: b8 00 00 00 00 mov $0x0,%eax400fd4: e8 d7 fa ff ff callq 400ab0 <__isoc99_sscanf@plt>400fd9: 83 f8 01 cmp $0x1,%eax400fdc: 75 07 jne 400fe5 <phase_4+0x24>400fde: 83 7c 24 0c 00 cmpl $0x0,0xc(%rsp)400fe3: 7f 05 jg 400fea <phase_4+0x29>400fe5: e8 53 06 00 00 callq 40163d <explode_bomb>400fea: 8b 7c 24 0c mov 0xc(%rsp),%edi400fee: e8 91 ff ff ff callq 400f84 <func4>400ff3: 83 f8 37 cmp $0x37,%eax400ff6: 74 05 je 400ffd <phase_4+0x3c>400ff8: e8 40 06 00 00 callq 40163d <explode_bomb>400ffd: 48 83 c4 18 add $0x18,%rsp401001: c3 retq 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,%rsp400f92: 89 fb mov %edi,%ebx400f94: b8 01 00 00 00 mov $0x1,%eax400f99: 83 ff 01 cmp $0x1,%edi400f9c: 7e 14 jle 400fb2 <func4+0x2e>400f9e: 8d 7b ff lea -0x1(%rbx),%edi400fa1: e8 de ff ff ff callq 400f84 <func4>400fa6: 89 c5 mov %eax,%ebp400fa8: 8d 7b fe lea -0x2(%rbx),%edi400fab: e8 d4 ff ff ff callq 400f84 <func4>400fb0: 01 e8 add %ebp,%eax400fb2: 48 8b 5c 24 08 mov 0x8(%rsp),%rbx400fb7: 48 8b 6c 24 10 mov 0x10(%rsp),%rbp400fbc: 48 83 c4 18 add $0x18,%rsp400fc0: c3?
要求是輸入一個數(只能有一個數),要求這個數比0大,而且將這個數作為 func4 的參數。然后要求func4函數的返回值為55(0x37).而func4這個函數是個遞歸函數,所以這題的關鍵是func4函數。我們只要寫出該函數的 C 形式,然后不同的數去試就ok了。
int func4(int n) {if (n <= 1)return 1;return func4(n-1) + func4(n-2); } int main(void) {int i;for (i = 2; 1; i++) {if (func4(i) == 55)break;}printf("%d\n", i); }?
輸出為 9,所以答案即為9.
?
phase_5
0000000000401002 <phase_5>:401002: 48 83 ec 18 sub $0x18,%rsp401006: 48 8d 4c 24 08 lea 0x8(%rsp),%rcx40100b: 48 8d 54 24 0c lea 0xc(%rsp),%rdx401010: be be 1e 40 00 mov $0x401ebe,%esi401015: b8 00 00 00 00 mov $0x0,%eax40101a: e8 91 fa ff ff callq 400ab0 <__isoc99_sscanf@plt>40101f: 83 f8 01 cmp $0x1,%eax401022: 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),%eax40102d: 83 e0 0f and $0xf,%eax401030: 89 44 24 0c mov %eax,0xc(%rsp)401034: 83 f8 0f cmp $0xf,%eax401037: 74 2c je 401065 <phase_5+0x63>401039: b9 00 00 00 00 mov $0x0,%ecx40103e: ba 00 00 00 00 mov $0x0,%edx401043: 83 c2 01 add $0x1,%edx401046: 48 98 cltq 401048: 8b 04 85 a0 1b 40 00 mov 0x401ba0(,%rax,4),%eax40104f: 01 c1 add %eax,%ecx401051: 83 f8 0f cmp $0xf,%eax401054: 75 ed jne 401043 <phase_5+0x41>401056: 89 44 24 0c mov %eax,0xc(%rsp)40105a: 83 fa 0c cmp $0xc,%edx40105d: 75 06 jne 401065 <phase_5+0x63>40105f: 3b 4c 24 08 cmp 0x8(%rsp),%ecx401063: 74 05 je 40106a <phase_5+0x68>401065: e8 d3 05 00 00 callq 40163d <explode_bomb>40106a: 48 83 c4 18 add $0x18,%rsp40106e: c3 retq?
這題也是要求你輸入兩個數字, 然后第一個數字只保留后四位,其他位置0(and $0xf,%eax)。且第一個輸入的數字作為int數組的索引從數組中取數,然后將得到的數字作為索引繼續從數組取數(每經過一次取數:edx+1,ecx不斷將取出的數加到自身)。。。直到取出15。此時要求edx為12,ecx等于第二個輸入的數。
在 0x401048 處設置斷點,不斷嘗試各種數字,看看這個數組中的內容到底是什么。
可以發現輸入7時,可以滿足取出15時要edx為12。此時ecx為93.
所以答案為 7 93
?
?
phase_6
00000000004010d9 <phase_6>:4010d9: 48 83 ec 08 sub $0x8,%rsp4010dd: ba 0a 00 00 00 mov $0xa,%edx4010e2: be 00 00 00 00 mov $0x0,%esi4010e7: e8 94 fa ff ff callq 400b80 <strtol@plt>4010ec: 89 05 8e 16 20 00 mov %eax,0x20168e(%rip) # 602780 <node0>4010f2: bf 80 27 60 00 mov $0x602780,%edi4010f7: e8 73 ff ff ff callq 40106f <fun6>4010fc: 48 8b 40 08 mov 0x8(%rax),%rax401100: 48 8b 40 08 mov 0x8(%rax),%rax401104: 48 8b 40 08 mov 0x8(%rax),%rax401108: 8b 15 72 16 20 00 mov 0x201672(%rip),%edx # 602780 <node0>40110e: 39 10 cmp %edx,(%rax)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,%rsp40111b: c3 retq?
查手冊得,strtol是將字符串中的數字轉化為特定進制,這里的參數edx為0xa,因此轉化為10進制。我們隨便輸入一個數字 100,在 4010ec 處設置斷點,發現eax中的數字就是100.
然后發現fun6的參數edi(0x602780)固定,那么輸出也應該是固定的,所以沒必要去看fun6。
引不引爆的關鍵在40110e處,我們在此處設置斷電,將edx,(rax)的內容都打印一下,
發現edx的數據是我們輸入的值100,而(rax)為600,如圖,因此我們只要開始輸入600應該就通過了(在?4010ec 中我們將100存入0x20168e(%rip)中,在 401108 中我們從?0x201672(%rip)?取出了100)。
因此答案為600.
?
?
secret_phase
?
轉載于:https://www.cnblogs.com/whuyt/p/4842368.html
總結
- 上一篇: 如何更好地推动泰山文化遗产的保护与传承?
- 下一篇: 如何更好地促进泰山旅游业的健康发展?