5

I'm working on a third-party program that aggregates data from a bunch of different, existing Windows programs. Each program has a mechanism for exporting the data via the GUI. The most brain-dead approach would have me generate extracts by using AutoIt or some other GUI manipulation program to generate the extractions via the GUI. The problem with this is that people might be interacting with the computer when, suddenly, some automated program takes over. That's no good. What I really want to do is somehow have a program run once a day and silently (i.e. without popping up any GUIs) export the data from each program.

My research is telling me that I need to hook each application (assume these applications are always running) and inject a custom DLL to trigger each export. Am I remotely close to being on the right track? I'm a fairly experienced software dev, but I don't know a whole lot about reverse engineering or hooking. Any advice or direction would be greatly appreciated.

Edit: I'm trying to manage the availability of a certain type of professional. Their schedules are stored in proprietary systems. With their permission, I want to install an app on their system that extracts their schedule from whichever system they are using and uploads the information to a central server so that I can present that information to potential clients.

4

1 に答える 1

5

必要な情報を抽出する 4 つの方法を知っていますが、それぞれに長所と短所があります。何かを行う前に、作成したソリューションは保証されておらず、実際、ターゲット アプリケーションが更新された場合に引き続き機能する可能性はほとんどないことに注意する必要があります。その理由は、いずれの場合も、データをエクスポートするための事前定義されたインターフェースではなく、実装の詳細に依存しているためです。

GUI のフック

最初の方法は、あなたが提案したように GUI をフックすることです。この場合、あなたがしていることは、実際のユーザーが見るものから読み取っているだけです。明確に定義された WinAPI をフックしているため、これは一般的に簡単です。1 つの危険は、プログラムが表示する内容が、それが表すはずの内部データと比較して矛盾または不完全であることです。

通常、WinAPI フックを実行するには、次の 2 つの一般的な方法があります。

  • DLL インジェクション。他のプログラムの仮想アドレス空間にロードする DLL を作成します。これは、ターゲットのメモリ全体への読み取り/書き込みアクセス (書き込み可能なアクセスはVirtualProtectで取得可能) があることを意味します。ここから、UI 情報を設定するために呼び出される関数をトランポリンできます。たとえば、ウィンドウのテキストが変更されたかどうかを確認するには、SetWindowText関数をトランポリンすることがあります。すべてのコントロールには、表示内容を設定するために使用されるさまざまなインターフェイスがあることに注意してください。この場合、表示を設定するためにコードによって呼び出される関数をフックしています。
  • WindowsHookExを設定します。内部的には、これは DLL インジェクションと同様に機能し、この場合は、コントロールによって受信されたメッセージの制御フローを拡張/破壊するための別の方法にすぎません。この場合に行う必要があるのは、各子コントロールのウィンドウ プロシージャをフックすることです。たとえば、項目がComboBoxに追加されると、CB_ADDSTRINGメッセージを受け取ります。この場合、表示が変更されたときに受信されるメッセージをフックしています。

このアプローチの 1 つの注意点は、ターゲットが WinAPI コントロールを使用または拡張している場合にのみ機能することです。

GUI からの読み取り

GUI をフックする代わりに、WinAPI を使用してターゲット ウィンドウから直接読み取ることができます。ただし、場合によっては、これが許可されない場合があります。この場合、やるべきことはあまりありませんが、うまくいくかどうか試してみてください。これは実際には最も簡単な方法かもしれません。通常、WM_GETTEXTなどのメッセージを送信して、ターゲット ウィンドウに現在表示されている内容を照会します。これを行うには、対象のコントロールを含む正確なウィンドウ階層を取得する必要があります。たとえば、エディット コントロールを読み取りたい場合、ウィンドウ階層でその上にある親ウィンドウを確認する必要があります。ウィンドウハンドルを取得するため。

メモリからの読み取り (上級)

このアプローチは最も複雑ですが、ターゲット プログラムを完全にリバース エンジニアリングできれば、一貫したデータを取得できる可能性が最も高くなります。このアプローチは、ターゲット プロセスからメモリを読み取ることによって機能します。この手法は、ゲームのハッキングで「機能」を追加し、ゲームの内部状態を観察するために非常に一般的に使用されます。

GUI に情報を格納するだけでなく、プログラムは多くの場合、すべてのデータの独自の内部モデルを保持していることを考慮してください。これは、使用されるコントロールが仮想であり、表示されるデータのサブセットを単にクエリする場合に特に当てはまります。これは、最初の 2 つのアプローチがあまり役に立たない状況の例です。このデータは、多くの場合、リストや配列など、ある種の抽象データ型で保持されます。秘訣は、メモリ内でこのリストを見つけて、値を直接読み取ることです。これは、ReadProcessMemoryを使用して外部的に実行するか、DLL インジェクションを使用して内部的に実行できます。問題は、主に次の 2 つの前提条件にあります。

  • まず、これらのデータ構造を確実に見つけることができなければなりません。これに関する問題は、特にASLRなどの機能では、コードが同じ場所にあることが保証されないことです。口語的に、これはコードシフトと呼ばれることがあります。モジュール ベースからのオフセットを使用し、 GetModuleHandleなどの関数を使用してモジュール ベース アドレスを動的に取得することで、ASLR を無効にすることができます。ASLR と同様に、これが発生する理由は、動的メモリ割り当て (たとえば を介しmallocた) によるものです。このような場合、ポインターを格納するヒープ アドレス (たとえば、 の戻り値malloc) を見つけ、それを逆参照して、リストを見つける必要があります。そのポインターは ASLR になりやすく、ポインターの代わりに、ダブルポインター、トリプルポインターなどになる可能性があります。
  • 直面する 2 番目の問題は、各リスト項目がプリミティブ型になることはめったにないということです。たとえば、文字配列 (文字列) のリストではなく、オブジェクトのリストに直面する可能性があります。各オブジェクト タイプをさらにリバース エンジニアリングし、内部レイアウトを理解する必要があります (少なくとも、オブジェクト ベースからのオフセットに関して、関心のあるプリミティブ値のオフセットを特定できる必要があります)。より高度な方法は、オブジェクトのvtableを実際にリバース エンジニアリングし、それらの「API」を呼び出すことを中心に展開します。

ここでは具体的な情報を提供できないことに気付くかもしれません。その理由は、その性質上、この方法を使用するにはターゲットの内部構造を詳細に理解する必要があり、そのため、詳細はターゲットがどのようにプログラムされたかによってのみ定義されるためです。リバース エンジニアリングの知識と経験がない限り、この道をたどりたいとは思わないでしょう。

ターゲットの内部 API をフックする (上級者向け)

上記のソリューションと同様に、データ構造を掘り下げる代わりに、内部 API を掘り下げます。前に vtable について説明したときに、これについて簡単に説明しました。これを行う代わりに、GUI が変更されたときに呼び出される内部 API を見つけようとすることになります。通常、ビュー/UI が変更された場合、WinAPI を直接呼び出して更新するのではなく、プログラムに独自のラッパー関数があり、それを呼び出して WinAPI を呼び出します。この関数を見つけてフックするだけです。これも可能ですが、リバース エンジニアリングのスキルが必要です。自分で呼び出したい関数が見つかるかもしれません。この場合、関数の場所を特定できるだけでなく、関数が取るパラメーターをリバース エンジニアリングする必要があります。

このアプローチは先進的だと思います。それは確かに実行可能であり、内部状態を観察してターゲットの動作を操作するためにゲームのハッキングで使用されるもう 1 つの一般的な手法ですが、困難です!


最初の 2 つの方法は、WinAPI プログラムからデータを読み取るのに適していて、はるかに簡単です。後者の 2 つの方法では、柔軟性が向上します。十分な作業があれば、ターゲットによってカプセル化されたあらゆるものを読み取ることができますが、多くのスキルが必要です。

ケースに関連する場合と関連しない場合がある別の懸念事項は、ターゲットが更新されるたびにソリューションを機能するように更新するのがいかに簡単かということです。最初の 2 つの方法では、ほとんどの場合、何も変更しないか、小さな変更を加える必要があります。2 番目の 2 つの方法では、ソース コードを少し変更しただけでも、依存しているオフセットが再配置される可能性があります。これに対処する 1 つの方法は、バイト署名を使用してオフセットを動的に生成することです。少し前に、これがどのように行われるかを説明する別の回答を書きました。

私が書いたことは、達成したいことに使用できるさまざまなテクニックの簡単な要約にすぎません。アプローチを見逃しているかもしれませんが、これらは私が知っていて、経験した最も一般的なものです。これらはそれ自体が大きなトピックであるため、特定のトピックについて詳しく知りたい場合は、新しい質問をすることをお勧めします。私が議論したすべてのアプローチで、それらのどれも外の世界に見える相互作用に悩まされていないことに注意してください。あなたが説明するように、それは「沈黙」です。


これは、私が書いた以前の回答から取り上げた、迂回/トランポリンに関する関連情報です。

プログラムが他のプロセスの実行を迂回する方法を探している場合は、通常、次の 2 つの方法のいずれかを使用します。

  • 動的 (ランタイム) 迂回 - これはより一般的な方法であり、Microsoft Detoursなどのライブラリで使用されます。これは、関数の最初の数バイトが無条件にインストルメンテーションに分岐するために上書きされる関連論文です。
  • (静的) バイナリ書き換え - これはルートキットではあまり一般的ではない方法ですが、研究プロジェクトで使用されています。バイナリを静的に解析して上書きすることで迂回を行うことができます。これを実行する Windows 用の古い (公開されていない) パッケージは Etch です。このホワイト ペーパーでは、概念的にどのように機能するかについて概要を説明します。

Detours は動的な迂回路の 1 つの方法を示していますが、業界、特にリバース エンジニアリングやハッキングの分野で使用されている方法は無数にあります。これらには、前述の IAT メソッドとブレークポイント メソッドが含まれます。これらの「正しい方向を示す」には、研究プロジェクトやリバース エンジニアリングの分野で行われる「研究」に目を向ける必要があります。

于 2012-04-13T13:09:43.063 に答える