Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
static_asm — x86/x86-64命令エンコーディングのためのヘッダオンリーC++2xコンパイル時アセンブラ | Kitploit
ツール/GitHubGitHub/mahmoudimus/static_asm
ペイロード生成コード分析エクスプロイトリバースエンジニアリングシェルコードバイナリ解析学習と教育シェルコード生成学習パスとコース
GitHubmahmoudimus/static_asm

static_asm

x86/x86-64命令エンコーディングのためのヘッダオンリーC++2xコンパイル時アセンブラ

リポジトリを見る
31167ヶ月前Kitploit レビュー済み

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有
ウェブサイト

static_asm

CI License

ヘッダーオンリーのC++20ライブラリで、コンパイル時のx86/x86-64命令エンコーディングを提供します。

このプロジェクトはBoost Software License 1.0とMIT Licenseのデュアルライセンスです。どちらかのライセンスを選択できます。

目的

  • 実用的かつ楽しい方法でx86アセンブリエンコーディングを学ぶ
  • 完全な型安全性を持ってコンパイル時にアセンブリ命令を生成する
  • ランタイムオーバーヘッドなしでシェルコードやJITコードテンプレートを作成する

クイックスタート

root@kitploit:~
#include "static_asm.hpp"

using namespace static_asm::x86::registers;
using namespace static_asm::x86::instructions;

// コンパイル時にマシンコードを構築
constexpr auto code = core::assemble(
    mov(rax, 0x12345678),    // mov rax, imm32
    add(rax, rcx),           // add rax, rcx
    xor_(r8, r8),            // xor r8, r8
    call(rax),               // call rax
    ret()                    // ret
);
// code は std::array<uint8_t, N> - 完全にconstexpr!

カテゴリ別の例

ALU操作

root@kitploit:~
// レジスタ間
add(rax, rbx);           // 48 01 D8
sub(ecx, edx);           // 29 D1
and_(r8, r9);            // 4D 21 C8
or_(rsi, rdi);           // 48 09 FE
xor_(eax, eax);          // 31 C0 (レジスタをゼロにする一般的なイディオム)
cmp(rax, rcx);           // 48 39 C8

// 即値とレジスタ
add(rax, 0x10);          // 48 83 C0 10 (符号拡張されたimm8)
add(rax, 0x10000);       // 48 05 00 00 01 00 (imm32)
sub(ecx, 100);           // 83 E9 64
and_(rdx, 0xFF);         // 48 83 E2 FF

// メモリオペランド付き
add(eax, dword_ptr(rbx));              // 03 03
add(rax, qword_ptr(rcx + 0x10));       // 48 03 41 10
sub(dword_ptr(rsp + 0x20), eax);       // 29 44 24 20

データ移動

root@kitploit:~
// レジスタ間
mov(rax, rbx);           // 48 89 D8
mov(eax, ecx);           // 89 C8
mov(r8, r9);             // 4D 89 C8

// 即値をレジスタへ
mov(rax, 0x12345678);    // 48 C7 C0 78 56 34 12
mov(eax, 0xDEADBEEF);    // B8 EF BE AD DE

// メモリ操作
mov(rax, qword_ptr(rbx));              // 48 8B 03
mov(eax, dword_ptr(rcx + 0x10));       // 8B 41 10
mov(qword_ptr(rsp + 0x8), rax);        // 48 89 44 24 08
mov(dword_ptr(rbp - 0x20), 0x100);     // C7 45 E0 00 01 00 00

// ゼロ/符号拡張
movzx(eax, bl);          // 0F B6 C3 (バイトをdwordにゼロ拡張)
movzx(rax, bx);          // 48 0F B7 C3 (ワードをqwordにゼロ拡張)
movsx(eax, cl);          // 0F BE C1 (バイトをdwordに符号拡張)
movsx(rax, dx);          // 48 0F BF C2 (ワードをqwordに符号拡張)
movsxd(rax, ecx);        // 48 63 C1 (dwordをqwordに符号拡張)

// 実効アドレスのロード
lea(rax, qword_ptr(rbx + rcx * s4));           // 48 8D 04 8B
lea(rax, qword_ptr(rbx + rcx * s8 + 0x10));    // 48 8D 44 CB 10

// 交換
xchg(rax, rbx);          // 48 87 D8

SIBアドレッシング (Scale-Index-Base)

root@kitploit:~
// [ベース + インデックス * スケール]
mov(eax, dword_ptr(rbx + rcx * s1));   // 8B 04 0B
mov(eax, dword_ptr(rbx + rcx * s2));   // 8B 04 4B
mov(eax, dword_ptr(rbx + rcx * s4));   // 8B 04 8B
mov(eax, dword_ptr(rbx + rcx * s8));   // 8B 04 CB

// [ベース + インデックス * スケール + 変位]
mov(rax, qword_ptr(rbx + rcx * s4 + 0x10));     // 48 8B 44 8B 10
mov(rax, qword_ptr(r12 + r13 * s8 + 0x1000));   // 4B 8B 84 EC 00 10 00 00

// SIBアドレスへのストア
mov(dword_ptr(rax + rdx * s4), ecx);            // 89 0C 90
mov(qword_ptr(rbx + rsi * s8 + 0x20), rax);     // 48 89 44 F3 20

// LEAとSIB(アドレス計算に便利)
lea(rax, qword_ptr(rbx + rcx * s4));            // 48 8D 04 8B
lea(rax, qword_ptr(rdi + rsi * s8 + 0x100));    // 48 8D 84 F7 00 01 00 00

シフトとローテート

root@kitploit:~
// 1によるシフト
shl(eax, 1);             // D1 E0
shr(rax, 1);             // 48 D1 E8
sar(ecx, 1);             // D1 F9

// 即値によるシフト
shl(eax, 4);             // C1 E0 04
shr(rax, 8);             // 48 C1 E8 08
sar(rdx, 16);            // 48 C1 FA 10

// CLレジスタによるシフト
shl(eax, cl);            // D3 E0
shr(rax, cl);            // 48 D3 E8

// ローテート
rol(eax, 1);             // D1 C0
ror(rax, 8);             // 48 C1 C8 08
rcl(ecx, cl);            // D3 D1
rcr(rdx, 1);             // 48 D1 DA

乗算と除算

root@kitploit:~
// 単一オペランド(結果はrdx:rax)
mul(rbx);                // 48 F7 E3 (符号なし: rdx:rax = rax * rbx)
imul(rcx);               // 48 F7 E9 (符号付き: rdx:rax = rax * rcx)
div(rbx);                // 48 F7 F3 (符号なし: rax = rdx:rax / rbx, rdx = 余り)
idiv(rcx);               // 48 F7 F9 (符号付き除算)

// 2オペランドIMUL (dest = dest * src)
imul(rax, rbx);          // 48 0F AF C3
imul(ecx, edx);          // 0F AF CA

// 3オペランドIMUL (dest = src * imm)
imul(rax, rbx, 10);      // 48 6B C3 0A
imul(ecx, edx, 1000);    // 69 CA E8 03 00 00

制御フロー

root@kitploit:~
// 無条件ジャンプ
jmp(0x10);               // EB 10 (short, 8ビットオフセット)
jmp(0x1000);             // E9 00 10 00 00 (near, 32ビットオフセット)
jmp(rax);                // FF E0 (間接)
jmp(here);               // EB FE (jmp $, 無限ループ)

// 条件付きジャンプ (8ビットオフセット)
jz(0x10);                // 74 10
jnz(0x20);               // 75 20
jb(0x08);                // 72 08 (below/carry)
jae(0x08);               // 73 08 (above or equal/no carry)
jl(0x10);                // 7C 10 (less than, 符号付き)
jge(0x10);               // 7D 10 (greater or equal, 符号付き)

// 条件付きジャンプ (長い分岐用の32ビットオフセット)
jz_near(0x10000);        // 0F 84 00 00 01 00
jnz_near(0x20000);       // 0F 85 00 00 02 00

// CallとReturn
call(rax);               // FF D0 (間接call)
call(0x100);             // E8 00 01 00 00 (相対call)
ret();                   // C3
ret(0x10);               // C2 10 00 (returnして16バイトポップ)

条件付き移動

root@kitploit:~
// 条件が真の場合に移動(分岐ペナルティなし!)
cmovz(rax, rbx);         // 48 0F 44 C3 (ゼロなら移動)
cmovnz(eax, ecx);        // 0F 45 C1 (ゼロでなければ移動)
cmovl(rax, rdx);         // 48 0F 4C C2 (lessなら移動, 符号付き)
cmovge(ecx, esi);        // 0F 4D CE (greater or equalなら移動, 符号付き)
cmovb(rax, rbx);         // 48 0F 42 C3 (belowなら移動, 符号なし)
cmovae(edx, edi);        // 0F 43 D7 (above or equalなら移動, 符号なし)

// メモリソース付き
cmovz(rax, qword_ptr(rbx));           // 48 0F 44 03
cmovnz(eax, dword_ptr(rcx + 0x10));   // 0F 45 41 10

ビット操作

root@kitploit:~
// ビットテスト
bt(eax, 5);              // 0F BA E0 05
bt(rax, rbx);            // 48 0F A3 D8

// ビットテスト & セット/リセット/補数
bts(eax, 10);            // 0F BA E8 0A (テストしてセット)
btr(rax, rcx);           // 48 0F B3 C8 (テストしてリセット)
btc(edx, 3);             // 0F BA FA 03 (テストして補数)

// ビットスキャン
bsf(eax, ecx);           // 0F BC C1 (前方スキャン、最初の1を探す)
bsr(rax, rbx);           // 48 0F BD C3 (後方スキャン、最初の1を探す)

// ポピュレーションカウントと先頭/末尾ゼロ
popcnt(eax, ecx);        // F3 0F B8 C1
lzcnt(rax, rbx);         // F3 48 0F BD C3
tzcnt(eax, edx);         // F3 0F BC C2

// バイトスワップ
bswap(eax);              // 0F C8 (バイト順を逆にする)
bswap(rax);              // 48 0F C8

文字列操作

root@kitploit:~
// 基本文字列操作([rsi] および/または [rdi] に対して動作)
movsb();                 // A4 (バイト [rsi] -> [rdi] に移動)
movsw();                 // 66 A5
movsd();                 // A5
movsq();                 // 48 A5

cmpsb();                 // A6 ([rsi] と [rdi] を比較)
stosb();                 // AA (al -> [rdi] にストア)
lodsb();                 // AC ([rsi] -> al にロード)
scasb();                 // AE (al と [rdi] を比較)

// REPプレフィックス付き(rcx回繰り返し)
rep_movsb();             // F3 A4 (memcpy)
rep_movsq();             // F3 48 A5 (高速memcpy、8バイトずつ)
rep_stosb();             // F3 AA (memset)
rep_stosq();             // F3 48 AB

// REPE/REPNE付き(等しい/等しくない間繰り返し)
repe_cmpsb();            // F3 A6 (不一致が発生するまで文字列を比較)
repne_scasb();           // F2 AE (文字列内のバイトをスキャン)

スタック操作

root@kitploit:~
push(rax);               // 50
push(rbx);               // 53
push(r8);                // 41 50
push(0x10);              // 6A 10 (push imm8)
push(0x1000);            // 68 00 10 00 00 (push imm32)

pop(rax);                // 58
pop(rbx);                // 5B
pop(r15);                // 41 5F

システム命令

root@kitploit:~
// システムコール
syscall_();              // 0F 05 (64ビットsyscall)
sysenter();              // 0F 34
sysexit();               // 0F 35

// 割り込み
int3();                  // CC (ブレークポイント)
int_(0x80);              // CD 80 (Linux 32ビットsyscall)
int_(0x21);              // CD 21 (DOS割り込み)

// CPU情報
cpuid();                 // 0F A2
rdtsc();                 // 0F 31
rdtscp();                // 0F 01 F9

// 特権
cli();                   // FA (割り込みクリア)
sti();                   // FB (割り込みセット)
hlt();                   // F4 (停止)

// 割り込みからの復帰
iret();                  // CF (16ビット)
iretd();                 // CF (32ビット)
iretq();                 // 48 CF (64ビット)

複数の命令のアセンブル

core::assemble() を使用して命令のバイト配列を連結します:

root@kitploit:~
constexpr auto prologue = core::assemble(
    push(rbp),
    mov(rbp, rsp),
    sub(rsp, 0x20)
);

constexpr auto epilogue = core::assemble(
    add(rsp, 0x20),
    pop(rbp),
    ret()
);

// 組み合わせる
constexpr auto full_function = core::assemble(prologue, epilogue);

インストール

オプション1: CMake FetchContent (推奨)

CMakeLists.txt に追加:

root@kitploit:~
include(FetchContent)
FetchContent_Declare(
    static_asm
    GIT_REPOSITORY https://github.com/mahmoudimus/static_asm.git
    GIT_TAG v1.0.0  # または特定のコミット
)
FetchContent_MakeAvailable(static_asm)

target_link_libraries(your_target PRIVATE static_asm::static_asm)

オプション2: CMake add_subdirectory

クローンするか、gitサブモジュールとして追加:

root@kitploit:~
git submodule add https://github.com/mahmoudimus/static_asm.git external/static_asm

次に CMakeLists.txt で:

root@kitploit:~
add_subdirectory(external/static_asm)
target_link_libraries(your_target PRIVATE static_asm::static_asm)

add_subdirectory または FetchContent でインクルードした場合、static_asm::static_asm インターフェースライブラリターゲットのみがプロジェクトに追加されます。テストとサンプルは、-DSTATIC_ASM_BUILD_TESTS=ON で明示的に有効にしない限りビルドされません。

オプション3: 単一ヘッダー

static_asm.hpp をリリースページからダウンロードし、直接インクルード:

root@kitploit:~
#include "static_asm.hpp"

オプション4: システムインストール

root@kitploit:~
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --install build --prefix /usr/local

その後、find_package を使用:

root@kitploit:~
find_package(static_asm REQUIRED)
target_link_libraries(your_target PRIVATE static_asm::static_asm)

ビルド

root@kitploit:~
# 設定
cmake -B build -DCMAKE_BUILD_TYPE=Release

# ビルド
cmake --build build

# テスト実行
ctest --test-dir build --output-on-failure

# サンプル付きでビルド (Clangのみ、インラインアセンブリを使用)
cmake -B build -DCMAKE_BUILD_TYPE=Release -DSTATIC_ASM_BUILD_EXAMPLES=ON

プラットフォームサポート:

  • Linux (GCC 11+, Clang 14+)
  • macOS (Apple Clang, Clang)
  • Windows (MSVC 2022+)

注: core::emit() インラインアセンブリ機能は、-O2最適化を有効にしたClangが必要です。

サポートされている命令

オペランドサポート:

  • すべての8/16/32/64ビット汎用レジスタ (AL-R15)
  • 拡張レジスタ (R8-R15, R8D-R15D, R8W-R15W, R8B-R15B)
  • 即値 (8/16/32/64ビット)
  • ベースレジスタと変位を持つメモリオペランド
  • SIBアドレッシング: [ベース + インデックス * スケール + 変位]、スケールファクター1, 2, 4, 8

注意: SIMD/AVX拡張はまだありません。

開発

環境セットアップ

このプロジェクトではPythonツール(コード生成、単一ヘッダーアマルガメーション)に uv を使用しています。

root@kitploit:~
# uvのインストール(まだの場合)
curl -LsSf https://astral.sh/uv/install.sh | sh

# インストールの確認
uv --version

# Pythonスクリプトはすべてuvで直接実行可能(依存関係は自動管理)
uv run scripts/gen_from_x86ref.py --help
uv run scripts/amalgamate.sh

必要なツール:

開発用のオプショナルツール:

ツール目的インストール
clang-formatコードフォーマットLLVMまたはシステムパッケージ経由
clang-tidy静的解析LLVMまたはシステムパッケージ経由

新しい命令の追加

オプション1: コードジェネレーターを使用

プロジェクトには、x86reference XMLデータベースを解析するジェネレーターが含まれています:

root@kitploit:~
# 命令データベースの概要表示
uv run scripts/gen_from_x86ref.py

# 特定の命令の詳細表示
uv run scripts/gen_from_x86ref.py -i lea
uv run scripts/gen_from_x86ref.py -i imul

# 命令データベースファイルの生成
uv run scripts/gen_from_x86ref.py --generate-db

# 網羅的なテストファイルの生成
uv run scripts/gen_from_x86ref.py --generate-tests

オプション2: 手動追加

  1. 命令データベースファイルに追加(instdb、prefix_db、prefix_0fdb 配列)
  2. encoder.hpp にエンコーダーをコーディングするか、既存のエンコーダーを拡張
  3. テストを追加

単一ヘッダーライブラリを作成するためのテクニック

任意のマルチファイルC++ライブラリを、手動での準備なしに信頼性の高いヘッダーオンリーバージョンに変換できる自動ツールはありません。以下のテクニックは、ライブラリが正しく、メンテナンス可能で、標準に準拠したまま、単一ヘッダーファイルにアマルガメーションできることを保証するのに役立ちます。

注: このプロジェクトはアマルガメーションに quom を、これらのルールの自動適用に google-build-using-namespace チェック付きの clang-tidy を使用しています。quomはまた、その処理機能を通じてテクニック#4(インラインマーカー)を部分的に処理します。

1. ソースファイルでの using namespace を避ける

.cpp ファイルのファイルスコープでの using namespace は、それらのファイルが後でヘッダーにインクルードされる場合に危険です。ヘッダーをインクルードするすべての翻訳単位のグローバル名前空間を汚染します。

代わりに推奨されるパターン:

root@kitploit:~
// 推奨: 実装を名前空間でラップ
namespace MyLib {
    Foo::Foo() {
        // ...
    }
}

または

root@kitploit:~
// 明示的な修飾(より冗長だが非常に明確)
MyLib::Foo::Foo() {
    // ...
}

2. 内部/プライベートAPIをネストされた名前空間に配置

パブリックAPIはメインの名前空間に配置する必要があります。エンドユーザーを対象としないものはすべて、detail や impl などのネストされた名前空間に隠す必要があります。

一般的な慣例:

root@kitploit:~
namespace MyLib {
    namespace detail {           // 広く使用されている
        // 内部クラス、関数など
    }
}

または

root@kitploit:~
namespace MyLib::impl {          // より短く、これも一般的
    // 内部実装の詳細
}

C++17以降では、インラインのネストされた名前空間定義をサポートしており、よりクリーンです:

root@kitploit:~
namespace MyLib::detail {
    class InternalHelper { /* ... */ };
}

3. ファイルスコープの静的データを static inline クラスメンバーに変換

.cpp ファイルで定義されたファイルスコープの static 変数は、ヘッダーオンリーの世界では問題になります(多重定義、ODR違反)。

モダン (C++17以上) な解決策:

root@kitploit:~
// 以前 ( .cpp 内)
namespace MyLib {
    static int s_counter = 0;

    int next_id() {
        return ++s_counter;
    }
}
root@kitploit:~
// 以後 (ヘッダーでも安全)
namespace MyLib::detail {
    struct Globals {
        static inline int counter = 0;
    };
}

inline int MyLib::next_id() {
    return ++detail::Globals::counter;
}

static inline 変数は、複数回インクルードされても単一の定義を持つことが保証されています。

4. クラス本体の外で定義された関数を inline とマーク

本体がヘッダーに現れる(しかしクラス定義の内部ではない)すべての関数、メンバー関数、コンストラクター、デストラクターは、One Definition Rule (ODR) 違反を避けるために inline とマークする必要があります。

多くのアマルガメーションスクリプトは純粋にテキストベースでC++セマンティクスを解析しないため、開発中はプレースホルダーマクロ(例: inline_t)を使用する一般的な慣例があります:

root@kitploit:~
// MyLib.h (または共通ヘッダー)
#define inline_t   /* 通常のビルドでは空 */

// MyLib.cpp (開発中)
namespace MyLib::detail {
    inline_t void Helper::do_work() {
        // 実装
    }
}

アマルガメーション中に、ツールが inline_t を inline に置き換えます:

root@kitploit:~
// アマルガメーション/変換後
inline void MyLib::detail::Helper::do_work() {
    // ...
}

任意のマクロ名を選択できます(例: MYLIB_INLINE, INLINE_IMP など)。 それに応じてアマルガメーションスクリプトを設定してください。

注: quom のようなツールは、C++インクルードセマンティクスを理解し、アマルガメーション中に関数定義を適切に処理することで、多くの場合に手動の inline マーカーの必要性を減らし、このプロセスを部分的に自動化できます。

まとめ — 4つの重要なルール

  1. 実装ファイル内で名前空間/ファイルスコープで using namespace … を決して書かない。
  2. すべての内部/非公開シンボルをネストされた名前空間 (detail / impl) に入れる。
  3. ファイルスコープの static データを、構造体/クラスの static inline メンバーに置き換える。
  4. 行外の関数本体を、インラインマーカーマクロでマークする(アマルガメーション中に置き換えられる)。

これらの4つのプラクティスに従うことで、純粋なテキストベースのアマルガメーションツールを使用する場合でも、単一ヘッダー配布への移行がはるかにスムーズになり、エラーが大幅に減少します。

クレジット

  • プロトタイピングに Godbolt
  • Intel x86-64 マニュアル
  • 出力の検証に Defuse.ca
  • Geek ABCリファレンス
  • 命令データベースXMLに mazegen/x86reference

謝辞

このプロジェクトは Midi12 による cx_assembler をベースにしています。元のライブラリは、C++におけるコンパイル時x86アセンブリエンコーディングの基盤を提供しました。

ツールをダウンロード
カテゴリ命令
ALUADD, ADC, SUB, SBB, AND, OR, XOR, CMP, TEST
単項INC, DEC, NEG, NOT
乗算/除算MUL, IMUL (1/2/3オペランド形式), DIV, IDIV
データ移動MOV, MOVABS, MOVZX, MOVSX, MOVSXD, LEA, XCHG, PUSH, POP
シフト/ローテートSHL, SHR, SAL, SAR, ROL, ROR, RCL, RCR
制御フローJMP, CALL, RET, RETF
条件付きジャンプJZ/JE, JNZ/JNE, JB/JC, JNB/JNC, JBE/JNA, JNBE/JA, JL, JNL, JLE, JNLE, JO, JNO, JS, JNS, JP, JNP (8ビットおよび32ビットオフセット)
条件付き移動CMOVA, CMOVAE, CMOVB, CMOVBE, CMOVE, CMOVG, CMOVGE, CMOVL, CMOVLE, CMOVNE, CMOVNO, CMOVNP, CMOVNS, CMOVO, CMOVP, CMOVS
ビット操作BT, BTC, BTR, BTS
ビットスキャン/カウントBSF, BSR, POPCNT, LZCNT, TZCNT, BSWAP
文字列操作MOVSB/W/D/Q, CMPSB/W/D/Q, LODSB/W/D/Q, STOSB/W/D/Q, SCASB/W/D/Q (REP/REPE/REPNEプレフィックス付き)
システムSYSCALL, SYSENTER, SYSEXIT, INT, INT3, IRET/D/Q, CLI, STI, HLT, CPUID, RDTSC, RDTSCP
その他NOP, UD2
ツール目的インストール
uvPythonパッケージ/プロジェクトマネージャーcurl -LsSf https://astral.sh/uv/install.sh | sh
quom単一ヘッダーアマルガメーションuv tool install quom
CMake 3.19以上ビルドシステムcmake.org
C++20コンパイラGCC 11+, Clang 14+, MSVC 2022+-