枚舉和移除進程和線程回調

進程回調可以監視進程的創建和退出,這個在前面的章節已經講過了。 某些遊戲保護的
驅動喜歡用這個函數來監視有沒有黑名單中的程序運行,如果運行則阻止運行或者把遊戲退
出。而線程回調則通常用來監控遠程線程的建立,如果發現有遠程線程注入到了遊戲進程裏,
則馬上把遊戲退出。

我們註冊的進程回調,會存儲在一個名爲 PspCreateProcessNotifyRoutine 的數組裏。
PspCreateProcessNotifyRoutine 可以理解成一個 PVOID 數組, 它記錄了系統裏所有進程回調
的地址。這個數組最大長度是 64*sizeof(PVOID)。 所以枚舉進程回調的思路如下:找到這個
數組的地址, 然後解密數組的數據, 得到所有回調的地址(這個數組記錄的數據並不是回調
的 地 址 , 而 是 經 過 加 密 地 址 , 需 要 解 密 才 行 )。 枚 舉 線 程 回 調 同 理 , 要 找 到
PspCreateThreadNotifyRoutine 的地址(這個數組最大長度也是 64*sizeof(PVOID)),然後解密
數據,並把解密後的地址打印出來。

至於怎麼處理這些回調就簡單了。可以使用標準函數(PsSetCreateProcessNotifyRoutine、
PsRemoveCreateThreadNotifyRoutine) 將其摘掉, 也可以直接在回調函數首地址寫入 RET 把
回調函數廢掉。 WIN64AST 就提供了兩種辦法處理,以對付某些奸詐的遊戲保護。
首先要獲得 PspCreateProcessNotifyRoutine 的地址。 PspCreateProcessNotifyRoutine 在
PspSetCreateProcessNotifyRoutine 函數裏出現了。 而 PspSetCreateProcessNotifyRoutine 則在
PsSetCreateProcessNotifyRoutine 中被調用(注意前一個是 PspXXX, 後一個是 PsXXX)。 找到
PspSetCreateProcessNotifyRoutine 之後,再匹配特徵碼

#include <ntddk.h>


void CreateThreadNotify1
(
IN HANDLE  ProcessId,
IN HANDLE  ThreadId,
IN BOOLEAN  Create
)
{
	DbgPrint("CreateThreadNotify1\n");
}

void CreateThreadNotify2
(
IN HANDLE  ProcessId,
IN HANDLE  ThreadId,
IN BOOLEAN  Create
)
{
	DbgPrint("CreateThreadNotify2\n");
}

void CreateThreadNotifyTest(BOOLEAN Remove)
{
	if (!Remove)
	{
		PsSetCreateThreadNotifyRoutine(CreateThreadNotify1);
		PsSetCreateThreadNotifyRoutine(CreateThreadNotify2);
	}
	else
	{
		PsRemoveCreateThreadNotifyRoutine(CreateThreadNotify1);
		PsRemoveCreateThreadNotifyRoutine(CreateThreadNotify2);
	}
}

ULONG64 FindPspCreateProcessNotifyRoutine()
{
	LONG			OffsetAddr = 0;
	ULONG64			i = 0, pCheckArea = 0;
	UNICODE_STRING	unstrFunc;
	//獲得PsSetCreateProcessNotifyRoutine的地址
	RtlInitUnicodeString(&unstrFunc, L"PsSetCreateProcessNotifyRoutine");
	pCheckArea = (ULONG64)MmGetSystemRoutineAddress(&unstrFunc);
	//獲得PspSetCreateProcessNotifyRoutine的地址
	memcpy(&OffsetAddr, (PUCHAR)pCheckArea + 4, 4);
	pCheckArea = (pCheckArea + 3) + 5 + OffsetAddr;
	DbgPrint("PspSetCreateProcessNotifyRoutine: %llx", pCheckArea);
	//獲得PspCreateProcessNotifyRoutine的地址
	for (i = pCheckArea; i<pCheckArea + 0xff; i++)
	{
		if (*(PUCHAR)i == 0x4c && *(PUCHAR)(i + 1) == 0x8d && *(PUCHAR)(i + 2) == 0x35)	//lea r14,xxxx
		{
			LONG OffsetAddr = 0;
			memcpy(&OffsetAddr, (PUCHAR)(i + 3), 4);
			return OffsetAddr + 7 + i;
		}
	}
	return 0;
}

//
VOID EnumCreateProcessNotify()
{
	int i = 0;
	BOOLEAN b;
	ULONG64	NotifyAddr = 0, MagicPtr = 0;
	ULONG64	PspCreateProcessNotifyRoutine = FindPspCreateProcessNotifyRoutine();
	DbgPrint("PspCreateProcessNotifyRoutine: %llx", PspCreateProcessNotifyRoutine);
	if (!PspCreateProcessNotifyRoutine)
		return;
	for (i = 0; i<64; i++)
	{
		MagicPtr = PspCreateProcessNotifyRoutine + i * 8;
		NotifyAddr = *(PULONG64)(MagicPtr);
		if (MmIsAddressValid((PVOID)NotifyAddr) && NotifyAddr != 0)
		{
			NotifyAddr = *(PULONG64)(NotifyAddr & 0xfffffffffffffff8);
			DbgPrint("[CreateProcess]%llx", NotifyAddr);
		}
	}
}

ULONG64 FindPspCreateThreadNotifyRoutine()
{
	ULONG64			i = 0, pCheckArea = 0;
	UNICODE_STRING	unstrFunc;
	RtlInitUnicodeString(&unstrFunc, L"PsSetCreateThreadNotifyRoutine");
	pCheckArea = (ULONG64)MmGetSystemRoutineAddress(&unstrFunc);
	DbgPrint("PsSetCreateThreadNotifyRoutine: %llx", pCheckArea);
	for (i = pCheckArea; i<pCheckArea + 0xff; i++)
	{
		if (*(PUCHAR)i == 0x48 && *(PUCHAR)(i + 1) == 0x8d && *(PUCHAR)(i + 2) == 0x0d)	//lea rcx,xxxx
		{
			LONG OffsetAddr = 0;
			memcpy(&OffsetAddr, (PUCHAR)(i + 3), 4);
			return OffsetAddr + 7 + i;
		}
	}
	return 0;
}


VOID EnumCreateThreadNotify()
{
	int i = 0;
	BOOLEAN b;
	ULONG64	NotifyAddr = 0, MagicPtr = 0;
	ULONG64	PspCreateThreadNotifyRoutine = FindPspCreateThreadNotifyRoutine();
	DbgPrint("PspCreateThreadNotifyRoutine: %llx", PspCreateThreadNotifyRoutine);
	if (!PspCreateThreadNotifyRoutine)
		return;
	for (i = 0; i<64; i++)
	{
		MagicPtr = PspCreateThreadNotifyRoutine + i * 8;
		NotifyAddr = *(PULONG64)(MagicPtr);
		if (MmIsAddressValid((PVOID)NotifyAddr) && NotifyAddr != 0)
		{
			NotifyAddr = *(PULONG64)(NotifyAddr & 0xfffffffffffffff8);
			DbgPrint("[CreateThread]%llx", NotifyAddr);
		}
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章