Plugin de transporte C2 serverless para AdaptixC2 v1.2 usando AWS Lambda + DynamoDB como infraestrutura de relay.

Plugin de transporte C2 serverless para AdaptixC2 v1.2 usando AWS Lambda + DynamoDB como infraestrutura de retransmissão. O tráfego do agente aparece como HTTPS de saída para endpoints da AWS, não exigindo portas de entrada nem IPs públicos no servidor 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
Fluxo de dados:
inbound do DynamoDBoutbound por até 8 segundos (preenche a lacuna assíncrona para registro)inbound do DynamoDB em busca de registros não processadosoutbound| Componente | Caminho | Finalidade |
|---|---|---|
| Agente Kharon | agent/ | Implante Kharon incluído (código-fonte C++) |
| Terraform | deploy/aws/ | Infraestrutura Lambda + DynamoDB + IAM + KMS |
| Relay Lambda | deploy/aws/lambda/ | Proxy stateless HTTP-para-DynamoDB com polling de saída |
| Plugin listener | listener/ | Plugin AdaptixC2, polling DynamoDB, ponte de protocolo Kharon |
| Configurações Kharon | kharon/ | Registro de comandos AXS e configuração para extensores de agente/listener |
| Patches | patches/ | Patches do código-fonte do AdaptixC2 para suporte a BeaconServerless |
| Perfis | profiles/ | Perfil HTTP malleable para Lambda URL |
| Scripts | scripts/ | Instalação, build, deploy, desinstalação |
aws configure)apt install clang lldapt install nasmapt install binutils-mingw-w64-x86-64No Console da 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
Verifique:
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
Este script irá:
dist/ (certificados, banco de dados, perfil)GOEXPERIMENT do binário do servidor.so) com as flags correspondentesBeaconServerlessrelay_api_key no seu 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 | Descrição | Padrão |
|---|---|---|
| AWS Region | Região onde a infraestrutura está implantada | us-east-1 |
| Lambda URL | Function URL da saída do Terraform | (obrigatório) |
| Relay API Key | Deve corresponder ao relay_api_key do Terraform | (opcional) |
| Inbound Table | Tabela DynamoDB para check-ins do agente | adaptix-inbound |
| Outbound Table | Tabela DynamoDB para respostas do servidor | adaptix-outbound |
| Poll Interval | Com que frequência verificar o DynamoDB (segundos) | 5 |
| TTL Hours | Expiração dos registros do DynamoDB | 24 |
O agente Kharon usa um protocolo binário customizado sobre HTTP:
[36-byte UUID][encrypted_checkin_data][16-byte LokyCrypt key][36-byte UUID][encrypted_payload] (sem chave no final)TotalLen-16 se sobrepõe à área do UUID. Para um pacote de 44 bytes, a chave começa no offset 28, sobrescrevendo os bytes 28-35 do UUID e todos os dados criptografados.O listener detecta todos os três formatos e os trata corretamente.
A natureza assíncrona do Lambda + DynamoDB significa que o listener ainda não processou o registro inbound quando a Lambda verifica pela primeira vez uma resposta. A Lambda consulta a tabela outbound por até 8 segundos após armazenar um registro inbound, dando tempo ao listener para processar e enfileirar a resposta. Isso é crítico para o registro (a resposta de Checkin deve chegar durante a fase de Checkin, não em um GetTask posterior).
As chaves de criptografia do agente são persistidas via TsExtenderDataSave/TsExtenderDataLoad (com suporte SQLite). Isso sobrevive a reinicializações do serviço. Ao reiniciar, o listener recupera as chaves do armazenamento persistente quando encontra um ID de agente conhecido.