Principle
Windows, each process has its own EPROCESS structure, which contains the basic information of the program, and the data has a process linked list, through the process list (doubly linked list) can find the structure of other processes EPROCESS , so you can use this to traverse the process in the system.
Using windbg eprocess The structure that can be seen, the important structure is now excerpted as follows:
Lkd> DT _eprocess-r1nt!_eprocess...+0x084Uniqueprocessid:ptr32 Void PID +0x088Activeprocesslinks: _list_entry Active process list (doubly linked list) +0x000Flink:ptr32 _list_entry +0x004Blink:ptr32 _list_entry...+0x174Imagefilename: [ -] UChar//Process Name...+0x1b0Peb:ptr32 _peb//peb, this less than +0x000Inheritedaddressspace:uchar +0x001Readimagefileexecoptions:uchar +0x002Beingdebugged:uchar +0x003Sparebool:uchar +0x004Mutant:ptr32 Void +0x008Imagebaseaddress:ptr32 Void +0x00cLdr:ptr32 _peb_ldr_data//point to Module node header... ...+0x258cookie:uint4b
Demo
VS2008SP1 on XP sp3,visual DDK.
Visual Studio was not used in the engineering options, and the department did not use DDK compiler, even if the default structure was used to build the solution, or it could not be loaded. So I delete all, write my own, fortunately there are DDK SDK can use VAX Smart tips. Note Generate Debug (chunk) version, otherwise the debugview output cannot be displayed.
#include "StdAfx.h"VOIDOnUnload (inchPdriver_object pdriverobject) {kdprint ("OnUnload called"));} NTSTATUS enum_services () {peprocess peprocess= NULL; Peprocess pfirsteprocess= NULL; ULONG Ulprocessname= 0; ULONG Ulprocessid= 0; Peprocess=Psgetcurrentprocess ();//get system Process _eprocess_address if(peprocess== 0) {Kdprint ("Psgetcurrentprocess error! \ r \ n "));returnStatus_success; } Kdprint (("peprocess addr is:%08x\r\n", peprocess)); Pfirsteprocess=peprocess;//lkd>!process 0 0 //lkd> DT _eprocess xxxxxxxx //+0x174 imagefilename: [+] "Smss.exe" //+0x084 uniqueprocessid:0x00000224 Void //lkd> db 864bb0a8-0x88+0x174 //864bb194 6d 2e 65-00 , xx xx, xx xx xx smss.exe ..... ASCII while(peprocess) {Ulprocessname=(ULONG) peprocess+0x174; Ulprocessid= *(ULONG*) (ULONG) peprocess+0x84); Kdprint (("pid=%d,process_name=%s", Ulprocessid,ulprocessname));//+0x088 activeprocesslinks: _list_entry [0x862669a8-0x865b76e8]//+0x000 flink:0x862669a8 _list_entry [0x863570a8-0x864bb0a8]//+0x004 blink:0x865b76e8 _list_entry [0x864bb0a8-0x8055b158]Peprocess=(peprocess) (*(ULONG*) (ULONG) peprocess+0x88)-0x88);//pointer to the list, not the eprocess_start,so-0x88 //Doubly linked list, to the end of the point pointing to the head node, indicating the end. Or the PID is not greater than 0, this does not know where to get from if(peprocess==Pfirsteprocess||(*(LONG*) ((LONG) peprocess+0x84)<= 0) {Kdprint ("enum over!\r\n")); Break } }returnStatus_success;} NTSTATUS DriverEntry (inchPdriver_object Pdriverobject,inchPunicode_string Registerypath) {kdprint ("Driver Loaded")); Kdprint (("Just a test.")); Pdriverobject -Driverunload=OnUnload; Enum_services ();returnStatus_success;}
Attention:
pEprocess = (PEPROCESS)(*(ULONG*)((ULONG)pEprocess+0x88)-0x88); //pointer to the list ,not the eprocess_start,SO -0x88
- Can not see two 0x88 subtract, think is 0. Because a former 0x88 to take the value of the pointer, after the end of the minus 0x88. (That is, take the address, get the result, the result -0x88).
- As in Peb, the list
—ldr_data_table_entry points to the next address of the same linked list structure, not the header address of the next process eprocess node. So we need -0x88.
Debug_view output:
00000001 0.00000000 OnUnload called 00000002 2.50107551 Driver Loaded 00000003 2.50109267 just a test. 00000004 2.50110865 peprocess Addr is:865b7660 00000005 2.50112438 PID=4,process_name=system 00000006 2.50113988 PID=548,process_name=smss.exe 00000007 2.50115538 PID=612,process_name=csrss.exe 00000008 2.50117064 PID=636,process_name=winlogon.exe 00000009 2.50118613 PID=688,process_name=services.exe 00000010 2.50120139 PID=700,process_name=lsass.exe 00000011 2.50121689 PID=856,process_name=vmacthlp.exe 00000012 2.50123215 PID=868,process_name=svchost.exe 00000013 2.50124717 PID=952,process_name=svchost.exe 00000014 2.50126266 PID=1044,process_name=svchost.exe 00000015 2.50127792 PID=1100,process_name=svchost.exe 00000016 2.50129294 PID=1160,process_name=svchost.exe 00000017 2.50130844 PID=1416,process_name=spoolsv.exe 00000018 2.50132370 PID=1664,process_name=vmtoolsd.exe 00000019 2.50133944 PID=1956,process_name=explorer.exe 00000020 2.50135541 PID=496,process_name=vmtoolsd.exe 00000021 2.50137067 PID=536,process_name=ctfmon.exe 00000022 2.50138617 PID=1256,process_name=alg.exe 00000023 2.50140166 PID=1772,process_name=wscntfy.exe 00000024 2.50141716 PID=448,process_name=devenv.exe 00000025 2.50143218 PID=524,process_name=conime.exe 00000026 2.50144792 PID=184,process_name=kernel Detectiv 00000027 2.50146341 PID=1284,process_name=windbg.exe 00000028 2.50147891 PID=1700,process_name=osrloader.exe 00000029 2.50149441 PID=1880,process_name=dbgview.exe 00000030 2.50150990 PID=428,process_name=mspdbsrv.exe 00000031 2.50152516 PID=1788,process_name=procexp.exe 00000032 2.50154066 PID=1656,process_name=wmiprvse.exe 00000033 2.50155592 PID=244,process_name=calc.exe 00000034 2.50157094 PID=1812,process_name=cmd.exe 00000035 2.50158644 PID=1588,process_name=notepad.exe 00000036 2.50160122 enum Over!
Kernel-Level process traversal