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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
packer-tutorial — Windows向けパッカーの書き方チュートリアル! | Kitploit
ツール/GitHubGitHub/frank2/packer-tutorial
リバースエンジニアリングマルウェア分析バイナリ解析学習と教育
GitHubfrank2/packer-tutorial

packer-tutorial

Windows向けパッカーの書き方チュートリアル!

リポジトリを見る
31932152年前Kitploit レビュー済み

人気

すべて見る →

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

すべてのツールを探索

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

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

PACKERS

目次

  1. パッカーとは何か?: パッカーの目的の紹介と、パッカーに必要な開発要素についてのガイド。
  2. 前提条件: このチュートリアルで使用するために必要なツール。
  3. 実際に試す: このチュートリアルで構築する内容のデモ。
  4. CMakeプロジェクトの設計: パッカーのやや複雑なニーズに合わせたビルドシステムを構築するためのミニCMakeチュートリアル。
  5. バイナリをスタブにパックする: パッカー/スタブの組み合わせのうちパッカー部分を書く方法のチュートリアル、およびWindows実行可能ファイル形式の入門。
    1. リソースの管理
    2. PEファイルの解析
    3. PEファイルの操作
  6. ローダーのシミュレーション: 対象の実行可能ファイルを展開してロードするための最小限のスタブ実行可能ファイルを構築する方法のチュートリアル、およびより高度なWindows実行可能ファイル操作の入門。
    1. メモリからPEを読み込む
    2. 実行のためにPEをロードする
    3. APIインポートの解決
    4. アドレスの解決
    5. 実行の移行
  7. さらなる演習: パッカー開発の知識をさらに深めるためのいくつかの演習。

難しそうに思えますか? このREADMEを要約したプレゼンテーション版を試してみてください。YouTube動画も近日公開予定です!

パッカーとは何か?

パッカーは、自身のアドレス空間(あるいは別プロセスのアドレス空間)内で別のプログラムを展開し起動するプログラムです。デバッガや仮想サンドボックスなどの解析環境を攻撃するベクターとして知られることもあります。主に以下のような用途で使われます:

  • 圧縮: パッカーは、特定のバイナリのコードを圧縮するために一般的に使われます。これは数少ない合法的な用途の1つです。圧縮型パッカーの例についてはUPXを参照してください。
  • 難読化: パッカーは、プログラムを難読化したり、リバースエンジニアリングから防御する目的でも使われます。リバースエンジニアリング対策パッカーの例については、Riot Gamesのpackmanパッカーを参照してください。
  • 回避: マルウェアは、アンチウイルスやEDRさえも回避するために、さまざまなパッカーを使用することがよくあります。回避型パッカーの例については、SmokeLoaderパッカーのこの分析を参照してください。

基本的に、パッカーにはほんのいくつかの基本ステップしかありません:

  1. 圧縮段階: 元の実行可能ファイルを圧縮、難読化、またはその両方を行い、新しいバイナリに変換する段階です。
  2. 展開段階: パックされた実行可能ファイルが、ロードのために元の実行可能ファイルを展開または難読化解除する段階です。
  3. ロード段階: パッカーが、ホストプラットフォームの実行可能ローダーと同様のさまざまな手順を模倣する段階です。実行可能バイナリの複雑さのため、どの程度の深さまでエミュレートするかにもよりますが、これが最も複雑なステップです。
  4. 実行段階: ホストのスタブ実行可能ファイルから、新たにロードされた(つまり展開された)コードへ制御が移る段階です。

同様にシンプルに、パッカーはいくつかの構成要素だけで成り立っています:

  • パッカー: この構成要素は、スタブ実行可能ファイル と呼ばれるものを準備し、指定されたバイナリを展開するために必要なデータを提供する役割を担います。これは最終的に圧縮段階です。
  • スタブ: このバイナリは、元のバイナリの展開、ロード、実行を担当するコード部分です。ご覧のとおり、スタブ実行可能ファイルがパッカーの大部分の重労働を行います。

パッカーの構築は厄介な場合があります。なぜなら、スタブをビルドし、何らかの方法でパッカー実行可能ファイルに組み込む必要があるからです。Windowsでは、単純なコンパイルを超えたVisual Studioのビルドシステムを学ぶのは骨の折れる作業になり得ます。幸い、CMakeはVisual Studioをサポートするシンプルでクロスプラットフォームなビルドシステムを提供し、高度にカスタマイズ可能です!

このチュートリアルでは、以下を教えることを目的としています:

  • パッカーの2つの主要部分を、まとまりのあるテスト可能なビルド環境に分割し統合する方法。
  • Windows実行可能ファイルを操作して、追加のロード可能なデータを追加する方法。
  • Windows実行可能ファイル内をナビゲートして、任意のデータを取得・ロードする方法。
  • Windowsローダーの一部をエミュレートして、Windows実行可能ファイルをロード・実行する方法。

すでにC++とCMakeに精通している方は、パッキングのセクションに直接進んでください。そうでない場合は、読み進めてください!

前提条件

  • C++の知識: このチュートリアルではポインタ演算を多用するため、C++を知らなければあまり役に立ちません。
  • Visual Studio: Visual Studioには、フル機能のWindows C++コンパイラが含まれています。このプロジェクトはVisual Studio 2019でテストされていますが、新しいバージョンでも問題ないはずです。
  • CMake: CMakeは、Visual Studioコンパイラ向けにビルドを構成するために使用するビルドシステムです。

実際に試す

まず、このビルドシステムが機能し、適切にパックされた実行可能ファイルを作成することを何らかの方法で確認しましょう。CMakeとVisual Studioをインストールしたら、お好みのターミナルでこのリポジトリのルートディレクトリに移動し、次のコマンドを実行してください:``` $ mkdir build $ cd build $ cmake ../

これにより、packerチュートリアルコードをビルドするために必要なプロジェクトファイルが作成されます。次に実行します:```
$ cmake --build ./ --config Release

This will build the packer project in Release mode. Then, you can run the following test:

これを実行すると、Release モードで packer プロジェクトがビルドされます。次に、次のテストを実行できます:``` $ ctest -C Release ./

すべてがうまくいけば、test\_pack と test_unpack は成功するはずです。パッキングの結果を自分で確認したい場合は、次のように表示されるはずです:```
$ ./packed.exe
I'm just a little guy!

これを実現したすべての構成要素について説明しましょう。

CMakeプロジェクトの設計

パッカーの主要コンポーネントが何であるかはわかりましたが、開発サイクルの一環としてパッカーをすぐにテストするにはどうすればよいでしょうか? バイナリのパックおよびアンパック処理を適切にテストするには、プロジェクト全体に3つ目のバイナリを追加する必要があります。つまり、全体として次の3つのプロジェクトが必要です:

  • パッカー
  • スタブ
  • パックするためのダミー実行ファイル

また、バイナリがスタブ実行ファイルに圧縮されるようにするための圧縮ライブラリも必要です。zlib がこれに最適です。

最初の段階でのプロジェクト階層は、次のようになるはずです:``` packer/ +---+ CMakeLists.txt + dummy/ | | | +---+ CMakeLists.txt | + src/ | | | +---+ main.cpp | + stub/ | | | +---+ CMakeLists.txt | + src/ | | | +---+ main.cpp | + src/ | | | +---+ main.cpp | + zlib-1.2.13/ | +---+ CMakeLists.txt + ...

各フォルダのmain.cppは、今のところ次のようにシンプルにできます:```cpp
#include <iostream>

int main(int argc, char *argv[]) {
    std::cout << "I'm just a little guy!" << std::endl;
    
    return 0;
}

すでに、対処すべき単純な依存関係チェーンがあることを確認しておきましょう。これは、CMake がいくつかの設定を追加することでうまく解決してくれます。

  • packer と stub は zlib に依存する
  • packer は stub に依存する
  • dummy は packer に依存する(packer によってパックされる必要があるため)

では、CMake の設定として、ルートプロジェクト、つまり packer から始めましょう。

CMake を扱うには、通常、最低バージョンの指定が必要です。CMake は長い間存在しており、以前のバージョンの長期的な使用をサポートしているためです。その後、packer プロジェクトを C++ プロジェクトとして宣言できます。```cmake

target a cmake version, you can target a lower version if you like

cmake_minimum_required(VERSION 3.24)

declare our packer as a C++ project (since zlib is a C project and the compilation

detection might get confused)

project(packer CXX)

また、パッカーを「MultiThreaded」(すなわち /MT)として宣言し、「MultiThreadedDLL」(すなわち /MD)の代わりにすることで、ランタイムDLLの依存関係を気にする必要がなくなります。```cmake
# this line will mark our packer as MultiThreaded, instead of MultiThreadedDLL
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

変数設定文の山かっこ内の文はジェネレータ式と呼ばれ、必要な場所で構成時のデータを解決するのに役立ちます。このファイル全体で頻繁に目にすることになるでしょう。このジェネレータ式は、構成がDebugであることを検出すると文字列Debugを出力し、それ以外の場合は何も出力しません。これにより、Debugコンパイルプロファイルが選択された場合はMultiThreadedDebugのランタイムライブラリが提供され、Releaseなどの非デバッグコンパイルプロファイルが選択された場合はMultiThreadedが提供されます。そこで何が起こっているのかをよく理解するには、条件付きジェネレータ式を参照してください。CMAKE_MSVC_RUNTIME_LIBRARY変数の詳細については、CMakeドキュメントを参照してください。

CMakeでは、Visual StudioがUIでプロジェクトを作成するときに自動的に行うように、ソースコードを階層に整理できます。また、フォルダー内を再帰的に検索して、一致するファイル名を見つけます。設定ファイルでは、ヘッダー(.hpp)、コード(.cpp)、リソーススクリプト(.rc)にグローバル再帰を設定しています。この例では、main.cppだけが必要ですが、これは大規模なプロジェクトにとって知っておくと便利です。```cmake

this will collect header, source and resource files into convenient variables

file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/src/.cpp) file(GLOB_RECURSE HDR_FILES ${PROJECT_SOURCE_DIR}/src/.hpp) file(GLOB_RECURSE RC_FILES ${PROJECT_SOURCE_DIR}/src/*.rc)

this will give you source groups in the resulting Visual Studio project

source_group(TREE "${PROJECT_SOURCE_DIR}" PREFIX "Header Files" FILES ${HDR_FILES}) source_group(TREE "${PROJECT_SOURCE_DIR}" PREFIX "Source Files" FILES ${SRC_FILES}) source_group(TREE "${PROJECT_SOURCE_DIR}" PREFIX "Resource Files" FILES ${RC_FILES})

ここで、CMakeはより正確には**メイクシステム**と表現すべきであることを説明しておきます。CMakeは、指定されたコンパイラに基づいて、与えられた環境に適した正しい「メイクシステム」を作成します。Linuxでは、これは検出された(または指定された)コンパイラ用のmakefileになります。Windows上の私たちにとっては、これは私たちのVisual Studioのバージョンと互換性のあるVisual Studioプロジェクトを生成します。つまり、MSVCメイクシステムを作成したら、必要に応じてVisual Studioだけをすべてに使用できるということです! 結局のところ、あなたはCMakeを使ってVisual Studioを構成しているのです。つまり、ここで行っていることは、プロジェクトをGUIで作成するときにVisual Studioが自動的に行う、プロジェクト内のファイルのツリーをVisual Studioで作成することに他なりません。

次に、依存プロジェクトを追加する必要があります。```cmake
# this will add zlib as a build target
add_subdirectory(${PROJECT_SOURCE_DIR}/zlib-1.2.13)

# this will add our stub project
add_subdirectory(${PROJECT_SOURCE_DIR}/stub)
ツールをダウンロード