zl程序教程

您现在的位置是:首页 >  其他

当前栏目

关于win7下r3窗口进程保护的一些方式

保护进程 方式 关于 一些 窗口 win7 R3
2023-09-11 14:13:58 时间

背景

随着Windows PG保护的出现,过去内核挂钩inline hook的时代逐渐远去,hook OpenProcess的日子也一去不复返了。那么,如果想在Windows操作系统上不那么轻易的被结束掉(这里主要考虑不在r3被结束,都在内核还干不掉你),有没有什么方法?

常见方式

通常情况下如果是在r0,注册一个ObRegisterCallbacks回调,对PROCESS_TERMINATE权限进行限制,就能解决别人调用TerminateProcess结束进程的情况。

if (pOperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE) 
{
		if (pOperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE)
				pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;

		if (pOperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess & PROCESS_DUP_HANDLE)
				pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= ~PROCESS_DUP_HANDLE;
}
			
if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
{
		if (pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE)
				pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;

		if (pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_DUP_HANDLE)
				pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_DUP_HANDLE;
}

 但是,对进程的运行原理有个基本了解的同学都知道,进程只是分配了一个'车间'的资源,最后还是线程去工作,结束掉你的线程,你的进程一样说再见,所以还得加上线程的限制,这样别人使用terminateThread也结束不了你的线程。

		if (pOperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
		{ 
			if (pOperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess & THREAD_TERMINATE)
				pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= ~THREAD_TERMINATE;
		}


		if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
		{
			if (pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & THREAD_TERMINATE)
				pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~THREAD_TERMINATE;
		}

上述描述的都是常见进程的保护手段,当然还有一些属性是可以进行修改的,比如THREAD_SUSPEND_RESUME,暂停你的线程,只要把你暂停了,就算没有结束你,你的进程不是一样的没法工作;还有就是PROCESS_VM_OPERATION,修改你的进程内存,制造一个异常,如果进程中没有hand,进程就会崩溃,从而导致进程死掉,当然还有很多的方法。这里不详细的展开,因为这不是本次想叙述的重点。

Win7 窗口进程保护

大多数同学都用过任务管理器,可能有的同学注意到,任务管理有两种结束进程的方式,第一种是在应用程序中去结束任务,这里出现的任务都是窗口程序。

第二种就是在进程中找到对应的进程去结束。

 第一种方式和第二种方式有什么区别?通过对taskmgr(任务管理器)的简单逆向,不难发现

任务管理器先调用了endtask,之后在调用 SendMessageTimeoutW往目标窗口发送了一个WM_CLOSE的消息,通知程序关闭窗口(Win10 有一点变更)

 关于消息的拦截,这里简单说明一下,不能使用WH_CALLWNDPROC消息钩子去拦截,虽然能够获取到消息,但是这里并不能删除和替换这个消息,这个消息依然会被窗口回调函数所获取。所以这里可以通过替换窗口回调函数过滤掉WM_CLOSE消息,使用GetWindowLongA和SetWindowLongA进行替换。

 EndTask的实现

该函数只是将消息发送到csrss进程中

endtask在winsrv.dll中实现,csrss会去加载这个dll。其中需要注意的是ReportHangInternal

 ReportHangInternal函数调用WersvcSendMessage,通过rpc的方式,发送异常到\\KernelObjects\\SystemErrorPortReady对象。

 \\KernelObjects\\SystemErrorPortReady对象被wersvc.dll所注册,这是windows的一个服务。在服务收到异常的时候会创建一个werfault.exe进程,并且提示你是否立刻结束这个进程(能够到达这里的前提是我们处理了WM_CLOSE消息,此时才会出现异常)

 点击立即结束之后werfault.exe进程通过setevent将消息告诉wersvc.dll服务,对应的是svchost进程。

wersvc.dll服务会再次尝试结束掉进程。

 最后简单梳理一下流程,taskmgr告诉csrss有一个窗口程序不关闭(当前窗口回调被hook,过滤了WM_CLOSE的消息),csrss接收之后往wersvc服务继续发消息,wersvc创建一个werfault.exe,werfault.exe在创建一个窗口告诉用户是否关闭程序,werfault.exe将结果告诉wersvc,wersvc最后尝试结束进程。

在此次流程中我们只需要先hook窗口的回调函数,接着添加ObRegisterCallbacks回调,处理TerminateProcess和terminateThread就能完成保护。

程序的保护

其实,还有一种方式进行保护,(运行程序的时候记得用管理员身份打开)那就是把当前进程设置为受保护进程,当进程死掉的时候就蓝屏,多的话不说,看下面的代码,其实RtlSetProcessIsCritical的实现也很简单,有兴趣的可以拿ida看一下,但是如果你用任务管理器结束窗口试试看,不会触发蓝屏?(想想为什么,多试试)。

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

typedef NTSTATUS(__cdecl* PRTLSETPROCESSISCRITICAL)(IN BOOLEAN NewValue, OUT PBOOLEAN OldValue OPTIONAL, IN BOOLEAN NeedBreaks);

BOOLEAN EnableDebugPrivilege()
{
	HANDLE hToken = NULL;
	LUID debugPrivilegeValueLuid = { 0 };
	TOKEN_PRIVILEGES tokenPrivilege = { 0 };

	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
		return FALSE;

	if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &debugPrivilegeValueLuid))
	{
		CloseHandle(hToken);
		return FALSE;
	}

	tokenPrivilege.PrivilegeCount = 1;
	tokenPrivilege.Privileges[0].Luid = debugPrivilegeValueLuid;
	tokenPrivilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPrivilege, sizeof(tokenPrivilege), NULL, NULL))
	{
		CloseHandle(hToken);
		return FALSE;
	}

	return TRUE;
}

BOOLEAN BSODCriticalProtect()
{
	if (!EnableDebugPrivilege())
		return FALSE;

	HMODULE  hNtdllMod = GetModuleHandleA("ntdll.dll");
	if (!hNtdllMod)
		return FALSE;

	PRTLSETPROCESSISCRITICAL pRtlSetProcessIsCritical;
	pRtlSetProcessIsCritical = (PRTLSETPROCESSISCRITICAL)GetProcAddress(hNtdllMod, "RtlSetProcessIsCritical");
	if (!pRtlSetProcessIsCritical)
		return FALSE;

	NTSTATUS status = pRtlSetProcessIsCritical(TRUE, NULL, FALSE);
	printf("你结束我你试试  status: %x\n", status);

	system("pause");

	status = pRtlSetProcessIsCritical(FALSE, NULL, FALSE);
	printf("别现在不行 status: %x\n", status);

	return TRUE;
}

int main(void)
{
	BSODCriticalProtect();
	system("pause");
	return 0;
}