Guide du langage du sommeil¶
Introduction au langage de script Sleep utilisé par le moteur CNA de Stentor : types de données, variables, opérateurs, flux de contrôle, fonctions, fermetures, tableaux, hachages et manipulation de chaînes.
Introduction¶
Le moteur de script de Stentor est construit sur CNA (Cobalt Strike's Aggressor Script), qui utilise le langage de script Sleep comme base. Sleep est un langage de script inspiré de Perl avec une syntaxe de type C, créé à l'origine par Raphael Mudge pour être intégré dans des applications Java.
Stentor implémente un interpréteur de veille complet côté serveur - comprenant un lexeur, un analyseur, un évaluateur et un validateur sémantique - permettant aux opérateurs d'écrire des scripts qui automatisent les opérations, réagissent aux événements de beacon, étendent le jeu de commandes et créent des flux de travail personnalisés. Contrairement à l'interpréteur Java de Cobalt Strike, le moteur CNA de Stentor est écrit en Go, offrant des performances natives et une intégration étroite avec le backend.
Les scripts CNA peuvent :
- Définissez des commandes de beacon personnalisées avec
alias - Réagissez aux événements du cycle de vie des beacons avec
on - Ajoutez des éléments de menu contextuel avec
popup - Remplacer le comportement par défaut avec les hooks
set - Enregistrez les commandes de la console avec
command - Associer les raccourcis clavier avec
bind
Sommeil contre CNA
Sleep est le langage de script de base (types de données, variables, opérateurs, flux de contrôle, fonctions). CNA étend Sleep avec des mots-clés spécifiques à C2 (alias, on, popup, set, command, bind) et des fonctions intégrées (bshell, bps, blog, etc.) pour interagir avec les beacons et la plateforme Stentor. Chaque script CNA est un code Sleep valide, mais tous les codes Sleep n'utilisent pas les fonctionnalités spécifiques à CNA.
Bonjour tout le monde¶
Le script CNA le plus simple imprime un message sur la console de script :
Chargement de votre script¶
Dans la console de script, utilisez la commande load :
Le script est analysé, validé et exécuté immédiatement. Vous devriez voir :
Lorsqu'un script est chargé, le moteur de Stentor effectue trois étapes :
- Parse -- Le lexer tokenise la source et l'analyseur crée un AST
- Valider – L'analyse sémantique vérifie les fonctions non définies et les problèmes variables
- Exécuter – Les exécutions de code de niveau supérieur (comme
println) et les mots-clés CNA (on,alias, etc.) enregistrent leurs gestionnaires
Types de données¶
L'évaluateur de sommeil de Stentor prend en charge les types de données suivants :
Cordes¶
Chaînes entre guillemets doubles avec prise en charge des séquences d'échappement et interpolation variable :
$greeting = "Hello";
$name = "Operator";
$message = "Welcome, $name!"; # interpolation: "Welcome, Operator!"
$path = "C:\\Users\\Public"; # escape: backslash
$multiline = "Line 1\nLine 2"; # escape: newline
Séquences d'échappement prises en charge : \n (nouvelle ligne), \t (tabulation), \\ (barre oblique inverse), \" (guillemet double), \r (retour chariot).
Interpolation de chaîne : Tout $variable à l'intérieur d'une chaîne entre guillemets est remplacé par sa valeur. Utilisez \$ pour inclure un signe dollar littéral. La variable spéciale $+ concatène les valeurs interpolées adjacentes sans espace :
Entiers¶
Entiers signés 64 bits, avec prise en charge des littéraux décimaux et hexadécimaux :
Doubles¶
Nombres à virgule flottante 64 bits :
Longue¶
Entiers explicites de 64 bits (distincts de int dans le système de types) :
Nul¶
La valeur nulle, représentée par $null :
Booléens¶
Valeurs booléennes issues des opérations de comparaison et de prédicat :
Tableaux¶
Listes ordonnées de valeurs, créées avec la syntaxe @(). Les tableaux sont indexés à zéro et peuvent contenir des types mixtes :
Hachages¶
Cartes clé-valeur (dictionnaires), créées avec la syntaxe %(). Les clés sont des chaînes :
Vérification du type
Utilisez la fonction typeof() pour inspecter le type d'une valeur au moment de l'exécution :
```sleep
println(typeof("hello")); # "String"
println(typeof(42)); # "Int"
println(typeof(@())); # "Array"
println(typeof(%())); # "Hash"
```
Des fonctions de prédicat sont également disponibles : `-isarray`, `-ishash`, `-isfunction`, `-isnumber`.
Variables¶
Sleep utilise des noms de variables préfixés par un sigil pour indiquer le type :
Variables scalaires¶
Les variables scalaires commencent par $ et contiennent une seule valeur (chaîne, nombre, valeur nulle, fonction, etc.) :
Variables de tableau¶
Les variables du tableau commencent par @ :
Variables de hachage¶
Les variables de hachage commencent par % :
Portée variable¶
Par défaut, les variables sont globales – accessibles depuis n'importe quelle fonction du script. Utilisez la fonction local() pour déclarer les variables comme locales à la fonction actuelle :
sub processBeacon {
local('$bid $info'); # $bid and $info are local to this function
$bid = $1;
$info = beacon_info($bid);
# $bid and $info are destroyed when this function returns
}
La fonction global() déclare explicitement les variables dans une portée globale (utile dans les fonctions où vous souhaitez garantir un accès global) :
Variables spéciales¶
| Variable | Description |
|---|---|
$1, $2, ... $n | Arguments positionnels des fonctions, alias et gestionnaires d'événements |
$0 | Pour les alias : la chaîne de commande complète (nom + arguments, non analysés) |
@_ | Tableau contenant tous les arguments passés à la fonction actuelle |
$null | La valeur nulle |
sub example {
println("First arg: $1");
println("Second arg: $2");
println("All args: " . join(", ", @_));
}
example("hello", "world");
# Output:
# First arg: hello
# Second arg: world
# All args: hello, world
Opérateurs¶
Opérateurs arithmétiques¶
| Opérateur | Description | Exemple |
|---|---|---|
+ | Ajout | $x = 5 + 3; |
- | Soustraction | $x = 10 - 4; |
* | Multiplication | $x = 6 * 7; |
/ | Division | $x = 20 / 4; |
% | Module | $x = 10 % 3; |
** | Exponentiation | $x = 2 ** 10; |
Espace requis
Sleep nécessite des espaces entre les opérateurs et les opérandes. $x=1+2; n'analysera pas. Écrivez plutôt $x = 1 + 2;.
Concaténation de chaînes¶
L'opérateur point (.) concatène les chaînes :
L'opérateur de répétition de chaîne (x) répète une chaîne :
Comparaison numérique¶
| Opérateur | Description | Exemple |
|---|---|---|
== | Égal | if ($x == 5) |
!= | Pas égal | if ($x != 0) |
< | Moins de | if ($x < 10) |
> | Plus grand que | if ($x > 0) |
<= | Inférieur ou égal | if ($x <= 100) |
>= | Supérieur ou égal | if ($x >= 1) |
Comparaison de chaînes¶
| Opérateur | Description | Exemple |
|---|---|---|
eq | Chaîne égale | if ($s eq "admin") |
ne | Chaîne différente | if ($s ne "") |
lt | Lexicographiquement moins | if ($a lt $b) |
gt | Lexicographiquement plus grand | if ($a gt $b) |
cmp | Comparer (renvoie -1/0/1) | $r = $a cmp $b; |
Opérateurs logiques¶
| Opérateur | Description | Exemple |
|---|---|---|
&& | ET logique (court-circuit) | if ($a && $b) |
\|\| | OU logique (court-circuit) | si ($a \|\| $b) |
! | NON logique | if (!$found) |
Correspondance de motifs¶
| Opérateur | Description | Exemple |
|---|---|---|
iswm | Correspondance générique (* et ?) | if ("admin*" iswm $user) |
ismatch | Correspondance Regex (définit matched()) | if ($str ismatch '(\d+)\.(\d+)') |
isin | Test d'adhésion | if ("key" isin %hash) |
Opérateurs d'affectation¶
| Opérateur | Description |
|---|---|
= | Mission simple |
+= | Ajouter et attribuer |
-= | Soustraire et attribuer |
*= | Multiplier et attribuer |
/= | Diviser et attribuer |
.= | Concaténer et attribuer |
&= | ET au niveau du bit et attribuer |
\|= | OU au niveau du bit et attribuer |
Opérateurs au niveau du bit¶
| Opérateur | Description |
|---|---|
& | ET au niveau du bit |
\| | OU au niveau du bit |
^ | XOR au niveau du bit |
<< | Décalage à gauche |
>> | Décalage à droite |
Flux de contrôle¶
si/sinon si/sinon¶
if ($integrity eq "High") {
println("Already elevated!");
}
else if ($integrity eq "Medium") {
println("Need to escalate privileges");
}
else {
println("Low integrity -- limited options");
}
while Boucles¶
pour les boucles¶
Style C pour les boucles avec les expressions init, condition et update :
boucles foreach¶
Parcourez les tableaux et les hachages :
# Iterate over an array
@targets = @("10.0.0.20", "10.10.10.21", "10.10.10.22");
foreach $target (@targets) {
println("Scanning: $target");
}
# Iterate with index
foreach $idx => $target (@targets) {
println("$idx: $target");
}
# Iterate over a hash
%config = %(sleep => 30, jitter => 20, protocol => "https");
foreach $key => $value (%config) {
println("$key = $value");
}
faire une pause et continuer¶
foreach $item (@items) {
if ($item eq "skip") {
continue; # skip to next iteration
}
if ($item eq "stop") {
break; # exit the loop
}
println($item);
}
essayer/attraper¶
Gestion des erreurs avec les blocs try-catch :
Ternaire avec iff()¶
La fonction iff() fournit une évaluation ternaire des courts-circuits :
Seule la branche correspondante est évaluée, ce qui rend iff() sûr pour les expressions ayant des effets secondaires.
Fonctions¶
Définir des fonctions¶
Les fonctions sont déclarées avec le mot-clé sub :
Arguments¶
Les arguments de fonction sont accessibles via les variables de position $1, $2, etc. Le tableau @_ contient tous les arguments :
sub add {
return $1 + $2;
}
sub printAll {
foreach $arg (@_) {
println($arg);
}
}
$sum = add(3, 7); # $sum = 10
printAll("a", "b", "c"); # prints a, b, c on separate lines
Valeurs de retour¶
Utilisez return pour renvoyer une valeur d'une fonction. Si aucun return n'est utilisé, la fonction renvoie le résultat de la dernière expression évaluée :
Fermetures¶
Une fermeture est une fonction anonyme (bloc de code) qui capture sa portée englobante. Les fermetures sont créées avec la syntaxe { ... } :
Invocation de fermetures -- Utilisez la notation entre parenthèses [$fn] ou [$fn : args] :
Références des fonctions¶
L'opérateur & crée une référence à une fonction nommée :
sub myFunction {
println("Called with: $1");
}
$ref = &myFunction;
[$ref : "test"]; # prints: Called with: test
Lambda¶
La fonction lambda() crée une copie d'une fonction avec des variables liées :
sub handler {
println("Beacon $bid says: $1");
}
# Create a handler copy with $bid pre-bound
$bound = lambda(&handler, $bid => "abc123");
[$bound : "hello"]; # prints: Beacon abc123 says: hello
Ce modèle est couramment utilisé avec les rappels CNA et les menus contextuels où vous devez transmettre le contexte à un gestionnaire qui s'exécutera ultérieurement.
Variables locales dans les fonctions¶
Utilisez local() pour déclarer des variables limitées à la fonction actuelle :
sub processTarget {
local('$ip $port $result');
$ip = $1;
$port = $2;
$result = scan($ip, $port);
return $result;
}
Utilisez toujours des produits locaux
Sans local(), les variables à l'intérieur des fonctions s'infiltrent dans la portée globale et persistent après le retour de la fonction. Cela peut provoquer des bugs subtils dans les scripts de longue durée. La meilleure pratique consiste à toujours déclarer les variables locales de fonction avec local().
Tableaux et hachages¶
Opérations sur les tableaux¶
| Fonction | Description | Exemple |
|---|---|---|
push(@arr, $val) | Ajouter une valeur à la fin | push(@targets, "10.10.10.23"); |
pop(@arr) | Supprimer et renvoyer le dernier élément | $last = pop(@queue); |
shift(@arr) | Supprimer et renvoyer le premier élément | $first = shift(@queue); |
add(@arr, $val, $idx) | Insérer à l'index | add(@list, "new", 2); |
size(@arr) | Obtenir la longueur du tableau | $len = size(@targets); |
copy(@arr) | Tableau de copie profonde | @clone = copy(@original); |
reverse(@arr) | Inverser sur place | reverse(@items); |
sublist(@arr, $start, $end) | Extraire le sous-tableau | @slice = sublist(@arr, 1, 4); |
sorta(@arr) | Trier par ordre alphabétique | sorta(@names); |
sortn(@arr) | Trier numériquement | sortn(@numbers); |
addAll(@dst, @src) | Ajouter tout depuis src | addAll(@all, @new); |
removeAll(@dst, @remove) | Supprimer les éléments correspondants | removeAll(@list, @exclude); |
Itération du tableau :
@beacons = @("beacon-1", "beacon-2", "beacon-3");
foreach $bid (@beacons) {
println("Processing: $bid");
}
# With index
foreach $i => $bid (@beacons) {
println("[$i] $bid");
}
Indexation des tableaux :
@items = @("first", "second", "third");
println(@items[0]); # "first"
println(@items[-1]); # "third" (negative index)
@items[1] = "SECOND"; # assignment
Opérations de hachage¶
| Fonction | Description | Exemple |
|---|---|---|
keys(%h) | Obtenez un tableau de toutes les clés | @k = keys(%config); |
values(%h) | Obtenir un tableau de toutes les valeurs | @v = values(%config); |
removeAt(%h, "key") | Supprimer la clé et renvoyer la valeur | $old = removeAt(%map, "key"); |
putAll(%dst, %src) | Fusionner src dans dst | putAll(%config, %overrides); |
ohash() | Créer un hachage ordonné | %oh = ohash(); |
size(%h) | Obtenir le nombre de clés | $n = size(%config); |
Accès au hachage et affectation :
%info = %(os => "Windows 10", arch => "x64");
# Read
$os = %info["os"];
# Write
%info["pid"] = 1234;
# Check membership
if ("arch" isin %info) {
println("Architecture: " . %info["arch"]);
}
# Delete
removeAt(%info, "pid");
Itération de hachage :
%targets = %(
"10.0.0.20" => "DC01",
"10.10.10.21" => "WEB01",
"10.10.10.22" => "SQL01"
);
foreach $ip => $hostname (%targets) {
println("$ip -> $hostname");
}
Opérations sur les chaînes¶
Concaténation¶
$full = "Hello" . " " . "World";
$full .= "!"; # compound concatenation
println($full); # "Hello World!"
Fonctions de chaîne communes¶
| Fonction | Description | Exemple |
|---|---|---|
strlen($s) | Longueur de chaîne | $len = strlen("hello"); -- 5 |
substr($s, $start, $end) | Sous-chaîne | substr("hello", 1, 3) -- "el" |
indexOf($s, $sub) | Rechercher la position de la sous-chaîne | indexOf("hello", "ll") -- 2 |
replace($s, $pattern, $rep) | Remplacer l'expression régulière | replace("foo bar", "bar", "baz") |
strrep($s, $old, $new) | Remplacement de la chaîne littérale | strrep("aabaa", "a", "x") -- "xxbxx" |
split($delim, $s) | Diviser en tableau | @parts = split(",", "a,b,c"); |
join($delim, @arr) | Joindre un tableau à une chaîne | $s = join(", ", @items); |
lc($s) | Minuscule | lc("HELLO") -- "hello" |
uc($s) | Majuscules | uc("hello") -- "HELLO" |
trim($s) | Supprimer les espaces | trim(" hi ") -- "hi" |
left($s, $n) | N premiers caractères | left("hello", 3) -- "hel" |
right($s, $n) | N derniers caractères | right("hello", 3) -- "llo" |
chr($code) | Caractère du point de code | chr(65) -- "A" |
asc($char) | Point de code du personnage | asc("A") -- 65 |
charAt($s, $idx) | Caractère à l'index | charAt("hello", 1) -- "e" |
matches($s, $pattern) | Groupes de capture Regex | @m = matches("v1.2", '(\d+)\.(\d+)'); |
Correspondance d'expression régulière¶
Sleep prend en charge la correspondance des expressions régulières avec ismatch et la fonction matched() :
$version = "Stentor v3.2.1";
if ($version ismatch 'v(\d+)\.(\d+)\.(\d+)') {
($major, $minor, $patch) = matched();
println("Major: $major, Minor: $minor, Patch: $patch");
}
La fonction matched() renvoie les groupes de capture de l'opération ismatch la plus récente.
Correspondance de caractères génériques¶
L'opérateur iswm effectue une correspondance avec des caractères génériques (* pour n'importe quel caractère, ? pour un seul caractère) :
if ("admin*" iswm $username) {
println("Admin user detected");
}
if ("10.10.10.??" iswm $ip) {
println("Internal subnet");
}
Formatage de chaîne¶
La fonction format() fournit un formatage de style printf :
Spécificateurs de format pris en charge : %s (chaîne), %d (entier), %f (flottant), %x (hex), %o (octal), %% (pourcentage littéral).
Conversion de types¶
| Fonction | Description | Exemple |
|---|---|---|
casti($val) | Convertir en entier | $n = casti("42"); |
castd($val) | Convertir en double | $d = castd("3.14"); |
castl($val) | Convertir en long | $l = castl($n); |
typeof($val) | Obtenir la chaîne du nom du type | typeof(42) -- "Int" |
expr($val) | Contraindre au numérique | $n = expr("100"); |
Chargement de script et console de script¶
La console de scripts¶
La console de script est un environnement interactif permettant de charger, de gérer et de déboguer les scripts CNA. Il fournit un REPL (Read-Eval-Print Loop) pour tester les expressions de sommeil et exécuter des instructions.
Commandes de la console¶
| Commande | Arguments | Description |
|---|---|---|
? | expression | Évaluer un prédicat Sleep et imprimer vrai/faux |
e | statement | Exécuter une instruction Sleep et afficher la sortie |
help | Répertorier toutes les commandes de console disponibles | |
load | /path/to/script.cna | Charger et exécuter un script CNA |
ls | Liste tous les scripts actuellement chargés | |
reload | script.cna | Décharger, réanalyser et réexécuter un script |
unload | script.cna | Décharger un script et supprimer ses inscriptions |
x | expression | Évaluer une expression de sommeil et imprimer sa valeur |
proff | script.cna | Désactiver le profileur pour un script |
profile | script.cna | Vider les statistiques de performances d'un script |
pron | script.cna | Activer le profileur pour un script |
troff | script.cna | Désactiver le suivi des fonctions pour un script |
tron | script.cna | Activer le suivi des fonctions pour un script |
Exemples :
x 2 + 2
# 4
x @("a", "b", "c")
# @("a", "b", "c")
e println("Hello World!");
# Hello World!
? "admin*" iswm "administrator"
# true
load /opt/scripts/my-automation.cna
# Script loaded successfully
ls
# /opt/scripts/my-automation.cna (loaded)
Chargement de scripts via API¶
Cycle de vie des scripts¶
Lorsqu'un script CNA est chargé, il suit un cycle de vie précis :
- Charger - Le fichier est lu à partir du disque (ou reçu via l'API)
- Parse -- Le lexer tokenise la source et l'analyseur construit un AST (Abstract Syntax Tree)
- Valider -- L'analyse sémantique vérifie les appels de fonctions non définis et les problèmes de variables ; les erreurs bloquent le chargement, les avertissements sont enregistrés
- Exécuter -- Le code de niveau supérieur s'exécute immédiatement (affectations de variables,
println, etc.) - S'inscrire -- Les mots-clés CNA (
on,alias,popup,set,command,bind) enregistrent leurs gestionnaires dans le registre du moteur.
Décharger nettoie
Lorsqu'un script est déchargé (via la commande unload ou l'API), tous ses gestionnaires enregistrés sont supprimés du registre. Cela inclut les alias, les événements, les hooks, les générateurs de fenêtres contextuelles, les commandes et les raccourcis clavier. Les enregistrements des autres scripts ne sont pas affectés.
Chargement et surveillance automatiques¶
Stentor prend en charge le chargement automatique de scripts à partir d'un répertoire :
- Chargement automatique : tous les fichiers
*.cnadu répertoire de scripts configuré sont chargés au démarrage - Mode veille : le moteur interroge le répertoire toutes les 2 secondes, chargeant automatiquement les nouveaux scripts, rechargeant les scripts modifiés et déchargeant les scripts supprimés.
Mots-clés de l’AIIC¶
CNA étend Sleep avec six mots-clés pour interagir avec la plateforme Stentor. Chaque mot-clé enregistre un gestionnaire qui se déclenche dans des conditions spécifiques.
on -- Gestionnaires d'événements¶
Enregistrez un gestionnaire qui se déclenche lorsqu'un événement spécifique se produit :
Le mot-clé on prend en charge un méta-événement générique * qui se déclenche pour TOUS les événements :
Plusieurs scripts peuvent enregistrer des gestionnaires pour le même événement : tous les gestionnaires se déclenchent.
alias – Commandes de beacon¶
Enregistrez une commande personnalisée disponible dans la console de beacon :
alias survey {
btask($1, "Running survey", "T1082");
bshell!($1, "whoami /all");
bshell!($1, "ipconfig /all");
bshell!($1, "netstat -na");
}
Arguments d'alias :
| Variable | Description |
|---|---|
$0 | Chaîne de commande complète (nom + arguments, non analysée) |
$1 | ID de beacon |
$2, $3, ... | Arguments individuels (séparés par des espaces, groupe de guillemets) |
popup -- Menus contextuels¶
Ajoutez des éléments aux menus contextuels dans l'interface utilisateur :
popup beacon_top {
item "Quick Survey" {
bshell($1, "whoami /groups");
}
menu "Network" {
item "ARP Table" {
bshell($1, "arp -a");
}
item "Connections" {
bshell($1, "netstat -na");
}
}
separator();
item "Hash Dump" {
bhashdump($1);
}
}
Hooks contextuels disponibles : beacon_top, beacon, beacon_bottom, ssh et hooks personnalisés.
set -- Remplacements de crochet¶
Remplacez le comportement par défaut de Stentor en définissant des valeurs de hook :
Les hooks utilisent la sémantique du dernier écrivain-gagnant : la valeur set du script chargé le plus récemment prend effet.
command -- Commandes de la console¶
Commandes d'enregistrement disponibles dans la console de script :
Après le chargement, tapez hello Operator dans la console de script pour voir Hello, Operator!.
bind -- Raccourcis clavier¶
Enregistrez les gestionnaires pour les raccourcis clavier :
Les raccourcis prennent en charge les modificateurs : Ctrl, Shift, Alt, Meta.
Référence croisée
Pour la liste complète des événements, des hooks et des hooks contextuels, consultez la référence Hooks & Events. Pour toutes les fonctions CNA intégrées (fonctions b*, requêtes de modèle de données, assistants d'interface utilisateur), consultez la [Référence des fonctions] (function-reference.md).
Exemples pratiques¶
Configurer automatiquement de nouvelles beacons¶
Définissez le temps de veille et la gigue lorsqu'un beacon s'enregistre pour la première fois :
on beacon_initial {
# Set 30-second sleep with 20% jitter
bsleep($1, 30, 20);
blog($1, "Auto-configured: 30s sleep, 20% jitter");
}
Alias de liste de processus personnalisés¶
Créez un alias qui répertorie les processus et enregistre l'action :
alias myps {
btask($1, "Listing processes", "T1057");
bps($1);
blog($1, "Process listing requested by operator");
}
Menu contextuel pour les actions courantes¶
Ajoutez un menu contextuel avec les commandes fréquemment utilisées :
popup beacon_top {
item "Quick Hash Dump" {
foreach $bid ($1) {
bhashdump($bid);
}
}
menu "Enumeration" {
item "Who Am I" {
foreach $bid ($1) {
bshell($bid, "whoami /all");
}
}
item "Network Info" {
foreach $bid ($1) {
bshell($bid, "ipconfig /all && arp -a");
}
}
}
}
Journalisation des événements¶
Enregistrez la sortie du beacon sur la console avec des horodatages :
on beacon_output {
local('$bid $text $time');
$bid = $1;
$text = $2;
$time = formatDate(ticks(), "HH:mm:ss");
println("[$time] Beacon $bid output: $text");
}
Script de traitement des données¶
Parcourez toutes les beacons et créez un résumé :
command beacon_report {
local('$entry $id $user $host');
println("=== Beacon Report ===");
foreach $entry (beacons()) {
$id = $entry["id"];
$user = $entry["user"];
$host = $entry["computer"];
println(format(" %-8s %-15s %s", substr($id, 0, 8), $user, $host));
}
println("Total: " . size(beacons()) . " beacons");
}
Fermetures avec rappels¶
Utilisez des fermetures pour les opérations asynchrones :
alias checkports {
local('$bid $target');
$bid = $1;
$target = $2;
btask($bid, "Scanning $target for common ports");
# Use a callback to process results
bportscan($bid, $target, "1-1024", "arp", lambda({
blog($bid, "Scan complete for $target");
}, $bid => $bid, $target => $target));
}
Configuration avec des hachages¶
Créez des configurations réutilisables :
%profiles = %(
"stealth" => %(sleep => 300, jitter => 50),
"normal" => %(sleep => 30, jitter => 20),
"fast" => %(sleep => 5, jitter => 10)
);
alias profile {
local('$bid $name $config');
$bid = $1;
$name = $2;
if ($name !isin %profiles) {
berror($bid, "Unknown profile: $name. Options: stealth, normal, fast");
return;
}
$config = %profiles[$name];
bsleep($bid, $config["sleep"], $config["jitter"]);
blog($bid, "Applied profile: $name (sleep=" . $config["sleep"] . "s, jitter=" . $config["jitter"] . "%)");
}
Commentaires¶
Les commentaires commencent par # et s'étendent jusqu'à la fin de la ligne :
Il n’y a pas de commentaires sur plusieurs lignes dans Sleep.
Prochaines étapes¶
- Référence de fonction -- Référence complète pour toutes les ~300+ fonctions intégrées de CNA
- Hooks & Events -- Scripts basés sur les événements avec plus de 24 hooks et plus de 57 événements
- Mode sans tête -- Exécutez des scripts CNA sans l'interface utilisateur