---
# System prepended metadata

title: 'Day 3 - [LAB] Bomb lab'
tags: [ithome2020]

---

# 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 這兩個部分