3

ボタンを表示するアプリケーションを想像してください: OK. ボタンがクリックされた直後に、プログラムの実行を中断し、WinDbg を使用して逆アセンブリを表示することは可能ですか? どうすればいいですか?このシナリオでは、ソース コードは利用できません。

4

2 に答える 2

8

したがって、あなたの説明は非常に一般的であり、あまり明確に定義されていません。正確な調査は、元に戻そうとしているアプリケーションによって異なります。記号があれば簡単に作業できますが、必須ではありません。

まず、いくつかの (些細な) 背景: Windows は、Windows メッセージを介してアプリケーションと通信します。アプリケーションはメッセージ キューからメッセージを取得し、ほとんどの場合、それらのメッセージを適切な Windows プロシージャにディスパッチします。

まず、「ボタンがクリックされた直後」とはどういう意味ですか? あなたは実際にはこのコードを気にしていないと思います。アプリケーションにカスタム ボタンを含めることもできますが、そのボタンが WM_LBUTTONDOWN メッセージをどのように処理するかは非常に重要です。あなたのアプリケーションには Windows ストック ボタン (user32.dll または comctl32.dll に実装されている) があり、あなたはそれを気にしないと仮定します。

WM_LBUTTONDOWN を処理するボタン コントロールの既定の実装は、ボタンを含むウィンドウに WM_COMMAND を送信することです。通常、調査するアプリケーションはそこで「クリック」を処理します。ここで、これが「OK」ボタンの場合、ID は IDOK (定義は 1) になり、「Enter」キーをクリックしたときにも Windows から同じメッセージが送信されます。

そのため、アプリケーションが WM_COMMAND をどのように処理するかを調べています。見つけたいのは、Windows の手順です。Spy++ でそれを行います。Spy を開き、ボタンを含むウィンドウを見つけます。探しているコードがそのウィンドウの Windows プロシージャにある可能性が最も高いです。Spy++ は、ウィンドウ プロシージャのアドレスを教えてくれます。

例として、メモ帳の [名前を付けて保存] ダイアログの [保存] ボタンを見てみましょう。私のマシンでは、アドレスは 0x73611142 で、ComCtl32.dll にあります。

WinDbg に移動し、関数を見てください。

0:000> u 73611142
COMCTL32!MasterSubclassProc
73611142 8bff            mov     edi,edi
73611144 55              push    ebp
73611145 8bec            mov     ebp,esp
73611147 6afe            push    0FFFFFFFEh
73611149 6858126173      push    offset COMCTL32!Ordinal377+0x146 (73611258)
7361114e 68a1b06273      push    offset COMCTL32!DllGetVersion+0x336f (7362b0a1)
73611153 64a100000000    mov     eax,dword ptr fs:[00000000h]
73611159 50              push    eax

これは確かに関数です。すべての Windows と同様に、 で始まりmove edi,edi、フレーム ポインターを設定します。

ブレークポイントを設定して Go を押すと、すぐにブレークします。見てみましょう:

0:000> bu 73611142
0:000> g
0:000> kb1

ChildEBP RetAddr Args to Child
0101f220 75d87443 00120c6a 00000046 00000000 COMCTL32!MasterSubclassProc

最初の引数 (00120c6a) は、ウィンドウのハンドルです。Spy++ の値と比較すると、同じはずです。2 番目の引数はメッセージです。私の場合、WM_WINDOWPOSCHANGING である 0x46 でした。

OK、これらすべてのメッセージを気にする必要はありません。気になるメッセージだけを中断したいと思います。0X0111 (winuser.h) である WM_COMMAND が気になります

次に、次のコマンドを入力します (少し複雑なコマンドです)。

0:000> bu 73611142 "j poi(esp+4)==00120c6a AND poi(esp+8)==111 AND poi(esp+''; 'gc'"
breakpoint 0 redefined

Windows プロシージャにブレークポイントを設定し、最初の引数 ( poi(esp+4) ) が Windows ハンドルで、2 番目の引数が 111 の場合にのみブレークするように WinDbg に指示します。「gc」は WinDBG に続行するよう指示します。条件が満たされない場合の実行。

これで、逆アセンブリをデバッグできます。シンボルがあれば作業は簡単になりますが、これは必須ではありません。いずれにせよ、Microsoft の簡易シンボルをシンボル サーバーからダウンロードすることを忘れないでください。デバッグしているコードが Windows API を呼び出している場合は、それを確認できます。

それはそれについてです。要件が異なる場合 (異なるウィンドウ、異なるメッセージなど) は、この手法を変更してください。Windows プロシージャを確実に見つけることができない場合は、最後の手段として、PostMessage または DispatchMessage にブレークポイントを設定することを検討してください (ただし、そのコードに従う必要があります)。重労働のリバースには、実行可能ファイルを逆アセンブルし、さまざまな相互参照を解決する IDA を使用します。

于 2013-01-19T18:28:26.330 に答える
2

pdbs があり、プライベート シンボルが削除されていないと仮定すると、次のようにボタン ハンドラーにブレークポイントを設定します。

bp myDLL!myWindowApp::onOKBtnClicked

pdbs がある場合は、x を使用して可能性の高いハンドラーを検索できます。

x myDLL!myWindowApp::*ok*

これは、どのdllと関数名が何であるかを知っているか推測できることを前提としています。そうでない場合は、spy++、Win Spy++、またはWin Detectiveを使用してこの情報を調べて、ボタンのハンドルを取得し、ウィンドウメッセージをインターセプトし、その情報からブレークポイントを設定します.

ブレークポイントに到達したら、uを使用してアセンブリ コードを表示できます。必要に応じてmsdn ガイドがあります。

于 2013-01-17T17:08:01.547 に答える