[note]枚举进程之一(基础科普篇)

  关于进程的枚举,以及查看进程信息,和查杀进程...等等..都是很古老的东西了,但是基础是改变不了的.

首先看看关于进程的枚举吧,当前ark的驱动枚举进程,离不开V大的这个思路表(如下):

 

killvxk的驱动查进程:
1.native api获得进程表a
2.通过activelist获得进程表b
3.通过pspCidTable获得进程表c
4.通过handletablelisthead获得进程表d
5.通过csrss的handletable用2种方法枚举获得进程表e和f
6.通过扫描当前进程的handletable获得进程表g
7.遍历表c的每一个进程的SessionProcessLinks获得进程表h
8.遍历表c的每一个进程Vm.WorkingSetExpansionLinks获得进程表i
9.通过Typelist分别取process和thread的表j和表k
10.通过表k得到进程表l
11.搜索内存中的threadobject和processobject得到进程表m
12.通过Wait/Dispatch得到进程表n
13.如果系统是Win2003以上遍历表c的每一个进程的MmProcessLinks得到表o
14.综合上面的进程表得到表p
15.对表p每一个进程做HandleTable,Vm.WorkXX,MmProcessXX,SessionProcessList扫描得到表q
16.枚举HWNDHandle得到进程表r
17.枚举JobObject得到表s
18.综合得表t,此时枚举结束~~

动态部分:
KiReadyThread
和KiSwapContext的钩子
还有KiService钩子
还有CreateProcessNotifyRoutine和CreateThreadNotifyRoutine
NtCreateThread钩子
动态维护一张表,静态枚举结束后综合两表~

 

虽然是思路,但还是具体看看实现机制吧.偶能写多少算多少,尽量写全~

1.关于native api 获取表a
这个是通过 ZwQuerySystemInformation()函数来实现的,传入 PROCESS_SYSTEM_INFORMATION,即可获得进程信息.

或者使用ZwQueryProcessInformation()函数..自己可以参考网上的很多代码~

 

ps下:关于这个native api 的进程隐藏,因为任务管理器,就是调用ZwQuerySystemInformation()来显示进程的,所以

只要在SSDT中,HOOK掉ZwQuerySystemInformation(),把自己需要隐藏的进程过滤掉就可以了...

具体代码可以参考Rootkit.com上的fuzen_op的HideProcessHookMdl.zip 这个程序

https://www.rootkit.com/download.php?browse=1&user=fuzen_op

 

代码
BOOL ListProcess()
{
// 导出函数
HMODULE hNtDll = GetModuleHandle("ntdll.dll");
ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation
= (ZWQUERYSYSTEMINFORMATION)GetProcAddress(hNtDll,"ZwQuerySystemInformation");

ULONG cbBuffer
= 0x10000;
LPVOID pBuffer
= NULL;

pBuffer
= malloc(cbBuffer);
if(pBuffer == NULL)
return -1;

// 获取进程信息
ZwQuerySystemInformation(SystemProcessesAndThreadsInformation,pBuffer,cbBuffer,NULL);
// 指针指向链表头部
PSYSTEM_PROCESS_INFORMATION pInfo = (PSYSTEM_PROCESS_INFORMATION)pBuffer;

printf(
"ProcessName PID Parent's PID ");

// 输出结果
for(;;)
{
printf(
"%ls,\t%d,\t%d\n",pInfo->ProcessName.Buffer,pInfo->ProcessId,pInfo->InheritedFromProcessId);

if(pInfo->NextEntryDelta == 0)
break;

// 读取下一个节点
pInfo = (PSYSTEM_PROCESS_INFORMATION)(((PUCHAR)pInfo)+pInfo->NextEntryDelta);
}
// 释放缓冲区
free(pBuffer);

return 0;
}

 

 

代码
//native api获得进程表
NTSTATUS NativeApiEnumProcess()
{
ULONG pNeededSize
=0;
int iCount = 1;
int bOver=0;
NTSTATUS status;
ULONG uSize;
PVOID pSi
=NULL;
PSYSTEM_PROCESS_INFORMATION pSpiNext
= NULL;
uSize
=0x8000;
if (KeGetCurrentIrql()!=PASSIVE_LEVEL)
{
return STATUS_UNSUCCESSFUL;
}
Again:
pSi
=ExAllocatePoolWithTag(NonPagedPool,uSize,'pro1');
if (pSi!=NULL)
{
status
=ZwQuerySystemInformation(SystemProcessesAndThreadsInformation,pSi,uSize,&pNeededSize);
if (uSize<pNeededSize)
{
ExFreePoolWithTag(pSi,
'pro1');
uSize
*=2;
goto Again;
}
uSize
=pNeededSize;
status
=ZwQuerySystemInformation(SystemProcessesAndThreadsInformation,pSi,uSize,&pNeededSize);
if (STATUS_SUCCESS==status)
{
pSpiNext
=(PSYSTEM_PROCESS_INFORMATION) pSi;
while (TRUE)
{
PEPROCESS Pepr
=NULL;
if (pSpiNext->ProcessId==0)
{

if (PsLookupProcessByProcessId((HANDLE)(pSpiNext->ProcessId),&Pepr)==STATUS_SUCCESS)
{

FindAndCheckProcess(TRUE,(ULONG)Pepr);
}

}
else
{


if (pSpiNext->ProcessId)
{
if (PsLookupProcessByProcessId((HANDLE)(pSpiNext->ProcessId),&Pepr)==STATUS_SUCCESS)
{

FindAndCheckProcess(TRUE,(ULONG)Pepr);
}


}

iCount
++;
}
if (pSpiNext->NextEntryOffset==0)
{

bOver
=1;
break;
}
pSpiNext
= (PSYSTEM_PROCESS_INFORMATION)((ULONG)pSpiNext + pSpiNext->NextEntryOffset);

}
ExFreePoolWithTag(pSi,
'pro1');

}
else
{
ExFreePoolWithTag(pSi,
'pro1');
return STATUS_UNSUCCESSFUL;
}

}
return STATUS_SUCCESS;



}

 

 

2.关于使用ActiveList获取表b

通过使用PsGetCurrentProcess()获得当前进程的PEPROCESS指针,即pCurrentEprocess,然后定位到ActiveList域,

也就是ActiveList=pCurrentEprocess+0x88;

(我这里是 winxp sp3),2k下和NT下略有不同,至于vista和win7没弄过..嘿嘿)

lkd> dt _eprocess 893d2020 
nt!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x06c ProcessLock      : _EX_PUSH_LOCK
   +0x070 CreateTime       : _LARGE_INTEGER 0x1cb55a9`3c885916
   +0x078 ExitTime         : _LARGE_INTEGER 0x0
   +0x080 RundownProtect   : _EX_RUNDOWN_REF
   +0x084 UniqueProcessId  : 0x00000bc0
   +0x088 ActiveProcessLinks : _LIST_ENTRY [ 0x8987a848 - 0x8945fca0 ]

 

ActiveProcessLinks域是个List_Entry结构.它的FLINK和BLINK成员指向前一个EPROCESS,和后一个EPROCESS

因此可以通过Activelist,遍历所有的EPROCESS结构,从而实现对进程枚举.

(贴个教主的code)

 

代码
VOID ShowEPROCESS(void)
{
DWORD EProcess,FirstEProcess;
LIST_ENTRY
* ActiveProcessLinks;
DWORD pid,dwCount
=0;
PUCHAR pImage;
PPROCESS_INFO ProcessInfo
={0};
EProcess
=FirstEProcess=(DWORD)PsGetCurrentProcess();
//pid=*(DWORD*)((char*)EProcess+EPROCESS_PID_OFFSET);
__try {
while ( EProcess!= 0)
{
dwCount
++;
pid
= *( (DWORD*)( EProcess + EPROCESS_PID_OFFSET ) );
pImage
= (PUCHAR)( EProcess + EPROCESS_IMAGENAME_OFFSET ) ;

DbgPrint (
"[Pid=%8d] EProcess=0x%08X %s\n", pid, EProcess, pImage) ;

ActiveProcessLinks
= (LIST_ENTRY*) ( EProcess + EPROCESS_FLINK_OFFSET ) ;
EProcess
= (DWORD)ActiveProcessLinks->Flink - EPROCESS_FLINK_OFFSET ;

if ( EProcess == FirstEProcess )
break ;
}
DbgPrint (
"ProcessCount = %d\n", dwCount ) ;
}
__except (
1 ) {
DbgPrint (
"EnumProcessList exception !" ) ;
}


}

 

 

 

 

 

posted @ 2010-09-16 22:36  Tbit  阅读(1309)  评论(0编辑  收藏  举报