Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2025-62821 — Microsoft HEIF Extension (msheif_store.dll) OOB-read | Kitploit
Outils/GitHubGitHub/hyunjungg/cve-2025-62821
Criminalistique MémoireAnalyse des VulnérabilitésExploitationRétro-ingénierieFuzzingAnalyse de Binaires
GitHubhyunjungg/cve-2025-62821

CVE-2025-62821

Microsoft HEIF Extension (msheif_store.dll) OOB-read

Voir le dépôt
il y a 11 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Extensions d'image HEIF de Microsoft (msheif_store.dll) : Sous-allocation du tampon source dans le chemin CopyPixels entraîne une lecture hors limites et une violation d'accès (DoS)

Lors du décodage d'une image HEIF malveillante via WIC, le codec msheif alloue un tampon source de 1 octet mais tente ensuite de copier une très grande quantité de données de pixels à partir de ce tampon pendant CopyPixels. La copie utilise memmove avec une taille dérivée de stride × hauteur du ROI, sans valider la longueur réelle du tampon source. Cela provoque une lecture hors limites et une violation d'accès immédiate (crash). En pratique, l'ouverture ou l'aperçu du HEIF malveillant entraîne un déni de service dans tout consommateur WIC qui passe par les extensions d'image HEIF.

Note de nommage : les noms de variables comme roi_height sont déduits du désassemblage pour la lisibilité et ne reflètent pas les noms de symboles du fournisseur.

ProduitMicrosoft HEIF Image Extensions
Modulemsheif_store.dll
Système d'exploitationWindows 11
Version de l'extension1.2.22.0 (Microsoft.HEIFImageExtension_1.2.22.0_x64__8wekyb3d8bbwe\x64\msheif_store.dll)
  1. Analyse de la cause racine

    a. Description détaillée de la vulnérabilité

    • Le pipeline de décodage calcule une grande longueur de copie pour memmove basée sur la géométrie de l'image (par exemple, copy_size = stride * abs(roi_height)).
    • Le tampon source qui devrait contenir les données d'image/élément décodées est sous-alloué à 1 octet, car :
      • CHEIFStreamReader_ReadItemData appelle CHEIFItemInfoEntry_GetDataSize pour calculer la longueur des données de l'élément.
      • Dans une branche d'échec spécifique, CHEIFItemInfoEntry_GetDataSize renvoie un succès mais laisse la taille calculée à 0.
      • CHEIFStreamReader_ReadItemData appelle ensuite MFCreateMemoryBuffer(0, &ppBuffer). Selon le comportement de MF, cela produit un tampon avec une allocation minimale de 1 octet.
    • En aval, CopyPixels valide la taille du tampon de destination mais ne valide pas la longueur du tampon source par rapport à la taille de copie demandée avant d'appeler memmove.
    • Résultat : memmove(dst, src, large_size) lit bien au-delà du src d'un octet, provoquant une erreur lors du chargement vectorisé.

    Ce bogue est indépendamment aggravé si la largeur de l'image/ROI est mal interprétée (par exemple, 0x01000100 = 16 777 472), ce qui gonfle le stride et la taille finale de copie. Cependant, la vulnérabilité principale est que la longueur de la source n'est pas vérifiée par rapport à la longueur de copie calculée.

root@kitploit:~
(7de0.78e4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
msheif_store!DllCanUnloadNow+0x228b1d:
00007ffd`841bc45d c5fe6f02        vmovdqu ymm0,ymmword ptr [rdx] ds:000002b0`65be6ff0=c0

0:000> !heap -p -a rdx
    address 000002b065be6ff0 found in
    _DPH_HEAP_ROOT @ 2b05bed1000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                             2b062c2f2d8:      2b065be6ff0                1 -      2b065be6000             2000
    ...
    00007ffe75b90563 MFPlat!operator new+0x0000000000000023
    00007ffe75b83d36 MFPlat!MFCreateMemoryBuffer+0x0000000000000056
    00007ffd840157b1 msheif_store!DllCanUnloadNow+0x0000000000081e71
		...

0:000> r r8
r8=0000000001000100

b. Flux de code à partir de l'entrée

root@kitploit:~
0:000> k
 # Child-SP          RetAddr               Call Site
00 0000005d`6a9aed98 00007ffe`6fdefcc2     msheif_store!DllCanUnloadNow+0x228b21
01 0000005d`6a9aeda0 00007ffe`6fcb3adc     msheif_store!DllCanUnloadNow+0x18c382
02 0000005d`6a9aee00 00007ffe`6fcb4513     msheif_store!DllCanUnloadNow+0x5019c
03 0000005d`6a9aeef0 00007ffe`6fcb96da     msheif_store!DllCanUnloadNow+0x50bd3
04 0000005d`6a9af0a0 00007fff`318551d5     msheif_store!DllCanUnloadNow+0x55d9a
05 0000005d`6a9af1a0 00007fff`318082eb     windowscodecs!CPyramidBase::CopyPixels+0xf5
06 0000005d`6a9af260 00007fff`31857e52     windowscodecs!CFormatConverter::CopyPixels+0x22b
07 0000005d`6a9af3e0 00007fff`31857e52     windowscodecs!CFormatConverterResolver::CopyPixels+0xc2
08 0000005d`6a9af480 00007ff6`15fb0f5d     heif_decoder!HEIF_LoadBitmapFromMemory+0x34d [C:\\\\Users\\\\test\\\\source\\\\repos\\\\heif_decoder\\\\heif_decoder\\\\heif_decoder.cpp @ 256]
09 0000005d`6a9af670 00007ff6`15fb1754     heif_decoder!HEIF_FuzzMemory+0x9b [C:\\\\Users\\\\test\\\\source\\\\repos\\\\heif_decoder\\\\heif_decoder\\\\heif_decoder.cpp @ 357]
0a 0000005d`6a9af830 00007ff6`15fb3039     heif_decoder!wmain+0x394 [C:\\\\Users\\\\test\\\\source\\\\repos\\\\heif_decoder\\\\heif_decoder\\\\heif_decoder.cpp @ 524]
0b 0000005d`6a9afaa0 00007ff6`15fb2ee2     heif_decoder!invoke_main+0x39 [D:\\\\a\\\\_work\\\\1\\\\s\\\\src\\\\vctools\\\\crt\\\\vcstartup\\\\src\\\\startup\\\\exe_common.inl @ 91]
0c 0000005d`6a9afaf0 00007ff6`15fb2d9e     heif_decoder!__scrt_common_main_seh+0x132 [D:\\\\a\\\\_work\\\\1\\\\s\\\\src\\\\vctools\\\\crt\\\\vcstartup\\\\src\\\\startup\\\\exe_common.inl @ 288]
0d 0000005d`6a9afb60 00007ff6`15fb30ce     heif_decoder!__scrt_common_main+0xe [D:\\\\a\\\\_work\\\\1\\\\s\\\\src\\\\vctools\\\\crt\\\\vcstartup\\\\src\\\\startup\\\\exe_common.inl @ 331]
0e 0000005d`6a9afb90 00007fff`3847e8d7     heif_decoder!wmainCRTStartup+0xe [D:\\\\a\\\\_work\\\\1\\\\s\\\\src\\\\vctools\\\\crt\\\\vcstartup\\\\src\\\\startup\\\\exe_wmain.cpp @ 17]
0f 0000005d`6a9afbc0 00007fff`3939c34c     KERNEL32!BaseThreadInitThunk+0x17
10 0000005d`6a9afbf0 00000000`00000000     ntdll!RtlUserThreadStart+0x2c

Appels internes résolus (renommés pour plus de clarté) :

root@kitploit:~
CWICHeifDecoderFrame::CopyPixels
 → CWICHeifBitmapSourceBase::CopyPixels_Transform
   → CWICHeifBitmapSourceBase::CopyPixels_Base
     → sub_7FFD8411FC40  // issues memmove
       → memmove         // AV (vmovdqu load from src)

c. Taille du tampon

  • HEIF malveillant qui force CHEIFItemInfoEntry_GetDataSize à emprunter un chemin précoce de « succès avec taille 0 » (par exemple, lorsque sub_7FFD8408B898 échoue et que la fonction renvoie un succès avec sizeBuffer = 0).

  • Tampon source : alloué via MFCreateMemoryBuffer(0) ⇒ 1 octet.

  • Taille de copie : dérivée comme copy_size = stride * abs(roi_height). Avec une largeur mal interprétée (par exemple, 0x01000100) et un BPP typique, le stride est énorme, conduisant à une très grande copy_size.

  • Appel vulnérable :

    root@kitploit:~
    __int64 sub_7FFD8411FC40(__m128i* dst, __int64 a2, __m128i* src, int a4,
                             unsigned int stride, unsigned int abs_roi_height)
    {
      if (src && dst) {
        if (stride == a2 && stride == a4) {
          // No validation that 'src' contains at least (stride * abs_roi_height) bytes
          memmove(dst, src, (size_t)abs_roi_height * stride); // AV here
        }
      }
    }
    
  • Pourquoi la source fait 1 octet (chemin d'allocation) :

    root@kitploit:~
    __int64 __fastcall CHEIFStreamReader_ReadItemData(__int64 *a1, __int64 *a2, IMFMediaBuffer **a3)
    {
      ppBuffer = 0i64;
      if ( v7(a2) )
      {
        *cbMaxLength = 0i64;
        result = (*(*a2 + 0xA0))(a2, cbMaxLength); // CHEIFItemInfoEntry_GetDataSize
        if ( result < 0 )
        {
          goto LABEL_10;
        }
        if ( *cbMaxLength > 0xC800000ui64 )
        {
          result = 0xC00D36BE;
          goto LABEL_23;
        }
        // cbMaxLength may still be 0 if GetDataSize returned success early
        result = MFCreateMemoryBuffer(cbMaxLength[0], &ppBuffer);
        if ( result < 0 )
        {
          goto LABEL_34;
        }
        ...
    }
    
    root@kitploit:~
    __int64 __fastcall CHEIFItemInfoEntry_GetDataSize(__int64 a1, unsigned __int64 *sizeBuffer)
    {
    
      if ( sizeBuffer )
      {
        *sizeBuffer = 0i64;
        DataLocationInfo = (*(*v5 + 0x78i64))(v5, 0x6D657461i64, &v32);
        if ( DataLocationInfo >= 0 )
        {
          v13 = v32;
          v14 = *(v32 + 0xF0);
          if ( v14 )
          {
            if ( !sub_7FFD8408B898((v14 + 0xC8), (a1 - 0x78), &v33, v31) )
            {
            // returns success (0/S_OK) without updating sizeBuffer
    	      // caller treats this as length=0 → MFCreateMemoryBuffer(0)
                DataLocationInfo = 0;
                goto LABEL_62;
              }
            v17 = v33;
            DataLocationInfo = CHEIFItemInfoEntry_GetDataLocationInfo(v5, v13, *(v33 + 16), &v29, &v30);
            if ( DataLocationInfo >= 0 )
            {
              for ( i = 0; ; ++i )
              {
                if ( i >= *v17 )
                {
                  *sizeBuffer = v6;
                  goto LABEL_62;
                }
                v21 = *(*(v17 + 8) + 24i64 * i + 16);
                }
                if ( v21 + v6 < v6 )
                  break;
                v6 += v21;
                DataLocationInfo = 0;
              }
    
             ...
             ...
    LABEL_62:
      sub_7FFD83F91AEC();
      return DataLocationInfo;
    }
    

d. Correctifs suggérés

Dans le chemin CopyPixels, valider que le tampon source contient au moins stride * abs(roi_height) octets (et que src_stride/src_height atteignent ou dépassent la région demandée). Sinon, échouer avec WINCODEC_ERR_INSUFFICIENTBUFFER (ou équivalent).

e. Méthodologie d'analyse (reconstruction de symboles)

Pour rendre le flux d'appels révisable, nous avons reconstruit les noms de fonctions internes dans IDA à partir des chaînes de journalisation du codec lui-même.

  • Objectif. Identifier des noms de fonctions lisibles pour les routines clés (…CopyPixels_Base, …CopyPixels_Transform, CHEIFStreamReader::ReadItemData, etc.) pour aligner la pile de crash avec le code décompilé.

  • Procédure :

    1. Trouver l'assistant de journalisation : dans la vue du décompilateur des appelants autour du crash, localiser un petit assistant qui est invoqué avec un argument chaîne constante ressemblant à un nom de fonction (par exemple, « CWICHeifBitmapSourceBase::CopyPixels_Base »).
      • Dans IDA : ouvrir la fonction au moment du crash, remonter d'un cadre, et inspecter les appels à l'entrée de la fonction pour un assistant prenant un littéral de chaîne.
    2. Collecter les appelants : utiliser les xrefs vers cet assistant pour lister toutes les fonctions appelantes.
    3. Extraire les noms : pour chaque appelant, ouvrir la vue décompilée et lire le deuxième argument de l'assistant (le littéral de chaîne). Cette chaîne contient systématiquement le nom de fonction prévu.
    4. Renommer les appelants : dans chaque appelant, appuyer sur N (Édition → Renommer) et définir le nom de la fonction sur la chaîne récupérée (par exemple, CWICHeifBitmapSourceBase::CopyPixels_Base).
    5. Répéter pour les cadres proches jusqu'à ce que toute la chaîne de crash ait des noms significatifs.

Validation. Après le renommage, repasser par les sites d'appel et confirmer que les types/le comportement des arguments correspondent aux étiquettes (par exemple, …CopyPixels_Base est l'endroit où le calcul stride/ROI et l'appel final à memmove ont lieu).

  1. Preuve de concept

  • Prérequis : extensions d'image HEIF du Microsoft Store installées/activées (nécessaire pour le décodage HEIC/HEIF).

  • Étapes pour reproduire

    1. Télécharger et enregistrer le fichier PoC joint (../access_violation_0000xxxxxxxxx461_00000xxxxxxxx6B0_1.heif) dans un dossier local.

    2. S'assurer que les extensions d'image HEIF sont installées (ouvrir le Microsoft Store → rechercher « HEIF Image Extensions » → Installer).

    3. Ouvrir le fichier PoC avec Microsoft Photos (double-cliquer sur le fichier si Photos est par défaut, ou Clic droit → Ouvrir avec → Photos).

  • Lien de téléchargement du logiciel

    Extensions d'image HEIF (Microsoft Store) https://apps.microsoft.com/detail/9pmmsr1cgpwg?hl=en-US&gl=US

Télécharger l’outil