x64下進程保護HOOK


x64(32)下的進程保護回調.

一丶進程保護線程保護

1.簡介以及原理

以前我們講過.SSDT 可以做很多事情.比如可以防止進程被結束
其實到了x64下.你也可以HOOK SSDT.只不過你需要過一下PatchGuard
但是在你過不了PG的情況下.其實操作系統也給你提供了回調進行保護.
這個回調 也可以稱作 對象鈎子(OBject)

這個回調主要函數則是 ** ObRegisterCallbacks() **
其實關於回調函數.去查詢MSDN即可. 以前博客也有說過.只不過現在
想重新寫一下.

MSDN: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-obregistercallbacks

這個函數其實就是不斷的填寫結構體即可. 根據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 回調代碼


NTKERNELAPI
UCHAR * 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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM