#define IOCTL_PROTECT_CONTROL CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
这里我们使用他来和应用程序通讯,Irp->AssociatedIrp.SystemBuffer这个结构中存放用户模式程序发送给驱动程序的数据。这里使用METHOD_BUFFERED方式时,I/O管理器创建一个足够大的内核模式拷贝缓冲区(与用户模式输入和输出缓冲区中最大的容量相同)。当派遣例程获得控制时,用户模式的输入数据被复制到这个拷贝缓冲区。在IRP完成之前,你应该向拷贝缓冲区填入需要发往应用程序的输出数据。当IRP完成时,你应该设置IoStatus.Information域等于放入拷贝缓冲区中的输出字节数。然后I/O管理器把数据复制到用户模式缓冲区并设置反馈变量
NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) { NTSTATUS ntStatus; PIO_STACK_LOCATION IrpStack; ULONG IoControlCode; ULONG inSize; ULONG outSize; ULONG *buff; IrpStack=IoGetCurrentIrpStackLocation(Irp); IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; switch(IoControlCode) { case IOCTL_PROTECT_CONTROL: inSize = IrpStack->Parameters.DeviceIoControl.InputBufferLength; outSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; buff = (ULONG*)Irp->AssociatedIrp.SystemBuffer ; pid=*buff; //获得要影藏进程的ID strcpy(Irp->UserBuffer,"Driver Start"); break; default: break; } ntStatus=Irp->IoStatus.Status; IoCompleteRequest(Irp,IO_NO_INCREMENT); return ntStatus; } |
要保护一个进程只用在调用ZwOpenProcess时返回一个STATUS_ACCESS_DENIED就可以了,相关的代码如下
NTSTATUS NewZwOpenProcess( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL ) { NTSTATUS ntStatus; if(pid==(ULONG)ClientId->UniqueProcess) { DbgPrint("保护进程 PID :%d /n",pid); return STATUS_ACCESS_DENIED; } ntStatus=OldZwOpenProcess( ProcessHandle, DesiredAccess, ObjectAttributes, ClientId ); return STATUS_SUCCESS; } |
这里我们要先定义相关宏:
#pragma pack(1) typedef struct ServiceDescriptorEntry { unsigned int *ServiceTableBase; unsigned int *ServiceCounterTableBase; //Used only in checked build unsigned int NumberOfServices; unsigned char *ParamTableBase; } ServiceDescriptorTableEntry, *PServiceDescriptorTableEntry; #pragma pack() extern ServiceDescriptorTableEntry KeServiceDescriptorTable; #define SYSTEMSERVICE(_function)KeServiceDescriptorTable.ServiceTableBase [*(PUCHAR)((PUCHAR)_function+1)] |
这里通过windbg反汇编可以看出
lkd> u ZwOpenProcess
nt!ZwOpenProcess:
804e6044 b87a000000 mov eax,7Ah
804e6049 8d542404 lea edx,[esp+4]
804e604d 9c pushfd
804e604e 6a08 push 8
804e6050 e8dc150000 call nt!KiSystemService (804e7631)
804e6055 c21000 ret 10h
nt!ZwOpenProcessToken:
804e6058 b87b000000 mov eax,7Bh
804e605d 8d542404 lea edx,[esp+4]
eax后的7Ah就是索引号,便有了宏定义。
NTSYSAPI NTSTATUS NTAPI ZwOpenProcess( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL ); typedef NTSTATUS (*ZWOPENPROCESS)( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL ); ZWOPENPROCESS OldZwOpenProcess; / NTSTATUS NewZwOpenProcess( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL ); 在DriverEntry中对CR0进行修改然后修改 SSDT表。 _asm { CLI MOV EAX, CR0 AND EAX, NOT 10000H MOV CR0, EAX } OldZwOpenProcess = (ZWOPENPROCESS)(SYSTEMSERVICE(ZwOpenProcess)) ; (ZWOPENPROCESS)(SYSTEMSERVICE(ZwOpenProcess)) = NewZwOpenProcess; _asm { MOV EAX, CR0 OR EAX, 10000H MOV CR0, EAX STI } |