基于IOAPIC重定位的 键盘监听技术及防御

来源:互联网 发布:剑灵捏脸数据图人男 编辑:程序博客网 时间:2024/05/21 23:01


摘 要 键盘监听技术会引起个人重要信息的泄露。通过对IOAPIC重定位技术的研究,实现了针对单核系统和多核系统的键盘监听和记录。在WindowsDriver Kits7.0.1中编译生成的驱动,能够记录键盘信息,引起重要信息的泄露。通过提出的防御键盘监听的方法能够有效地预防键盘监听。

关键词 IOAPIC重定位 键盘监听 防御

中图分类号  TP3    文献标识码  A     

       Hooking Keyboard Basing On Redirectionof IOAPIC
   Abstraction
  HookingKeyboard can cause leaking of personal important information . Throughredirection of IOAPIC, we can hook and record information of keyboard in singlecore or multiple cores system. The driver that WDK7.1.0compile can record information of keyboard, causing important informationleading. Some methods can use to defend the hooking keyboard.

Keywords Redirection of IOAPIC  HookingKeyboard Defence

0  引言

键盘监听是指在使用键盘的人不知情的情况下,通过隐蔽的方式记录下键盘的每一次敲击的行为。对于电子商务、网上银行和虚拟货币等新兴业务,键盘监听技术可能会导致重要信息的泄露。目前常见的监听方法是在内核模式下通过驱动的方式实现键盘监听。

1  单核CPU的键盘监听

1.1 IOAPIC概述


图1  IOAPIC与CPU关系框图

IOAPIC是I/OAdvanced Progrmmable Interrupt Controller的简写,叫做输入输出高级可编程中断控制器。可以用于单个核心CPU,也可以用于多个核心CPU,是一种新型的可编程硬件[1]。当一个IRQ(中断请求,Interrupt Request)发生时,IOAPIC决定将IRQ发送给哪个CPU核心,以及以何种形式发送等。IOAPIC与CPU核心的关系如图1所示。

其中,IDT是Interrupt Description Table的简写,叫做中断描述符表,ISR是Interrupt Service Routine的简写,叫做中断服务例程。当键盘中断产生时,会有一个IRQ发送到IOAPIC,以下是处理键盘中断的基本步骤:

第1步,IOAPIC通过自身寄存器的值确定CPU使用IDT表中的项的索引号;

第2步,CPU读取IDT项中的中断号来确定中断服务例程;

第3步,CPU执行确定的中断服务例程处理中断。

表1 IOAPIC 寄存器表


  

 

比特位

描述

..............

                  ..............

7:0

中断向量-读/写,共8bit,表示该中断对应的中断向量,该向量的取值范围是0x10h到0xFEh。







表1是IOAPIC寄存器的寄存器名、偏移地址和访问权限表。从表中可知,IOAPIC重定位表的偏移地址范围是0x10~0x3F,共48项,对应0~23个中断。每个中断对应2个IOAPIC寄存器。每个寄存器为4个字节,则每个中断对应8个字节共64位[2]。

偏移地址

寄存器名

访问权限

0x00h

IOAPIC ID

读/写

0x01h

IOAPIC 版本

只读

0x02h

IOAPIC 仲裁ID

只读

0x10~0x3Fh

重定位表

读写








表2  中断对应IOAPIC寄存器含义

 表2是外部中断对应的IOAPIC寄存器每个位的含义,PS/2键盘产生的中断是IRQ1。从表中可以看出,IRQ1对应的64位的最后8位表示该中断对应的中断向量。读取对应寄存器中的内容即可得到对应的中断向量。

可以通过IOAPIC,对其寄存器的内容进行读取和写入,从而获得或修改PS/2键盘中断对应的中断向量,从而实现键盘监听。通过IOAPIC的两个特殊寄存器实现IOAPIC寄存器的读写。这两个寄存器叫做“IO寄存器选择寄存器”和“IO窗口寄存器”。“IO寄存器选择寄存器”的功能是选择要读写的IOAPIC寄存器,“IO窗口寄存器”的功能是保存了指定寄存器的内容。当“IO寄存器选择寄存器”指定了寄存器之后,“IO窗口寄存器”的内容即为指定寄存器的内容。以上两个特殊寄存器是4个字节,共32位。

寄存器名

内存地址

比特位

描述

IOREGSEL

0xFEC0xy00h

31:8

保留

7:0

IOAPIC寄存器地址

IOWIN

0xFEC0xy10h

31:0

IOAPIC寄存器内容

 






图3 IOAPIC的两个特殊寄存器含义

图3是以上两个特殊寄存器的含义,其中IOREGSEL表示“IO寄存器选择寄存器”,IOWIN表示“IO窗口寄存器”,x的范围是0x0~0xFh,y的取值范围是0x0h,0x4h,0x8h和0xCh。在Windows中x的取值是0x0h,y的取值是0x0h。也就是说,在Windows中,IOREGSEL寄存器的物理地址是0xFEC00000h,IOWIN寄存器的物理地址是0xFEC00010h。

PS/2键盘对应的寄存器偏移地址是0x12h和0x13h。将IOREGSEL寄存器的低8位设置为0x12,则此时IOWIN中包含的内容则是偏移量为0x12h的寄存器的内容,而该内容的低8位是IRQ1对应的中断向量。

1.2 IOAPIC重定位的实现

IOAPIC重定位就是对IOWIN寄存器的低8位进行修改,将其改为自定义的中断向量号。由于0xFEC00000和0xFEC00010h是寄存器的物理地址,而物理地址是不能直接进行读写操作,所以需要通过MmMapIoSpace()函数将物理地址映射为虚拟地址,之后对该虚拟地址进行读写操作。

pVirtualAddress= MmMapIoSpace(physicAddress, 0x14, MmNonCached);

其中,physicalAddress表示物理地址的起始地址,其值为0xFEC00000,0x14表示要映射的物理地址的大小,MmNonCached表示了虚拟内存的属性。函数的返回值pVirtualAddress表示了映射的虚拟地址。

接下来获取IOREGSEL寄存器和IOWIN寄存器的虚拟起始地址,设置IOREGSEL寄存器的内容为0x12h。

P2C_U8 *io_reg_sel;

P2C_U32 *io_win;

P2C_U32 newWinValue;

io_reg_sel =(P2C_U8*)pVirtualAddress;

io_win =(P2C_U32*)((P2C_U8*)pVirtualAddress + 0x10);

*io_reg_win = 0x12h;

其中,P2C_U8表示一个8位的变量,P2C_U32表示一个32位的变量,io_reg_sel表示IOREGSEL寄存器的地址,io_win表示IOWIN寄存器的地址。然后设置IOWIN寄存器的内容为自定义的中断向量,其中newInterruptVector是一个8bit变量,表示自定义中断向量的索引号。

newWinValue = *io_win;

newWinValue &= 0xFFFFFF00h;

newWinValue |= newInterruptVector;

*io_win = newWinValue;

1.2 修改IDT项

1.2.1获取IDT的地址

P2C_IDTR idtr;

_asm sidt idrt;

其中,sidt是汇编指令,其作用是读取IDT的地址,P2C_IDTR是自定义的IDT地址的结构,如下所示。

typedef struct P2C_IDTR_{

  P2C_U16 limit;

  P2C_U32 base;

}P2C_IDTR, *PP2C_IDTR;

其中,成员变量base表示IDT的基地址。

1.2.2 在IDT中添加自定义项

添加自定义项的步骤是将原先PS/2键盘所对应的IDT项拷贝到一个空闲项处,之后将拷贝后的项中ISR对应的地址设置为自定义例程地址。

PS/2键盘中断对应的中断向量的索引号为0x93h,以下代码用于获取PS/2键盘对应IDT项的地址:

idtr[idleID] = idtr[0x93];

其中,idtr是获取的IDT的初始地址,idleID是IDT中的空闲项,即为自定义项。接下来将自定义项中ISR的地址修改为自定义ISR例程地址。

idtr[idleID].offset_low =(P2C_U16*)(p2cInterruptProc);

idtr[idleID].offset_high =(P2C_U16*)(p2cInterruptProc>>16);

其中,p2cInterruptProc是自定义的ISR例程地址。

通过以上修改,当PS/2键盘中断发生时,IOAPIC根据已修改的IO_WIN寄存器中的内容得到IDT中的已修改项,之后根据该修改项得到自定义的ISR例程,通过自定义的ISR例程获取按键信息。

2  多核CPU的键盘监听

对于多核的操作系统,每个CPU都有自己的IDT,因此需要分别对每个CPU的IDT进行修改。可以采用延迟过程调用(DPC,Deferred Procedure Call)的方法实现对每个CPU的IDT进行修改。

DPC例程一般和中断服务例程(ISR,Interrupt Service Routine)配合使用。ISR例程处于很高的IRQL,会打断正常运行的线程。而DPC例程运行于相对较低的DISPACTCH_LEVEL级别。因此,一般将不需要紧急处理的代码放在DPC例程中,而将需要紧急处理的代码放在ISR中[3][4]。

for( i = 0; i <KeNumberProcessors; i++ )

{

KeInitializeDpc(&pkDpc[i], MyFunction, i);

KeSetTargetProcessorDpc(&pkDpc[i], i);

KeInsertQueueDpc(&pkDpc[i], NULL, NULL);

}

其中,pkDpc是DPC对象指针类型PKDPC的数组;MyFunction是自定义函数,其功能是单核系统中提到到修改IOAPIC和IDT;KeNumberProcessors是内核自带变量,表示系统中内核的数量;KeInitializeDpc()函数初始化DPC对象,并将DPC例程函数指定给DPC对象;KeSetTargetProcessorDpc()函数将DPC对象与指定的CPU绑定;KeInsertQueueDpc()函数将DPC对象插入到CPU的DPC请求队列中,如果没有别的中断请求,则内核则执行DPC请求队列中DPC对象对应的DPC例程。

3  按键信息的记录

将按键信息保存在本地文件中实现信息的记录。在内核模式中将信息保存在文件中的流程与在用户模式中类似:创建/打开文件、保存数据、关闭文件[5][6]。

3.1 创建/打开文件

可调用内核函数ZwCreateFile实现文件的创建或打开。通过该函数的参数指定其功能是打开文件还是创建文件。该函数还需要一个类型为OBJECT_ATTRIBUTES类型的参数,用来指定文件的属性,可以通过InitializeObjectAttribute函数实现OBJECT_ATTRIBUTES类型的变量的初始化。

3.2 保存数据

通过ZwWriteFile函数实现数据的保存。该函数通过HANDLE类型的参数表示要保存数据的文件句柄,该文件句柄即为ZwCreateFile函数创建的文件句柄。

3.3 关闭文件

通过ZwClose函数实现文件的关闭。该函数的参数是HANDLE类型的变量,即为以上两个参数操作的文件句柄。

在WDK7.1.0(WindowsDriver Kits 7.0.1)中将代码编译为驱动文件后,在单核系统和多核系统下进行测试,可在指定的文件中记录下按键信息。接下来可以通过网络技术将该记录发送至网络中指定位置处,实现键盘按键的远程监听。

4  键盘监听的防御

键盘监听防御的措施主要包括使用反键盘监听程序,使用软键盘和打乱输入顺序等方法[7][8]。

4.1 使用反键盘监听程序

键盘监听程序的基本原理是先于应用程序获取键盘输入,而如果有程序能够先于键盘监听程序获取键盘输入,则就可以实现反监听的功能。

以上提到的基于IOAPIC重定位的键盘监听技术处于最底层,能够先于其它程序获取键盘输入。因此该技术也能用于反键盘监听程序中。需要按键输入的应用程序在运行的同时,启动一个基于该IOAPIC重定位技术的驱动程序,在该驱动程序中截获按键信息,对按键信息进行判断,并把判断的结果反馈给应用程序而不再把按键信息传递给键盘驱动等程序,这样其他程序就无法监听按键信息了。

4.2 使用软键盘

软键盘并不是在键盘上,而是在“屏幕”上。可以分为软件虚拟键盘、系统自带键盘和新式硅胶键盘三种。软键盘是通过软件模拟键盘,利用鼠标点击输入字符。软键盘的按键处理原理与普通键盘的按键处理原理不同,因此通过使用软键盘,可以绕过一些键盘监听软件。

4.3 打乱输入顺序

打乱输入顺序的方法可以使得键盘监听软件的记录也被打乱。

例如,可以先输入几个随机字符,然后用鼠标选择输入的随机字符,再输入几个其他的随机字符来替代之前的输入,重复以上步骤。在输入真正账号或密码时,也可以使用以上方法,多次重复,打乱键盘监听软件的记录。

除了上述三种方法外,还需要注意在网吧或酒店等公共场所的电脑上输入重要信息时,要检查电脑上有无不明设备,或者在公共场所的电脑上不要输入重要的敏感信息。

5  小结

本文描述了基于IOAPIC重定位实现键盘监听的实现方法和对键盘监听的防御措施。通过修改IOAPIC的寄存器内容实现重定位,通过修改IDT的内容,使得自定义函数能够处理键盘按键信息。对于多核系统,可以采用DPC的技术实现对每个内核的IDT进行修改,从而实现键盘的监听。通过使用反键盘监听程序、软键盘和打乱输入顺序等方法对键盘监听进行防御。

参 考 文 献

[1] 张帆,史彩成.Windows驱动开发技术详解[M]. 北京:电子工业出版社, 2008.

[2] intel. 82093AA I/O ADVANCED PROGRAMMABLE INTERRUPTCONTROLLER[S].

[3] Walter Oney. PROGRAMMING THE MICROSOFT WINDOWSDRIVER MODEL[M]. Microsoft Press, 2003.

[4] Mark E.Russinovich. 深入解析Windows操作系统第4版[M]. 北京:电子工业出版社,2008.

[5] 谭文,杨潇,邵坚磊.Windows内核安全编程[M] 北京:电子工业出版社,2009

[6] 谭文,邵坚磊. 从汇编语言到Windows内核编程[M] 北京:电子工业出版社,2008

[7] 李辉.黑客攻防与计算机病毒分析[M].北京:电子信息技术出版社,2012.

[8] 程秉辉.木马防护全攻略[M].北京:科学出版社,2010.

 

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 黑号抽不中天猫购物券怎么办 退款后购物津贴怎么办 天猫优惠券过期怎么办 淘宝店复核不过怎么办 房产新人没客源怎么办 淘宝商品被监管怎么办 天猫店铺监管怎么办 普票超额了怎么办 开票金额超过限额怎么办 淘宝拉入黑名单怎么办 淘宝卖食品证件怎么办 京东额度不够怎么办 天猫盒子内存不足怎么办 10086办无限流量怎么办 天猫营业额不够怎么办 试电笔电阻坏了怎么办 父子间车辆过户怎么办 房子卖了天然气怎么办 社保这个月没扣怎么办 员工不交社保怎么办 公司没交社保怎么办 微信转账受限怎么办 支付宝违规限制怎么办 微信转账不还钱怎么办 碳放久了不爱起火怎么办 闻碳火时间久了怎么办 被代运营诈骗怎么办 被上海聚连骗了怎么办? 蓝领贷逾期半年怎么办 淘宝店倒闭售后怎么办 淘宝店铺宝贝被下架怎么办 医院被托管编制怎么办 领码分百万账号异常怎么办 拼多多帐号异常怎么办 qq钱包交易异常怎么办 托管公司跑了怎么办? 花呗退款没到账怎么办 车辆过户了车牌怎么办 货车资格证脱审怎么办 廉租房夫妻离婚怎么办 二手车行驶证怎么办的?