Plugin di trasporto C2 serverless per AdaptixC2 v1.2 che utilizza AWS Lambda + DynamoDB come infrastruttura di relay.

Plugin di trasporto C2 serverless per AdaptixC2 v1.2 che utilizza AWS Lambda + DynamoDB come infrastruttura di relay. Il traffico dell'agente appare come HTTPS in uscita verso endpoint AWS, senza richiedere porte in ingresso o IP pubblici sul server C2.
Kharon Agent (target)
|
| HTTPS GET/POST (outbound only, randomly alternated)
v
AWS Lambda Function URL (stateless relay)
|
| Store inbound / Poll outbound (up to 8s)
v
DynamoDB (inbound + outbound tables)
^
| Poll every 5 seconds
|
Listener Plugin (inside AdaptixC2)
|
| TsAgent API + TsExtenderData (key persistence)
v
AdaptixC2 Teamserver + UI
Flusso dei dati:
inbound di DynamoDBoutbound per un massimo di 8 secondi (colma il gap asincrono per la registrazione)inbound di DynamoDB per i record non elaboratioutbound| Componente | Percorso | Scopo |
|---|---|---|
| Agente Kharon | agent/ | Implant Kharon incluso (sorgente C++) |
| Terraform | deploy/aws/ | Infrastruttura Lambda + DynamoDB + IAM + KMS |
| Relay Lambda | deploy/aws/lambda/ | Proxy stateless HTTP-to-DynamoDB con polling outbound |
| Plugin listener | listener/ | Plugin AdaptixC2, polling DynamoDB, bridge protocollo Kharon |
| Configurazioni Kharon | kharon/ | Registrazione comandi AXS e configurazione per extender agente/listener |
| Patch | patches/ | Patch del sorgente AdaptixC2 per il supporto BeaconServerless |
| Profili | profiles/ | Profilo HTTP malleable per Lambda URL |
| Script | scripts/ | Installazione, build, deploy, disinstallazione |
aws configure)apt install clang lldapt install nasmapt install binutils-mingw-w64-x86-64Nella Console AWS:
adaptix-deployerAmazonDynamoDBFullAccessAWSLambda_FullAccessIAMFullAccessCloudWatchLogsFullAccess{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"kms:*","Resource":"*"}]}KMSFullAccessaws configure
# AWS Access Key ID: <paste access key>
# AWS Secret Access Key: <paste secret key>
# Default region: us-east-1
# Default output format: json
Verifica:
aws sts get-caller-identity
# Build the Lambda relay binary (cross-compiled for Amazon Linux)
./scripts/build_relay.sh
# Deploy Lambda + DynamoDB + IAM with Terraform
./scripts/deploy_infra.sh
# Note the Lambda Function URL from the output, e.g.:
# lambda_function_url = "https://xxxxx.lambda-url.us-east-1.on.aws"
./scripts/install.sh /path/to/AdaptixC2
Questo script:
dist/ (certificati, database, profilo)GOEXPERIMENT dal binario del server.so) con i flag corrispondentiBeaconServerlessrelay_api_key nel tuo terraform.tfvars)profiles/lambda_default.jsonBeaconServerlessdeploy/aws/terraform.tfvars)region = "us-east-1"
function_name = "adaptix-relay"
relay_api_key = "your-secret-key-here"
tags = {
Project = "adaptix-serverless"
}
| Campo | Descrizione | Default |
|---|---|---|
| AWS Region | Regione in cui è distribuita l'infrastruttura | us-east-1 |
| Lambda URL | Function URL dall'output di Terraform | (obbligatorio) |
| Relay API Key | Deve corrispondere a relay_api_key di Terraform | (opzionale) |
| Inbound Table | Tabella DynamoDB per i check-in degli agenti | adaptix-inbound |
| Outbound Table | Tabella DynamoDB per le risposte del server | adaptix-outbound |
| Poll Interval | Frequenza di controllo di DynamoDB (secondi) | 5 |
| TTL Hours | Scadenza dei record DynamoDB | 24 |
L'agente Kharon utilizza un protocollo binario personalizzato su HTTP:
[36-byte UUID][encrypted_checkin_data][16-byte LokyCrypt key][36-byte UUID][encrypted_payload] (nessuna chiave finale)TotalLen-16 si sovrappone all'area dell'UUID. Per un pacchetto di 44 byte, la chiave inizia all'offset 28, sovrascrivendo i byte 28-35 dell'UUID e tutti i dati cifrati.Il listener rileva tutti e tre i formati e li gestisce correttamente.
La natura asincrona di Lambda + DynamoDB significa che il listener non ha ancora elaborato il record inbound quando Lambda controlla per la prima volta la presenza di una risposta. Lambda esegue il polling della tabella outbound per un massimo di 8 secondi dopo aver memorizzato un record inbound, dando al listener il tempo di elaborare e accodare la risposta. Questo è critico per la registrazione (la risposta di Checkin deve arrivare durante la fase di Checkin, non in un successivo GetTask).