Refactored textarea from console, eventlog and buildlog into a separate widget to reduce code duplication.
This commit is contained in:
138
src/modules/systeminfo.nim
Normal file
138
src/modules/systeminfo.nim
Normal file
@@ -0,0 +1,138 @@
|
||||
import ../common/[types, utils]
|
||||
|
||||
# Declare function prototypes
|
||||
proc executePs(ctx: AgentCtx, task: Task): TaskResult
|
||||
proc executeEnv(ctx: AgentCtx, task: Task): TaskResult
|
||||
|
||||
# Module definition
|
||||
let module* = Module(
|
||||
name: protect("systeminfo"),
|
||||
description: protect("Retrieve information about the target system and environment."),
|
||||
moduleType: MODULE_SITUATIONAL_AWARENESS,
|
||||
commands: @[
|
||||
Command(
|
||||
name: protect("ps"),
|
||||
commandType: CMD_PS,
|
||||
description: protect("Display running processes."),
|
||||
example: protect("ps"),
|
||||
arguments: @[],
|
||||
execute: executePs
|
||||
),
|
||||
Command(
|
||||
name: protect("env"),
|
||||
commandType: CMD_ENV,
|
||||
description: protect("Display environment variables."),
|
||||
example: protect("env"),
|
||||
arguments: @[],
|
||||
execute: executeEnv
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
# Implement execution functions
|
||||
when not defined(agent):
|
||||
proc executePs(ctx: AgentCtx, task: Task): TaskResult = nil
|
||||
proc executeEnv(ctx: AgentCtx, task: Task): TaskResult = nil
|
||||
|
||||
when defined(agent):
|
||||
|
||||
import winim
|
||||
import os, strutils, sequtils, strformat, tables, algorithm
|
||||
import ../agent/protocol/result
|
||||
import ../common/utils
|
||||
|
||||
# TODO: Add user context to process information
|
||||
type
|
||||
ProcessInfo = object
|
||||
pid: DWORD
|
||||
ppid: DWORD
|
||||
name: string
|
||||
children: seq[DWORD]
|
||||
|
||||
proc executePs(ctx: AgentCtx, task: Task): TaskResult =
|
||||
|
||||
echo protect(" [>] Listing running processes.")
|
||||
|
||||
try:
|
||||
var processes: seq[DWORD] = @[]
|
||||
var procMap = initTable[DWORD, ProcessInfo]()
|
||||
var output: string = ""
|
||||
|
||||
# Take a snapshot of running processes
|
||||
let hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
|
||||
if hSnapshot == INVALID_HANDLE_VALUE:
|
||||
raise newException(CatchableError, protect("Invalid permissions.\n"))
|
||||
|
||||
# Close handle after object is no longer used
|
||||
defer: CloseHandle(hSnapshot)
|
||||
|
||||
var pe32: PROCESSENTRY32
|
||||
pe32.dwSize = DWORD(sizeof(PROCESSENTRY32))
|
||||
|
||||
# Loop over processes to fill the map
|
||||
if Process32First(hSnapshot, addr pe32) == FALSE:
|
||||
raise newException(CatchableError, protect("Failed to get processes.\n"))
|
||||
|
||||
while true:
|
||||
var procInfo = ProcessInfo(
|
||||
pid: pe32.th32ProcessID,
|
||||
ppid: pe32.th32ParentProcessID,
|
||||
name: $cast[WideCString](addr pe32.szExeFile[0]),
|
||||
children: @[]
|
||||
)
|
||||
|
||||
procMap[pe32.th32ProcessID] = procInfo
|
||||
|
||||
if Process32Next(hSnapshot, addr pe32) == FALSE:
|
||||
break
|
||||
|
||||
# Build child-parent relationship
|
||||
for pid, procInfo in procMap.mpairs():
|
||||
if procMap.contains(procInfo.ppid):
|
||||
procMap[procInfo.ppid].children.add(pid)
|
||||
else:
|
||||
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"
|
||||
|
||||
# Format and print process
|
||||
proc printProcess(pid: DWORD, indentSpaces: int = 0) =
|
||||
if not procMap.contains(pid):
|
||||
return
|
||||
|
||||
var process = procMap[pid]
|
||||
let indent = " ".repeat(indentSpaces)
|
||||
|
||||
output &= fmt"{process.pid:<10}{process.ppid:<10}{indent}{process.name:<25}" & "\n"
|
||||
|
||||
# Recursively print child processes with indentation
|
||||
process.children.sort()
|
||||
for childPid in process.children:
|
||||
printProcess(childPid, indentSpaces + 2)
|
||||
|
||||
# Iterate over root processes
|
||||
processes.sort()
|
||||
for pid in processes:
|
||||
printProcess(pid)
|
||||
|
||||
return createTaskResult(task, STATUS_COMPLETED, RESULT_STRING, string.toBytes(output))
|
||||
|
||||
except CatchableError as err:
|
||||
return createTaskResult(task, STATUS_FAILED, RESULT_STRING, string.toBytes(err.msg))
|
||||
|
||||
proc executeEnv(ctx: AgentCtx, task: Task): TaskResult =
|
||||
|
||||
echo protect(" [>] Displaying environment variables.")
|
||||
|
||||
try:
|
||||
var output: string = ""
|
||||
for key, value in envPairs():
|
||||
output &= fmt"{key}: {value}" & '\n'
|
||||
|
||||
return createTaskResult(task, STATUS_COMPLETED, RESULT_STRING, string.toBytes(output))
|
||||
|
||||
except CatchableError as err:
|
||||
return createTaskResult(task, STATUS_FAILED, RESULT_STRING, string.toBytes(err.msg))
|
||||
Reference in New Issue
Block a user