Profile Management
Upload, manage, and deploy malleable profiles using the nexus-api.py CLI tool.
Overview
Profiles can be added to a running NexusC2 server without restarting. This enables:
- Rapid iteration during profile development
- Deploying new traffic patterns without downtime
- Automation and scripting of profile management
For profile structure and transform reference, see Malleable Profiles.
The nexus-api.py Script
NexusC2 includes a comprehensive CLI tool for API interaction at scripts/nexus-api.py. This is the recommended way to interact with profiles programmatically.
Setup
# Create and activate a virtual environment (recommended)
cd scripts
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install requests
# Login with certificate (credentials saved to ~/.nexus_api_env)
./nexus-api.py --cert ../server/certs/api_server.crt login -u operator1
# Or set certificate path via environment variable
export NEXUS_API_CERT="../server/certs/api_server.crt"
./nexus-api.py login -u operator1
Getting the Templates
Download the profile template to start customizing:
./nexus-api.py profiles template -o my-profiles.toml
Templates are available at:
- HTTP profiles:
server/docker/templates/listener_template.toml - SMB profiles:
server/docker/templates/smb_profile_template.toml - Test profiles:
server/docker/templates/listener_test_transforms.toml
Creating Custom Profiles
HTTP Profiles
HTTP profiles use TOML format with three coordinated profile types:
# GET Profile - How agents poll for commands
[[http_profiles.get]]
name = "custom-get"
path = "/api/status"
method = "GET"
[http_profiles.get.client_id]
output = "header:X-Session-ID"
[[http_profiles.get.client_id.transforms]]
type = "base64url"
# POST Profile - How agents send results
[[http_profiles.post]]
name = "custom-post"
path = "/api/submit"
method = "POST"
content_type = "application/json"
[http_profiles.post.client_id]
output = "header:X-Session-ID"
[[http_profiles.post.client_id.transforms]]
type = "base64url"
[http_profiles.post.data]
output = "body"
[[http_profiles.post.data.transforms]]
type = "gzip"
[[http_profiles.post.data.transforms]]
type = "base64"
# Server Response Profile - How server responds
[[http_profiles.server_response]]
name = "custom-response"
content_type = "application/json"
[http_profiles.server_response.data]
output = "body"
[[http_profiles.server_response.data.transforms]]
type = "base64"
For complete examples, see Profile Examples.
SMB Profiles
SMB profiles define named pipe traffic obfuscation for lateral movement:
# SMB Profile - Named pipe traffic transforms
[[smb_link.profiles]]
name = "custom-smb"
[smb_link.profiles.data]
output = "body"
[[smb_link.profiles.data.transforms]]
type = "gzip"
[[smb_link.profiles.data.transforms]]
type = "xor"
value = "my_custom_key" # Auto-replaced with per-build unique key
[[smb_link.profiles.data.transforms]]
type = "prepend"
value = "\u0005\u0000\u0000\u0003" # DCE/RPC header mimicry
For SMB profile examples mimicking Windows services, see SMB Transforms.
Uploading Profiles
Via nexus-api.py
# Upload HTTP profiles
./nexus-api.py profiles upload my-profiles.toml
# Upload SMB profiles
./nexus-api.py profiles upload server/docker/templates/smb_profile_template.toml
Output (success):
Status: success
Message: Successfully added 4 profile(s)
GET profiles added:
+ custom-get
POST profiles added:
+ custom-post
Server Response profiles added:
+ custom-response
SMB profiles added:
+ custom-smb
Output (partial success with errors):
Status: partial
Message: Some profiles added with errors
GET profiles added:
+ custom-get
SMB profiles added:
+ custom-smb
Errors:
! POST profile 'custom-post': path is required
Via GUI Client
- Navigate to Tools > Upload Profiles
- Select your
.tomlfile - Review the upload confirmation showing added profiles
- New profiles appear immediately in listener creation dropdowns
Validation
Profiles are validated before being added:
| Profile Type | Required Fields |
|---|---|
| GET | name, path |
| POST | name, path |
| Server Response | name |
| SMB | name |
Additional validations:
- Duplicate names are rejected
- Invalid transform types are rejected
- HTTP params must have
name,location, andtype - SMB transforms must use valid types:
base64,base64url,hex,gzip,netbios,xor,prepend,append,random_prepend,random_append
Synchronization
When profiles are uploaded:
- Validation - TOML parsed, profiles validated
- Config Update - Profiles added to in-memory configuration
- Service Sync - Agent-handler receives profiles via gRPC
- Client Broadcast - All connected clients notified of new profiles
New profiles are immediately available for:
- Creating new listeners
- Building new payloads
Note: Existing listeners and deployed payloads continue using their compiled profiles.
Managing Profiles
List Profiles
List all profiles (HTTP and SMB):
./nexus-api.py profiles list
List specific HTTP profile types:
./nexus-api.py profiles list-get
./nexus-api.py profiles list-post
./nexus-api.py profiles list-response
List profile names only (includes SMB):
./nexus-api.py profiles names
Example output:
GET Profiles:
- default-get
- microsoft-graph-get
POST Profiles:
- default-post
- microsoft-graph-post
Server Response Profiles:
- default-response
- microsoft-graph-response
SMB Profiles:
- default-smb
- spoolss-profile
- srvsvc-profile
Get Profile Details
./nexus-api.py profiles get get custom-get
./nexus-api.py profiles get post custom-post
./nexus-api.py profiles get response custom-response
Delete a Profile
./nexus-api.py profiles delete get custom-get
./nexus-api.py profiles delete post custom-post
./nexus-api.py profiles delete response custom-response
Creating Listeners with Custom Profiles
After uploading profiles, bind them to a listener:
HTTPS Listener with HTTP Profiles:
./nexus-api.py listeners create \
-n my-https-listener \
-P HTTPS \
-p 443 \
--get-profile custom-get \
--post-profile custom-post \
--response-profile custom-response
SMB Listener with SMB Profile:
./nexus-api.py listeners create \
-n my-smb-listener \
-P SMB \
--pipe-name spoolss \
--smb-profile spoolss-profile
Best Practices
- Use consistent naming - Name related profiles similarly (e.g.,
linkedin-get,linkedin-post,linkedin-response) - Test transforms locally - Verify encoding/decoding works before deploying
- Coordinate profile sets - GET, POST, and Response profiles should use compatible transforms
- Version your profiles - Keep profile TOML files in version control
- Document custom profiles - Note the purpose and traffic pattern being mimicked
nexus-api.py Reference
For complete API documentation, see the script help:
./nexus-api.py --help
./nexus-api.py profiles --help
Environment variables supported:
NEXUS_API_URL- API base URL (default: https://localhost:8443)NEXUS_API_TOKEN- JWT access token (saved after login)NEXUS_API_CERT- Path to server certificate for TLS verification
Related Documentation
- Malleable Profiles - HTTP profile structure and transforms
- SMB Transforms - SMB profile structure and Windows pipe mimicry
- Profile Examples - Complete HTTP profile examples
- API Documentation - REST API reference