2012-03-10 9 views
3

DLL内に関数のアドレスが見つかりました。私のDLLではなく、このDLLのソースコードがありません。このDLLは頻繁には頻繁に変更されるものではありませんが、変更すると逆アセンブルで問題を見つけることができます。それを署名することについてWebでいくつかのノートを見て、次にこの保存された署名でそれを見つける。 これを実装する方法のアイデアや実際の例を教えてください。Windows DLLの署名で関数を検索

+0

ヘッダーファイルやドキュメントなしで作業する方法がわかりません。 –

+0

使用したい機能をDLLからエクスポートしていません。内部DLL機能です。 –

+0

はい、それはあなたがその機能を呼び出すとは思わない微妙なメッセージです。 –

答えて

7

これは、過去に行ったコード署名スキャンによって実現できます。このコンセプトは主に、機能が頻繁に更新の間にあまり変化しないことに頼っていますが、他の機能が拡張または縮小されることによって前後にプッシュされたため、単に再配置されます。

解体誰、のはMessageBoxAの例を見てみましょうが、私のために次のようになります。

765DEA11 > 8BFF    MOV EDI,EDI 
765DEA13 55    PUSH EBP 
765DEA14 8BEC    MOV EBP,ESP 
765DEA16 833D 749A5E76 00 CMP DWORD PTR DS:[765E9A74],0 
765DEA1D 74 24   JE SHORT USER32.765DEA43 
765DEA1F 64:A1 18000000 MOV EAX,DWORD PTR FS:[18] 
765DEA25 6A 00   PUSH 0 
765DEA27 FF70 24   PUSH DWORD PTR DS:[EAX+24] 
765DEA2A 68 A49E5E76  PUSH USER32.765E9EA4 
765DEA2F FF15 34145876 CALL DWORD PTR DS:[<&KERNEL32.Interlocke>; kernel32.InterlockedCompareExchange 
765DEA35 85C0    TEST EAX,EAX 
765DEA37 75 0A   JNZ SHORT USER32.765DEA43 
765DEA39 C705 A09E5E76 01>MOV DWORD PTR DS:[765E9EA0],1 
765DEA43 6A 00   PUSH 0 
765DEA45 FF75 14   PUSH DWORD PTR SS:[EBP+14] 
765DEA48 FF75 10   PUSH DWORD PTR SS:[EBP+10] 
765DEA4B FF75 0C   PUSH DWORD PTR SS:[EBP+C] 
765DEA4E FF75 08   PUSH DWORD PTR SS:[EBP+8] 
765DEA51 E8 73FFFFFF  CALL USER32.MessageBoxExA 
765DEA56 5D    POP EBP 
765DEA57 C2 1000   RETN 10 

トリックはあなたがアップデートで同じ滞在する可能性があると考え、コードのいくつかのブロックを推測することですが、さらに重要なことは、この機能に固有のことです。通常、エピローグ/プロローグをスキャンするのは無駄です。私はおそらく次のブロックを取るでしょう:

765DEA16 833D 749A5E76 00 CMP DWORD PTR DS:[765E9A74],0 
765DEA1D 74 24   JE SHORT USER32.765DEA43 
765DEA1F 64:A1 18000000 MOV EAX,DWORD PTR FS:[18] 
765DEA25 6A 00   PUSH 0 
765DEA27 FF70 24   PUSH DWORD PTR DS:[EAX+24] 
765DEA2A 68 A49E5E76  PUSH USER32.765E9EA4 
765DEA2F FF15 34145876 CALL DWORD PTR DS:[<&KERNEL32.Interlocke>; 

ブロックの長さを選ぶときにバランスをとる必要があります。ブロックが長くなればなるほど、関数を一意に識別する可能性が高くなりますが、更新中にコードが挿入される可能性が高くなります。つまり、分割されたことを意味します。私が選択したブロックには、参照。これらは、次の更新に移転することができるので、私たちは、任意のデータまたは関数のアドレスに依存することはできませんので、我々はワイルドカードで、それらのバイトを埋める:

765DEA16 833D XXXXXXXX 00 CMP DWORD PTR DS:[XXXXXXXX],0 
765DEA1D 74 XX   JE SHORT XXXXXXXX 
765DEA1F 64:A1 18000000 MOV EAX,DWORD PTR FS:[18] 
765DEA25 6A 00   PUSH 0 
765DEA27 FF70 24   PUSH DWORD PTR DS:[EAX+24] 
765DEA2A 68 XXXXXXXX  PUSH XXXXXXXX 
765DEA2F FF15 XXXXXXXX CALL DWORD PTR DS:[XXXXXXXX] 

これが私たちのバイトの署名が今であることを意味:

0x83の0x3D 0x? 0x? 0x? 0x? 0x74 0x? 0x64 0xA1 0x18 0x00 0x00 0x00 0x6A 0x00 0xFF 0x70 0x24 0x68 0x? 0x? 0x? 0x? 0xFF 0x15 0x? 0x? 0x? 0x?

0x?バイトは、変更が予想されるバイトであるワイルドカードを示します。他のバイトは、更新で変更されないと予想されるバイトです。実行時にバイトを使用して関数を見つけるには、ワイルドカードを考慮してこれらのバイトをスキャンする必要があります。プロセスはとてもおおよそ次のとおりです。

  • 列挙プロセスのすべての実行可能ページ(VirtualQueryEx
  • 我々は(アカウントにワイルドカードを取ったバイトの署名のためのスキャン - これはスキップforループとして実装するのは簡単ですワイルドカードバイト)
  • は、真の関数のアドレスを取得enumeratのではなく、実際にあなたがこのケースでは(本来の機能からブロックのオフセットを取得したアドレス、0x765DEA16 - 0x765DEA11 => 0x5

を修正するには実行可能なすべてのページを表示するには、この場合には、そのモジュール内で関数が存在するモジュール(user32.dll)を見つけて、そのモジュール内でのみ検索すれば十分です。

+0

私はその関数をcからどのように呼び出すことができるのだろうか。それをポインタに割り当てて、それを呼び出しますか?それは動作しますか? –

+0

@alFReDNSH関数が引数を取らない場合は、そうすることができます。なぜなら、呼び出し規約の違いを無視することができるからです。それ以外の場合は、適切にキャストするように注意する必要があります。 –

+0

最初の引数としてintをとり、intを返した場合は、次のようになりますか? int lolz = 1; int(* foo)(int); foo = <機能アドレス>; lolz = foo(lolz); –

関連する問題