3

ワトソン博士の情報を含むエンドユーザーからクラッシュレポートを受け取り、それらを使用してクラッシュが発生した場所(つまり、コードのどの行)を見つけたいと思います。

出荷するexeはデジタル署名されているため、クラッシュレポートのEIPを使用することはできません。これにより、すべてのオフセットが変更されます。ただし、クラッシュ情報には「CS:EIPのバイト数」も含まれています。これは、クラッシュが発生したEIPから始まる最初の16バイトです。次のようになります。

Bytes at CS:EIP:
85 c4 14 c3 8b ff 55 8b ec 6a 0a 6a 00 ff 75 08

これらの16バイトは、exeファイルで1回だけ発生します。HEXビューアだけを使用してEXEでオフセットを見つけることができますが、デバッグ中にそこにジャンプしてソースにある行を確認するには、EXEがロードされた後のメモリ内のオフセットを知る必要があります。

ロード後にプログラムのコードセグメントをスキャンする最良の方法は何ですか?EXEのベースオフセットがどこにあるかを見つけるコードを追加し、それを循環して、memcmpを使用してバイトパターンが発生する場所を見つけることはできますか?

また、EXEのベースオフセットがどこにあるかをどのように見つけることができますか?

4

5 に答える 5

4

私は同じ問題に対して非常に単純なアプローチを使用しています。

まず、コード セグメントの物理的な (ファイル内の) オフセットを見つけるために、実行可能ファイルをダンプします。

次に、これらの「魔法の」バイトがバイナリにあるメモリアドレスからそれを減算します。

次に、プログラムをデバッガーで実行し、このオフセットをコード セグメントの仮想アドレスに追加します。

       .text name
  10EE8E virtual size
    1000 virtual address (00401000 to 0050FE8D)
  10F000 size of raw data

 --> 400 file pointer to raw data (00000400 to 0010F3FF) <--

       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
60000020 flags
         Code
         Execute Read
于 2012-03-02T10:50:19.723 に答える
2

ollydbgのようなものを使用すると、実行中にプロセス メモリをスキャンし、見つかったポイントを表示するときに file:line とソース コードをレポートすることができます (pdb が正しくリンクされている限り)。ファイルを静的に開くと、仮想化されたアドレスを表示することもできます。

于 2012-03-02T10:02:46.797 に答える
1

または、基本的なツールだけを使用している場合は、Visual Studio またはプラットフォーム SDK からdumpbin(別名) を使用できます。link /dump /allすべての再配置が適用された 16 進ダンプおよび/または逆アセンブリを提供し、PDB を選択してシンボル名をリストに追加します。クラッシュが原因でロード時に DLL が別のアドレスに再配置された可能性がありますがdumpbin /headers、DLL のデフォルトのベース オフセットを調べるために使用します。

ワトソン博士は、そこにあるバイト数だけでなく、EIP 値も教えてくれませんか? 私がそれを使用してからしばらく経ちました。より良い解決策は、 WinQualにサインアップすることです。その後、エンド ユーザーはクラッシュ ダンプを Microsoft にアップロードし、そこから収集することができ、実際のミニ ダンプとヒープ ダンプを確認できます。

于 2012-03-02T10:12:08.643 に答える
0

あまりエレガントではありませんが、私が見つけた可能な解決策をここに投稿しています。GetModuleHandle をベース オフセットとして使用することが正しいかどうかはわかりませんが、これまでに試した 2 ~ 3 件のエラー レポートで動作しているようです。

unsigned char buf[] = { 0x85, 0xc4, 0x14, 0xc3, 0x8b, 0xff, 0x55, 0x8b, 0xec, 0x6a, 0x0a, 0x6a, 0x00, 0xff, 0x75, 0x08  };
HMODULE hModule = GetModuleHandle(NULL);
char* ii;
for (ii = (char*) hModule; memcmp(ii, buf, sizeof(buf)); ii++);

char buf2[1000];
sprintf(buf2, "%p", ii);
MessageBox(0,buf2,0,0);
于 2012-03-02T11:14:46.383 に答える