> Windows Syscalls
ntoskrnl.exeT1562.001T1106

NtAreMappedFilesTheSame

Détermine si deux vues mappées sont adossées au même fichier (test d'identité du file object).

Prototype

NTSTATUS NtAreMappedFilesTheSame(
  PVOID File1MappedAsAnImage,
  PVOID File2MappedAsFile
);

Arguments

NameTypeDirDescription
File1MappedAsAnImagePVOIDinPointeur dans une vue mappée avec SEC_IMAGE (typiquement une base de DLL/EXE chargée).
File2MappedAsFilePVOIDinPointeur dans une vue mappée depuis un mapping de fichier régulier (tout type de section).

IDs de syscalls par version de Windows

Version de WindowsID de syscallBuild
Win10 15070x8Awin10-1507
Win10 16070x8Awin10-1607
Win10 17030x8Bwin10-1703
Win10 17090x8Bwin10-1709
Win10 18030x8Cwin10-1803
Win10 18090x8Cwin10-1809
Win10 19030x8Cwin10-1903
Win10 19090x8Cwin10-1909
Win10 20040x8Ewin10-2004
Win10 20H20x8Ewin10-20h2
Win10 21H10x8Ewin10-21h1
Win10 21H20x8Ewin10-21h2
Win10 22H20x8Ewin10-22h2
Win11 21H20x8Ewin11-21h2
Win11 22H20x8Ewin11-22h2
Win11 23H20x8Ewin11-23h2
Win11 24H20x90win11-24h2
Server 20160x8Awinserver-2016
Server 20190x8Cwinserver-2019
Server 20220x8Ewinserver-2022
Server 20250x90winserver-2025

Module noyau

ntoskrnl.exeNtAreMappedFilesTheSame

APIs liées

NtCreateSectionNtMapViewOfSectionNtMapViewOfSectionExGetModuleHandleWLoadLibraryExW

Stub du syscall

4C 8B D1            mov r10, rcx
B8 90 00 00 00      mov eax, 0x90      ; Win11 24H2 SSN
F6 04 25 08 03 FE 7F 01   test byte ptr [0x7FFE0308], 1
75 03               jne short +3
0F 05               syscall
C3                  ret
CD 2E               int 2Eh
C3                  ret

Notes non documentées

Un petit utilitaire étonnamment porteur : le noyau parcourt les `MM_SECTION_OBJECT_POINTERS` des deux adresses, compare le `FILE_OBJECT` sous-jacent (plus précisément les `SectionObjectPointer`) et retourne `STATUS_SUCCESS` lorsqu'ils renvoient au même fichier de backing — même si les deux vues diffèrent en attributs (image vs data), en protection, en taille ou en offset. Les deux arguments sont *nommés* de manière asymétrique (Image vs File) pour des raisons historiques ; en pratique, l'un comme l'autre peut être de n'importe quel type et la comparaison est symétrique.

Usage courant par les malwares

Joue dans les deux camps. **Usage défensif (et EDR)** : ouvrir `\KnownDlls\ntdll.dll`, mapper une copie fraîche en tant que fichier, puis appeler `NtAreMappedFilesTheSame(LoadedNtdllBase, FreshNtdllMap)`. Si la réponse est *même*, la ntdll chargée a le même fichier de backing — les défenseurs comparent alors octet-à-octet les sections `.text` pour découvrir les hooks inline EDR/AV et les écraser avec les octets vierges. C'est le fondement de toute primitive de désrochage moderne (Perun's Fart, FreshyCalls, SysWhispers3 +unhook, RefleXXion). **Usage offensif** : un implant **DLL-hollowed** (son image module écrasée en mémoire alors que le fichier sous-jacent reste intact) peut appeler ceci sur lui-même pour détecter la falsification — auto-défense symétrique contre les unhookers blue-team. Certains checks d'évasion sandbox utilisent aussi cet appel pour confirmer qu'une DLL chargée provient bien de `\System32\` plutôt que d'une copie attaquante redirigée.

Opportunités de détection

Quasi aucun signal de détection propre : le syscall est rare en logiciel bénin mais de plus en plus courant dans l'outillage de sécurité (Defender, CrowdStrike, SentinelOne y passent tous lors de leurs comparaisons d'unhooking). Le signal fort, c'est le *pairing* : un processus qui ouvre `\KnownDlls\ntdll.dll` (ou mappe toute DLL système depuis `\System32`) puis appelle immédiatement `NtAreMappedFilesTheSame` contre sa propre ntdll chargée effectue une danse d'unhooking. Les éditeurs EDR s'auto-protègent de plus en plus en supprimant les astuces d'identification par identité de section — si l'appel retourne same sur une DLL que l'EDR attend différente, l'EDR peut détecter *cela* et réagir.

Exemples de syscalls directs

cVerify a fresh ntdll maps the same file as the loaded one

// Defender / red-team unhooking helper.
HANDLE hSection = OpenSectionByName(L"\\KnownDlls\\ntdll.dll");
PVOID  freshBase = NULL; SIZE_T viewSize = 0;
NtMapViewOfSection(hSection, NtCurrentProcess(),
                   &freshBase, 0, 0, NULL, &viewSize,
                   ViewShare, 0, PAGE_READONLY);

PVOID loadedNtdll = GetModuleHandleW(L"ntdll.dll");

if (NtAreMappedFilesTheSame(loadedNtdll, freshBase) == STATUS_SUCCESS) {
    // Same backing file: safe to byte-compare and unhook .text.
    PatchTextSectionFromFresh(loadedNtdll, freshBase);
}

asmx64 direct stub (Win11 24H2)

; NtAreMappedFilesTheSame direct stub — SSN 0x90 on Win11 24H2
NtAreMappedFilesTheSame PROC
    mov  r10, rcx
    mov  eax, 90h
    syscall
    ret
NtAreMappedFilesTheSame ENDP

rustSelf-check for DLL hollowing

// An implant uses this call to detect that its own module image was
// overwritten in memory (DLL hollowing) — the section identity persists
// even if the bytes changed.
use ntapi::ntmmapi::NtAreMappedFilesTheSame;
use winapi::shared::ntdef::PVOID;

unsafe fn module_was_hollowed(loaded: PVOID, fresh: PVOID) -> bool {
    let s = NtAreMappedFilesTheSame(loaded, fresh);
    if s != 0 {
        // Section identity differs — module image has been replaced.
        return true;
    }
    // Same section: byte-compare to decide if .text was rewritten.
    text_section_differs(loaded, fresh)
}

Mappings MITRE ATT&CK

Last verified: 2026-05-20