1。先要声名一些函数(已经导出)

// 1. 声明要使函数
NTKERNELAPI NTSTATUS PsSuspendProcess(PEPROCESS pEProcess);
NTKERNELAPI UCHAR* PsGetProcessImageFileName(IN PEPROCESS pEProcess);
NTKERNELAPI NTSTATUS PsResumeProcess(PEPROCESS pEProcess);
NTKERNELAPI HANDLE PsGetProcessInheritedFromUniqueProcessId(IN PEPROCESS pEProcess);

// 根据PID返回进程EPROCESS,失败返回NULL
PEPROCESS LookupProcess(HANDLE hPid)
{
	PEPROCESS pEProcess = NULL;
	if (NT_SUCCESS(PsLookupProcessByProcessId(
		hPid, &pEProcess)))
		return pEProcess;
	return NULL;
}

//挂起进程
BOOLEAN KernelSuspendProcess(ULONG Id)
{
	//1. 先根据ID得到EPORCESS
	PEPROCESS pEProcess;
	if ((pEProcess = LookupProcess((HANDLE)Id) )!= NULL)
	{
		//2. 暂停进程
		if (NT_SUCCESS(PsSuspendProcess(pEProcess)))
			return FALSE;
	}
	return TRUE;

}

//恢复进程
BOOLEAN KernelResumeProcess(ULONG Id)
{
	//1. 先根据ID得到EPORCESS
	PEPROCESS pEProcess;
	if ((pEProcess = LookupProcess((HANDLE)Id)) != NULL)
	{
		//2. 暂停进程
		if (NT_SUCCESS(PsResumeProcess(pEProcess)))
			return FALSE;
	}
	return TRUE;

}

//结束进程
void KernelKillProcess() {
	HANDLE            hProcess = NULL;
	CLIENT_ID         ClientId = { 0 };
	OBJECT_ATTRIBUTES objAttribut =
	{ sizeof(OBJECT_ATTRIBUTES) };
	ClientId.UniqueProcess = (HANDLE)1234; // PID
	ClientId.UniqueThread = 0;
	// 打开进程,如果句柄有效,则结束进程
	ZwOpenProcess(
		&hProcess,    // 返回打开后的句柄
		1,            // 访问权限
		&objAttribut, // 对象属性
		&ClientId);   // 进程ID结构
	if (hProcess) {
		ZwTerminateProcess(hProcess, 0);
		ZwClose(hProcess);
	};
}


//遍历进程
VOID EnumProcess() {
	PEPROCESS pEProc = NULL;
	// 循环遍历进程(假设线程的最大值不超过0x25600)
	ULONG i = 0;
	for (i = 4; i<0x25600; i = i + 4) {
		// a.根据PID返回PEPROCESS
		pEProc = LookupProcess((HANDLE)i);
		if (!pEProc) continue;
		// b. 打印进程信息
		DbgPrint("EPROCESS=%p PID=%ld PPID=%ld Name=%s\n",
			pEProc, (UINT32)PsGetProcessId(pEProc),
			(UINT32)PsGetProcessInheritedFromUniqueProcessId(pEProc),
			PsGetProcessImageFileName(pEProc));
		// c. 将进程对象引用计数减1
		ObDereferenceObject(pEProc);
		DbgPrint("\n");
	}
}

注意这里不是那种普通的通过链遍历得到的。因为有可能故意断链。这里通过暴力的遍历(同时进程id都是偶数)