2

user32にブレークポイントを設定しようとしています!RegisterClipboardFormat明らかに、この関数はエクスポートされます(link / dump / exports-すぐそこにあります)。MicrosoftシンボルサーバーからPDBファイルをダウンロードする前に、次の機能を見つけることができます。

0:001> lm m user32
start    end
76eb0000 76fcf000   USER32     (export symbols)       c:\Windows\system32\USER32.dll

0:001> x user32!RegisterClipboardFormat*
76ec4eae USER32!RegisterClipboardFormatA (<no parameter info>)
76ec6ffa USER32!RegisterClipboardFormatW (<no parameter info>)

問題はありません。これらの関数のいずれかを「bu」することができます。しかし、Microsoft PDBサーバーからPDBシンボルをダウンロードすると、次のようになります。

0:001> 
start    end        module name
76d50000 76e6f000   USER32     (pdb symbols)          c:\symbols\user32.pdb\561A146545614951BDB6282F2E3522F72\user32.pdb

0:000> x user32!RegisterClipboardFormat

WinDBGはシンボルを見つけることができません。ただし、RegisterWindowMesssageを見つけることができます。

0:000> x user32!RegisterWindowMessage*
76d64eae          USER32!RegisterWindowMessageA = <no type information>
76d66ffa          USER32!RegisterWindowMessageW = <no type information>

関数のアドレスが同じであることに注意してください(これはWindows 8の場合です)。以前のバージョンについてはわかりません。これは、オプティマイザまたはDEFファイル(EXPORTセクションのfunc1 = func2)でおそらく達成されます。'link / dump / exports'は、RegisterWindowMessageとRegisterClipboardFormatが同じRVAを持っていることを示しています。

問題は、私がこれにあまりにも多くの時間を費やしたことです。だから私の質問は:

  1. WinDBG内から、欠落しているエイリアスエクスポートシンボルを見つける簡単な方法はありますか。
  2. RegisterClipboardFormatWでのみ中断したいとします。正しく思い出せば、どこかにJMP命令があるはずです(呼び出し側モジュールのインポートテーブル内)。そのシンボルを見つけるにはどうすればよいですか?すべての呼び出しモジュールでこのエントリを見つける方法はありますか?
4

1 に答える 1

3

RegisterWindowMessageとは同じRVAを持っているためRegisterClipboardFormat、同じ実装を共有します。どうやらWindowsは2つを区別せず、クリップボード形式とウィンドウメッセージの両方が同じ識別子のドメインを共有しているようです。

最初の質問-エクスポートされた関数に対応する実装関数を見つける方法。(シンボルが修正されていると仮定します)最初に、エクスポートのRVAを計算します。

C:\>link /dump /exports C:\Windows\Syswow64\user32.dll |findstr RegisterClipboardFormat
   2104  24F 00020AFA RegisterClipboardFormatA
   2105  250 00019EBD RegisterClipboardFormatW

次に、WinDbgで、DLLのロード元の開始アドレスを見つけます。コマンドを実行するlmlml、すべてのモジュールを一覧表示します。必要なのは、目的のモジュールを見つけることだけです。

0:001> lml
start    end        module name
75460000 75560000   USER32   

開始アドレスへのオフセットとしてRVAを使用して、それに対応するシンボルを取得します。

0:002> ln 75460000+00020AFA
(75480afa)   USER32!RegisterWindowMessageA   |  (75480b4a)   USER32!MsgWaitForMultipleObjects
Exact matches:
0:002> ln 75460000+00019EBD
(75479ebd)   USER32!RegisterWindowMessageW   |  (75479eea)   USER32!NtUserGetProcessWindowStation
Exact matches:

したがって、ここで実際に、RegisterClipboardFormatが実際にRegisterWindowMessageを呼び出すことがわかりました。

2番目の質問-ブレークポイントをRegisterClipboardFormatにのみ配置し、RegisterWindowMessageには配置しない方法。それらは同じ実装を共有しているため、一般的には不可能です。たとえば、アプリが呼び出さGetProcAddress("RegisterClipboardFormat")れ、ある関数または別の関数が呼び出されたかどうかを判断するのに苦労する場合があります。ただし、インポートされた関数を介して呼び出しが行われたことがわかっている場合は、これを行うことができます。インポートされたすべての関数は、アプリケーションのインポートアドレステーブルで宣言されます。インポートアドレステーブルのエントリにアクセスブレークポイントを設定すると、呼び出しが行われる前にブレークすることができますこれはコンパイラ固有の可能性がありますが、VisualC++がインポートアドレステーブルのエントリにシンボリック名を割り当てることは知っています。この場合、ブレークポイントを設定するのは簡単です。

ba r4 MyModule!_imp_RegisterClipboardFormatA
于 2012-05-29T04:21:31.647 に答える