//fuckaid driver
//xxx by MJ0011 2007-12-4 14:44
#include
#include
#include
#include
#define DEVICE_KBD_DEVICE 0x9801
#define IOCTL_SET_KBD_INPUT CTL_CODE(DEVICE_KBD_DEVICE , 0x912 , METHOD_BUFFERED , FILE_ANY_ACCESS )
// ================================================================
// KEYBOARD I/O REGISTERS ON THE PC
// ================================================================
// 60h data
// 64h command (write)
// 64h Status (read)
//
// Bits in Status register (names from Linux source)
// b7 PERR parity error in data received from keyboard
// b6 GTO receive timeout
// b5 transmit timeout (or PS/2 mouse?)
// b4 keyboard is locked
// b3 0=60h was the port last accessed, 1=61h was last (?)
// b2 System Flag status: 0=power-up/reset, 1=selftest OK (?)
// b1 IBF input buffer full (data from host to keyboard)
// b0 OBF output buffer full (data from keyboard to host)
//
// Bits in Output Port of 8042 chip (Table P0383 in PORTS.A)
// The Output Port is written by controller command D1h,
// and read by controller command D0h
// b7 keyboard data output
// b6 keyboard clock output
// b5 input buffer NOT full
// b4 output buffer NOT empty
// b3 (varies)
// b2 (varies)
// b1 A20 gate
// b0 system reset (THIS BIT SHOULD ALWAYS BE SET TO 1)
//
// Bits in Input Port of 8042 chip
// The Input Port is read by controller command C0h
// b7 keyboard NOT locked
// b6-b0 (varies)
//
// Bits in "Command Byte" (confusing name; from Table P0404 in PORTS.A)
// The "Command Byte" is written by controller command 60h
// and read by controller command 20h
// (names from Linux source)
// b7 (reserved)
// b6 KCC convert set 2 scancodes to set 1 ("IBM PC compatibility mode")
// b5 DMS disables PS/2 mouse when set
// b4 disables keyboard when set
// b3 ignore keyboard lock switch when set
// b2 SYS System Flag (same as b2 in Status register, it seems)
// b1 enables IRQ12 from PS/2 mouse when set
// b0 EKI enables IRQ1 on keyboard output buffer full
//
// Result Byte for interface self-tests (Table P0406 in PORTS.A)
// Returned by controller commands A9h or ABh
// 0 no error
// 1 clock line stuck low
// 2 clock line stuck high
// 3 data line stuck low
// 4 data line stuck high
char __stdcall __SetKdbIo(BYTE KeyScanCode)
{
__asm
{
LoopWaitForKdbOK :
in al , 0x64
;64号端口为AT Keyboard controller 8042芯片的状态/控制端口
and al , 2
jnz LoopWaitForKdbOK
;等待状态端口OK
;等待status register 的IBF位为1
;就是等待host 到 keyboard的Input Buffer full
;参见上资料
mov al , 0xD2
out 0x64 , al
;向64端口发送控制命令
;0xD2号命令是写键盘output buffer的命令
;参考:[url]http://lezy.51.net/sub/i8042.htm[/url]
LoopWaitForCmdOK:
in al , 0x64
and al , 2
jnz LoopWaitForCmdOK
;等待命令完成
;等待status register 的IBF位为1
;就是等待host 到 keyboard的Input Buffer full
mov al , byte ptr[esp + 4]
;获得要写入的scan code
out 0x60 , al
;60号端口是AT KeyBoard controller 8042的Input/Output Buffer端口
;向键盘写入一个scan code
;相当于一次模拟按键
retn 4
}
}
char __stdcall _SetKbdIo(BYTE KeyScanCode)
{
return __SetKdbIo(KeyScanCode);
}
char __stdcall SetKbdIo(PVOID InBuffer, ULONG InputLen)
{
ULONG i;
char result;
for ( i = 0; i < InputLen; ++i )
result = _SetKbdIo(*(BYTE *)((ULONG)InBuffer + i));
return result;
}
NTSTATUS __stdcall CommonDispatch(PDEVICE_OBJECT devobj, PIRP Irp)
{
ULONG InputBufferLen;
PIO_STACK_LOCATION irpstack;
PIRP pIrp;
char *buf;
PVOID InBuffer;
NTSTATUS stat;
DbgPrint("Entering InputDispatch");
pIrp = Irp;
irpstack = IoGetCurrentIrpStackLocation(Irp);
InBuffer = Irp->AssociatedIrp.SystemBuffer ;
Irp->IoStatus.Status = 0;
Irp->IoStatus.Information = 0;
InputBufferLen = irpstack->Parameters.DeviceIoControl.InputBufferLength;
// Irp = v7;
if ( irpstack->MajorFunction == IRP_MJ_CREATE )
{
buf = "IRP_MJ_CREATE";
goto show_debug;
}
if ( irpstack->MajorFunction == IRP_MJ_CLOSE )
{
buf = "IRP_MJ_CLOSE";
show_debug:
DbgPrint(buf);
goto endreq;
}
if ( irpstack->MajorFunction == IRP_MJ_DEVICE_CONTROL )
{
DbgPrint("IRP_MJ_DEVICE_CONTROL");
if ( irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SET_KBD_INPUT)
{
DbgPrint("IOCTL_INPUTDRV_KBDINPUT");
if ( InputBufferLen )
SetKbdIo(InBuffer, InputBufferLen);
}
else
{
DbgPrint("ERROR: Unknown IRP_MJ_DEVICE_CONTROL");
pIrp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
}
endreq:
stat = pIrp->IoStatus.Status;
IofCompleteRequest(pIrp, 0);
DbgPrint("Leaving InputDispatch");
return stat;
}
NTSTATUS __stdcall DrvUnload(PDRIVER_OBJECT drvObj )
{
UNICODE_STRING DestinationString;
DbgPrint("Entering InputUnload");
RtlInitUnicodeString(&DestinationString, L"//DosDevices//fuckaid");
if ( !NT_SUCCESS(IoDeleteSymbolicLink(&DestinationString)) )
DbgPrint("ERROR: IoDeleteSymbolicLink");
else
IoDeleteDevice(drvObj->DeviceObject);
return DbgPrint("Leaving InputUnload");
}
NTSTATUS __stdcall DriverEntry(PDRIVER_OBJECT DriverObject, int a2)
{
NTSTATUS stat2;
PDRIVER_OBJECT drvobj;
NTSTATUS stat;
NTSTATUS stat3;
PDEVICE_OBJECT DeviceObject;
UNICODE_STRING DestinationString;
UNICODE_STRING SymbolicLinkName;
DbgPrint("fuckaid Driver xxx by MJ0011!/n");
DeviceObject = 0;
DbgPrint((CHAR *)"Entering DriverEntry");
RtlInitUnicodeString(&DestinationString, (const WCHAR *)"//Device//fuckaid");
drvobj = DriverObject;
stat = IoCreateDevice(DriverObject, 0, &DestinationString, DEVICE_KBD_DEVICE , 0, TRUE, &DeviceObject);
stat2 = stat;
if ( !NT_SUCCESS(stat) )
{
DbgPrint("ERROR: IoCreateDevice failed");
}
else
{
drvobj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)CommonDispatch;
drvobj->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)CommonDispatch;
drvobj->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)CommonDispatch;
drvobj->DriverUnload = (PDRIVER_UNLOAD)DrvUnload;
RtlInitUnicodeString(&SymbolicLinkName, L"//DosDevice//fuckaid");
stat3 = IoCreateSymbolicLink(&SymbolicLinkName, &DestinationString);
stat2 = stat3;
if ( !NT_SUCCESS(stat3) )
{
DbgPrint("ERROR: IoCreateSymbolicLink failed");
IoDeleteDevice(DeviceObject);
}
}
DbgPrint("Leaving DriverEntry");
return stat2;
}