# Day 3 - [LAB] Bomb lab ###### tags: `ithome2020` ## main 這題目設計的重點就是這兩個 phase ,要想辦法在 gdb 中繞過這兩個 condition,避免他觸發 exit(1) * [day3Bomb/bomb.c](https://github.com/ian910297/ithome2020/blob/master/day3Bomb/bomb.c) * phase_1: 要修改掉 x 的數值,不然在 ubuntu 底下會被強制瀏覽 pornhub.com ```shell= void phase_1() { int x=12; if(x==12) { system("google-chrome --incognito pornhub.com"); exit(1); } else { printf("pass phase_1\n"); } } ``` * phase_2: 要輸入一串字串,原理是差不多的,但組語的程式碼會稍加複雜 ```shell= void phase_2() { char text[] = "pornhub"; char input[100]; scanf("%s", input); if(strcmp(input, text)==0) {// match printf("pass phase_2\n"); } else { exit(1); } } ``` 開始執行 gdb 後,記得把斷點設在 phase_1 / phase_2,至於怎麼執行,到底是要用 step 還是 stepi,請自行判斷,以下只會節錄重點 ```shell= (gdb) r Starting program: /home/demonic/gitPro/ithome2020/day3Bomb/bomb Missing separate debuginfos, use: zypper install glibc-debuginfo-2.26-lp152.25.10.x86_64 [Detaching after fork from child process 18108] sh: google-chrome: command not found [Inferior 1 (process 18104) exited with code 01] (gdb) b phase_2 Breakpoint 1 at 0x400695: file bomb.c, line 16. (gdb) b phase_1 Breakpoint 2 at 0x40065f: file bomb.c, line 6. ``` ## phase_1 以下組語語法是 AT&T 系列的 ```clike= Dump of assembler code for function phase_1: 0x0000000000400657 <+0>: push %rbp 0x0000000000400658 <+1>: mov %rsp,%rbp 0x000000000040065b <+4>: sub $0x10,%rsp => 0x000000000040065f <+8>: movl $0xc,-0x4(%rbp) 0x0000000000400666 <+15>: cmpl $0xc,-0x4(%rbp) 0x000000000040066a <+19>: jne 0x400680 <phase_1+41> 0x000000000040066c <+21>: mov $0x400798,%edi 0x0000000000400671 <+26>: callq 0x400540 <system@plt> 0x0000000000400676 <+31>: mov $0x1,%edi 0x000000000040067b <+36>: callq 0x400570 <exit@plt> 0x0000000000400680 <+41>: mov $0x4007be,%edi 0x0000000000400685 <+46>: callq 0x400530 <puts@plt> 0x000000000040068a <+51>: nop 0x000000000040068b <+52>: leaveq 0x000000000040068c <+53>: retq ``` 可以發現,重點是要去找 rbp 這個 register,然後對他 -0x4 的位置,進行操作,把數值從 0xc 改掉,改成任意其他數字都好 ```shell= (gdb) p $rbp $14 = (void *) 0x7fffffffe560 (gdb) p 0x7fffffffe560 $15 = 140737488348512 (gdb) p *0x7fffffffe560 $16 = -6800 (gdb) p *(0x7fffffffe560-0x4) $17 = 12 (gdb) p *(0x7fffffffe560-0x4)=2 $18 = 2 (gdb) p *(0x7fffffffe560-0x4) $19 = 2 ``` ## phase_2 ```shell= Dump of assembler code for function phase_2: 0x000000000040068d <+0>: push %rbp 0x000000000040068e <+1>: mov %rsp,%rbp 0x0000000000400691 <+4>: sub $0x70,%rsp => 0x0000000000400695 <+8>: movabs $0x6275686e726f70,%rax 0x000000000040069f <+18>: mov %rax,-0x8(%rbp) 0x00000000004006a3 <+22>: lea -0x70(%rbp),%rax 0x00000000004006a7 <+26>: mov %rax,%rsi 0x00000000004006aa <+29>: mov $0x4007cb,%edi 0x00000000004006af <+34>: mov $0x0,%eax 0x00000000004006b4 <+39>: callq 0x400560 <__isoc99_scanf@plt> 0x00000000004006b9 <+44>: lea -0x8(%rbp),%rdx 0x00000000004006bd <+48>: lea -0x70(%rbp),%rax 0x00000000004006c1 <+52>: mov %rdx,%rsi 0x00000000004006c4 <+55>: mov %rax,%rdi 0x00000000004006c7 <+58>: callq 0x400550 <strcmp@plt> 0x00000000004006cc <+63>: test %eax,%eax 0x00000000004006ce <+65>: jne 0x4006dc <phase_2+79> 0x00000000004006d0 <+67>: mov $0x4007ce,%edi 0x00000000004006d5 <+72>: callq 0x400530 <puts@plt> 0x00000000004006da <+77>: jmp 0x4006e6 <phase_2+89> 0x00000000004006dc <+79>: mov $0x1,%edi 0x00000000004006e1 <+84>: callq 0x400570 <exit@plt> 0x00000000004006e6 <+89>: leaveq 0x00000000004006e7 <+90>: retq ``` 這邊的重點是要先 step 到 scanf,然後隨便輸入一組字串,接著 step 到 strcmp 這種東西都有很多改法,我覺得從 test %eax, %eax 下手也是行得通,不過這邊我打算去讀 "pornhub" 的字串到底存在哪裡,把那個字串讀出來,讓我知道要輸入什麼即可~~ 其實從組語中,很輕易可以觀察到,scanf 所使用的記憶體位置是 -0x70(%rbp),而 pornhub 字串肯定存在 -0x8(%rbp),我們只需要把他打印出來,即可知道 scanf 要輸入什麼~~ ```shell= (gdb) p $rbp-0x8 $4 = (void *) 0x7fffffffe558 (gdb) x $rbp-0x8 0x7fffffffe558: 0x6e726f70 (gdb) p (char*)$rbp-0x8 $5 = 0x7fffffffe558 "pornhub" ``` ## Next 從上面兩個簡單的範例,我們就可以感受到 gdb 的強大,可以任意修改數值,當然也可以修改程式碼,讓那一行直接變成另外一條指令,只是我懶得去查 opcode 在那邊修修改改 而且 GDB 可做到的可不只是這樣,甚至可以 reverse debugging,就是當你已經執行到下一步,仍舊可以返回,這部分可以參考 [GDB and Reverse Debugging](https://www.sourceware.org/gdb/news/reversible.html),但這種功能並不支援所有的平台,像我最近在開發的 RISC-V 就沒支援這東西,或許我吃飽太閒的時候,可以把他 porting 上去~~ 下一篇會介紹 ptrace 要怎麼使用,並使用 ptrace 製作一個簡易的 breakpoint,這邊要注意一件事,ptrace 會使用到 parent/child process 的概念,可能會看得很問號 除此之外,接下來要寫的文章我要稍做一些調整,會加入 systemtap 以及 debuginfod 這兩個部分