win进程保护 by eprocess结构体

如未特殊说明均在以下机器测试

Windows 7 Professional with Service Pack 1 (x86) - DVD (Chinese-Simplified)

ed2k://|file|cn_windows_7_professional_with_sp1_x86_dvd_u_677162.iso|2653276160|08F65018BD9B5BC8D77C1C7C5615A329|/

Windows 10 (business edition), version 1903 (updated June 2019) (x64) - DVD (Chinese-Simplified)

ed2k://|file|cn_windows_10_business_edition_version_1903_updated_june_2019_x64_dvd_830837d9.iso|5032351744|DFF5FF3B87D209D16ECE7543255FA573|/

_object_Head.flag用户态进程保护

对于32位内核,一般的内核结构(如eprocess)会有一个_object_Head 在内核结构-0x18处 置_object_Head.flag为KernelOnlyAccess会导致用户态打不开进程句柄

64位内核同样只是偏移不同

#include "drivercommon.h"


PEPROCESS g_eprocess = NULL;

NTKERNELAPI UCHAR* PsGetProcessImageFileName(__in PEPROCESS Process);

PEPROCESS FindProcessByName(UCHAR* targetName) {
PEPROCESS pEprocess = NULL;
NTSTATUS status;
for (int i = 4; i < 100000; i += 4) {
PEPROCESS ptmpEprocess = NULL;
status = PsLookupProcessByProcessId((HANDLE)i, &ptmpEprocess);
if (NT_SUCCESS(status) && ptmpEprocess) {
UCHAR* name = PsGetProcessImageFileName(ptmpEprocess);
ObReferenceObject(ptmpEprocess);
if (!_stricmp(targetName, name)) {
return ptmpEprocess;
}
}
}
return pEprocess;
}


VOID SetProcessProtect(PEPROCESS eprocess) {//会导致到不开句柄
PUCHAR ObjHead = NULL;
#ifdef _WIN64
/*union
{
UCHAR Flags; //0x1b
struct
{
UCHAR NewObject:1; //0x1b
UCHAR KernelObject:1; //0x1b
UCHAR KernelOnlyAccess:1; //0x1b
UCHAR ExclusiveObject:1; //0x1b
UCHAR PermanentObject:1; //0x1b
UCHAR DefaultSecurityQuota:1; //0x1b
UCHAR SingleHandleEntry:1; //0x1b
UCHAR DeletedInline:1; //0x1b
};
};*/
ObjHead = (PUCHAR)eprocess - 0x30;
*(ObjHead + 0x1b) |= 4;
#else
/*
#define OB_FLAG_NEW_OBJECT 0x01
#define OB_FLAG_KERNEL_OBJECT 0x02
#define OB_FLAG_CREATOR_INFO 0x04
#define OB_FLAG_EXCLUSIVE_OBJECT 0x08
#define OB_FLAG_PERMANENT_OBJECT 0x10
#define OB_FLAG_DEFAULT_SECURITY_QUOTA 0x20
#define OB_FLAG_SINGLE_HANDLE_ENTRY 0x40
#define OB_FLAG_DELETED_INLINE 0x80

*/
ObjHead = (PUCHAR)eprocess - 0x18;
*(ObjHead + 0xf) |= 4;
#endif // _WIN64
LOG("protect");
}
VOID CloseProcessProtect(PEPROCESS eprocess) {
PUCHAR ObjHead = NULL;
#ifdef _WIN64
ObjHead = (PUCHAR)eprocess - 0x30;
*(ObjHead + 0x1b) &= ~4;
#else
ObjHead = (PUCHAR)eprocess - 0x18;
*(ObjHead + 0xf) &= ~4;
#endif // _WIN64

LOG("close protect");
}




VOID DriverUnload(_In_ struct _DRIVER_OBJECT* DriverObject) {
UNREFERENCED_PARAMETER(DriverObject);
LOG("%s", __FUNCTION__);
CloseProcessProtect(g_eprocess);
g_eprocess = NULL;
}


NTSTATUS DriverEntry(
__in struct _DRIVER_OBJECT* DriverObject,
__in PUNICODE_STRING RegistryPath
) {
UNREFERENCED_PARAMETER(RegistryPath);
DriverObject->DriverUnload = DriverUnload;
LOG("%s", __FUNCTION__);
//DbgBreakPoint();
g_eprocess = FindProcessByName("dbgview.exe");
if (g_eprocess) {
SetProcessProtect(g_eprocess);
}
return STATUS_SUCCESS;
}

image-20240618211304064

image-20240618211152326

EPROCESS.ActiveProcessLinks进程断链进程隐藏

image-20240618234708242

断链后要再InitializeListHead被断链的list_entry

RemoveEntryList后 ActiveProcessLinks的flink和blink依旧指向之前的,这样该进程在销毁时,会重新操作flibk和blink可能导致蓝屏
InitializeListHead使链表F和B都指向字节
ListHead->Flink = ListHead->Blink = ListHead;

#include "drivercommon.h"

PEPROCESS FindProcessByName(PWCH targetName) {
NTSTATUS status;
for (int i = 4; i < 0x100000; i += 4) {
PEPROCESS process = NULL;
status = PsLookupProcessByProcessId((HANDLE)i, &process);
if (NT_SUCCESS(status) && process) {
ObDereferenceObject(process);
PUNICODE_STRING curName = NULL;
status = SeLocateProcessImageName(process, &curName);

if (NT_SUCCESS(status) && curName) {
if (curName->Length) {
_wcsupr(curName->Buffer);
if (wcsstr(curName->Buffer, targetName)) {
LOG("%S", targetName);
return process;
}
}
ExFreePoolWithTag(curName, 0);
}
}
}
LOG("not found");
return NULL;
}

ULONG GetActiveProcessLinksOffset() {
UNICODE_STRING funcName = { 0 };
RtlInitUnicodeString(&funcName, L"PsGetProcessId");
PUCHAR funcAddr = (PUCHAR)MmGetSystemRoutineAddress(&funcName);

if (!funcAddr) {
return -1;
}

for (int i = 0; i < 0x100; i++) {
#ifdef _WIN64
if (funcAddr[i] == 0x8b && funcAddr[i + 1] == 0x81) {
#else
if (funcAddr[i] == 0x8b && funcAddr[i + 1] == 0x80) {

#endif // _WIN64

/*
struct _EPROCESS
{
struct _KPROCESS Pcb; //0x0
struct _EX_PUSH_LOCK ProcessLock; //0x98
union _LARGE_INTEGER CreateTime; //0xa0
union _LARGE_INTEGER ExitTime; //0xa8
struct _EX_RUNDOWN_REF RundownProtect; //0xb0
VOID* UniqueProcessId; //0xb4
struct _LIST_ENTRY ActiveProcessLinks;
.......
}
*/
return (*(PULONG)(funcAddr + i + 2)) + sizeof(SIZE_T);//通过SIZE_T适配32位,64位

}
}
}

VOID DriverUnload(_In_ struct _DRIVER_OBJECT* DriverObject) {
UNREFERENCED_PARAMETER(DriverObject);
LOG("%s", __FUNCTION__);
}

NTSTATUS DriverEntry(
__in struct _DRIVER_OBJECT* DriverObject,
__in PUNICODE_STRING RegistryPath
) {
UNREFERENCED_PARAMETER(RegistryPath);
DriverObject->DriverUnload = DriverUnload;
LOG("%s", __FUNCTION__);
PEPROCESS process = FindProcessByName(L"DBGVIEW.EXE");
if (NULL == process) {
return STATUS_UNSUCCESSFUL;
}
DbgBreakPoint();
ULONG offset = GetActiveProcessLinksOffset();
PLIST_ENTRY ActiveProcessLinks = (PLIST_ENTRY)((PUCHAR)process + offset);
RemoveEntryList(ActiveProcessLinks);
/*
RemoveEntryList后 ActiveProcessLinks的flink和blink依旧指向之前的,这样该进程在销毁时,会重新操作flibk和blink可能导致蓝屏
init使链表F和B都指向字节
ListHead->Flink = ListHead->Blink = ListHead;
*/
InitializeListHead(ActiveProcessLinks);
return STATUS_SUCCESS;
}

BreakOnTermination

EPROCESS.BreakOnTermination : 0y0 为1时标识临界进程杀死会导致蓝屏

以下代码仅仅win7下测试

#include "drivercommon.h"

PEPROCESS FindProcessByName(PWCH targetName) {
NTSTATUS status;
for (int i = 4; i < 0x100000; i += 4) {
PEPROCESS process = NULL;
status = PsLookupProcessByProcessId((HANDLE)i, &process);
if (NT_SUCCESS(status) && process) {
ObDereferenceObject(process);
PUNICODE_STRING curName = NULL;
status = SeLocateProcessImageName(process, &curName);

if (NT_SUCCESS(status) && curName) {
if (curName->Length) {
_wcsupr(curName->Buffer);
if (wcsstr(curName->Buffer, targetName)) {
LOG("%S", targetName);
return process;
}
}
ExFreePoolWithTag(curName, 0);
}
}
}
LOG("not found");
return NULL;
}

VOID DriverUnload(_In_ struct _DRIVER_OBJECT* DriverObject) {
UNREFERENCED_PARAMETER(DriverObject);
LOG("%s", __FUNCTION__);
}
NTSTATUS DriverEntry(
__in struct _DRIVER_OBJECT* DriverObject,
__in PUNICODE_STRING RegistryPath
) {
UNREFERENCED_PARAMETER(RegistryPath);
DriverObject->DriverUnload = DriverUnload;
LOG("%s", __FUNCTION__);
PEPROCESS process = FindProcessByName(L"DBGVIEW.EXE");
if (NULL == process) {
return STATUS_UNSUCCESSFUL;
}
PUCHAR targetAd = (PUCHAR)process + 0x270;
ULONG32 origin = *(PULONG32)(targetAd);
origin |= 0x2000;
*(PULONG32)(targetAd) = origin;
return STATUS_SUCCESS;
}