実行すると”Give me your shellcode:”と挑発的なことを言ってくるプログラムが題材
使えれば良いやradare2(静的解析編):拾い物のコンパスによくまとめられている、radar2というフレームワークを使う。
gdbとかobjdumpとか、そういうオーソドックスなものより表示が人間にわかりやすい感じで大変嬉しい。
CTFマニアには常識だったのかもしれないが…ついさっき知った。
$ r2 orw [0x080483d0]> aaa <...中略...> [0x080483d0]> afl <...中略...> [0x080483d0]> s sym.main [0x08048548]> VV <...中略...> :> pdf@sym.main ;-- main: / (fcn) sym.main 81 | sym.main (); | ; var int local_4h_2 @ ebp-0x4 | ; var int local_4h @ esp+0x4 | ; DATA XREF from 0x080483e7 (entry0) | 0x08048548 8d4c2404 lea ecx, [local_4h] ; 4 | 0x0804854c 83e4f0 and esp, 0xfffffff0 | 0x0804854f ff71fc push dword [ecx - 4] | 0x08048552 55 push ebp | 0x08048553 89e5 mov ebp, esp | 0x08048555 51 push ecx | 0x08048556 83ec04 sub esp, 4 | 0x08048559 e86dffffff call sym.orw_seccomp | 0x0804855e 83ec0c sub esp, 0xc | 0x08048561 68a0860408 push str.Give_my_your_shellcode: ; 0x80486a0 ; "Give my your shellcode:" | 0x08048566 e815feffff call sym.imp.printf ; int printf(const char *format) | 0x0804856b 83c410 add esp, 0x10 | 0x0804856e 83ec04 sub esp, 4 | 0x08048571 68c8000000 push 0xc8 ; 200 | 0x08048576 6860a00408 push obj.shellcode ; 0x804a060 | 0x0804857b 6a00 push 0 | 0x0804857d e8eefdffff call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte) | 0x08048582 83c410 add esp, 0x10 | 0x08048585 b860a00408 mov eax, obj.shellcode ; 0x804a060 | 0x0804858a ffd0 call eax | 0x0804858c b800000000 mov eax, 0 | 0x08048591 8b4dfc mov ecx, dword [local_4h_2] | 0x08048594 c9 leave | 0x08048595 8d61fc lea esp, [ecx - 4] 0x08048598 c3 ret
なお、参考までにobjdumpコマンドでの逆アセンブルだとこんな感じ。radare2での逆アセンブルの方がパッと見で理解しやすいと思う。
$ objdump -d orw 08048548 <main>: 8048548: 8d 4c 24 04 lea 0x4(%esp),%ecx 804854c: 83 e4 f0 and $0xfffffff0,%esp 804854f: ff 71 fc pushl -0x4(%ecx) 8048552: 55 push %ebp 8048553: 89 e5 mov %esp,%ebp 8048555: 51 push %ecx 8048556: 83 ec 04 sub $0x4,%esp 8048559: e8 6d ff ff ff call 80484cb <orw_seccomp> 804855e: 83 ec 0c sub $0xc,%esp 8048561: 68 a0 86 04 08 push $0x80486a0 8048566: e8 15 fe ff ff call 8048380 <printf@plt> 804856b: 83 c4 10 add $0x10,%esp 804856e: 83 ec 04 sub $0x4,%esp 8048571: 68 c8 00 00 00 push $0xc8 8048576: 68 60 a0 04 08 push $0x804a060 804857b: 6a 00 push $0x0 804857d: e8 ee fd ff ff call 8048370 <read@plt> 8048582: 83 c4 10 add $0x10,%esp 8048585: b8 60 a0 04 08 mov $0x804a060,%eax 804858a: ff d0 call *%eax 804858c: b8 00 00 00 00 mov $0x0,%eax 8048591: 8b 4d fc mov -0x4(%ebp),%ecx 8048594: c9 leave 8048595: 8d 61 fc lea -0x4(%ecx),%esp 8048598: c3 ret 8048599: 66 90 xchg %ax,%ax 804859b: 66 90 xchg %ax,%ax 804859d: 66 90 xchg %ax,%ax 804859f: 90 nop
このwriteup[pwnable.tw] orw — 100pts : Giuseppeがよくできており、もうこれを見るだけで全部済む。
(この記事はソレのほぼ翻訳版みたいな内容なのでwriteupってタイトルにするのをためらった)
0x08048576から0x0804857dまでで、read関数を用いてobj.shellcodeの指すアドレスに最大200バイト、シェルコードを読み込ませている。(“Give me your shellcode:”の後に入力したものが格納される)
続く0x08048585 ~ 0x0804858aで、obj.shellcodeの指すアドレスにジャンプしている。
特に落とし穴はなく、問題文にある通りopen, read, writeシステムコールのみを使って/home/orw/flagを読めば良い。
実際のシェルコードは先ほどの参考writeupに載ってるのでそちらを参照するとして、
流れ的にはopenで/home/orw/flagのファイルディスクリプタを取得、readでファイルディスクリプタで指定した/home/orw/flagからシェルコードの末尾以降にファイルの内容を読み出し、writeで標準出力にそれを出力する。
コメント