[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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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;
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//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)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 !" ) ;
}
}