KalProtect
///
好久好久没有写博客了,实在是太忙了,最近研究网络过滤,磁盘过滤还真没闲过,今天刚吃饭回来,都晚上11点半了。前几天有个朋友问我驱动级保护如何去写,我就把源码给他了,正好,我今天想起来了,也发到博客里面大家一起研究。当然,更多的也是方便初学者~~~
此驱动为进程保护驱动,比较的底层,使用的inline hook。 当然,和微点主防比起来,还不够变态!人家EAT钩子也用上了。而我就不必那么的折腾了,毕竟我写了是自己来用。
此驱动程序还是相当的完整的,不过是有依赖性的,因此编译通过后是无法加载成功!
此驱动我没有过多的讲解,遇到不懂的就百度谷歌吧,自己能够全部领悟了,也就能写出自己的自保驱动呢~~~
#include <ntddk.h>
#include <ntstrsafe.h>
#define PAGEDCODE code_seg("PAGE")
#define LOCKEDCODE code_seg()
#define INITCODE code_seg("INIT")
#define PAGEDDATA data_seg("PAGE")
#define LOCKEDDATA data_seg()
#define ININDATA data_seg("INIT")
typedef struct _SSDT_ENTRY
{
PULONG ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
PULONG ParamTableBase;
}SSDT_ENTRY;
NTSTATUS ObOpenObjectByPointer(
__in PVOID Object,
__in ULONG HandleAttributes,
__in_opt PACCESS_STATE PassedAccessState,
__in ACCESS_MASK DesiredAccess,
__in_opt POBJECT_TYPE ObjectType,
__in KPROCESSOR_MODE AccessMode,
__out PHANDLE Handle
);
#define IOCTL_KALPROTECT_PROCESS CTL_CODE(FILE_DEVICE_UNKNOWN,0x885,METHOD_BUFFERED,FILE_ANY_ACCESS) //发给SSDTSEARCH驱动 1100006驱动 来获得PsTerminateSystemThread的首地址。
#define IOCTL_FOUR CTL_CODE(FILE_DEVICE_UNKNOWN,0x844,METHOD_BUFFERED,FILE_ANY_ACCESS) //此控制码对应着SSDT设备的控制。是本驱动发给SSDT驱动的控制码。
///
#define IOCTL_ONE CTL_CODE(FILE_DEVICE_UNKNOWN,0x871,METHOD_BUFFERED,FILE_ANY_ACCESS) //用户层要求进程保护 自保护
#define IOCTL_TWO CTL_CODE(FILE_DEVICE_UNKNOWN,0x872,METHOD_BUFFERED,FILE_ANY_ACCESS) //用户层要求取消进程保护 自保护
#define IOCTL_THR CTL_CODE(FILE_DEVICE_UNKNOWN,0x873,METHOD_BUFFERED,FILE_ANY_ACCESS) //用户层要求文件保护 自保护
#define IOCTL_FOU CTL_CODE(FILE_DEVICE_UNKNOWN,0x874,METHOD_BUFFERED,FILE_ANY_ACCESS) //用户层要求取消文件保护 自保护
#define NtTerminateProcessID 0x101
#define NtOpenProcessID 0x7A //这里保护自己进程不被打开。
typedef NTSTATUS (*XXPspTerminateThreadByPointer)(PULONG,NTSTATUS); //和WRK不同的是,这个函数原本就是2个参数,而不是3个。千万注意。不然就会导致堆栈不平衡啦
KTIMER timer;
KDPC mydpc;
LARGE_INTEGER largeint;
PULONG InsertAddress;
LONG RootkitAddress;
BOOLEAN PROCESSHOOK;
PULONG OpenProcessInsertAddress;
LONG OpenProcessRootkitAddress;
BOOLEAN OPENPROCESSHOOK;
ULONG PspTerminateThreadByPointerAddressXX=NULL;
char* ProtectNameOne="Kal-el.exe";
char* ProtectNameTwo="KalelSVC1.exe";
char* ProtectNameThr="KalSVC2.exe";
char* ProtectNameFou="KalSVC3.exe";
typedef struct _device_ext //设备扩展
{
PDEVICE_OBJECT pdeviceobj; //设备对象指针
UNICODE_STRING devicename; //设备对象名
UNICODE_STRING sylinkname; //设备链接名
PULONG NativeSSDTBuffer; //将来这里缓冲区将会放入内核地址。而这些地址是从SSDT驱动获得。
ULONG NtTerminateProcessAddress;
ULONG PsTerminateSystemThreadAddress;
BOOLEAN PROCESSHOOKORNOT; //挂钩状态。 进程钩子的状态 进程保护就1个钩子 会运用DPC钩子保护技术
PULONG PsTerminateSystemThreadInsertAddress;
PULONG PsTerminateSystemThreadNativeAddressToRecover;
PULONG NtTerminateProcessInsertAddress;
PULONG NtTerminateProcessNativeAddressToRecover;
///上面一堆和防结束进程有关。现在开始防打开进程
ULONG NtOpenProcessAddress;
ULONG ObOpenObjectByPointerAddress;
BOOLEAN OPENPROCESSHOOKORNOT;
ObOpenObjectByPointer
PULONG NtOpenProcessInsertAddress;
PULONG NtOpenProcessNativeAddressToRecover;
}DEVICE_EXT,*PDEVICE_EXT;
VOID DPCFUN()
{
ULONG xxx;
_asm
{
cli
push eax;
mov eax,CR0;
mov xxx,eax;
and eax,0x0FFFEFFFF;
mov CR0,eax;
pop eax;
sti
};
if(PROCESSHOOK==TRUE)
{
*InsertAddress=(ULONG)RootkitAddress;
}
if(OPENPROCESSHOOK==TRUE)
{
*OpenProcessInsertAddress=(ULONG)OpenProcessRootkitAddress;
}
_asm
{
push eax;
mov eax,xxx;
mov CR0,eax;
pop eax;
};
KeSetTimer(&timer,largeint,&mydpc);
}
NTSTATUS
MyPspTerminateThreadByPointer(
IN PULONG Thread, //强制改变指针类型。毕竟PETHREAD结构很烦。还必须加入头什么的。之后一个套一个的结构,可以去死了
IN NTSTATUS ExitStatus
)
{
PULONG ProcessE=NULL; //本来是EPROCESS结构的
char* ProcessName;
XXPspTerminateThreadByPointer YKPspTerminateThreadByPointer;
YKPspTerminateThreadByPointer=(XXPspTerminateThreadByPointer)PspTerminateThreadByPointerAddressXX;
ProcessE=*(PULONG)((char*)Thread+0x220);
ProcessName=((char*)ProcessE+0x174);
if ((_stricmp(ProcessName, ProtectNameOne) == 0 )|| (_stricmp(ProcessName, ProtectNameTwo) == 0 )|| (_stricmp(ProcessName, ProtectNameThr) == 0) || (_stricmp(ProcessName, ProtectNameFou) == 0)) //如果为我的4个进程那么决绝访问。
{
return;
}
YKPspTerminateThreadByPointer(Thread,ExitStatus);
return ;
}
NTSTATUS MyObOpenObjectByPointer(
__in PVOID Object,
__in ULONG HandleAttributes,
__in_opt PACCESS_STATE PassedAccessState,
__in ACCESS_MASK DesiredAccess,
__in_opt POBJECT_TYPE ObjectType,
__in KPROCESSOR_MODE AccessMode,
__out PHANDLE Handle
)
{
NTSTATUS status=STATUS_SUCCESS;
char* ProcessName;
ProcessName=((char*)Object+0x174);
if ((_stricmp(ProcessName, ProtectNameOne) == 0 )|| (_stricmp(ProcessName, ProtectNameTwo) == 0 )|| (_stricmp(ProcessName, ProtectNameThr) == 0) || (_stricmp(ProcessName, ProtectNameFou) == 0)) //如果为我的4个进程那么决绝访问。
{
return STATUS_ACCESS_DENIED;
}
status=ObOpenObjectByPointer(Object,HandleAttributes,PassedAccessState,DesiredAccess,ObjectType,AccessMode,Handle);
return status;
}
_declspec(naked)RootkitNtTerminateProcess() //和PsTerminateSystemThread有关 涉及到文件的删除
{
_asm
{
push ebp;
mov ebp,esp;
sub esp,0x10;
mov ebp,MyPspTerminateThreadByPointer;
mov dword ptr [esp],ebp;
mov ebp,dword ptr [esp+10h];
ret 10h;
};
}
_declspec(naked)RootkitNtOpenProcess()
{
_asm
{
push ebp;
mov ebp,esp;
sub esp,0x10;
mov ebp,MyObOpenObjectByPointer;
mov dword ptr [esp],ebp;
mov ebp,dword ptr [esp+10h];
ret 10h;
};
}
NTSTATUS DispatchGeneral(PDEVICE_OBJECT pdevice_obj,PIRP pirp) //默认的IRP处理函数
{
NTSTATUS status;
status=STATUS_SUCCESS;
pirp->IoStatus.Status=status;
pirp->IoStatus.Information=0;
IoCompleteRequest(pirp,IO_NO_INCREMENT);
return status;
}
VOID MyUnload(PDRIVER_OBJECT pdriverobj) //卸载函数
{
PDEVICE_EXT pdeviceext;
PDEVICE_OBJECT pdeviceobj;
UNICODE_STRING sylinkname;
LONG uAttr=0;
KIRQL oldirql;
pdeviceobj=pdriverobj->DeviceObject;
pdeviceext=(PDEVICE_EXT)pdeviceobj->DeviceExtension;
KeCancelTimer(&timer);
oldirql=KeRaiseIrqlToDpcLevel();
_asm
{
cli
push eax;
mov eax,CR0;
mov uAttr,eax;
and eax,0x0FFFEFFFF;
mov CR0,eax;
pop eax;
sti
};
if(pdeviceext->PROCESSHOOKORNOT==TRUE)
{
*(pdeviceext->NtTerminateProcessInsertAddress)=(ULONG)(pdeviceext->NtTerminateProcessNativeAddressToRecover);
}
if(pdeviceext->OPENPROCESSHOOKORNOT==TRUE)
{
*(pdeviceext->NtOpenProcessInsertAddress)=(ULONG)(pdeviceext->NtOpenProcessNativeAddressToRecover);
}
_asm
{
push eax;
mov eax,uAttr;
mov CR0,eax;
pop eax;
};
KeLowerIrql(oldirql);
RtlInitUnicodeString(&sylinkname,L"\\??\\KalProtectDeviceSymLink");
if (pdeviceext->pdeviceobj)
{
IoDeleteDevice(pdeviceext->pdeviceobj); //删除设备
}
IoDeleteSymbolicLink(&sylinkname);
}
NTSTATUS MyControl(PDEVICE_OBJECT pdevice_obj,PIRP pirp)
{
NTSTATUS status=STATUS_SUCCESS;
PDEVICE_EXT pdeviceext=NULL;
ULONG i=0; //循环用的变量
UCHAR CheckPspTerminateThreadByPointer[]={0x00,0xFF,0x75,0x08,0x50,0xE8};//PsTerminateSystemThread搜索PspTerminateThreadByPointer用到的特征。第一个特征不要比对~~
UCHAR NtCheckPspTerminateThreadByPointer[]={0x00,0xFF,0x75,0x0C,0x56,0xE8};//NtTerminateProcess搜索PspTerminateThreadByPointer用到的特征。第一个特征同样不要比对~~
UCHAR NtCheckObOpenObjectByPointer[]={0x75,0xC8,0xFF,0x75,0xDC,0xE8};//NtOpenProcess搜索PspTerminateThreadByPointer用到的特征。
PULONG PsTerminateSystemThreadAddr;
PULONG NtTerminateProcessAddr;
PULONG NtOpenProcessAddr;
ULONG PsTerminateSystemThreadOffset;
ULONG NtTerminateProcessOffset;
ULONG NtTerminateProcessRootkitOffset;
ULONG NtOpenProcessOffset;
ULONG NtOpenProcessRootkitOffset;
UCHAR* PointYK=NULL;
LONG uAttr=0;
KIRQL oldirql;
BOOLEAN SearchedOrNot=FALSE;
BOOLEAN SearchedOrNotTwo=FALSE;
BOOLEAN SearchedOrNotThr=FALSE;
PIO_STACK_LOCATION stack=IoGetCurrentIrpStackLocation(pirp);
ULONG inputlength=stack->Parameters.DeviceIoControl.InputBufferLength;
ULONG outputlength=stack->Parameters.DeviceIoControl.OutputBufferLength;
ULONG ControlCode=stack->Parameters.DeviceIoControl.IoControlCode;
pdeviceext=(PDEVICE_EXT)pdevice_obj->DeviceExtension;
switch (ControlCode)
{
case IOCTL_ONE: //开始挂钩 进程保护
pdeviceext->PROCESSHOOKORNOT=FALSE;
PROCESSHOOK=FALSE;
PsTerminateSystemThreadAddr=pdeviceext->PsTerminateSystemThreadAddress; //得到 PsTerminateSystemThread的地址。
PointYK=(char*)PsTerminateSystemThreadAddr;
for (i=0;i<100;i++)
{
if (PointYK[i+1]==CheckPspTerminateThreadByPointer[1] && PointYK[i+2]==CheckPspTerminateThreadByPointer[2] && PointYK[i+3]==CheckPspTerminateThreadByPointer[3] && PointYK[i+4]==CheckPspTerminateThreadByPointer[4] && PointYK[i+5]==CheckPspTerminateThreadByPointer[5])
{
pdeviceext->PsTerminateSystemThreadInsertAddress=(PULONG)(PointYK+i+6);
pdeviceext->PsTerminateSystemThreadNativeAddressToRecover=(ULONG)*(pdeviceext->PsTerminateSystemThreadInsertAddress);
PsTerminateSystemThreadOffset=(ULONG)(pdeviceext->PsTerminateSystemThreadInsertAddress)+4;
PspTerminateThreadByPointerAddressXX=(LONG)(pdeviceext->PsTerminateSystemThreadNativeAddressToRecover)+PsTerminateSystemThreadOffset; //PspTerminateThreadByPointer 的真实地址。请重视下LONG值 千万别是ULONG 毕竟这个偏移值有正偏也会有负偏
SearchedOrNot=TRUE; //表示搜索PspTerminateThreadByPointer地址成功。
break;
}
}
if(SearchedOrNot==FALSE)// 如果搜索PspTerminateThreadByPointer地址失败,那么就直接返回
{
status=STATUS_UNSUCCESSFUL;
break;
}
以上唯一的目的就是获得PspTerminateThreadByPointer的地址。下面开始挂钩
NtTerminateProcessAddr=pdeviceext->NtTerminateProcessAddress;
PointYK=(char*)NtTerminateProcessAddr;
for (i=170;i<250;i++)
{
if (PointYK[i+1]==NtCheckPspTerminateThreadByPointer[1] && PointYK[i+2]==NtCheckPspTerminateThreadByPointer[2] && PointYK[i+3]==NtCheckPspTerminateThreadByPointer[3] && PointYK[i+4]==NtCheckPspTerminateThreadByPointer[4] && PointYK[i+5]==NtCheckPspTerminateThreadByPointer[5])
{
pdeviceext->NtTerminateProcessInsertAddress=(PULONG)(PointYK+i+6);
pdeviceext->NtTerminateProcessNativeAddressToRecover=(ULONG)*(pdeviceext->NtTerminateProcessInsertAddress);
NtTerminateProcessOffset=(ULONG)(pdeviceext->NtTerminateProcessInsertAddress)+4;
NtTerminateProcessRootkitOffset=(ULONG)RootkitNtTerminateProcess-NtTerminateProcessOffset;
InsertAddress=pdeviceext->NtTerminateProcessInsertAddress; //涉及到DPC例程,所以必须使用全局变量
RootkitAddress=NtTerminateProcessRootkitOffset; //涉及到DPC例程,所以必须使用全局变量
SearchedOrNotTwo=TRUE; //表示搜索PspTerminateThreadByPointer地址成功。
break;
}
}
if(SearchedOrNotTwo==FALSE)// 如果搜索PspTerminateThreadByPointer的插入位置失败,那么就直接返回失败
{
status=STATUS_UNSUCCESSFUL;
break;
}
上面是关于结束进程钩子的全部前期准备工具。只差挂钩这个动作了
NtOpenProcessAddr=pdeviceext->NtOpenProcessAddress;
PointYK=(char*)NtOpenProcessAddr;
for (i=500;i<600;i++)
{
if (PointYK[i]==NtCheckObOpenObjectByPointer[0] && PointYK[i+1]==NtCheckObOpenObjectByPointer[1] && PointYK[i+2]==NtCheckObOpenObjectByPointer[2] && PointYK[i+3]==NtCheckObOpenObjectByPointer[3] && PointYK[i+4]==NtCheckObOpenObjectByPointer[4] && PointYK[i+5]==NtCheckObOpenObjectByPointer[5])
{
pdeviceext->NtOpenProcessInsertAddress=(PULONG)(PointYK+i+6);
pdeviceext->NtOpenProcessNativeAddressToRecover=(ULONG)*(pdeviceext->NtOpenProcessInsertAddress);
NtOpenProcessOffset=(ULONG)(pdeviceext->NtOpenProcessInsertAddress)+4;
NtOpenProcessRootkitOffset=(ULONG)RootkitNtOpenProcess-NtOpenProcessOffset;
OpenProcessInsertAddress=pdeviceext->NtOpenProcessInsertAddress; //涉及到DPC例程,所以必须使用全局变量
OpenProcessRootkitAddress=NtOpenProcessRootkitOffset; //涉及到DPC例程,所以必须使用全局变量
SearchedOrNotThr=TRUE;
break;
}
}
if(SearchedOrNotThr==FALSE)//
{
status=STATUS_UNSUCCESSFUL;
break;
}
上面是关于打开进程钩子的全部前期准备工具。只差挂钩这个动作
oldirql=KeRaiseIrqlToDpcLevel();
_asm
{
cli
push eax;
mov eax,CR0;
mov uAttr,eax;
and eax,0x0FFFEFFFF;
mov CR0,eax;
pop eax;
sti
};
if(SearchedOrNotTwo==TRUE)
{
*(pdeviceext->NtTerminateProcessInsertAddress)=(ULONG)NtTerminateProcessRootkitOffset;
pdeviceext->PROCESSHOOKORNOT=TRUE; //这个东西是必须的。因为将来要恢复钩子。必须判断下。毕竟你挂钩失败的时候再恢复钩子,那么会导致错误的地址。导致蓝屏
PROCESSHOOK=TRUE;
}
if(SearchedOrNotThr==TRUE)
{
*(pdeviceext->NtOpenProcessInsertAddress)=(ULONG)NtOpenProcessRootkitOffset;
pdeviceext->OPENPROCESSHOOKORNOT=TRUE; //这个东西是必须的。因为将来要恢复钩子。必须判断下。毕竟你挂钩失败的时候再恢复钩子,那么会导致错误的地址。导致蓝屏
OPENPROCESSHOOK=TRUE;
}
_asm
{
push eax;
mov eax,uAttr;
mov CR0,eax;
pop eax;
};
KeLowerIrql(oldirql);
KeSetTimer(&timer,largeint,&mydpc); //使用DPC
break;
case IOCTL_TWO: //解除挂钩
KeCancelTimer(&timer); //先关闭DPC 之后再还原。
oldirql=KeRaiseIrqlToDpcLevel();
_asm
{
cli
push eax;
mov eax,CR0;
mov uAttr,eax;
and eax,0x0FFFEFFFF;
mov CR0,eax;
pop eax;
sti
};
if(pdeviceext->PROCESSHOOKORNOT==TRUE)
{
*(pdeviceext->NtTerminateProcessInsertAddress)=(ULONG)(pdeviceext->NtTerminateProcessNativeAddressToRecover);
}
if(pdeviceext->OPENPROCESSHOOKORNOT==TRUE)
{
*(pdeviceext->NtOpenProcessInsertAddress)=(ULONG)(pdeviceext->NtOpenProcessNativeAddressToRecover);
}
_asm
{
push eax;
mov eax,uAttr;
mov CR0,eax;
pop eax;
};
KeLowerIrql(oldirql);
break;
default:
status=STATUS_INVALID_VARIANT;
}
pirp->IoStatus.Status=status;
pirp->IoStatus.Information=0;
IoCompleteRequest(pirp,IO_NO_INCREMENT);
return status;
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath)
{
NTSTATUS status=STATUS_SUCCESS;
PDEVICE_OBJECT pdeviceobj;
PDEVICE_EXT pdeviceext;
UNICODE_STRING devicename;
UNICODE_STRING sylinkname;
UNICODE_STRING TargetDeviceName; //SSDTSEARCH
HANDLE TargetDeviceHandle;
OBJECT_ATTRIBUTES TargetDeviceObjectAttribute; //SSDTSEARCH
ULONG i;
char* PointYK;
IO_STATUS_BLOCK status_block;
__declspec(dllimport) SSDT_ENTRY KeServiceDescriptorTable;
largeint.QuadPart=-50000;
KeInitializeDpc(&mydpc,(PKDEFERRED_ROUTINE)DPCFUN,NULL);
KeInitializeTimer(&timer);
RtlInitUnicodeString(&devicename,L"\\Device\\KalProtectDevice");
RtlInitUnicodeString(&sylinkname,L"\\??\\KalProtectDeviceSymLink");
RtlInitUnicodeString(&TargetDeviceName,L"\\Device\\SSDTSearchDevice"); //我们这个驱动将会打开SSDT驱动的SSDTSearchDevice设备。来获取SSDT表的所有内容.
InitializeObjectAttributes(&TargetDeviceObjectAttribute,&TargetDeviceName,OBJ_CASE_INSENSITIVE,NULL,NULL);
pDriverObject->DriverUnload=MyUnload;
//
for (i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
{
pDriverObject->MajorFunction[i]=DispatchGeneral;
}
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=MyControl; //注册控制函数。不管设备有多少,控制函数就一个。所以到时候需要判断。
status=IoCreateDevice(pDriverObject,sizeof(DEVICE_EXT),&devicename,FILE_DEVICE_UNKNOWN,0,FALSE,&pdeviceobj); //开始创建设备 为独占设备。 只有VB会控制这个设备
if (!NT_SUCCESS(status))
{
return status;
}
status=IoCreateSymbolicLink(&sylinkname,&devicename);
if (!NT_SUCCESS(status))
{
IoDeleteDevice(pdeviceobj);
return status;
}
pdeviceobj->Flags |= DO_BUFFERED_IO; //我这个设备支持缓冲区方式。
pdeviceext=(PDEVICE_EXT)pdeviceobj->DeviceExtension;
pdeviceext->pdeviceobj=pdeviceobj;
pdeviceext->devicename=devicename;
pdeviceext->sylinkname=sylinkname;
pdeviceext->PsTerminateSystemThreadAddress=NULL; //先赋值为NULL 也就是32位的0
pdeviceext->NativeSSDTBuffer=(PULONG)ExAllocatePool(PagedPool,KeServiceDescriptorTable.NumberOfService*4); //划分一个SSDT表一样大的空间。
status=ZwCreateFile(&TargetDeviceHandle,GENERIC_ALL,&TargetDeviceObjectAttribute,&status_block,NULL,FILE_ATTRIBUTE_NORMAL,FILE_SHARE_READ,FILE_OPEN,FILE_SYNCHRONOUS_IO_NONALERT,NULL,0);//打开SSDT 设备。
if (!NT_SUCCESS(status)) //如果打开失败,那么返回失败。同时让驱动加载失败。
{
return STATUS_UNSUCCESSFUL;
}
///现在开始发送控制码给SSDT 来获得PsTerminateSystemThread地址
status=ZwDeviceIoControlFile(TargetDeviceHandle,NULL,NULL,NULL,&status_block,IOCTL_KALPROTECT_PROCESS,NULL,0,&(pdeviceext->PsTerminateSystemThreadAddress),sizeof(ULONG)); //如果成功,那么获得PsTerminateSystemThread的地址。
if (!NT_SUCCESS(status)) //如果控制失败,那么返回失败。同时让驱动加载失败。
{
ZwClose(TargetDeviceHandle);
return STATUS_UNSUCCESSFUL;
}
status=ZwDeviceIoControlFile(TargetDeviceHandle,NULL,NULL,NULL,&status_block,IOCTL_FOUR,NULL,0,pdeviceext->NativeSSDTBuffer,KeServiceDescriptorTable.NumberOfService*4); //如果成功,那么原始的SSDT表将会成功获取。
if (!NT_SUCCESS(status)) //如果控制失败,那么返回失败。同时让驱动加载失败。
{
ZwClose(TargetDeviceHandle);
return STATUS_UNSUCCESSFUL;
}
ZwClose(TargetDeviceHandle); //需要的东西已经获得。句柄可以关闭了
if (pdeviceext->PsTerminateSystemThreadAddress==NULL) //如果获得的地址为空,也就是说获取失败,那么返回为失败。
{
status=STATUS_UNSUCCESSFUL;
}
pdeviceext->NtTerminateProcessAddress=(pdeviceext->NativeSSDTBuffer)[NtTerminateProcessID];
pdeviceext->NtOpenProcessAddress=(pdeviceext->NativeSSDTBuffer)[NtOpenProcessID];
if (pdeviceext->NtTerminateProcessAddress==NULL || pdeviceext->NtOpenProcessAddress==NULL ) //如果获得的地址为空,也就是说获取失败,那么返回为失败。
{
status=STATUS_UNSUCCESSFUL;
}
return status;
}