Implemented agent registration to match new binary structure instead of json.
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import streams, strutils
|
||||
import ./types
|
||||
|
||||
import ./[types, utils]
|
||||
type
|
||||
Packer* = ref object
|
||||
stream: StringStream
|
||||
@@ -34,6 +33,19 @@ proc addArgument*(packer: Packer, arg: TaskArg): Packer {.discardable.} =
|
||||
packer.addData(arg.data)
|
||||
return packer
|
||||
|
||||
proc addVarLengthMetadata*(packer: Packer, metadata: seq[byte]): Packer {.discardable.} =
|
||||
|
||||
# Add length of metadata field
|
||||
packer.add(cast[uint32](metadata.len))
|
||||
|
||||
if metadata.len <= 0:
|
||||
# Field is empty (e.g. not domain joined)
|
||||
return packer
|
||||
|
||||
# Add content
|
||||
packer.addData(metadata)
|
||||
return packer
|
||||
|
||||
proc pack*(packer: Packer): seq[byte] =
|
||||
packer.stream.setPosition(0)
|
||||
let data = packer.stream.readAll()
|
||||
@@ -102,4 +114,15 @@ proc getArgument*(unpacker: Unpacker): TaskArg =
|
||||
of BOOL:
|
||||
result.data = unpacker.getBytes(1)
|
||||
else:
|
||||
discard
|
||||
discard
|
||||
|
||||
proc getVarLengthMetadata*(unpacker: Unpacker): string =
|
||||
|
||||
# Read length of metadata field
|
||||
let length = unpacker.getUint32()
|
||||
|
||||
if length <= 0:
|
||||
return ""
|
||||
|
||||
# Read content
|
||||
return unpacker.getBytes(int(length)).toString()
|
||||
@@ -13,7 +13,8 @@ type
|
||||
PacketType* = enum
|
||||
MSG_TASK = 0'u8
|
||||
MSG_RESPONSE = 1'u8
|
||||
MSG_REGISTER = 100'u8
|
||||
MSG_REGISTER = 2'u8
|
||||
MSG_CHECKIN = 100'u8
|
||||
|
||||
ArgType* = enum
|
||||
STRING = 0'u8
|
||||
@@ -101,27 +102,36 @@ type
|
||||
|
||||
# Agent structure
|
||||
type
|
||||
|
||||
# All variable length fields are stored as seq[byte], prefixed with 4 bytes indicating the length of the following data
|
||||
AgentMetadata* = object
|
||||
agentId*: uint32
|
||||
listenerId*: uint32
|
||||
username*: seq[byte]
|
||||
hostname*: seq[byte]
|
||||
domain*: seq[byte]
|
||||
ip*: seq[byte]
|
||||
os*: seq[byte]
|
||||
process*: seq[byte]
|
||||
pid*: uint32
|
||||
isElevated*: uint8
|
||||
sleep*: uint32
|
||||
|
||||
AgentRegistrationData* = object
|
||||
username*: string
|
||||
hostname*: string
|
||||
domain*: string
|
||||
ip*: string
|
||||
os*: string
|
||||
process*: string
|
||||
pid*: int
|
||||
elevated*: bool
|
||||
sleep*: int
|
||||
header*: Header
|
||||
# encMaterial*: seq[byte] # Encryption material for the agent registration
|
||||
metadata*: AgentMetadata
|
||||
|
||||
Agent* = ref object
|
||||
name*: string
|
||||
listener*: string
|
||||
agentId*: string
|
||||
listenerId*: string
|
||||
username*: string
|
||||
hostname*: string
|
||||
domain*: string
|
||||
process*: string
|
||||
pid*: int
|
||||
ip*: string
|
||||
os*: string
|
||||
process*: string
|
||||
pid*: int
|
||||
elevated*: bool
|
||||
sleep*: int
|
||||
jitter*: float
|
||||
|
||||
53
src/common/utils.nim
Normal file
53
src/common/utils.nim
Normal file
@@ -0,0 +1,53 @@
|
||||
import strutils, sequtils, random, strformat
|
||||
|
||||
proc generateUUID*(): string =
|
||||
# Create a 4-byte HEX UUID string (8 characters)
|
||||
(0..<4).mapIt(rand(255)).mapIt(fmt"{it:02X}").join()
|
||||
|
||||
proc uuidToUint32*(uuid: string): uint32 =
|
||||
return fromHex[uint32](uuid)
|
||||
|
||||
proc uuidToString*(uuid: uint32): string =
|
||||
return uuid.toHex(8)
|
||||
|
||||
proc toString*(data: seq[byte]): string =
|
||||
result = newString(data.len)
|
||||
for i, b in data:
|
||||
result[i] = char(b)
|
||||
|
||||
proc toBytes*(data: string): seq[byte] =
|
||||
result = newSeq[byte](data.len)
|
||||
for i, c in data:
|
||||
result[i] = byte(c.ord)
|
||||
|
||||
proc toUint32*(data: seq[byte]): uint32 =
|
||||
if data.len != 4:
|
||||
raise newException(ValueError, "Expected 4 bytes for uint32")
|
||||
|
||||
return uint32(data[0]) or
|
||||
(uint32(data[1]) shl 8) or
|
||||
(uint32(data[2]) shl 16) or
|
||||
(uint32(data[3]) shl 24)
|
||||
|
||||
proc toHexDump*(data: seq[byte]): string =
|
||||
for i, b in data:
|
||||
result.add(b.toHex(2))
|
||||
if i < data.len - 1:
|
||||
if (i + 1) mod 4 == 0:
|
||||
result.add(" | ") # Add | every 4 bytes
|
||||
else:
|
||||
result.add(" ") # Regular space
|
||||
|
||||
proc toBytes*(value: uint16): seq[byte] =
|
||||
return @[
|
||||
byte(value and 0xFF),
|
||||
byte((value shr 8) and 0xFF)
|
||||
]
|
||||
|
||||
proc toBytes*(value: uint32): seq[byte] =
|
||||
return @[
|
||||
byte(value and 0xFF),
|
||||
byte((value shr 8) and 0xFF),
|
||||
byte((value shr 16) and 0xFF),
|
||||
byte((value shr 24) and 0xFF)
|
||||
]
|
||||
Reference in New Issue
Block a user