先发代码
参考了:
https://bbs.pediy.com/thread-200048.htm forwardbob
https://bbs.pediy.com/thread-168023-1.htm tianhz
http://www.cnblogs.com/aliflycoris/p/5468175.html LycorisGuard
这三位大牛的代码以及原理
#ifndef CXX_PROTECTPROCESSX64_H
#define CXX_PROTECTPROCESSX64_H
#include <ntifs.h>
#define PROCESS_TERMINATE 0x0001
#define PROCESS_VM_OPERATION 0x0008
#define PROCESS_VM_READ 0x0010
#define PROCESS_VM_WRITE 0x0020
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObj, IN PUNICODE_STRING pRegistryString);
VOID DriverUnload(IN PDRIVER_OBJECT pDriverObj);
typedef struct _LDR_DATA_TABLE_ENTRY64
{
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;
ULONG64 OriginalBase;
LARGE_INTEGER LoadTime;
} LDR_DATA_TABLE_ENTRY64, *PLDR_DATA_TABLE_ENTRY64;
NTKERNELAPI
UCHAR *
PsGetProcessImageFileName(
__in PEPROCESS Process
);
char* GetProcessImageNameByProcessID(ULONG ulProcessID);
NTSTATUS ProtectProcess(BOOLEAN Enable);
OB_PREOP_CALLBACK_STATUS
preCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pOperationInformation);
#endif
#ifndef CXX_PROTECTPROCESSX64_H
# include "ProtectProcessx64.h"
#endif
PVOID obHandle;//定义一个void*类型的变量,它将会作为ObRegisterCallbacks函数的第二个参数。
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT pDriverObj, IN PUNICODE_STRING pRegistryString)
{
//NTSTATUS status = STATUS_SUCCESS;
UNREFERENCED_PARAMETER(pRegistryString);
PLDR_DATA_TABLE_ENTRY64 ldr;
pDriverObj->DriverUnload = DriverUnload;
// 绕过MmVerifyCallbackFunction。
ldr = (PLDR_DATA_TABLE_ENTRY64)pDriverObj->DriverSection;
ldr->Flags |= 0x20;
ProtectProcess(TRUE);
return STATUS_SUCCESS;
}
NTSTATUS ProtectProcess(BOOLEAN Enable)
{
UNREFERENCED_PARAMETER(Enable);
OB_CALLBACK_REGISTRATION obReg;
OB_OPERATION_REGISTRATION opReg;
memset(&obReg, 0, sizeof(obReg));
obReg.Version = ObGetFilterVersion();
obReg.OperationRegistrationCount = 1;
obReg.RegistrationContext = NULL;
RtlInitUnicodeString(&obReg.Altitude, L"321000");
memset(&opReg, 0, sizeof(opReg)); //初始化结构体变量
//下面请注意这个结构体的成员字段的设置
opReg.ObjectType = PsProcessType;
opReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
opReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)&preCall; //在这里注册一个回调函数指针
obReg.OperationRegistration = &opReg; //注意这一条语句
return ObRegisterCallbacks(&obReg, &obHandle); //在这里注册回调函数
}
OB_PREOP_CALLBACK_STATUS
preCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pOperationInformation)
{
HANDLE pid = PsGetProcessId((PEPROCESS)pOperationInformation->Object);
char szProcName[16] = { 0 };
UNREFERENCED_PARAMETER(RegistrationContext);
strcpy(szProcName, GetProcessImageNameByProcessID((ULONG)pid));
if (!_stricmp(szProcName, "calc.exe"))
{
if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
{
if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE)
{
//Terminate the process, such as by calling the user-mode TerminateProcess routine..
pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;
}
if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_VM_OPERATION) == PROCESS_VM_OPERATION)
{
//Modify the address space of the process, such as by calling the user-mode WriteProcessMemory and VirtualProtectEx routines.
pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_OPERATION;
}
if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_VM_READ) == PROCESS_VM_READ)
{
//Read to the address space of the process, such as by calling the user-mode ReadProcessMemory routine.
pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_READ;
}
if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_VM_WRITE) == PROCESS_VM_WRITE)
{
//Write to the address space of the process, such as by calling the user-mode WriteProcessMemory routine.
pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_WRITE;
}
}
}
return OB_PREOP_SUCCESS;
}
char*GetProcessImageNameByProcessID(ULONG ulProcessID)
{
NTSTATUS Status;
PEPROCESS EProcess = NULL;
Status = PsLookupProcessByProcessId((HANDLE)ulProcessID, &EProcess); //EPROCESS
//通过句柄获取EProcess
if (!NT_SUCCESS(Status))
{
return FALSE;
}
ObDereferenceObject(EProcess);
//通过EProcess获得进程名称
return (char*)PsGetProcessImageFileName(EProcess);
}
VOID
DriverUnload(IN PDRIVER_OBJECT pDriverObj)
{
UNREFERENCED_PARAMETER(pDriverObj);
DbgPrint("driver unloading...\n");
ObUnRegisterCallbacks(obHandle); //obHandle是上面定义的 PVOID obHandle;
}
还有就是VS2017这个编译器我要吐槽一下
还以为是错误害我找半天 ,绝望的时候编译一下居然过了,伤心
另外还有一个编译警告没解:决HANDLE到ULONG的指针截断
问题找到了 直接把这个函数形参的定义改成HANDLE传递就行(谢谢一位不知名的面试官)
希望知道的朋友赐教
无签名加载驱动用的是:
http://www.m5home.com/bbs/forum.php?mod=viewthread&tid=4356
TA大佬的方法