13

私はたくさん検索しましたが、「フック」が正確に何であるかについてはまだ不明です. たとえば、wiki Answersでこの投稿を読みました。

フックは、別のコード片の前にコード片を挿入する方法です。これにより、最初のコード片が 2 番目のコード片の前に実行され、最初のコード片に動作を監視および/またはフィルタリングする機会が与えられます。コードの 2 番目の部分の。例としては、マウス フックが考えられます。これにより、フック コードでマウスを監視しながら、同時に元のマウス イベント処理ルーチンの機能を維持できます。

この投稿も読みましたが、「フック」が正確に何であるかはまだわかりません。誰かが「フック」とは何かを素人の言葉で説明できますか? 「フック」を書く人がいるのはなぜですか?また、Javaで「フック」を書くことは可能ですか?

ノート:

Java でキーロガーを書きたかったのですが、友人の 1 人が、C で「フック」を作成する必要があると言いました。キーロガー全体を Java で書くことはできませんか (Windows でのみ動作するように)。

編集

キーロガーに関する回答をお願いします。kernelフックを使用して、押されたキーに関する情報をアプリケーションに提供する依頼するにはどうすればよいまたは、JNI を使用してアプリケーションを OS に登録するにはどうすればよいですか? アプリケーションで、ユーザーが押したキーを記録したい。

4

8 に答える 8

6

フックという言葉を少なくとも2つの異なる概念に関連付けます。

a)オブザーバーパターン。クラスを使用すると、特定のイベントで通知されるリスナーを追加できます。これは、Swing、サーブレットAPI、および多くのサードパーティフレームワーク全体で見つけることができます。

b)テンプレートメソッドパターン。抽象クラスは、どのメソッドがどの順序で呼び出されるかを定義し、実装クラスはこれらのメソッドをオーバーライドできます。この例はそれほど一般的ではありません、たまに見られます。

于 2011-09-02T15:19:51.897 に答える
6

フッキングから-ウィキペディア、

コンピューター プログラミングでは、フックという用語は、ソフトウェア コンポーネント間で渡される関数呼び出しまたはメッセージまたはイベントをインターセプトすることによって、オペレーティング システム、アプリケーション、またはその他のソフトウェア コンポーネントの動作を変更または拡張するために使用されるさまざまな手法をカバーしています。このように傍受された関数呼び出し、イベント、またはメッセージを処理するコードは、「フック」と呼ばれます。

Java に組み込まれた良い例はRuntime.addShutdownHook. シャットダウン フックは、単に初期化されているが開始されていないスレッドです。仮想マシンがシャットダウン シーケンスを開始すると、登録されているすべてのシャットダウン フックが不特定の順序で開始され、同時に実行されます。

Runtime.addShutdownHook(new Thread(){
    @Override
    public void run(){
        // do something before application terminates
    }
});
于 2011-09-02T15:24:33.117 に答える
1

これの他の名前は、デリゲートまたはコールバックである可能性があります。

Javaでのこの例は、MouseListener(http://download.oracle.com/javase/tutorial/uiswing/events/mouselistener.html)です。MouseListenerは、などのメソッドとのインターフェースmouseClicked(MouseEvent e)です。ユーザーからのマウスアクションに応答するために、実装MouseListenerし、ユーザーがクリックすると、Java Swingライブラリがリスナークラスを呼び出します(を呼び出して登録した後)addMouseListener

于 2011-09-02T15:20:16.670 に答える
1

以下に簡単な例を示します。

public void hookableMethod(HookObject hook, String param) { 
String innerParam = param;
if(hook != null) { 
 innerParam = hook.someHookMethod(innerParam);  
}

//rest of the code is working with inner param
}

この非常に単純化された例では、hookableMethod は、外部エンティティがそれをフックする方法を提供します。つまり、外部オブジェクト参照を渡し、この外部オブジェクトが最初に実行されます。したがって、元の実装の一部ではない何らかの処理が必要な場合は、元のソースにパッチを適用するのではなく、参照を渡すだけで実行できます。

于 2011-09-02T15:21:00.570 に答える
1

低レベルのデバイス イベントをキャプチャするには、ネイティブ コード(JNI、JNA など) を実行する必要があり、システムに大きく依存します。Linux では、おそらくカーネルと通信する必要はなく、おそらく X11 サーバーと通信する必要があります。

于 2011-09-08T16:45:43.767 に答える
1

あなたの場合、フックはOSにリスナー(ハンドラー)を登録するためのソフトウェアメカニズムです。このハンドラー (アプリケーション内のメソッドなど) は、キー イベントが発生した (キーが押された) ときに OS から通知されます。

これはオブザーバー パターンの単なるアプリケーションです。

架空の例:

    class MyKBHandler implements ISomeKeyboardListener {
        public void onKeyDown(<params containing key info here>){
            //Your code here, doing something with the params.
        }
    }

    MyKBHandler handler = new MyKBHandler();
    <someOSLibrary>.register(handler);

彼らが他の回答であなたに言ったように、ネイティブコードの一部に依存せずに Java でこれを行う方法はありません.ターゲットとする OS に関連する言語を選択するのが最も簡単な方法だと思います. Windows の場合は、C# で行います。

このリンクを確認してください:

http://msdn.microsoft.com/en-us/library/ms632589%28VS.85%29.aspx

于 2011-09-05T10:49:03.527 に答える
1

キーロガーに関しては: はい、そのほとんどをJavaで書くことができますが、たとえばグローバルフックを使用すると、DLL/スレッド/その他のプロセスに「注入」されるものは何でも、JNIモジュールに入れる必要があります...すべてのプロセスが JVM などをホストするわけではありません。これは Java では機能しません。したがって、JNI と C を使用して、キーロガーのその部分の DLL を作成する必要があります。

編集 - コメントによると:

この記事では、グローバル フックの機能と注入の意味などについて詳しく説明します。

于 2011-09-02T15:46:25.630 に答える
0

まず、次のようなマネージャー クラスを定義する必要があります。

package foo.bar

public class SomeHookManager {
    public static void initialize (...) {
        // <pre-initialization-routing>
        _native_init_();
        // <post-initialization-routing>
    }

    public static void registerCallback (IHookCallback callback)
    { /* save this callback */ }

    // this method will be invoked in your C code.
    protected static void invokeCallback () { /* invoke the saved callback */ }

    // this is a native method, the native modifier tells the compiler this method
    // is implemented in C, and linked at runtime.
    protected native static void _native_init_ ();
}

次にjavah、Cヘッダーを生成するために使用します。結果は次のようになります(実際にこのコードをコンパイルしていないため、これは仮説です):

/*
 * Class:     Win32
 * Method:    _native_init_
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_foo_bar_Win32_native_init_
    (JNIEnv * env, jobject obj);

C プロジェクトを作成し、このファイルをインクルードして、このメソッドを実装します。実際のフックがいつトリガーされたかを確認しinvokeCallback、C コードを呼び出します。

jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mId = (*env)->GetStaticMethodID(env, cls, "invokeCallback", "()V");
if (mId == 0) { /* error handling */ }
(*env)->CallStaticVoidMethod(env, cls, mId);

C プロジェクトを DLL ファイルにコンパイルしhookimpl_win32.dll、Java コードのどこかに動的にリンクします。

static {
    System.loadLibrary("hookimpl_win32"); // no need of .dll or .so in Unix alike OS's
}

dll が jar と同じフォルダーにあることを確認してください。または-Djava.library.path=/path/to/your/dlls、VM args で指定します。

すべてのキーストロークをログに記録する方法については、OS は通常、キーイベントをインターセプトするためのいくつかの API を提供しています。Windows システムでは、グローバル キー メッセージをインターセプトすることでこれを実現できます。他のシステムでの経験はありません。とにかく、静かな低レベルである適切な割り込みを設定できます。いつでも答えをググることができます。:)

于 2011-09-09T04:55:37.927 に答える