Keyboard Hook
作者:admin 日期:2010-04-20
Hook is a mechanism, by which a function can intercept events before they reach an application. The function can act on events, modify or discard them. Functions which receive the events are called Filter Functions, every Filter Function is classified by its type. Hooks provide powerful capabilities: Procces or modify every message; Record or play back keyboard and mouse events; Prevent another filter from being called; And many more capabilities... Generally, there are two types of hooks: System-wide, and Thread-specific. The System-wide hook is used for filtering messages of all applications(IE: when writing a key logger). And the Thread-specific hook is used for filtering messages of a specific thread. In this tutorial, I'll cover just System-wide keyboard hook. To set a System-wide hook we need a DLL.
A DLL is an indirectly executable which doesn't have a message loop to receive user input. DLLs are seperate files containing functions(not only) that can be called by programs and other DLLs. To the end-user a DLL is a program that can't be executed directly from the Program Manger(or other Shells), but from the system's point of view, there are two differences between DLLs and applications: DLLs cannot have multiple running instances loaded in memory. and DLLs attach themselves to processes, only application instances are processes. DLL stands for Dynamic-Link Library. Dynamic-Link is a mechanism to link libraries to applications at run time. These libraries(DLLs) reside in their own executable files(.dll) and are not copied into applications' executable files(.exe) as with Static-Link libraries. It's important to understand that a .DLL is loaded into the address space of the specified linking application and not into the global heap! The advantages of using dynamic linking method are:
They can be updated without requiring applications to be recompiled or relinked.
When several applications use the same .DLL, the .DLL is just loaded once for all applications(reducing memory and disk space).
The reason we need a DLL for a System-wide hook is because we want the Filter Function to be in any application address space. So when you set the hook message filter function which lies in the .dll Windows maps the .dll automatically into all applications' address space. Thus you get your filter function called for every process! Therefore when we dynamic linking the hook which is in a .DLL it becomes a System-wide hook(ofcourse it depends on the type of Filter Function too). Okay, now after the important theoretical material..
Let's start coding the .DLL for the System-wide keyboard hook, and then I'll explain how to dynamic linking the .DLL into our application.
Please download the source code in order to see how it's all written and done.
// This is our keyboard callback proc:
// _declspec(dllexport) means that we want to let other
// applications/DLLs call this function, in same cases you don't
// need this prefix, but for safety we'll use it.
_declspec(dllexport) LRESULT CALLBACK KBHookProc(int Code,
WPARAM wParam, LPARAM lParam)
{
// If code is less than 0 we call the next hook,
// this is how hooks work, nothing special
if (Code < 0) return(CallNextHookEx(hhook, Code, wParam, lParam));
// Info about what happens with the keyboard
if (lParam & (1 << 31)) // Bit 31 tells whether a key is down
// Call the next hook.
return(CallNextHookEx(hhook, Code, wParam, lParam));
}
// This is same as WinMain/Main but for DLLs,
// you get the DLL instance, Reason of how your .DLL is called, reserved.
BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason,
LPVOID lpReserved)
{
// There are actually 4 reasons, we'll process just 2 of them,
// because it's enough for our prog.
if (dwReason == DLL_PROCESS_ATTACH) // Loading the .DLL
{
if(pcount == 0)
{
// Init // First loading time
// Set hook..
}
pcount++;
}
else if (dwReason == DLL_PROCESS_DETACH)
{
// UnInit before the system frees the .DLL from memory.
if(pcount == 1)
{
// Free
// Kill hook..
}
pcount--;
}
return(1);
}
You see, it's pretty easy, I would say. Anyways, pcount is our process counter, it says how many times the .DLL has been called. pcount is a special variable, it has to be in the global heap, because if it won't then everytime our .DLL is called it will be initialized to 0 again and again...so in order to prevent that, we tell the compiler to put the variable in the global heap. We do that for the hook handle too, because we set the hook only once. If we set the hook everytime the .DLL is called, it will be a messed hook and it wouldn't work properly and as we wish! In order to tell the compiler we want it to put the variable in global heap we do this:
#pragma data_seg("SharedBlock")
HHOOK hhook = NULL;
int pcount = 0;
#pragma data_seg()
Notice every variable has to be initialized. ok we are going to HHOOK hhook = NULL; unsigned long keystrokes = 0; int pcount = 0; #pragma data_seg() We soon finish writing the .DLL, every .DLL file has to have a .DEF file to direct the compiler. In the .DEF file we tell the compiler the functions we want to export, yes, those with the _declspec(dllexport), and we tell the compiler about the shared data block. (See the source code for full understanding the .DEF file). Once the .DLL file is ready, you have to copy it to the application which loads the .DLL directory or to copy it to %windir%\system.
OK, that's it for the .DLL stuff, now let's load the .DLL we just created! First we have to declare pointers to functions with the parameters they receive.
typedef void (*LPFunction)(void);
LPFunction function = NULL;
// This is a pointer to a function which has no
// parameters and which returns a void.
HMODULE DLLmodule = LoadLibrary("mydll.dll");
if (!DLLmodule) // .DLL file is not found!
// This function gets the code of the specific wanted function from memory,
// Notice the upper case letters, the wanted function name is to be exactly,
// as in the .DEF file and .CPP file of the DLL we wrote.
function = (LPFucntion)GetProcAddress(DLLmodule, "Function");
if (!function) // Function implementation code is not found!
// Now you can call function.
function();
// After finish using the .DLL, don't forget to free it!
FreeLibrary(DLLmodule);
相关文章
api hook 与pe文件格式的关系
原版请看
http://www.keylogger.org/articles/arkon/keyboard-hook-6.html
有附件下载。
A DLL is an indirectly executable which doesn't have a message loop to receive user input. DLLs are seperate files containing functions(not only) that can be called by programs and other DLLs. To the end-user a DLL is a program that can't be executed directly from the Program Manger(or other Shells), but from the system's point of view, there are two differences between DLLs and applications: DLLs cannot have multiple running instances loaded in memory. and DLLs attach themselves to processes, only application instances are processes. DLL stands for Dynamic-Link Library. Dynamic-Link is a mechanism to link libraries to applications at run time. These libraries(DLLs) reside in their own executable files(.dll) and are not copied into applications' executable files(.exe) as with Static-Link libraries. It's important to understand that a .DLL is loaded into the address space of the specified linking application and not into the global heap! The advantages of using dynamic linking method are:
They can be updated without requiring applications to be recompiled or relinked.
When several applications use the same .DLL, the .DLL is just loaded once for all applications(reducing memory and disk space).
The reason we need a DLL for a System-wide hook is because we want the Filter Function to be in any application address space. So when you set the hook message filter function which lies in the .dll Windows maps the .dll automatically into all applications' address space. Thus you get your filter function called for every process! Therefore when we dynamic linking the hook which is in a .DLL it becomes a System-wide hook(ofcourse it depends on the type of Filter Function too). Okay, now after the important theoretical material..
Let's start coding the .DLL for the System-wide keyboard hook, and then I'll explain how to dynamic linking the .DLL into our application.
Please download the source code in order to see how it's all written and done.
// This is our keyboard callback proc:
// _declspec(dllexport) means that we want to let other
// applications/DLLs call this function, in same cases you don't
// need this prefix, but for safety we'll use it.
_declspec(dllexport) LRESULT CALLBACK KBHookProc(int Code,
WPARAM wParam, LPARAM lParam)
{
// If code is less than 0 we call the next hook,
// this is how hooks work, nothing special
if (Code < 0) return(CallNextHookEx(hhook, Code, wParam, lParam));
// Info about what happens with the keyboard
if (lParam & (1 << 31)) // Bit 31 tells whether a key is down
// Call the next hook.
return(CallNextHookEx(hhook, Code, wParam, lParam));
}
// This is same as WinMain/Main but for DLLs,
// you get the DLL instance, Reason of how your .DLL is called, reserved.
BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason,
LPVOID lpReserved)
{
// There are actually 4 reasons, we'll process just 2 of them,
// because it's enough for our prog.
if (dwReason == DLL_PROCESS_ATTACH) // Loading the .DLL
{
if(pcount == 0)
{
// Init // First loading time
// Set hook..
}
pcount++;
}
else if (dwReason == DLL_PROCESS_DETACH)
{
// UnInit before the system frees the .DLL from memory.
if(pcount == 1)
{
// Free
// Kill hook..
}
pcount--;
}
return(1);
}
You see, it's pretty easy, I would say. Anyways, pcount is our process counter, it says how many times the .DLL has been called. pcount is a special variable, it has to be in the global heap, because if it won't then everytime our .DLL is called it will be initialized to 0 again and again...so in order to prevent that, we tell the compiler to put the variable in the global heap. We do that for the hook handle too, because we set the hook only once. If we set the hook everytime the .DLL is called, it will be a messed hook and it wouldn't work properly and as we wish! In order to tell the compiler we want it to put the variable in global heap we do this:
#pragma data_seg("SharedBlock")
HHOOK hhook = NULL;
int pcount = 0;
#pragma data_seg()
Notice every variable has to be initialized. ok we are going to HHOOK hhook = NULL; unsigned long keystrokes = 0; int pcount = 0; #pragma data_seg() We soon finish writing the .DLL, every .DLL file has to have a .DEF file to direct the compiler. In the .DEF file we tell the compiler the functions we want to export, yes, those with the _declspec(dllexport), and we tell the compiler about the shared data block. (See the source code for full understanding the .DEF file). Once the .DLL file is ready, you have to copy it to the application which loads the .DLL directory or to copy it to %windir%\system.
OK, that's it for the .DLL stuff, now let's load the .DLL we just created! First we have to declare pointers to functions with the parameters they receive.
typedef void (*LPFunction)(void);
LPFunction function = NULL;
// This is a pointer to a function which has no
// parameters and which returns a void.
HMODULE DLLmodule = LoadLibrary("mydll.dll");
if (!DLLmodule) // .DLL file is not found!
// This function gets the code of the specific wanted function from memory,
// Notice the upper case letters, the wanted function name is to be exactly,
// as in the .DEF file and .CPP file of the DLL we wrote.
function = (LPFucntion)GetProcAddress(DLLmodule, "Function");
if (!function) // Function implementation code is not found!
// Now you can call function.
function();
// After finish using the .DLL, don't forget to free it!
FreeLibrary(DLLmodule);
相关文章
api hook 与pe文件格式的关系
原版请看
http://www.keylogger.org/articles/arkon/keyboard-hook-6.html
有附件下载。
评论: 0 | 查看次数: 9165