AdaptixC2 Konfigurasieâuittrekking en TTPs
Reading time: 8 minutes
tip
Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
AdaptixC2 is 'n modulaire, openâsource postâexploitation/C2 framework met Windows x86/x64 beacons (EXE/DLL/service EXE/raw shellcode) en BOF support. Hierdie blad dokumenteer:
- Hoe sy RC4âgepakte konfigurasie ingebed is en hoe om dit uit beacons te onttrek
- Netwerk-/profielâindikators vir HTTP/SMB/TCPâluisteraars
- Algemene loader- en persistentieâTTPs wat in die veld waargeneem is, met skakels na relevante Windows tegniekbladsye
Beaconâprofiele en velde
AdaptixC2 ondersteun drie primĂȘre beaconâtipes:
- BEACON_HTTP: web C2 met konfigureerbare servers/poorte/SSL, method, URI, headers, userâagent, en 'n persoonlike parameternaam
- BEACON_SMB: namedâpipe peerâtoâpeer C2 (intranet)
- BEACON_TCP: direkte sockets, opsioneel met 'n voorafgevoegde merker om die protokolâbegin te obfuskeer
Tipiese profielvelde waargeneem in HTTP beaconâkonfigurasies (na ontsleuteling):
- agent_type (u32)
- use_ssl (bool)
- servers_count (u32), servers (array of strings), ports (array of u32)
- http_method, uri, parameter, user_agent, http_headers (lengthâprefixed strings)
- ans_pre_size (u32), ans_size (u32) â used to parse response sizes
- kill_date (u32), working_time (u32)
- sleep_delay (u32), jitter_delay (u32)
- listener_type (u32)
- download_chunk_size (u32)
Example default HTTP profile (from a beacon build):
{
"agent_type": 3192652105,
"use_ssl": true,
"servers_count": 1,
"servers": ["172.16.196.1"],
"ports": [4443],
"http_method": "POST",
"uri": "/uri.php",
"parameter": "X-Beacon-Id",
"user_agent": "Mozilla/5.0 (Windows NT 6.2; rv:20.0) Gecko/20121202 Firefox/20.0",
"http_headers": "\r\n",
"ans_pre_size": 26,
"ans_size": 47,
"kill_date": 0,
"working_time": 0,
"sleep_delay": 2,
"jitter_delay": 0,
"listener_type": 0,
"download_chunk_size": 102400
}
Waargenome kwaadwillige HTTP-profiel (werklike aanval):
{
"agent_type": 3192652105,
"use_ssl": true,
"servers_count": 1,
"servers": ["tech-system[.]online"],
"ports": [443],
"http_method": "POST",
"uri": "/endpoint/api",
"parameter": "X-App-Id",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.6167.160 Safari/537.36",
"http_headers": "\r\n",
"ans_pre_size": 26,
"ans_size": 47,
"kill_date": 0,
"working_time": 0,
"sleep_delay": 4,
"jitter_delay": 0,
"listener_type": 0,
"download_chunk_size": 102400
}
Versleutelde konfigurasieâverpakking en laaipad
Wanneer die operator op Create in die builder klik, inkorporeer AdaptixC2 die versleutelde profiel as 'n tail blob in die beacon. Die formaat is:
- 4 bytes: configuration size (uint32, littleâendian)
- N bytes: RC4âencrypted configuration data
- 16 bytes: RC4 key
Die beacon loader kopieer die 16âbyte key vanaf die einde en RC4âdecrypts die Nâbyte blok in plek:
ULONG profileSize = packer->Unpack32();
this->encrypt_key = (PBYTE) MemAllocLocal(16);
memcpy(this->encrypt_key, packer->data() + 4 + profileSize, 16);
DecryptRC4(packer->data()+4, profileSize, this->encrypt_key, 16);
Praktiese implikasies:
- Die hele struktuur woon dikwels binne die PE .rdata-seksie.
- Onttrekking is deterministies: lees size, lees die ciphertext van daardie grootte, lees die 16âbyte key wat onmiddellik daarna geplaas is, en dan RC4âdecrypt.
Konfigurasie-onttrekking werkvloei (verdedigers)
Skryf 'n onttrekker wat die beacon logika naboots:
- Lokaliseer die blob binne die PE (gewoonlik .rdata). 'n Pragmatiese benadering is om .rdata te deursoek vir 'n plausibele [size|ciphertext|16âbyte key] uitleg en probeer RC4.
- Lees die eerste 4 bytes â size (uint32 LE).
- Lees die volgende N=size bytes â ciphertext.
- Lees die finale 16 bytes â RC4 key.
- RC4âdecrypt die ciphertext. Parse dan die plain profile soos:
- u32/boolean scalars soos hierbo vermeld
- lengthâprefixed strings (u32 length followed by bytes; trailing NUL can be present)
- arrays: servers_count gevolg deur daardie aantal [string, u32 port] pare
Minimal Python proofâofâconcept (standalone, geen eksterne afhanklikhede) wat werk met 'n vooraf-onttrekte blob:
import struct
from typing import List, Tuple
def rc4(key: bytes, data: bytes) -> bytes:
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % len(key)]) & 0xFF
S[i], S[j] = S[j], S[i]
i = j = 0
out = bytearray()
for b in data:
i = (i + 1) & 0xFF
j = (j + S[i]) & 0xFF
S[i], S[j] = S[j], S[i]
K = S[(S[i] + S[j]) & 0xFF]
out.append(b ^ K)
return bytes(out)
class P:
def __init__(self, buf: bytes):
self.b = buf; self.o = 0
def u32(self) -> int:
v = struct.unpack_from('<I', self.b, self.o)[0]; self.o += 4; return v
def u8(self) -> int:
v = self.b[self.o]; self.o += 1; return v
def s(self) -> str:
L = self.u32(); s = self.b[self.o:self.o+L]; self.o += L
return s[:-1].decode('utf-8','replace') if L and s[-1] == 0 else s.decode('utf-8','replace')
def parse_http_cfg(plain: bytes) -> dict:
p = P(plain)
cfg = {}
cfg['agent_type'] = p.u32()
cfg['use_ssl'] = bool(p.u8())
n = p.u32()
cfg['servers'] = []
cfg['ports'] = []
for _ in range(n):
cfg['servers'].append(p.s())
cfg['ports'].append(p.u32())
cfg['http_method'] = p.s()
cfg['uri'] = p.s()
cfg['parameter'] = p.s()
cfg['user_agent'] = p.s()
cfg['http_headers'] = p.s()
cfg['ans_pre_size'] = p.u32()
cfg['ans_size'] = p.u32() + cfg['ans_pre_size']
cfg['kill_date'] = p.u32()
cfg['working_time'] = p.u32()
cfg['sleep_delay'] = p.u32()
cfg['jitter_delay'] = p.u32()
cfg['listener_type'] = 0
cfg['download_chunk_size'] = 0x19000
return cfg
# Usage (when you have [size|ciphertext|key] bytes):
# blob = open('blob.bin','rb').read()
# size = struct.unpack_from('<I', blob, 0)[0]
# ct = blob[4:4+size]
# key = blob[4+size:4+size+16]
# pt = rc4(key, ct)
# cfg = parse_http_cfg(pt)
Tips:
- When automating, use a PE parser to read .rdata then apply a skuiwende venster: for each offset o, try size = u32(.rdata[o:o+4]), ct = .rdata[o+4:o+4+size], candidate key = next 16 bytes; RC4âdecrypt and check that string fields decode as UTFâ8 and lengths are sane.
- Ontleed SMB/TCPâprofiele deur dieselfde lengteâvoorafgeplakte konvensies te volg.
Network fingerprinting and hunting
HTTP
- Common: POST to operatorâselected URIs (e.g., /uri.php, /endpoint/api)
- Pasgemaakte headerâparameter gebruik vir beacon ID (e.g., XâBeaconâId, XâAppâId)
- Userâagents mimicking Firefox 20 or contemporary Chrome builds
- Pollingâkadens sigbaar via sleep_delay/jitter_delay
SMB/TCP
- SMB namedâpipe listeners vir intranet C2 waar web egress beperk is
- TCP beacons kan 'n paar bytes voor verkeer vooraan sit om protocolbegin te obfuskeer
Loader and persistence TTPs seen in incidents
Inâmemory PowerShell loaders
- Laai Base64/XOR payloads af (InvokeâRestMethod / WebClient)
- Allocate unmanaged memory, copy shellcode, switch protection to 0x40 (PAGE_EXECUTE_READWRITE) via VirtualProtect
- Execute via .NET dynamic invocation: Marshal.GetDelegateForFunctionPointer + delegate.Invoke()
Check these pages for inâmemory execution and AMSI/ETW considerations:
Persistence mechanisms observed
- Startup folder shortcut (.lnk) to reâlaunch a loader at logon
- Registry Run keys (HKCU/HKLM ...\CurrentVersion\Run), often with benignâsounding names like "Updater" to start loader.ps1
- DLL searchâorder hijack by dropping msimg32.dll under %APPDATA%\Microsoft\Windows\Templates for susceptible processes
Technique deepâdives and checks:
Privilege Escalation with Autoruns
Hunting ideas
- PowerShell spawning RWâRX transitions: VirtualProtect to PAGE_EXECUTE_READWRITE inside powershell.exe
- Dynamic invocation patterns (GetDelegateForFunctionPointer)
- Startup .lnk under user or common Startup folders
- Suspicious Run keys (e.g., "Updater"), and loader names like update.ps1/loader.ps1
- Userâwritable DLL paths under %APPDATA%\Microsoft\Windows\Templates containing msimg32.dll
Notes on OpSec fields
- KillDate: timestamp after which the agent selfâexpires
- WorkingTime: hours when the agent should be active to blend with business activity
These fields can be used for clustering and to explain observed quiet periods.
YARA and static leads
Unit 42 published basic YARA for beacons (C/C++ and Go) and loader APIâhashing constants. Consider complementing with rules that look for the [size|ciphertext|16âbyteâkey] layout near PE .rdata end and the default HTTP profile strings.
References
- AdaptixC2: A New Open-Source Framework Leveraged in Real-World Attacks (Unit 42)
- AdaptixC2 GitHub
- Adaptix Framework Docs
- Marshal.GetDelegateForFunctionPointer â Microsoft Docs
- VirtualProtect â Microsoft Docs
- Memory protection constants â Microsoft Docs
- Invoke-RestMethod â PowerShell
- MITRE ATT&CK T1547.001 â Registry Run Keys/Startup Folder
tip
Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.