Files
conquest/src/common/types.nim

383 lines
12 KiB
Nim

import tables
import parsetoml, json
import system
import mummy
when defined(client):
import whisky
# Custom Binary Task structure
const
MAGIC* = 0x514E3043'u32 # Magic value: C0NQ
VERSION* = 1'u8 # Version 1
HEADER_SIZE* = 48'u8 # 48 bytes fixed packet header size
type
PacketType* = enum
MSG_TASK = 0'u8
MSG_RESULT = 1'u8
MSG_REGISTER = 2'u8
MSG_HEARTBEAT = 100'u8
ArgType* = enum
STRING = 0'u8
INT = 1'u8
SHORT = 2'u8
LONG = 3'u8
BOOL = 4'u8
BINARY = 5'u8
HeaderFlags* = enum
# Flags should be powers of 2 so they can be connected with or operators
FLAG_PLAINTEXT = 0'u16
FLAG_ENCRYPTED = 1'u16
FLAG_COMPRESSED = 2'u16
FLAG_FRAGMENTED = 4'u16
CommandType* = enum
CMD_SLEEP = 0'u16
CMD_SHELL = 1'u16
CMD_PWD = 2'u16
CMD_CD = 3'u16
CMD_LS = 4'u16
CMD_RM = 5'u16
CMD_RMDIR = 6'u16
CMD_MOVE = 7'u16
CMD_COPY = 8'u16
CMD_PS = 9'u16
CMD_ENV = 10'u16
CMD_WHOAMI = 11'u16
CMD_BOF = 12'u16
CMD_DOWNLOAD = 13'u16
CMD_UPLOAD = 14'u16
CMD_SCREENSHOT = 15'u16
CMD_DOTNET = 16'u16
CMD_SLEEPMASK = 17'u16
CMD_MAKE_TOKEN = 18'u16
CMD_STEAL_TOKEN = 19'u16
CMD_REV2SELF = 20'u16
CMD_TOKEN_INFO = 21'u16
CMD_ENABLE_PRIV = 22'u16
CMD_DISABLE_PRIV = 23'u16
CMD_EXIT = 24'u16
CMD_SELF_DESTRUCT = 25'u16
StatusType* = enum
STATUS_COMPLETED = 0'u8
STATUS_FAILED = 1'u8
STATUS_IN_PROGRESS = 2'u8
ResultType* = enum
RESULT_STRING = 0'u8
RESULT_BINARY = 1'u8
RESULT_NO_OUTPUT = 2'u8
LogType* {.size: sizeof(uint8).} = enum
LOG_INFO = "[INFO] "
LOG_ERROR = "[FAIL] "
LOG_SUCCESS = "[DONE] "
LOG_WARNING = "[WARN] "
LOG_COMMAND = "[>>>>] "
LOG_OUTPUT = ""
LOG_INFO_SHORT = "[*] "
LOG_ERROR_SHORT = "[-] "
LOG_SUCCESS_SHORT = "[+] "
LOG_WARNING_SHORT = "[!] "
SleepObfuscationTechnique* = enum
NONE = 0'u8
EKKO = 1'u8
ZILEAN = 2'u8
FOLIAGE = 3'u8
ExitType* {.size: sizeof(uint8).} = enum
EXIT_PROCESS = "process"
EXIT_THREAD = "thread"
ModuleType* = enum
MODULE_ALL = 0'u32
MODULE_SLEEP = 1'u32
MODULE_SHELL = 2'u32
MODULE_BOF = 4'u32
MODULE_DOTNET = 8'u32
MODULE_FILESYSTEM = 16'u32
MODULE_FILETRANSFER = 32'u32
MODULE_SCREENSHOT = 64'u32
MODULE_SITUATIONAL_AWARENESS = 128'u32
MODULE_TOKEN = 256'u32
# Encryption
type
Uuid* = uint32
Bytes* = seq[byte]
Key* = array[32, byte]
Iv* = array[12, byte]
AuthenticationTag* = array[16, byte]
KeyRC4* = array[16, byte]
# Packet structure
type
Header* = object
magic*: uint32 # [4 bytes ] magic value
version*: uint8 # [1 byte ] protocol version
packetType*: uint8 # [1 byte ] message type
flags*: uint16 # [2 bytes ] message flags
size*: uint32 # [4 bytes ] size of the payload body
agentId*: Uuid # [4 bytes ] agent id, used as AAD for encryption
seqNr*: uint32 # [4 bytes ] sequence number, used as AAD for encryption
iv*: Iv # [12 bytes] random IV for AES256 GCM encryption
gmac*: AuthenticationTag # [16 bytes] authentication tag for AES256 GCM encryption
TaskArg* = object
argType*: uint8 # [1 byte ] argument type
data*: seq[byte] # variable length data (for variable data types (STRING, BINARY), the first 4 bytes indicate data length)
Task* = object
header*: Header
taskId*: Uuid # [4 bytes ] task id
listenerId*: Uuid # [4 bytes ] listener id
timestamp*: uint32 # [4 bytes ] unix timestamp
command*: uint16 # [2 bytes ] command id
argCount*: uint8 # [1 byte ] number of arguments
args*: seq[TaskArg] # variable length arguments
TaskResult* = object
header*: Header
taskId*: Uuid # [4 bytes ] task id
listenerId*: Uuid # [4 bytes ] listener id
timestamp*: uint32 # [4 bytes ] unix timestamp
command*: uint16 # [2 bytes ] command id
status*: uint8 # [1 byte ] success flag
resultType*: uint8 # [1 byte ] result data type (string, binary)
length*: uint32 # [4 bytes ] result length
data*: seq[byte] # variable length result
# Checkin binary structure
type
Heartbeat* = object
header*: Header # [48 bytes ] fixed header
listenerId*: Uuid # [4 bytes ] listener id
timestamp*: uint32 # [4 bytes ] unix timestamp
# Registration binary structure
type
# All variable length fields are stored as seq[byte], prefixed with 4 bytes indicating the length of the following data
AgentMetadata* = object
listenerId*: Uuid
username*: seq[byte]
hostname*: seq[byte]
domain*: seq[byte]
ip*: seq[byte]
os*: seq[byte]
process*: seq[byte]
pid*: uint32
isElevated*: uint8
sleep*: uint32
jitter*: uint32
modules*: uint32
Registration* = object
header*: Header
agentPublicKey*: Key # [32 bytes ] Public key of the connecting agent for key exchange
metadata*: AgentMetadata
# Agent structure
type
Agent* = ref object
agentId*: string
listenerId*: string
username*: string
impersonationToken*: string
hostname*: string
domain*: string
ipInternal*: string
ipExternal*: string
os*: string
process*: string
pid*: int
elevated*: bool
sleep*: int
jitter*: int
tasks*: seq[Task]
modules*: uint32
firstCheckin*: int64
latestCheckin*: int64
sessionKey*: Key
# Session entry for client UI
UIAgent* = ref object
agentId*: string
listenerId*: string
username*: string
impersonationToken*: string
hostname*: string
domain*: string
ipInternal*: string
ipExternal*: string
os*: string
process*: string
pid*: int
elevated*: bool
sleep*: int
jitter*: int
modules*: uint32
firstCheckin*: int64
latestCheckin*: int64
# Listener structure
type
Protocol* {.size: sizeof(uint8).} = enum
HTTP = "http"
Listener* = ref object
server*: Server
listenerId*: string
hosts*: string
address*: string
port*: int
protocol*: Protocol
UIListener* = ref object
listenerId*: string
hosts*: string
address*: string
port*: int
protocol*: Protocol
#[
Client <-> Server WebSocket communication
]#
type
EventType* = enum
CLIENT_HEARTBEAT = 0'u8 # Basic checkin
CLIENT_KEY_EXCHANGE = 200'u8 # Unencrypted public key sent by both parties for key exchange
# Sent by client
CLIENT_AGENT_BUILD = 1'u8 # Generate an agent binary for a specific listener
CLIENT_AGENT_TASK = 2'u8 # Instruct TS to send queue a command for a specific agent
CLIENT_LISTENER_START = 3'u8 # Start a listener on the TS
CLIENT_LISTENER_STOP = 4'u8 # Stop a listener
CLIENT_LOOT_REMOVE = 5'u8 # Remove loot on the team server
CLIENT_LOOT_GET = 6'u8 # Request file/screenshot from the team server for preview or download
CLIENT_AGENT_REMOVE = 7'u8 # Delete agent from the team server database
# Sent by team server
CLIENT_PROFILE = 100'u8 # Team server profile and configuration
CLIENT_LISTENER_ADD = 101'u8 # Add listener to listeners table
CLIENT_AGENT_ADD = 102'u8 # Add agent to sessions table
CLIENT_AGENT_CHECKIN = 103'u8 # Update agent checkin
CLIENT_AGENT_PAYLOAD = 104'u8 # Return agent payload binary
CLIENT_CONSOLE_ITEM = 105'u8 # Add entry to a agent's console
CLIENT_EVENTLOG_ITEM = 106'u8 # Add entry to the eventlog
CLIENT_BUILDLOG_ITEM = 107'u8 # Add entry to the build log
CLIENT_LOOT_ADD = 108'u8 # Add file or screenshot stored on the team server to preview on the client, only sends metadata and not the actual file content
CLIENT_LOOT_DATA = 109'u8 # Send file/screenshot bytes to the client to display as preview or to download to the client desktop
CLIENT_IMPERSONATE_TOKEN = 110'u8 # Access token impersonated
CLIENT_REVERT_TOKEN = 111'u8 # Revert to original logon session
Event* = object
eventType*: EventType
timestamp*: int64
data*: JsonNode
# Context structures
type
KeyPair* = object
privateKey*: Key
publicKey*: Key
Profile* = TomlValueRef
WsConnection* = ref object
when defined(server):
ws*: mummy.WebSocket
when defined(client):
ws*: whisky.WebSocket
sessionKey*: Key
Conquest* = ref object
dbPath*: string
listeners*: Table[string, Listener]
threads*: Table[string, Thread[Listener]]
agents*: Table[string, Agent]
keyPair*: KeyPair
profile*: Profile
client*: WsConnection
WorkingHours* = ref object
enabled*: bool
startHour*: int32
startMinute*: int32
endHour*: int32
endMinute*: int32
SleepSettings* = ref object
sleepDelay*: uint32
jitter*: uint32
sleepTechnique*: SleepObfuscationTechnique
spoofStack*: bool
workingHours*: WorkingHours
AgentCtx* = ref object
agentId*: string
listenerId*: string
hosts*: string
sleepSettings*: SleepSettings
killDate*: int64
sessionKey*: Key
agentPublicKey*: Key
profile*: Profile
registered*: bool
# Structure for command module definitions
type
Argument* = object
name*: string
description*: string
argumentType*: ArgType
isRequired*: bool
Command* = object
name*: string
commandType*: CommandType
description*: string
example*: string
arguments*: seq[Argument]
dispatchMessage*: string
execute*: proc(config: AgentCtx, task: Task): TaskResult {.nimcall.}
Module* = object
name*: string
description*: string
moduleType*: ModuleType
commands*: seq[Command]
# Definitions for ImGui User interface
type
ConsoleItem* = ref object
itemType*: LogType
timestamp*: string
text*: string
ConsoleItems* = ref object
items*: seq[ConsoleItem]
AgentBuildInformation* = ref object
listenerId*: string
sleepSettings*: SleepSettings
verbose*: bool
killDate*: int64
modules*: uint32
LootItemType* = enum
DOWNLOAD = 0'u8
SCREENSHOT = 1'u8
LootItem* = ref object
itemType*: LootItemType
lootId*: string
agentId*: string
host*: string
path*: string
timestamp*: int64
size*: int