PE Explorer を利用した Mona のデバッグの仕方

背景と目的

Mona で特定の eip 範囲で CPU 時間が使われている。
この eip はソースコード上ではどこにマッピングされているかを知りたい。
通常は ld -Map で吐かれるリンクマップでシンボルとリニアアドレスの対応はとれるが、DLL などでは表示されないみたい。

流れ

  1. その eip 範囲のメモリをダンプする
  2. ダンプしたメモリにマッチする DLL を特定する
  3. DLL を PE Explorer で開いて、処理の場所を特定する

1. eip 範囲のメモリをダンプする

適当な一例。
良い子はマネしないでね。

void dumpMemory()
{
    uint32_t* p = (uint32_t*)0xA0029D73;

    for (int i = 0; i < 100; i++)
    {
        logprintf("%x ", p[i]);
    }
}

2. ダンプしたメモリにマッチする DLL を特定する

for i in `find -name "*.DLL"` ; do echo $i; od -x $i -Ax | grep -A2 '4589 8bf4 f445 5b5b 5d5e'; done

マッチした部分は、先頭からのオフセットが出力されているので、このオフセットをキーにして次の作業を行う。

DLL を PE Explorer で開いて、処理の場所を特定する

マッチしたオフセットが 0x25D0 だったと仮定。

  1. PE Explorer に DLL を読み込ませる
  2. .text section を選択して disassembler ボタンを押す
  3. disassemble 画面に Virtual Address と Pointer to RawData という値があるのでメモする
  4. disassemble 画面で Virtual Address + (0x25D0 - Pointer to RawData) の結果の Virtual Address の部分の出力結果を見る
  5. そのアドレスに探していたバイト列があれば正解
  6. そのアドレスから上にスクロールしていくと、どの手続きの中の処理か?が分かる。
  7. さらに細かく調べるなら関数を gcc -S で出力した結果と比べて関数内のどの処理かを見極める。


ああ。投げやりだ。。