What is a "hook" and how can I write one in Java? And how to communicate with kernel to know the keys pressed by the user/registering with OS
Although I searched a lot, it is still unclear to me as to what exactly a "hook" is. For instance, I read this post on wiki answers :
A hook is a method of interposing a piece of code in front of another piece of code, so that the first piece of code executes before the second piece of code, giving the first piece of code an opportunity to monitor and/or filter the behavior of the second piece of code. An example might be a mouse hook, allowing the hook code to monitor the mouse while at the same time preserving the functionality of the original mouse event processing routine.
I also read this post, but I still don't understand what a "hook" exactly is. Can someone please explain, in layman terms, what is a "hook"? Why exactly do some write a "hook"? Also, is it possible to write a "hook" in Java?
Note:
I wanted to write a keylogger in java and one of my friend said that you will have to write a "hook" in C. Can't I write the whole keylogger in Java (to be operated on windows only)?
EDIT
please give an answer w.r.t keylogger. How can i ask kernel
to giv开发者_运维知识库e the information about the key pressed to my application using hooking ? Or how can i register my application with OS using JNI? I want my application to record keys pressed by the user.
I would associate the word hook with at least two different concepts:
a) the Observer Pattern, where a Class lets you add a Listener that will be notified on certain events. You can find this all over Swing, the Servlet API and many 3rd party frameworks.
b) The Template Method pattern. An abstract class defines what methods are called in what order, and the implementing class may override these methods. Examples of this are not that common, but you see them every once in a while.
From Hooking - Wikipedia,
In computer programming, the term hooking covers a range of techniques used to alter or augment the behavior of an operating system, of applications, or of other software components by intercepting function calls or messages or events passed between software components. Code that handles such intercepted function calls, events or messages is called a "hook".
A good example built into Java would be Runtime.addShutdownHook
. A shutdown hook is simply an initialized but unstarted thread. When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently.
Runtime.addShutdownHook(new Thread(){
@Override
public void run(){
// do something before application terminates
}
});
Other names for this might be delegate or callback.
An example of this in Java is the MouseListener (http://download.oracle.com/javase/tutorial/uiswing/events/mouselistener.html). MouseListener
is an interface with methods such as mouseClicked(MouseEvent e)
. In order to respond to mouse actions from the user, you would implement MouseListener
and when the user clicks, the Java Swing library will call your listener class (after you register it by calling addMouseListener
.
Here is a simple example:
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
}
In this oversimplified example the hookableMethod provides a way for an external entity to hook it - that is pass external object reference and this external object is going to be executed first. So if you need to have some sort of processing which is not part of the original implementation you can do it simply by passing a reference and not by patching the original source.
As for the keylogger: yes you can write most of it in Java BUT a small part will have to go into a JNI module because for example with a global hook a DLL/thread/whatever gets "injected" into other processes... since not all process host a JVM etc. this won't work in Java... thus you need to use JNI and some C to write a DLL for that part of your keylogger...
EDIT - as per comment:
This article describes in-depth what global hooks do and what is meant by injecting etc...
In your case, a hook is a software mechanism to register a listener (handler) in the OS. This handler (a method in your application, for instance) will be notified by the OS when a key event is fired (key pushed).
This is just an application of the observer pattern.
A fictional example:
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);
As they have told you in other answers, there's no way to do this in Java without relying in some piece of native code.I think the easiest way to go is to choose a language related to the OS you are targeting. For windows, I'd do it with C#.
Check this link:
http://msdn.microsoft.com/en-us/library/ms632589%28VS.85%29.aspx
Capturing low level device events needs running native code (JNI, JNA, etc) and is highly system-dependent. On Linux you won't probably need to communicate with kernel, most probably with X11 sever.
First you have to define a manager class, that is something like:
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_ ();
}
Then use javah
to generate a C header, the result is something like (I didn't actually compile this code, so this is hypothetical):
/*
* Class: Win32
* Method: _native_init_
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_foo_bar_Win32_native_init_
(JNIEnv * env, jobject obj);
Create a C project, include this file and implement this method. Make sure when the actual hook triggered, call invokeCallback
in your C code:
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mId = (*env)->GetStaticMethodID(env, cls, "invokeCallback", "()V");
if (mId == 0) { /* error handling */ }
(*env)->CallStaticVoidMethod(env, cls, mId);
Compile the C project into a DLL file, say hookimpl_win32.dll
, and dynamicly link it somewhere in your Java code:
static {
System.loadLibrary("hookimpl_win32"); // no need of .dll or .so in Unix alike OS's
}
Make sure the dll is in the same folder with your jar. Or specify -Djava.library.path=/path/to/your/dlls
in VM args.
As to how you can log every key stroke, OS usually provide some API's for you to intercept key event. For Windows systems, you may achieve this by intercepting global key messages. I don't have any experiences on other systems. Anyway, you can set proper interrupts, which is quiet low level. You can always google your answer out. :)
精彩评论