Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
mkPIVM — 任意のx86/x64シェルコードから、ポリモーフィックな位置独立仮想マシン(PIVM)を生成します。 | Kitploit
ツール/GitHubGitHub/d7ead/mkpivm
ペイロード生成エクスプロイトリバースエンジニアリングシェルコードマルウェア分析レッドチーミング
GitHubd7ead/mkpivm

mkPIVM

任意のx86/x64シェルコードから、ポリモーフィックな位置独立仮想マシン(PIVM)を生成します。

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

人気

すべて見る →

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

すべてのツールを探索

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

すべてのツールを見る →
共有


Read the research paper (written for 1.0.0).

mkPIVM は、Windows x86 および x64(まもなく Linux 対応)向けの、ポリモーフィックな位置独立シェルコード仮想化ツールです。

生のシェルコードを入力として受け取り、別の生のブロブを出力します。それは、元の命令のリフティング(lifting)され、暗号化された形で保存されたバージョンを解釈する、小さな仮想マシンです。出力自体も位置独立コードであり、リモートスレッドローダーからコードケイブデトゥアまで、元のシェルコードが動作するあらゆる場所で実行できます。シードごとの各パラメータは独立に変化します: 暗号ファミリ、レジスタスロットレイアウト、オペコードからハンドラへの置換、ディスパッチャのトポロジ、ジャンクガジェットパターン、IR難読化の挿入ポイント。同じ入力からの2つのビルドは、数万バイトのうち偶然一致するバイトが100未満です。

理由: ネイティブシェルコードはシグネチャ検出されやすいものです。それをインスタンスごとのVMとインスタンスごとの暗号で包めば、静止状態で有用なものは何も残らず、命令をバイトコードにリフティングすることで、ディスク上のバイトとx86の構造を知っているあらゆる逆アセンブラとの間にもう1つの壁ができます。私が文献調査で確認した限り、このパイプラインを正確に提供する公開ツールはありません: 生のPICを受け取り、生のポリモーフィックVM PICを出力する。そこで、そのことを要求された研究論文に記載しました。正直なところ、これまでに誰も(公に)これをやっていないという私の認識が正しければ、そして私はかなり自信がありますが、驚きです。それでも、お楽しみください。

関連研究と計画

  • Linux サポートはまもなく追加される予定です。

クイックスタート```

mkpivm.exe shellcode.bin --arch x64 -o out.bin

Your PIVMは熱々で準備完了です。それが最も簡単な道です。他のいくつかのモードは、元の命令がどの程度積極的に仮想化されるか、出力がスタンドアロンのblobかパッチ適用済みのPEか、そしてリフトが実行されるかどうかさえも変えます。

# Showcase

証拠はあります。以下で、mkPIVMがMeterpreterステージャーを完全に仮想化し(ちなみにバニラです)、explorer.exeに注入して、コールバックをキャプチャする様子をビデオで見ることができます。もちろんこれは一例にすぎず、シェルコード内の命令がサポートされていれば、mkPIVMはもっと多くのことに適用できます。サポートされていない場合は、Issueを作成してシェルコードを送ってください。対応します。

こちらで[見る](https://github.com/D7EAD/mkPIVM/raw/refs/heads/main/media/mkpivm-showcase.mp4)。./media にホストされています。残念ながら埋め込めません。

こちらが、その正確に仮想化されたサンプルのVirusTotalレポートです(06/04/2026時点)。

<img src="https://assets.kitploit.com/production/public/readmes/7466/3f4a6dbe2777c02fb32f71749a5b1fa2aa324cb0dac2f77d5681bbe3a4e17a81.png">

...そして、パックされたバージョンは、仮想化すらされておらず、エントロピーが著しく高くなっています。

<img src="https://assets.kitploit.com/production/public/readmes/7466/47f68372e31a2c24fa49eb71648adbdf8944977db90d645df337125c1bdfa8e3.png">

こちらは比較用の、通常のCobalt Strikeビーコンの結果です。

<img src="https://assets.kitploit.com/production/public/readmes/7466/76e2107589cd2b1b65c846a671aed173aa5e6d89630f5e9d283d99c546a2d566.png">

このツールの出力のエントロピーテレメトリには細心の注意が払われており、その結果、シェルコードのエントロピーは、パッキングモード以外では、ntdll.dllやkernel32.dllなどの典型的なWindows WinAPI DLLよりも低くなっています。エントロピーの比較は次のとおりです。

| ファイル | バイト | エントロピー |
|------|-------|---------|
| `p_m64.bin` | 3,969 | **7.1181** |
| `msvcrt.dll` | 699,888 | 6.5319 |
| `wininet.dll` | 2,724,528 | 6.4934 |
| `shell32.dll` | 7,839,992 | 6.3639 |
| `kernel32.dll` | 836,232 | 6.3597 |
| `crypt32.dll` | 1,538,632 | 6.3010 |
| `rpcrt4.dll` | 1,162,672 | 6.2405 |
| `ntdll.dll` | 2,522,104 | 6.1934 |
| `v.bin` | 29,229 | **6.0442** |

## モード早見表

| モード | フラグ | 変更内容 |
|------|-------|--------------|
| Default | none | 入力全体をリフトする。すべてが仮想化される。 |
| Packer | `--pack` | リフトしない。入力を暗号化データとしてラップし、実行時に復号してジャンプインする。 |
| Hybrid | `--ranges A:B,...` | 選択されたバイト範囲のみをリフトする。残りはネイティブのまま。 |
| Stacked | `--pack --ranges A:B` | ハイブリッドblobを構築し、その後パックでラップする。 |
| Detour | `--embed-into PE --at RVA` | 事前にビルドしたblobを取得し、PEに埋め込み、選択したRVAにjmpをパッチする。 |
| Scan | `--scan` | 入力のCFGから有効な`--ranges`候補を出力して終了する。 |
| RX | `--rx` | PAGE_EXECUTE_READ blob。データアイランドは保存時は暗号化されたまま。blob内のPEBウォーカーがVirtualProtectを解決し、state_initでその場で復号する。 |
| RX w/ Loader | `--rx --rx-loader-vp` | `--rx` と同じだが、ローダーがVirtualProtectをblobの最初の引数として渡す。PEBウォーカーは不要。 |

すべてのモードは `--seed`、`--arch`、`--input-format`、`--format` を尊重します。ビルドパイプラインとランタイムフローについては、以下の各モードのセクションを参照してください。

## デフォルトの仮想化

リフターはCFG全体を走査し、すべての命令をカスタムIRに変換します。IRは2つの難読化パスを通過し、その後、各insnをシードごとのバイトコード形状にエンコードするコーデックを通過します。ブロックテーブル、ハンドラテーブル、データアイランドは、バイトコードと同じ1バイト単位のストリーム暗号で暗号化されます。実行時にはプロローグがこれら3つの領域をその場で復号し、ディスパッチャループがバイトコードバイトを1つずつ取得し、復号して処理を実行するハンドラにディスパッチします。

### ビルドパイプライン

生のシェルコードを、出力される仮想化blobに変換するためにビルドが実行する手順を、最初から最後まで示します。_以下のすべてのグラフは1.0.0リリースに適用されます。それ以降これらは変更されていますが、考え方は同じです。_```mermaid
flowchart TB
    A[shellcode.bin] --> CFG[CFGBuilder: identify blocks via Zydis disasm + recursive descent]
    SEED[seed u64] --> VMC[VMConfig: pick cipher kind, reg perm, opcode map, dispatcher topology]
    CFG --> LIFT[LifterRegistry: lower each block to IR]
    LIFT --> RBT[resolve_branch_targets: link BR_CC/BR/CALL_VM/LOOP_DEC to target_block_id; synthesize JMP_NATIVE block for any out-of-range jcc]
    RBT --> OBF1[obfuscate_ir_dead_inject: 20% per insn-gap, IMM Tmp2/Tmp3 random]
    OBF1 --> OBF2[obfuscate_ir_opaque_predicates: 25% per block, split block with IMM Tmp3=0 + TEST + BR_CC NZ random_block, never taken]
    OBF2 --> ENC[BytecodeBuilder: each codec emits its variant for this seed]
    ENC --> CDATA[compact data island: bytes not covered by any CFG block]
    CDATA --> PROMO[promote LEA-fixup target VAs back into data island if CFG put them in code]
    ENC --> BTAB[build block table: va_off to bytecode_off pairs]
    PROMO --> ECIPH[encrypt data island with cipher_init]
    BTAB --> ECIPH2[encrypt block table with cipher_init]
    ENC --> ECIPH3[encrypt bytecode per-block with cipher_init reset at each block start]
    VMC --> STUB[VMCodeGen::emit_full: prologue, state init, dispatcher tail, handlers, sbox_inv, exit handler]
    STUB --> HTAB[handler table: 256 entries, each a 32-bit offset from handler_base; encrypted at rest]
    ECIPH --> ASM[finalize: stub + trampolines + sbox_inv + bytecode + data island + block table]
    ECIPH2 --> ASM
    ECIPH3 --> ASM
    HTAB --> ASM
    ASM --> OUT[out.bin]

ランタイムフロー

ホストローダーがバイト0で呼び出したときの、生成されたblobの動作。プロローグからディスパッチャのフェッチ、各種終了パスまで。```mermaid flowchart TB ENTRY[blob entry at byte 0] --> PROL[prologue: push NV regs in seed-shuffled order, pushfq, allocate frame, lea state_ptr] PROL --> SI[emit_state_init body, gated by init_flag byte] SI --> ZERO[zero VM regs via seed-permuted xor source] ZERO --> CINIT[set cipher_state register, store cipher_init at cipher_extra+48] CINIT --> SBOX[copy sbox_inv table from blob to cipher_extra+256] SBOX --> NONCE[derive runtime nonce: rdtsc XOR cipher_init, store at cipher_extra+80] NONCE --> DDI[decrypt data island in place via emit_fetch_byte_dec loop] DDI --> DBT[decrypt block table in place] DBT --> DHT[decrypt handler table in place] DHT --> XHT[XOR each handler table entry with the runtime nonce so memory image is process-variant] XHT --> SET_INIT[set init_flag = 1 to gate subsequent vm_entry invocations] SET_INIT --> DISP[dispatcher tail] DISP --> FB[fetch one byte via emit_fetch_byte_dec, decrypts using cipher_state] FB --> HLU["load handler offset: mov scratch_b_32, [handler_base + op*4]"] HLU --> UXOR["xor scratch_b_32, [state_ptr + cipher_extra + runtime_nonce_off]"] UXOR --> SXD[movsxd to 64 bit, lea handler_addr = handler_base + offset, jmp handler] SXD --> H[handler body: fetch operands via stream cipher, perform op, advance state] H --> NEXT{terminator?} NEXT -- no --> DISP NEXT -- BR/BR_CC --> CRESET[cipher_reset to cipher_init, advance ip to target block] CRESET --> DISP NEXT -- CALL_VM --> CRESET NEXT -- JMP_NATIVE imm --> MARSH["marshal VM regs to host regs, rsp = VM_RSP, jmp [target_slot]"] NEXT -- CALL_NATIVE --> PUSHTR[push trampoline addr to VM_RSP, marshal, jmp target] NEXT -- RET_VM --> POPSS[pop shadow stack, jmp to popped trampoline addr] POPSS --> CRESET NEXT -- exit_handler reached --> EPI[restore NV regs, ret to caller of vm_entry]

ランタイムノンスのトリックは、メモリスキャン対策の要となる手法です。ハンドラテーブルは、`rdtsc XOR cipher_init`から導出された値とXORされた状態でメモリ上に存在するため、同じブロブをロードした2つのプロセスは、バイト単位で異なるハンドラテーブルを保持します。ディスパッチャは、ルックアップ時に追加のXORを1回行ってマスクを解除します。

## パッカーモード: `--pack`

逆のトレードオフです。リフターは実行されません。元のシェルコードは暗号化された状態でデータアイランドに格納され、IRは単一の合成`JMP_NATIVE imm=0`になります。プロローグは、デフォルトモードが即座に実行するデータアイランドの復号を意図的にスキップします。代わりに、その唯一のJMP_NATIVEハンドラが最初に発火したとき、データアイランドをその場で復号し、マーカーバイトを設定してから、制御を今や平文となったシェルコードのバイト0へ移します。シェルコードはそこからネイティブに実行されます。
ツールをダウンロード