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 が見つかると、修正が自動で失敗し、手動で修正する必要があります。

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

これで、プログラムの脱壳が完了しました。

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