驱动编写与调试(3)

这里我们先定义一个控制码

 

#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                   
}

你可能感兴趣的:(技术,attributes,access,function,file,struct,汇编)