better ps

This commit is contained in:
maksw committed 2026-06-09 18:37:35 +02:00
1 parent 325149006c
commit c1a291c4c9
8 files changed
+228 -26

No files matched your search

+4 -2
View File
@@ -115,7 +115,9 @@ uint32_t KeGetHandleRights(PROCESS* process, uint32_t handle);
LIST_ENTRY* KeGetProcessList(void);
PROCESS* KeGetCurrentProcess(void);
PROCESS* KeGetSystemProcess(void);
/* Copy a snapshot of process IDs into caller-provided storage. */
size_t KeCopyProcessIds(uint32_t* pidsOut, size_t maxCount);
struct SYS_PROCESS_INFO;
/* Copy a snapshot of rich process information into caller-provided storage. */
size_t KeCopyProcessInfo(struct SYS_PROCESS_INFO* infoOut, size_t maxCount);
/* Find a live process by its ProcessId. Bumps refcount; caller must ObDereferenceObject. */
PROCESS* KeGetProcessById(uint32_t pid);
+1
View File
@@ -126,6 +126,7 @@ KSTATUS MmProtectUserRegion(PROCESS* process, void* base, size_t size, uint64_t
KSTATUS MmDestroyUserRegion(PROCESS* process, void* base);
void MmDestroyAllUserRegions(PROCESS* process);
KSTATUS MmQueryUserRegion(PROCESS* process, const void* address, void** baseOut, size_t* sizeOut, uint64_t* pageFlagsOut, USER_REGION_TYPE* typeOut, uint32_t* regionFlagsOut);
void MmQueryProcessUserMemory(PROCESS* process, size_t* regionCountOut, size_t* reservedBytesOut, size_t* committedBytesOut);
size_t MmGetUserRegionSize(PROCESS* process, const void* base);
size_t MmGetUserRegionSizeByBase(const void* base);
+74 -2
View File
@@ -10,6 +10,7 @@
#include <kernel/ob_object.h>
#include <kernel/ke_cpu.h>
#include <kernel/hal/hal_apic.h>
#include <ntlite/syscall.h>
// ---------------------------------------------------------------------------
// Global process list
@@ -64,15 +65,86 @@ KSTATUS KeCreateSystemProcess(PROCESS** out) {
return STATUS_SUCCESS;
}
size_t KeCopyProcessIds(uint32_t* pidsOut, size_t maxCount) {
static uint32_t KiCountProcessHandlesLocked(PROCESS* process) {
uint32_t count = 0;
if (!process) return 0;
for (uint32_t i = 1; i < HANDLE_TABLE_SIZE; i++) {
if (process->Handles[i].Object) count++;
}
return count;
}
static void KiCopyTruncatedString(char* dst, size_t dstSize, const char* src, size_t srcLen) {
if (!dst || dstSize == 0) return;
size_t n = 0;
if (src) {
while (n + 1 < dstSize && n < srcLen && src[n]) {
dst[n] = src[n];
n++;
}
}
dst[n] = '\0';
}
size_t KeCopyProcessInfo(struct SYS_PROCESS_INFO* infoOut, size_t maxCount) {
KiProcessInit();
PROCESS* current = KeGetCurrentProcess();
PROCESS* system = KeGetSystemProcess();
uintptr_t flags = KeAcquireSpinlock(&gProcessListLock);
size_t count = 0;
LIST_ENTRY* head = &gProcessList;
for (LIST_ENTRY* node = head->Fwd; node != head; node = node->Fwd) {
PROCESS* p = CONTAINING_RECORD(node, PROCESS, GlobalLink);
if (pidsOut && count < maxCount) pidsOut[count] = p->ProcessId;
if (infoOut && count < maxCount) {
SYS_PROCESS_INFO* info = &infoOut[count];
memset(info, 0, sizeof(*info));
info->Size = sizeof(*info);
info->ProcessId = p->ProcessId;
info->ImageBase = p->ImageBase;
info->ImageSize = p->ImageSize;
info->PebBase = p->UserPebBase;
info->ModuleCount = p->ModuleCount;
uintptr_t handleFlags = KeAcquireSpinlock(&p->HandleLock);
uint32_t threadCount = p->ThreadCount;
uint32_t handleCount = KiCountProcessHandlesLocked(p);
int exitCode = p->ExitCode;
long terminating = p->Terminating;
long exited = p->Exited;
KeReleaseSpinlock(&p->HandleLock, handleFlags);
info->ThreadCount = threadCount;
info->HandleCount = handleCount;
info->ExitCode = exitCode;
if (exited) {
info->State = SYS_PROCESS_STATE_EXITED;
info->Flags |= SYS_PROCESS_FLAG_EXITED;
} else if (terminating) {
info->State = SYS_PROCESS_STATE_TERMINATING;
info->Flags |= SYS_PROCESS_FLAG_TERMINATING;
} else {
info->State = SYS_PROCESS_STATE_RUNNING;
}
if (p == system) info->Flags |= SYS_PROCESS_FLAG_SYSTEM;
if (p == current) info->Flags |= SYS_PROCESS_FLAG_CURRENT;
MmQueryProcessUserMemory(p, &info->UserRegionCount,
&info->UserReservedBytes,
&info->UserCommittedBytes);
KiCopyTruncatedString(info->Name, sizeof(info->Name), p->Name, sizeof(p->Name));
uintptr_t cwdFlags = KeAcquireSpinlock(&p->CwdLock);
info->CurrentDrive = p->CurrentDrive;
KiCopyTruncatedString(info->CurrentDirectory, sizeof(info->CurrentDirectory),
p->CurrentDirectory, p->CurrentDirectoryLength);
KeReleaseSpinlock(&p->CwdLock, cwdFlags);
}
count++;
}
KeReleaseSpinlock(&gProcessListLock, flags);
+6 -6
View File
@@ -2012,7 +2012,7 @@ static uint64_t SyscallKillProcess(uint64_t a0, uint64_t a1, uint64_t a2,
}
// ---------------------------------------------------------------------------
// SYS_GET_PROCESS_LIST (65) a0=*pidsOut a1=maxCount a2=*countOut
// SYS_GET_PROCESS_LIST (6) a0=*SYS_PROCESS_INFO[] a1=maxCount a2=*countOut
// ---------------------------------------------------------------------------
static uint64_t SyscallGetProcessList(uint64_t a0, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5) {
@@ -2025,20 +2025,20 @@ static uint64_t SyscallGetProcessList(uint64_t a0, uint64_t a1, uint64_t a2,
if (!KSUCCESS(s)) return s;
}
size_t total = KeCopyProcessIds(NULL, 0);
size_t total = KeCopyProcessInfo(NULL, 0);
size_t toCopy = total < maxCount ? total : maxCount;
if (toCopy) {
size_t bytes = 0;
if (!KiMulSize(toCopy, sizeof(uint32_t), &bytes)) return STATUS_INVALID_PARAMETER;
if (!KiMulSize(toCopy, sizeof(SYS_PROCESS_INFO), &bytes)) return STATUS_INVALID_PARAMETER;
uint32_t* tmp = (uint32_t*)MmAllocatePool(bytes);
SYS_PROCESS_INFO* tmp = (SYS_PROCESS_INFO*)MmAllocatePool(bytes);
if (!tmp) return STATUS_NO_MEMORY;
size_t copied = KeCopyProcessIds(tmp, toCopy);
size_t copied = KeCopyProcessInfo(tmp, toCopy);
if (copied < toCopy) toCopy = copied;
KSTATUS s = CopyToUser((void*)(uintptr_t)a0, tmp, toCopy * sizeof(uint32_t));
KSTATUS s = CopyToUser((void*)(uintptr_t)a0, tmp, toCopy * sizeof(SYS_PROCESS_INFO));
MmFreePool(tmp);
if (!KSUCCESS(s)) return s;
}
+22
View File
@@ -1204,6 +1204,28 @@ KSTATUS MmQueryUserRegion(PROCESS* process, const void* address, void** baseOut,
return STATUS_NOT_FOUND;
}
void MmQueryProcessUserMemory(PROCESS* process, size_t* regionCountOut, size_t* reservedBytesOut, size_t* committedBytesOut) {
size_t regions = 0;
size_t reserved = 0;
size_t committed = 0;
if (process) {
uintptr_t flags = KeAcquireSpinlock(&process->UserRegionLock);
for (LIST_ENTRY* node = process->UserRegions.Fwd; node != &process->UserRegions; node = node->Fwd) {
USER_VA_REGION* r = CONTAINING_RECORD(node, USER_VA_REGION, ProcessLink);
regions++;
reserved += r->ReservationSize;
committed += r->CommittedSize;
}
KeReleaseSpinlock(&process->UserRegionLock, flags);
}
if (regionCountOut) *regionCountOut = regions;
if (reservedBytesOut) *reservedBytesOut = reserved;
if (committedBytesOut) *committedBytesOut = committed;
}
size_t MmGetUserRegionSize(PROCESS* process, const void* base) {
if (!process || !base) return 0;
uintptr_t procFlags = KeAcquireSpinlock(&process->UserRegionLock);