Improved looking for EPROCESS::ActiveProcessLinks algo

This commit is contained in:
JKornev 2021-08-28 02:08:47 +03:00
parent 59439bae79
commit 331952e7fc
4 changed files with 115 additions and 69 deletions

View File

@ -1,6 +1,7 @@
#include "KernelAnalyzer.h"
#include "Helper.h"
#include <Zydis/Zydis.h>
#include <stdlib.h>
typedef struct _KernelInternals {
ULONG ActiveProcessLinksOffset;
@ -20,6 +21,14 @@ PVOID GetPspCidTablePointer()
return s_NTinternals.PspCidTable;
}
PLIST_ENTRY GetActiveProcessLinksList(PEPROCESS Process)
{
if (!s_NTinternals.ActiveProcessLinksOffset)
return NULL;
return (PLIST_ENTRY)((ULONG_PTR)Process + s_NTinternals.ActiveProcessLinksOffset);
}
// =========================================================================================
BOOLEAN Disassemble(PVOID fn, SIZE_T size, BOOLEAN(*InstructionCallback)(ZyanU64,ZydisDecodedInstruction*,PVOID), PVOID params)
@ -168,9 +177,93 @@ VOID LookForPspCidTable()
}
}
VOID LookActiveProcessLock()
// =========================================================================================
BOOLEAN IsKernelAddress(PVOID Address)
{
//Disassemble()
#ifdef _M_AMD64
ULONG_PTR kernelStarts = 0x800000000000;
#else
ULONG_PTR kernelStarts = 0x80000000;
#endif
if ((ULONG_PTR)Address <= kernelStarts)
return FALSE;
if (!MmIsAddressValid(Address))
return FALSE;
return TRUE;
}
BOOLEAN IsValidActiveProcessLinksOffset(PEPROCESS Process, HANDLE ProcessId, ULONG Offset)
{
// EPROCESS ActiveProcessLinks field is next to UniqueProcessId
// ...
// + 0x0b4 UniqueProcessId : Ptr32 Void
// + 0x0b8 ActiveProcessLinks : _LIST_ENTRY
// + 0x0c0 Flags2 : Uint4B
// ...
__try
{
HANDLE UniqueProcessId = *(HANDLE*)((ULONG_PTR)Process + Offset - sizeof(HANDLE));
if (UniqueProcessId != ProcessId)
return FALSE;
PLIST_ENTRY ActiveProcessLinks = (PLIST_ENTRY)((ULONG_PTR)Process + Offset);
if (!IsKernelAddress(ActiveProcessLinks->Blink) || !IsKernelAddress(ActiveProcessLinks->Flink))
return FALSE;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return FALSE;
}
return TRUE;
}
ULONG FindActiveProcessLinksOffset(PEPROCESS Process)
{
#ifdef _M_AMD64
ULONG knownOffsets[] = { 0xE8/*Vista*/, 0x188/*7*/, 0x2E8/*8*/, 0x2F0/*TH1*/, 0x448/*20H1*/ };
ULONG lookingStartOffset = 0xC0;
ULONG lookingPeakOffset = 0x500;
#else
ULONG knownOffsets[] = { 0xA0/*Vista*/, 0xB8/*7*/, 0xE8/*20H1*/ };
ULONG lookingStartOffset = 0x80;
ULONG lookingPeakOffset = 0x200;
#endif
HANDLE processId = PsGetProcessId(Process);
// Fast check
for (ULONG i = 0; i < _countof(knownOffsets); i++)
{
if (IsValidActiveProcessLinksOffset(Process, processId, knownOffsets[i]))
return knownOffsets[i];
}
// Slow check
for (ULONG offset = lookingStartOffset; offset < lookingPeakOffset; offset += sizeof(void*))
{
if (IsValidActiveProcessLinksOffset(Process, processId, offset))
return offset;
}
return 0;
}
VOID LookForActiveProcessLinks()
{
s_NTinternals.ActiveProcessLinksOffset = FindActiveProcessLinksOffset(PsGetCurrentProcess());
if (s_NTinternals.ActiveProcessLinksOffset)
LogInfo("EPROCESS->ActiveProcessList offset is %x", s_NTinternals.ActiveProcessLinksOffset);
else
LogWarning("Failed to find EPROCESS->ActiveProcessList");
//TODO: PspActiveProcessLock
}
// =========================================================================================
@ -208,7 +301,7 @@ VOID InitializeKernelAnalyzer()
return;
LookForPspCidTable();
LookActiveProcessLock();
LookForActiveProcessLinks();
}
VOID DestroyKernelAnalyzer()

View File

@ -6,3 +6,5 @@ VOID InitializeKernelAnalyzer();
VOID DestroyKernelAnalyzer();
PVOID GetPspCidTablePointer();
PLIST_ENTRY GetActiveProcessLinksList(PEPROCESS Process);

View File

@ -173,49 +173,6 @@ OB_PREOP_CALLBACK_STATUS ThreadPreCallback(PVOID RegistrationContext, POB_PRE_OP
return OB_PREOP_SUCCESS;
}
//TODO:
// - Find an offset on driver initialization step
BOOLEAN FindActiveProcessLinksOffset(PEPROCESS Process, ULONG* Offset)
{
#ifdef _M_AMD64
ULONG peak = 0x300;
#else
ULONG peak = 0x150;
#endif
HANDLE* ptr = (HANDLE*)Process;
HANDLE processId;
ULONG i;
if (g_activeProcessListOffset)
{
*Offset = g_activeProcessListOffset;
return TRUE;
}
processId = PsGetProcessId(Process);
// EPROCESS ActiveProcessLinks field is next to UniqueProcessId
// ...
// + 0x0b4 UniqueProcessId : Ptr32 Void
// + 0x0b8 ActiveProcessLinks : _LIST_ENTRY
// + 0x0c0 Flags2 : Uint4B
// ...
for (i = 15; i < peak / sizeof(HANDLE); i++)
{
if (ptr[i] == processId)
{
ULONG offset = sizeof(HANDLE) * (i + 1);
InterlockedExchange((LONG volatile*)&g_activeProcessListOffset, offset);
LogInfo("EPROCESS->ActiveProcessList offset is %x", offset);
*Offset = offset;
return TRUE;
}
}
return FALSE;
}
VOID UnlinkProcessFromList(PLIST_ENTRY Current)
{ // https://github.com/landhb/HideProcess/blob/master/driver/hideprocess.c
PLIST_ENTRY Previous, Next;
@ -239,18 +196,13 @@ VOID UnlinkProcessFromList(PLIST_ENTRY Current)
//
VOID UnlinkProcessFromActiveProcessLinks(PProcessTableEntry Entry)
{
PEPROCESS Process = Entry->reference;
ULONG eprocListOffset = 0;
PLIST_ENTRY CurrentList = NULL;
if (!FindActiveProcessLinksOffset(Process, &eprocListOffset))
PLIST_ENTRY CurrentList = GetActiveProcessLinksList(Entry->reference);
if (!CurrentList)
{
LogError("Error, can't find active process list offset, eprocess:%p", Process);
LogWarning("Error, can't get active process links list, eprocess:%p", Entry->reference);
return;
}
CurrentList = (PLIST_ENTRY)((ULONG_PTR)Process + eprocListOffset);
// We use g_activeProcListLock to sync our modification inside hidden and raise
// IRQL to disable special APC's because we want to minimize a BSOD chance because
// of lack of the ActiveProcessLinks syncronization
@ -279,31 +231,30 @@ VOID LinkProcessFromList(PLIST_ENTRY Current, PLIST_ENTRY Target)
VOID LinkProcessToActiveProcessLinks(PProcessTableEntry Entry)
{
PEPROCESS Process = Entry->reference;
ULONG eprocListOffset = 0;
PLIST_ENTRY CurrentList = NULL, TargetList = NULL;
PEPROCESS System;
NTSTATUS status;
if (!FindActiveProcessLinksOffset(Process, &eprocListOffset))
{
LogWarning("Warning, can't find active process list offset, eprocess:%p", Process);
return;
}
status = PsLookupProcessByProcessId(SYSTEM_PROCESS_ID, &System);
if (!NT_SUCCESS(status))
{
LogWarning("Warning, can't find active system process");
LogWarning("Error, can't find active system process");
return;
}
CurrentList = (PLIST_ENTRY)((ULONG_PTR)Process + eprocListOffset);
TargetList = (PLIST_ENTRY)((ULONG_PTR)System + eprocListOffset);
CurrentList = GetActiveProcessLinksList(Entry->reference);
TargetList = GetActiveProcessLinksList(System);
KeAcquireGuardedMutex(&g_activeProcListLock);
LinkProcessFromList(CurrentList, TargetList);
KeReleaseGuardedMutex(&g_activeProcListLock);
if (CurrentList && TargetList)
{
KeAcquireGuardedMutex(&g_activeProcListLock);
LinkProcessFromList(CurrentList, TargetList);
KeReleaseGuardedMutex(&g_activeProcListLock);
}
else
{
LogWarning("Error, can't get active process links list, eprocess:%p,%p", Entry->reference, System);
}
ObDereferenceObject(System);
}

View File

@ -72,7 +72,7 @@
- Поддержка case-sensetive путей на Windows 10
- Реализовать сокрытие процессов
+ Сделать видимыми скрытые процессы после выгрузки и /unhide
- Улучшить алгоритм поиска офсета
+ Улучшить алгоритм поиска офсета
+ Добавить конфигурацию в реестр
- Реализовать скрытие процесса из PspCidTable
- Добавить сокрытие потоков из PspCidTable