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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
metasm — これはmetasmのメインリポジトリです。Rubyで書かれたフリーのアセンブラ/ディスアセンブラ/コンパイラです。 | Kitploit
ツール/GitHubGitHub/jjyg/metasm
コード分析リバースエンジニアリングシェルコードデバッガバイナリ解析
GitHubjjyg/metasm

metasm

これはmetasmのメインリポジトリです。Rubyで書かれたフリーのアセンブラ/ディスアセンブラ/コンパイラです。

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

人気

すべて見る →

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

すべてのツールを探索

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

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

Metasm、Rubyアセンブリ操作スイート

  • samples/ 内のサンプルスクリプト -- ファイル先頭のコメントを読んでください
  • すべてのファイルは LGPL の条件の下でライセンスされています

著者: Yoann Guillot

基本概要:

Metasm を使用すると、実行可能ファイルフォーマット(ExeFormat)を操作できます: PE、ELF、Mach-O、Shellcode など。 ExeFormat には3つのアプローチがあります:

  • ゼロから組み立てる(コンパイルする)
  • 既存のフォーマットを逆コンパイルする
  • ファイル構造を操作する

すぐに使えるスクリプトは samples/ サブディレクトリにあります。スクリプトのヘッダのコメントを確認してください。運が良ければ --help 引数も試せます。

詳細については、doc/ サブディレクトリを確認してください。テキストファイルは misc/txt2html.rb スクリプトを使用して html にコンパイルできます。

以下は Metasm 内部の簡単な概要です。

アセンブリ:

コンパイル時には、まずソーステキスト(主に命令/データ/パディングディレクティブの並びからなる ruby String)から始め、それをパースします。

その文字列は Preprocessor インスタンスに渡されます(#if、#ifdef、#include、#define、/* */ などを処理し、gcc -E と100%互換であるべきです)。これはアセンブラソース用の AsmPreprocessor にカプセル化されています(asm マクロ定義、'equ'、asm の ';' コメントを処理するため)。 これを行うインターフェースは ExeFormat#parse(text[, filename, lineno]) または ExeFormat.assemble(.new、#parse、#assemble を呼び出します)です。

(Asm)Preprocessor はトークンを ExeFormat に返し、ExeFormat はそれらを Data、Padding、Labels、またはパーサディレクティブとしてパースします。パーサディレクティブは常にドットで始まります。これらは汎用(.pad、.offset...)または ExeFormat 固有(.section、.import、.entrypoint...)です。これらは #parse_parser_instruction() によって処理されます。 ExeFormat が単語を認識しない場合、その単語は CPU インスタンスに渡され、CPU インスタンスが命令(Instructions)のパースを担当します(または例外を発生させます)。 これらすべてのトークンは、ExeFormat の @source 属性内の1つ以上の配列に格納されます(Shellcode の @source は Array であり、PE/ELF の場合はハッシュ [section name] => [Array of parsed data] です)。 すべての即値は任意の Expression にすることができます(後述)。

その後、ExeFormat#assemble を使用してソースをバイナリセクションにアセンブルできます。

セクションバイナリが利用可能になると、ExeFormat#encode_file(filename[, format]) を使用してバイナリ実行可能ファイル全体をディスクに書き込むことができます。

PE と ELF には、既知の OS 固有関数のインポート関連データを自動生成する autoimport 機能が含まれています(例: 'strcpy' への未解決の呼び出しは、実行時にバイナリが libc ライブラリにリンクされるようなデータを生成します)。

samples/{exe,pe,elf}encode.rb は asm ソースファイルを引数として受け取り、動作する実行可能ファイルにコンパイルできます。

CPU クラスは個々の命令のパースとエンコードを担当します。現在の Ia32 パーサは Intel 構文を使用します(例: mov eax, 42)。 汎用パーサは、行頭に置かれコロンが続く文字列をラベルとして認識します(例: 'some_label:')。GCC スタイルのローカルラベルも使用できます(例: '1:' は '1b'(後方)または '1f'(前方)で参照され、必要なだけ再定義できます)。 データは 'db' 形式の記法で指定します(例: 'dd 42h'、'db "blabla", 0') samples/asmsyntax.rb を参照してください。

EncodedData:

Metasm では、すべてのバイナリデータは EncodedData として格納されます。 EncodedData には3つの主要な属性があります:

  • #data -- 生のバイナリデータを保持します(通常は ruby String ですが、VirtualString も参照)
  • #export -- エクスポート名(ラベル名)を #data 内のオフセットに関連付けるハッシュ
  • #reloc -- キーが #data 内のオフセットで、値が Relocation オブジェクトであるハッシュ Relocation オブジェクトは、エンディアンネス(:little/:big)、タイプ(符号なし32ビット用の :u32)、およびターゲット(ここに格納される意図された値)を持ちます。 ターゲットは任意の算術/論理 Expression です。

EncodedData はまた、#virtsize(例: .bss セクション用)と #ptr(デコード時に使用される内部オフセット)を持ちます。

EncodedData は、Hash の変数名 => 値(値は Expression または数値である必要があります)でフィックスアップできます。これを行うと、各リロケーションのターゲットがバインディングを使用してバインドされ、結果が計算可能な場合(Expression で外部変数名が使用されていない場合)、結果はリロケーションのサイズ/符号/エンディアンネス情報を使用してエンコードされます。オーバーフローした場合(8ビット符号付きリロケーションに128を格納しようとするなど)、EncodeError 例外が発生します。:a32 タイプを使用すると、オーバーフローを静かに切り詰めることができます。 リロケーションのターゲットが数値でない場合、EncodedData#fixup を使用するとターゲットは変更されず、#fixup! を使用するとバインドされたターゲットに置き換えられます。

逆アセンブル:

このコードは metasm/decode.rb ソースファイルにあり、Disassembler クラスを定義しています。

ディスアセンブラには、デコード済みの ExeFormat(どの仮想アドレスにどのデータがあるかを判断できるようにするため)とエントリポイント(仮想アドレスまたはエクスポート名)が必要です。 これにより、命令の逆アセンブルを開始できます。:setip としてマークされた Opcode に遭遇すると、CPU にジャンプ先を尋ね(レジスタ値を含む可能性のある Expression、例: jmp eax)、数値が見つかるまで命令をバックトレースします。

デコード中、Disassembler はアドレス(式/整数の #normalize() されたもの)を DecodedInstruction に関連付ける #decoded ハッシュを維持します。

逆アセンブルは InstructionBlock グラフを生成します。各ブロックは DecodedInstruction のリストと、次の/前のブロックへのポインタ(アドレスによる)を保持します。

ディスアセンブラはまた、命令によるデータアクセスをトレースし、それらの Xref を格納します。 バックトレースのパラメータは調整でき、考慮する最大深さは #backtrace_maxblocks_data を使用して :r/:w バックトレース(命令メモリ xref)に対して特に変更できます。 Expression がバックトレースされると、通過した各ブロックがマークされ、ループが検出され、既存のブロックへの新しいコードパスが見つかった場合にこの新しいパスを使用してバックトレースを再開できるようになります。

ディスアセンブラはほとんど仮定を置きません。特に、関数が戻ることを想定しません。'ret' 命令のバックトレースが決定的な場合にのみ戻ると見なされます。これは非常に強力ですが、バックトレース処理のエラーが完全な停止につながる可能性があることも意味し、またディスアセンブラがかなり遅いことも意味します。

コードが整形式であることが分かっている場合(つまり、すべての call が戻ると仮定する)、特別なメソッド #disassemble_fast を使用してこの問題を回避できます。

サブ関数が見つかると、特別な DecodedFunction が作成され、関数の効果の要約を保持します(強化された DecodedInstruction のようなもの)。これにより、バックトラッカーはサブ関数を 'ステップオーバー' でき、速度が大幅に向上します。DecodedFunction はコールバックベースにすることができ、非常に動的な動作を可能にします。

外部関数呼び出しは、専用の DecodedFunction を作成し、いくつかの API 情報(例: スタックフィックスアップ情報、基本的なパラメータアクセス...)を保持します。この情報は、事前にパースされた C ヘッダから導出できます。C 関数プロトタイプが利用できない場合は、特別な 'default' エントリが使用され、関数が標準 ABI を持つと仮定します。

Ia32 は特定の :default エントリを実装しており、最後の 'call' 命令が戻ると仮定して自動スタックフィックスアップ解決を処理します。これにより予期しない結果が生じる可能性があります。最大の正確性を得るには、すべての外部関数の情報を保持する C ヘッダが推奨されます(完全な Visual Studio インストールとターゲットバイナリからそのようなヘッダを生成するスクリプトについては samples/factorize-headers-peimports を参照)。

Ia32 はまた、特定の GetProcAddress/dlsym コールバックを実装しており、パラメータをバックトレースできれば正しい戻り値を生成します。

完全なディスアセンブラを実装したスクリプトは samples/disassemble{-gui}.rb です。GUI のキーバインディングについてはコメントを参照してください。

ExeFormat の操作:

ExeFormat をエンコード/デコードできます(つまり、セクション、インポート、ヘッダなどをデコードします)。

コンストラクタ: ExeFormat.decode_file(str), ExeFormat.decode_file_header(str) メソッド: ExeFormat#encode_file(filename), ExeFormat#encode_string

PE および ELF ファイルには、LoadedPE/LoadedELF 対応版があり、これらのフォーマットのメモリマップ版を操作できます(例: 実行中のプロセスをデバッグするため)。

VirtualString:

VirtualString は String のようなオブジェクトです。そのスライスを読み取ったり、書き換えたりできます。EncodedData#data として使用できるため、ほとんどの Metasm アルゴリズムの仮想化が可能になります。 VirtualString の長さは変更できません。 VirtualString のスライスを取ると、String(小さなサイズの場合)または別の VirtualString(もう一方への 'ウィンドウ')が返されます。小さな VirtualString を強制的に取得するには、#dup(offset, length) メソッドを使用できます。 未実装のメソッドが呼び出された場合、その呼び出しは VirtualString の完全なコピーである frozen String に転送されます(可能であれば避けるべきです。基になる文字列が非常に大きく、アクセスが遅い可能性があります)。

現在、3つの VirtualString が実装されています:

  • VirtualFile -- ファイルをページサイズのチャンク単位でオンデマンドにロードします。
  • WindowsRemoteString -- 別のプロセスの仮想メモリをマップします(WinDbgAPI を介して Windows デバッグ API を使用)。
  • LinuxRemoteString -- 別のプロセスの仮想メモリをマップします(ptrace 権限が必要で、メモリ読み取りは /proc/pid/mem を使用して行われます)。

Win/Lin バージョンは非常に強力で、ライブプロセスの逆アセンブル/パッチ適用などを簡単に行えます(LoadedPE/LoadedELF を ExeFormat として使用)。

デバッグ:

Metasm にはデバッグを処理するためのいくつかのインターフェースが含まれています。 WinOS クラスと LinOS クラスは、基盤となる OS プロセスへのアクセスを提供します(例: OS.current.find_process('foobar') は、ファイル名に foobar を含む実行中のプロセスを取得します。その後、process.mem を使用してそのメモリにアクセスできます)。

Windows と Linux の低レベルデバッグ API には、基本的な ruby インターフェース(PTrace と WinAPI)があります。これらは統一された高機能 Debugger クラスによって使用されます。 リモートデバッグは GDB サーバーワイヤプロトコルを通じてサポートされています。

高レベルデバッガは、次の ruby 行で作成できます: Metasm::OS.current.create_debugger('foo')

ホストデバッガクラスは一度に1種類しか存在できません。複数のプロセスをデバッグするには、既存のクラスを使用して他のプロセスにアタッチします。これは、Windows と Linux での OS デバッグ API の動作方法によるものです。

低レベルバックエンドは os/ サブディレクトリで定義され、フロントエンドは debug.rb で定義されます。

Linux コンソールデバッグインターフェースは samples/lindebug.rb で利用できます。これは(簡略化された)SoftICE 風のルックアンドフィールを使用します。gdb-server ソケットと通信でき、[udp:]host:port ターゲットを使用します。

disassembler-gui サンプルは、ターゲットとして 'live:' を使用する場合にライブプロセスとの対話を可能にします。

C パーサ:

Metasm には手書きの C パーサが含まれています。 私が知っているすべての構文を処理します(16進浮動小数点を除く):

  • static const L"bla"
  • 可変引数
  • 不完全型
  • attributes(()), __declspec()
  • #pragma once
  • #pragma pack()
  • C99 宣言子 - type bla = { [ 2 ... 14 ].toto = 28 };
  • ネストされた関数
  • __int8 などのネイティブ型
  • ラベルアドレス (&&label) また、これらのすべてがパースされることに注意してください。ただし、そのほとんどは Ia32/X64 バックエンド(現在実装されている唯一のバックエンド)ではコンパイルに失敗します。

C ファイルのパースは、既存の ExeFormat と parse_c_file メソッドを使用して行う必要があります。これにより、フォーマット固有のマクロ/ABI が正しく定義されます(例: 'long' 型のサイズ、関数にパラメータを渡す ABI など)。

C::Parser.parse(text) を使用して C 文字列をパースすると、Parser オブジェクトを受け取ります。#toplevel フィールド(C::Block)を持ち、#structs、#symbols、#statements を保持します。トップレベル関数は #symbol ハッシュにあり、そのキーはシンボル名で、関数を保持する C::Variable オブジェクトに関連付けられています。関数のパラメータ/属性は func.type を通じてアクセスでき、コードは func.initializer にあり、それ自体が C::Block です。その下には、C::Statement(If、While、Asm、CExpression...)のツリー状構造があります。

C::Parser は #precompiled によって、コンパイルが容易な簡略化バージョンに変換できます。typedef は削除され、制御シーケンスは 'if (XX) goto YY;' などに変換されます。

C プログラムをコンパイルするには、PE/ELF.compile_c を使用します。これにより、exe 固有のマクロ(例: PE または ELF)が定義された C::Parser が作成されます。

ベンダー固有のヘッダでは、#pragma prepare_visualstudio(Microsoft Visual Studio ヘッダをパースするため)または prepare_gcc(gcc 用)のいずれかを使用する必要がある場合があります。後者は自動検出される場合とされない場合があります。 テスト済みのベンダーヘッダは VS2003(DDK を含む)と gcc4 です。結果は環境によって異なります。

現在、C コードの CPU#compilation は asm ソース(テキスト)を生成し、それをパースしてバイナリコードにアセンブルできます。

ExeFormat#compile_c および samples/exeencode.rb を参照してください。

ツールをダウンロード