进程之驱动保护
序
最近在分析某度盘加速软件的时候会发现,我开的代理或者工作的时候使用的抓包软件会莫名其妙的掉,比如Proxifer
什么的,当时很纳闷。后经过资料查找发现,这个软件不单单做代理分流用,还可以用于软件的https抓包……所以一切都是那么显然了,遂很好奇抓抓玩一玩了。
开始
其实感觉过这东西应该没啥难度,修改一下名字就完事了,或者某些不是用时钟做进程监控的,打开程序再打开代理就行。然后主要想练练驱动开发,就小记一下驱动开发的代码,主要是进程对象的回调。
首先注册一下自己的回调函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| NTSTATUS SetProcessCallbacks() { NTSTATUS status = STATUS_SUCCESS; OB_CALLBACK_REGISTRATION obCallbackReg = { 0 }; OB_OPERATION_REGISTRATION obOperationReg = { 0 }; RtlZeroMemory(&obCallbackReg, sizeof(OB_CALLBACK_REGISTRATION)); RtlZeroMemory(&obOperationReg, sizeof(OB_OPERATION_REGISTRATION)); obCallbackReg.Version = ObGetFilterVersion(); obCallbackReg.OperationRegistrationCount = 1; obCallbackReg.RegistrationContext = NULL; RtlInitUnicodeString(&obCallbackReg.Altitude, L"321000"); obCallbackReg.OperationRegistration = &obOperationReg; obOperationReg.ObjectType = PsProcessType; obOperationReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE; obOperationReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)(&ProcessPreCall); status = ObRegisterCallbacks(&obCallbackReg, &g_obProcessHandle); if (!NT_SUCCESS(status)) { DbgPrint("ObRegisterCallbacks Error[0x%X]\n", status); return status; } return status; }
|
这里的Altitude
一定不能为空。
然后我们实现一下当操作进程句柄的时候,产生回调的处理办法。当结束一个进程,肯定要获取进程句柄,此时,我们可以给他进行降低权限,这样想结束进程的这个进程就会发现权限不够结束失败。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| OB_PREOP_CALLBACK_STATUS ProcessPreCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pObPreOperationInfo) { if (*PsProcessType != pObPreOperationInfo->ObjectType) { return OB_PREOP_SUCCESS; }
HANDLE pid = PsGetProcessId((PEPROCESS)pObPreOperationInfo->Object); char szProcName[16] = { 0 }; UNREFERENCED_PARAMETER(RegistrationContext); strcpy(szProcName, GetProcessNameByProcessID(pid));
if (!_stricmp(szProcName, "Proxifier.exe")) { if (OB_OPERATION_HANDLE_CREATE == pObPreOperationInfo->Operation) { if (1 == (1 & pObPreOperationInfo->Parameters->CreateHandleInformation.OriginalDesiredAccess)) { pObPreOperationInfo->Parameters->CreateHandleInformation.DesiredAccess = 0; } } else if (OB_OPERATION_HANDLE_DUPLICATE == pObPreOperationInfo->Operation) { if (1 == (1 & pObPreOperationInfo->Parameters->DuplicateHandleInformation.OriginalDesiredAccess)) { pObPreOperationInfo->Parameters->DuplicateHandleInformation.DesiredAccess = 0; } } } return OB_PREOP_SUCCESS; }
|
主要就是判断一下,操作的那个进程,是不是要保护的,是的话就提示权限不足,不然所有进程都结束不了感觉有点影响正常操作了。
另外补充一小小的工具函数
1 2 3 4 5 6 7 8 9 10 11 12 13
| char* GetProcessNameByProcessID(HANDLE pid) { NTSTATUS status; PEPROCESS EProcess = NULL; status = PsLookupProcessByProcessId(pid, &EProcess);
if (!NT_SUCCESS(status)) { return FALSE; } ObDereferenceObject(EProcess); return (char*)PsGetProcessImageFileName(EProcess); }
|
该函数就是在内核状态下,通过PID
获取进程的名称,这样一边我们判断是否是保护函数。
自黑
但是,该保护方式有个缺陷,并不是所有进程都走回调函数的,所以像一些内存清空大法,甚至使用
1 2 3 4 5
| BOOL EndTask( HWND hWnd, BOOL fShutDown, BOOL fForce );
|
就可以轻松绕过该回调拦截。