banner
lca

lca

真正的不自由,是在自己的心中设下牢笼。

《ゼロから始めるIDAリバースエンジニアリング》学習ノート-14(プログラムのデバッグの概要)

image

何がパッキングですか?#

この章では、upx パッキングプログラムのアンパックを示します。

パッキングとは、プログラムの実行可能コードを隠すために圧縮または暗号化の手段を用いることを指し、容易に逆コンパイルされるのを防ぎます。パッキングはプログラムに追加のセクション(STUB、スタブ)を追加し、プログラムが実行を開始した後、暗号化されたファイルを復号化してメモリ内の他のセクションに保存するか、元のプログラム内のセクションを作成し、復号化されたコードにジャンプして実行します。

ほとんどの場合、IAT(インポートテーブル)やファイルヘッダー(HEADER)を破壊することでファイルを保護します。これらは、元のファイルをアンパックされるのを防ぐために、逆デバッグコードを追加します。

die を使用してパッキングされているかどうかを確認します。

image

上の図から、upx 3.91 バージョンでパッキングされていることがわかります。プログラムは 32 ビット、i386 アーキテクチャです。

パッキングされたファイルの読み込み#

image

パッキングされたファイルを読み込むときは、入力セクションの作成をチェック解除し、手動読み込みをチェックします。

OK をクリックすると、次のウィンドウがポップアップし、確認をクリックします。

image.png

パッキング後のプログラムのエントリ

元のプログラムのエントリ

パッキング後のプログラムのエントリはアドレス 0x409BE0 であり、元のファイルのアドレスは 0x401000 です。

ファイルとメモリの使用量#

これら 2 つのファイルのセクションを比較すると、パッキングされたファイルのファイルヘッダーの下に upx0 セクションがあり、使用されるメモリは元のファイル内の他のセクションよりも大きいです。

image

元のファイル

image.png

パッキングファイル

パッキングファイルの upx0 ブロックは0x409000で終了し、元のファイルのヘッダー以下のセクションは0x401000から0x408200までです。プログラムが実行されると、ハードディスク上では 1k しか占有しないかもしれませんが、メモリ内では 20k 以上を占有する可能性があります。

image

上の図のように、元のファイルの CODE セクションの開始アドレスは0x401000で、セクションファイルのサイズ(ファイル内のセクションサイズ)は 0x600 バイト、メモリサイズ(仮想サイズ)は 0x1000 バイトを占有しています。

image.png

パッキングファイルに移ると、上の図のように、upx0 セクションの起点は0x401000で、upx0 セクションのハードディスク上のサイズは 0 ですが、メモリ使用量は 0x8000 バイトです。プログラムはここで元のプログラムコードを保存するために十分なスペースを占有し、その後ジャンプして実行します。

image.png

パッキングファイルの 0x401000 でのジャンプ

0x401000 の前にある dword_はデータ型が DWORD であることを示し、"?" はメモリ位置を占有しているが、何も内容が保存されていないことを示し、dup は 0xc00 個の dword、つまり 0x3000 バイトを示します。0x404000 も同様に 0x1400 バイトを占有しています。

image.png

したがって、合計で 0x8000 バイトが元のコードの内容を保存するために使用されています。

image.png

下の図のように、0x401000 で x キーを押すと、ここに 2 つの参照があることがわかります(後でこの部分を見ていきます)。

image.png

実行可能コードの参照

upx1 セクションファイルの使用量は 0xe00、メモリ使用量は 0x1000 です。

image.png

upx1 セクションのファイルおよびメモリ使用量

プログラムは元のコードを隠すためにいくつかの簡単な暗号化を使用している可能性があり、このセクションの起点 0x409000 にはいくつかの参照があります。

image.png

0x409000 の参照

1 つの参照は(下方)実行可能部分から来ており、クリックするとその場所にジャンプします。

image.png
プログラムのエントリ

スタブと OEP#

上の図のプログラムエントリの後のスタブで、ESI レジスタは 0x409000 というアドレスを渡します。以下の図のように、実行可能コードは元のファイルのパッキングされたコードの下にあり、upx1 ブロックに属しています。したがって、upx1 ブロックには元のファイルが暗号化された後に保存された内容と 0x409be0 以降のスタブコードが存在します。

image.png

追跡された実行可能コード

下の図では、プログラムが 0x409000 から内容を読み取り、何らかの計算を経て0x401000EDI=ESI-0x8000)に保存することがわかります。プログラムは ESI が指す内容をソースとして読み取り、操作を実行した後、EDI が指す内容に保存し、元のコードを復元します。

image.png

upx0 セクションに戻ると、upx0 セクションには 1 つの参照があります。

image.png

0x401000 の参照

下の図には、0x401000 に無条件にジャンプする 1 つの参照があります。これは上の図の 0x401000 の参照です。

image.png

jmp nearは次のアドレスに直接ジャンプする命令です。したがって、ここでスタブを実行し、元のコードを生成した後、プログラムは 0x401000(OEP、元のエントリポイント)にジャンプします。これは元のプログラムのエントリ(プログラムが最初に実行される場所)であり、対応するスタブエントリ(スタブエントリポイント)は 0x409be0 です。

その後、元のプログラムエントリは単にORIGINAL ENTRY POINTまたはOEPと呼ばれます。パッキングされたプログラムの場合、具体的な位置を知ることはできませんが、このプログラムには OEP があり、OEP は 0x401000 です。

OEP を探す#

ほとんどの場合、元のプログラムを取得することはできないため、パッキングプログラムの OEP アドレスを直接取得することはできません。次に、OEP を見つける方法を紹介します。

STUB が復号化操作を完了し、元のコードを生成した後、プログラムを実行するためにジャンプします。一般的に、元のコードが書き込まれるブロックで実行される最初の命令が OEP です。

OEP に入る前にブレークポイントを設定し、ここに到達する前に元のプログラムが生成されているかどうかを確認します。

image.png

ジャンプポイントにブレークポイントを設定

ローカルウィンドウデバッガーを選択してデバッグを開始し、ブレークポイントに到達するまで実行します。

image.png

image.png

ブレークポイントに到達

プログラムがブレークポイントに到達したら、F8 キーを押してステップ実行します。

image.png

警告メッセージが表示され、upx0 セクションが元々データとして解析されていたため、クリックしてコードとして解析します。

image.png

OEP に到達

現在、プログラムは元のコードを復号化し、実行にジャンプしました。ここでのコードは元のプログラムの 0x401000 のコードに非常に似ています。しかし、関数(loc_401000)として定義されていないため、グラフィカルビューに切り替えることはできません。ただし、これも自動的に実現できます。

image.png

IDA インターフェースの左下隅には隠れたメニューがあり、右クリックして「プログラムを再分析」を選択します。これで 0x401000 に戻ると、sub_401000 が表示され、これは関数であることを示し、スペースキーを押すとグラフィカルビューに切り替えることができます。

image.png

再分析後のコード

image.png

sub_401000

実行ブレークポイントを通じて OEP を探す#

OEP を見つける別の方法は、最初のセクションの最初の実行命令を見つけることです。この方法は時々成功します。

デバッガーでパッキングされたプログラムを起動し、エントリポイントで一時停止します。

image.png

スタブエントリポイント

セクションの起点、つまり 0x401000 に移動します。

image.png

F2 を押してブレークポイントを設定し、実行時に中断するように設定します。読み取りまたは書き込み時ではなく、そうでないと復号化中にパスワードを読み取ったり、元のコードを書き込むときに中断されます。具体的な位置がわからないため、著者はセクション全体のブレークポイント(0x8000 バイト)を設定しました。

image.png

設定が完了すると、すべての命令が赤くなります。

image.png

セクション全体にブレークポイントを設定

次に、メニューバー-デバッガー-ブレークポイント-ブレークポイントリストを開き、他のブレークポイントを無効にします。

image.png

その後、プログラムを実行します。

image.png

ブレークポイントをトリガー

この方法が成功した場合、OEP は 0x401000 であることがわかり、このブレークポイントを無効にします。

image.png

OEP

再分析後、0x401000 が関数として認識されます。

これまでに、OEP を見つける 2 つの方法を紹介しました。復号化コードのメモリスナップショットを作成します。次に行うべきことは、DUMP(ダンプ)および IAT を再構築して、パッキングされていない実行可能なプログラムを取得することです。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。