As most of you know I have been playing with the more low level functions in NT lately and this is a process walk without using the PSAPI or ToolHelp32 DLL's, not very useful I guess but the information is more extensive than you would get with either form of process walk :

First the structures necessary :

VM_COUNTERS STRUCT

PeakVirtualSize DD
VirtualSize DD
PageFaultCount DD
PeakWorkingSetSize DD
WorkingSetSize DD
QuotaPeakPagedPoolUsage DD
QuotaPagedPoolUsage DD
QuotaPeakNonPagedPoolUsage DD
QuotaNonPagedPoolUsage DD
PagefileUsage DD
PeakPagefileUsage DD
ENDS

CLIENT_ID STRUCT
UniqueProcess DD
UniqueThread DD
ENDS

SYSTEM_THREAD STRUCT
KernelTime DQ
UserTime DQ
CreateTime DQ
WaitTime DD
StartAddress DD
ClientId CLIENT_ID <>
Priority DD
BasePriority DD
ContextSwitches DD
ThreadState DD // 2=running; 5=waiting
WaitReason DD
ENDS

UNICODE_STRING STRUCT
Length DW
MaximumLength DW
Buffer DD
ENDS

SYSTEM_PROCESS_INFORMATION STRUCT
Next DD
ThreadCount DD
Reserved01 DD
Reserved02 DD
Reserved03 DD
Reserved04 DD
Reserved05 DD
Reserved06 DD
CreateTime DQ
UserTime DQ
KernelTime DQ
usName UNICODE_STRING <>
BasePriority DD
UniqueProcessId DD
InheritedFromUniqueProcessId DD
HandleCount DD
Reserved07 DD
Reserved08 DD
VmCounters VM_COUNTERS <>
CommitCharge DD
Threads SYSTEM_THREAD <>
ENDS


Now the process walk :

DATA SECTION

textbuffer DB MAX_PATH DUP (?)
outbuffer DB MAX_PATH DUP (?)
pBuffer DD ?

CODE SECTION

Start:
; This buffer needs to be huge it is the whole snapshot in one place
invoke VirtualAlloc,0,20000h,MEM_COMMIT,PAGE_READWRITE
mov [pBuffer],eax

; Take a process snapshot
invoke NTDLL:NtQuerySystemInformation, 5, [pBuffer], 20000h, 0
mov edi,[pBuffer]
L0:
mov ebx,[edi+SYSTEM_PROCESS_INFORMATION.UniqueProcessId]
or ebx,ebx
jz >L1
mov eax,[edi+SYSTEM_PROCESS_INFORMATION.usName.Buffer]
movzx edx,W[edi+SYSTEM_PROCESS_INFORMATION.usName.Length]
invoke WideCharToMultiByte,0,0,eax,edx,offset textbuffer,256,0,0
invoke wsprintfA,offset outbuffer,"PID %u Process name %s",
ebx, offset textbuffer
add esp,16
; outbuffer format = "PID 144 Process name SMSS.EXE"
PrintString(outbuffer)
L1:
mov eax,[edi+SYSTEM_PROCESS_INFORMATION.Next]
add edi,eax
or eax,eax
jnz <L0
:
invoke VirtualFree,[pBuffer],0,MEM_RELEASE

invoke ExitProcess,0
Posted on 2004-07-07 12:20:07 by donkey
Just as a technical note, the Threads field of the SYSTEM_PROCESS_INFORMATION can be more than 1 structure, there is 1 for each thread but there is a minimum of 1 (ofcourse). This is the reason behind using the Next field to walk to the next process.
Posted on 2004-07-07 12:33:32 by donkey
Is there anything similar to Win9x?
Posted on 2004-07-07 15:10:55 by comrade
Hi comrade

No, there is nothing like this in Win9x, I am thinking about finding a way to get the bottom and top addresses of the process database in shared memory (above 2Gig) and walking through that, but the docs on 9x are pretty limited and hard to find. The Platform SDK and DDK no longer have much about them, most of this information is from the DDK so I am looking through my archives for my copy of the 98 DDK.
Posted on 2004-07-07 16:29:46 by donkey
Comrade,

MS doesn't support Win9x as NT systems.
Posted on 2004-07-08 05:27:45 by Vortex
Great stuff, Donkey :)
Can you think of a way to hide from this? :tongue:
Posted on 2004-07-08 05:52:29 by Homer

Great stuff, Donkey :)
Can you think of a way to hide from this? :tongue:


No, I can' think of a way though I have not really tried, most of the HideProcess type applications use a ToolHelp32 or PSAPI API hook to hide themselves so they would probably be ineffective here. But I have no way of testing it.
Posted on 2004-07-08 13:47:56 by donkey
most also do hook NtQuerySystemInformation
Posted on 2004-07-08 13:54:04 by Drocon
That's what I was driving at :)
Posted on 2004-07-08 18:57:46 by Homer

Comrade,

MS doesn't support Win9x as NT systems.


MS doesn't support undocumented functions either, yet there is this undocumented process walk!
Posted on 2004-07-08 23:01:12 by comrade
Hi comrade,

I have found my copy of the 98DDK but have some other stuff in NT to finish first. I imagine there is a way to walk the processes though. I have to go through the DDK to find out some stuff about how process handles are assigned in 9x anyway, I need to walk the processes in order to translate the obfuscated handle value to a PID, 9x is so incredibly lame in the way it assigns PIDs.

What I am thinking is that I can get the fs:[18] address and round it down to the nearest page boundary then walk up till there are no more processes. Have to try it out soon, it would not be possible to hide a process from that walk.
Posted on 2004-07-08 23:23:45 by donkey
The obsuficated PID was uncovered by Pietrik, no?
Posted on 2004-07-08 23:50:03 by comrade
I am not sure who found it first, Jibz told me about it. My problem is that it is based on fs:[18], and in 9x that changes from process to process, it is static in NT. So I need to find a way to get the offset at fs:[18] in a remote process given only it's handle.
Posted on 2004-07-09 00:07:44 by donkey
Sounds like a job for a remote thread (process injection) :)
Alternatively, there's always the (very slow) debugapi ?
Posted on 2004-07-09 00:23:28 by Homer
Nah, can't do it with anything like that, it is for my system library. I have a GetPIDFromhProcessNT function and would like a similar one for 9x. I am looking at a process walk through the PDB database. I can check the fs:[30h] address against the handle I have to see if it de-obfuscates to the same as the PID in the PDB entry. Or something like that, I haven't really planned it all out yet as I have put it on a back burner while I explore the NT low level stuff.
Posted on 2004-07-09 01:03:06 by donkey