banner
lca

lca

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

《ゼロから始めるIDAリバースエンジニアリング》学習ノート-16(Aspack脱殻)

puahad と popad#

加壳プログラム:unpackme.aspack.2.2、インターネットで検索可能。

image.png

ida を開き、プログラムを手動でロードし、入力セクションの作成をオフにします。

image.png

加壳プログラムのエントリ

上の図で、最初の命令はpushadで、pushadはすべての汎用レジスタの値をスタックにプッシュします。

pushadは以下の順序で全レジスタの値をスタックに保存します。

image.png

pushad の値の順序

popadpushadの逆の操作で、スタックから値を取り出し、以下の順序でレジスタに保存します。

image.png

ほとんどのシンプルなシェルでは、pushad命令を使用してレジスタの初期状態を保存し、その後OEPにジャンプしてメモリ内の元のコードを実行する前にPOPADを使用してレジスタの初期状態を復元します。
この規則に従って、pushad-popad法を使用してOEPを簡単に見つけることができます。

idapython を使用したデバッグ#

pushad-popad法とは何でしょうか?

デバッガを使用してプログラムを実行します。デバッガを実行する方法は 2 つあります。1 つ目はメニューバー-デバッガ-デバッガの選択、local windows debuggerを選択する方法、2 つ目は python を使用してデバッガを実行する方法です。今回は 2 つ目の方法でデバッガを実行します。

1、import idcで idc モジュールをインポートし、idc.loadと入力して tab キーで補完し、idc.load_debuggerを見つけ、パラメータはidc.load_debugger("win32",0) //1はリモートデバッグ、戻り値が True であれば実行成功を示します。

image.png

load_debugger をロードし、パラメータを設定

この時点でlocal windows debuggerがロードされました。

image.png

pusha の後にブレークポイントを設定します。

image.png

pusha の後にブレークポイントを設定

pushad-popad法は、pushad の後の命令の前に、スタック上に保存されたレジスタの値の位置を見つけ、その位置にブレークポイントを設定します。プログラムが元のコードを復号した後、OEP にジャンプする前に popad を使用してレジスタの初期値を復元し、そのブレークポイントをトリガーして実行を一時停止させ、OEP の位置を特定します。

F2 キーを押して pusha の次の命令にブレークポイントを設定すると、pusha の実行後にデバッグが一時停止します。(pusha は pushad に似ています)

python を使用してブレークポイントを設定する場合、次のような文を使用できます:

idaapi.add_bpt(0x46b002,0,idc.BPT_SOFT)
idaapi.add_bpt(0x46b002,0,0)
  • 最初のパラメータはブレークポイントのアドレス
  • 2 番目のパラメータはブレークポイントの長さ
  • 3 番目のパラメータはブレークポイントのタイプ(ソフトウェアブレークポイント BPT_SOFT または 0)

image.png

デバッガを選択し、最初のブレークポイントを設定した後、デバッガを起動してプログラムを実行し、そのブレークポイントで一時停止させる必要があります。F9 キーを押すか、python 文を使用してプログラムを実行します。

idc.StartDebugger("","","");

高バージョン(ida 7.7)では、上記のコマンドがエラーを返すため、次のコマンドを使用する必要があります。

idc.start_process("","","")

上記の文を実行すると、デバッガは以前設定したブレークポイント、つまり0x46b002に到達します。

image.png

ブレークポイント0x46b002に到達

下の図では、スタックビューの値は pushad が保存したレジスタの値であり、その後 popad 命令を通じて読み取られます。したがって、最初の行にブレークポイントを設定できます。

image.png

このデバッグでは、ブレークポイントの位置は 0x19ff54 で、esp の実行スタックの位置です。

ESP の右側の小さな矢印をクリックすると、対応するウィンドウのそのアドレス(ここではアセンブリウィンドウ)にジャンプします。

image.png

F2 を押してここにブレークポイントを設定し、実行時ではなく、読み取りと書き込み時にトリガーされるように変更します。

image.png

ウィンドウが表示されない場合は、メニューのデバッガー - ブレークポイント - ブレークポイントリストを開き、右クリックして設定を編集を選択します。

python を使用してブレークポイントを設定する場合、次のようにインストールできます:

idaapi.add_bpt(0x19ff54,1,3)

image.png

ブレークポイントリストは以下の通りです。

image.png

ブレークポイントリスト

上記のコードでは、最初のパラメータはブレークポイントのアドレス、2 番目のパラメータはブレークポイントのサイズ、3 番目のパラメータはタイプを示し、3 は read-write access(読み取りと書き込み)を表します。この文を実行することは、手動でブレークポイントを設定するのと同じです。

BPT_EXEC = 0,
BPT_WRITE = 1,
BPT_RDWR = 3,
BPT_SOFT = 4,

ブレークポイントタイプのパラメータ

ブレークポイントリストで、最初に設定したブレークポイントを右クリックし、DISABLE を選択して無効にするか、次の python 文を使用します。

image.png

idaapi.enable_bpt(0x46b002,0)

image.png

  • 最初のパラメータはブレークポイントのアドレス
  • 2 番目のパラメータが 1 の場合はブレークポイントを有効にし、0 の場合は無効にします

0x46b002 が緑色にマークされている場合は無効を示し、スタック上のブレークポイントは赤色で有効を示します。

image.png

F9 キーを押してデバッグを続行するか、次の python 文を入力します。

idaapi.continue_process()

下の図では、デバッグが popad 命令によってレジスタの初期値を取得した後に中断され、プログラムは OEP、つまり 0x4271b0 にジャンプします。なぜなら、push ret は jmp に似ているからです。

image.png

popa 命令

OEP までステップ実行を続けます。

image.png

OEP エントリを見つけたので、実行可能ファイルを再分析し、関数を識別できます。

image.png

プログラムを再分析

image.png

idapython を使用したダンプ#

OEP を見つけた後、次のステップはダンプを行うことです。ファイルのベースアドレスと実行可能ファイルの最後のセクションの最高アドレスが必要です。

image.png

上の図から、ベースアドレスは 0x40000、最高アドレスは 0x46e000 であることがわかります。

ダンプスクリプトは以下の通りです:

import idaapi
import idc
import struct

start_ea = 0x400000
end_ea = 0x46e000
step = 4  # 各アドレスのデータは4バイトを占める

file_path = "dump.bin"
with open(file_path, "wb") as f:
    for ea in range(start_ea, end_ea, step):
        # 指定されたアドレスの4バイトデータを読み取り、リトルエンディアンに変換
        bin_data = struct.pack("<L", idaapi.get_32bit(ea))
        f.write(bin_data)

ファイル - スクリプトファイルから上記の py スクリプトをロードし、実行後、現在のディレクトリに dump.bin ファイルが生成され、その拡張子を exe に変更します。

peeditor を使用して、セクションビューを開き、すべてのセクションを右クリックして dumpfixer を選択します。

image.png

この時点で、アイコンが修正されました。

image.png

アイコンを修正した後、Scylla 0.98 を使用してプロセスをデバッグ対象の加壳ファイルにアタッチします。現在 OEP エントリに到達しています。

image.png

このプロセスをロードします。

image.png

OEP を 004271B0 として入力し、IAT Autosearch と Get Imports をクリックします。

image.png

無効な API が 1 つ見つかると、修正が自動で失敗し、手動で修正する必要があります。

image.png

0x460818 の API

上の図で、0x460818 は最初の有効セクションの API 関数で、その上には未認識の API アドレスが多数あります。

最初の未認識の 0x46080c の内容を確認し、D キーを押してデータタイプを変更し、バイトを再構成します。以下の図のように:

image.png

ここにある内容は有効なアドレスを指しておらず、CTRL+X を押しても参照はありません。

image.png

本当の API 関数には、どこで呼び出されているかを示す参照情報があるはずです。

したがって、これらは API 関数ではないため、削除できます。

image.png

clear キーをクリックし、IAT Autosearch をクリックして、ポップアップウィンドウで「いいえ」を選択します。

image.png

現在の IAT の開始位置は 0x460810 で、Get Import をクリックするとすべての API を見つけることができます。

image.png

Fix Dump をクリックしてファイルをダンプし、以前にエクスポートしたファイルを選択します。

image.png

最後に、脱壳プログラムが正常に実行されます。

image.png

これで、プログラムの脱壳は終了です。

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