目录
x64(32)下的进程保护回调.
一丶进程保护线程保护
1.简介以及原理
以前我们讲过.SSDT 可以做很多事情.比如可以防止进程被结束
其实到了x64下.你也可以HOOK SSDT.只不过你需要过一下PatchGuard 但是在你过不了PG的情况下.其实操作系统也给你提供了回调进行保护. 这个回调 也可以称作 对象钩子(OBject)这个回调主要函数则是 ** ObRegisterCallbacks() **
其实关于回调函数.去查询MSDN即可. 以前博客也有说过.只不过现在 想重新写一下.MSDN:
这个函数其实就是不断的填写结构体即可. 根据MSDN说明去填写.
函数其实特别简单.参数1就是一个结构体,你去填写. 参数2就是一个句柄.当你卸载的时候会使用.
结构体中会包含一个结构体. 主要是为了你可以一次设置多个回调.
新的结构体只不过是指定你要监控的类型以及回调函数地址.唯一重点就是 在x64下.因为你没驱动签名的驱动则不能使用这些操作系统提供的回调.例如还有的 (PsSetCreateProcessEx) 等等.
但是没事.因为国外早有人逆向出来为什么不能使用.而我们只需要设置一个标志即可.只需要在程序入口处.添加代码即可.
如下:
PLDR_DATA_TABLE_ENTRY ldr; ldr = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection; ldr->Flags |= 0x20;//加载驱动的时候会判断此值。必须有特殊签名才行,增加0x20即可。否则将调用失败
结构体定义如下:
typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY64 InLoadOrderLinks; LIST_ENTRY64 InMemoryOrderLinks; LIST_ENTRY64 InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; USHORT LoadCount; USHORT TlsIndex; PVOID SectionPointer; ULONG CheckSum; PVOID LoadedImports; PVOID EntryPointActivationContext; PVOID PatchInformation; LIST_ENTRY64 ForwarderLinks; LIST_ENTRY64 ServiceTagLinks; LIST_ENTRY64 StaticLinks; PVOID ContextInformation; ULONG OriginalBase; LARGE_INTEGER LoadTime;} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
这里注意的大小即可.32位下.使用LIST_ENTRY32即可.
此时按照我们结构体进行填写.安装驱动即可. 至于回调怎么写.自己查看MSDN看一下就明白了.你自己写你自己的回调函数即可.如下:
函数声明放到了Driver.h中.自己定义的头文件中.不影响.1.2 代码
#include "Driver.h"NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath){ ULONG iCount = 0; NTSTATUS ntStatus; PLDR_DATA_TABLE_ENTRY ldr; ldr = (PLDR_DATA_TABLE_ENTRY)pDriverObj->DriverSection; ldr->Flags |= 0x20; pDriverObj->DriverUnload = DriverUnLoad; /*ntStatus = InitDeviceAnSybolicLinkName(pDriverObj); if (!NT_SUCCESS(ntStatus)) { return ntStatus; } ntStatus = InitDisPatchFunction(pDriverObj); if (!NT_SUCCESS(ntStatus)) { return ntStatus; }*/ InitHook(); return STATUS_SUCCESS;}//我们的回调函数OB_PREOP_CALLBACK_STATUS MyObjectCallBack( PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation){ DbgPrint("1111\r\n"); return STATUS_SUCCESS;}PVOID g_ObjHandle;VOID InitHook(){ //进行HOOK 回调钩子写法. OB_OPERATION_REGISTRATION oper; //你的回调函数以及类型都放在这个结构体中,可以是结构体数组. OB_CALLBACK_REGISTRATION CallbackRegistration; CallbackRegistration.Version = OB_FLT_REGISTRATION_VERSION; //版本号 CallbackRegistration.OperationRegistrationCount = 1;//下几个钩子,也就是结构体数组个数 RtlUnicodeStringInit(&CallbackRegistration.Altitude, L"600000");//给个UNICODEstring表明您是干啥的 CallbackRegistration.RegistrationContext = NULL; //当你的回调函数到的时候参数是什么.由这里给出 CallbackRegistration.OperationRegistration = &oper; //钩子结构体类型设置. //为钩子结构体赋值 oper.ObjectType = PsProcessType; //进程操作的类型.当进程操作回来. PsThreadType则是线程操作 oper.Operations = OB_OPERATION_HANDLE_CREATE; //操作的类型是将要打开.以及将要重复 oper.PreOperation = MyObjectCallBack; //有两个指针,前指针跟后指针.意思分别是 进程创建之前通知你还是之后 oper.PostOperation = NULL; ObRegisterCallbacks(&CallbackRegistration,&g_ObjHandle);}VOID UnHook(){ ObUnRegisterCallbacks(g_ObjHandle);}
1.3注意的问题
编写代码的时候会发生蓝屏.原因是你设置前指针后.后指针需要设置为NULL
因为如果是进程保护的话. 当创建进程的时候则会遍历对象数组.依次调用. 而你的前指针会调用.而后指针没有设置为NULL.而是一个垃圾值所以就会引发蓝屏. 这个是个需要注意的.二丶丶回调函数写法
2.1 遇到的问题.
关于回调函数中.我们相看访问权限.但是发现却没有.
MSDN只是告诉你什么是什么.我们要怎么知道. 首先先列出#define PROCESS_TERMINATE (0x0001) // winnt#define PROCESS_CREATE_THREAD (0x0002) // winnt#define PROCESS_SET_SESSIONID (0x0004) // winnt#define PROCESS_VM_OPERATION (0x0008) // winnt#define PROCESS_VM_READ (0x0010) // winnt#define PROCESS_VM_WRITE (0x0020) // winnt// begin_ntddk begin_wdm begin_ntifs#define PROCESS_DUP_HANDLE (0x0040) // winnt// end_ntddk end_wdm end_ntifs#define PROCESS_CREATE_PROCESS (0x0080) // winnt#define PROCESS_SET_QUOTA (0x0100) // winnt#define PROCESS_SET_INFORMATION (0x0200) // winnt#define PROCESS_QUERY_INFORMATION (0x0400) // winnt#define PROCESS_SET_PORT (0x0800)#define PROCESS_SUSPEND_RESUME (0x0800) // winnt
然后查找WRK可以看得到.
然后我们可以单独在回调中写代码了.
2.2 回调代码
NTKERNELAPIUCHAR * PsGetProcessImageFileName(__in PEPROCESS Process);OB_PREOP_CALLBACK_STATUS MyObjectCallBack( PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation){ PEPROCESS pProcess = NULL; UCHAR *pszName = NULL; pProcess = (PEPROCESS)OperationInformation->Object; pszName = PsGetProcessImageFileName(pProcess); //判断标志是否要打开进程 if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) { //获取名字匹配 if (strstr(pszName, "calc")) { KdPrint(("%s \r\n", pszName)); //判断是不是结束 if ((OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == 1) { //如果是我们的.则设置DesiredAccess权限.去掉结束权限. OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = ~PROCESS_TERMINATE; return STATUS_UNSUCCESSFUL; } } } return STATUS_SUCCESS;}