# Root Cause Analysis — CVE-2025-27727

## Overview

| Field | Value |
|-------|-------|
| **CVE** | CVE-2025-27727 |
| **Binary** | msi.dll (Windows Installer) |
| **Patch Date** | April 8, 2025 |
| **KB** | KB5055523 (Windows 11 24H2) |
| **Pre-patch Version** | 5.0.26100.3323 |
| **Post-patch Version** | 5.0.26100.3775 |
| **CVSS** | 7.8 (Important) |
| **CWE** | CWE-59: Improper Link Resolution Before File Access ('Link Following') |
| **Impact** | Elevation of Privilege — Low-privileged user → SYSTEM |
| **Reporter** | Simon (@sim0nsecurity) |
| **Reference** | [Exodus Intelligence Blog](https://blog.exodusintel.com/2026/07/06/microsoft-windows-installer-folder-delete-privilege-escalation/) |

## Vulnerability Summary

CVE-2025-27727 is a logic vulnerability in the Windows Installer service (`msiexec.exe`, running as SYSTEM) exposed through the `CMsiConfigurationManager` COM interface in `msi.dll`. The vulnerability allows a low-privileged user to cause the MSI service to delete an arbitrary folder by scheduling its path in the `TempPackages` registry key via the `SetEEUIDirectoryAndFilter()` COM method. The service does not validate that the folder being deleted was actually created by the installer — it blindly trusts whatever paths are stored in `TempPackages`.

The folder-deletion primitive can be chained into full SYSTEM code execution by:
1. Deleting `C:\Config.Msi` (the MSI rollback folder)
2. Re-creating it with a NULL DACL
3. Swapping legitimate rollback scripts (`.rbs`) with malicious ones during a failing MSI install
4. The MSI service executes the attacker-controlled rollback scripts as SYSTEM

## Ghidra-Verified Call Flow (Pre-Patch, msi.dll 5.0.26100.3323)

```
User-mode COM client (any privilege level)
  │
  ├─► CoCreateInstance(CLSID {000C101C-...}) → CreateMsiServer @ 0x180116420
  │     └─ Instantiates CMsiConfigurationManager COM object
  │
  ├─► CMsiConfigurationManager::MsiBeginTransactionW (vtable offset 0xA0)
  │     └─ CMsiTransaction::CreateTransaction() → creates global transaction object
  │
  ├─► CMsiConfigurationManager::SetEEUIDirectoryAndFilter @ 0x18018ba10 (vtable offset 0xC8)
  │     ├─ EnterCriticalSection(&g_csServerInterfaceLock)
  │     ├─ Reads CMsiTransaction::m_pMsiTransaction (global transaction)
  │     ├─ IsAdmin() check
  │     │   └─ If NOT admin:
  │     │       ├─ StartImpersonating() — impersonates calling user
  │     │       ├─ CreateFileW(param_1, 0x10000 [DELETE], 1 [FILE_SHARE_READ],
  │     │       │              NULL, 3 [OPEN_EXISTING],
  │     │       │              0x2200000 [FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT],
  │     │       │              NULL)
  │     │       │   └─ Verifies caller has DELETE permission on folder
  │     │       │   └─ FILE_FLAG_OPEN_REPARSE_POINT prevents following junctions
  │     │       └─ StopImpersonating()
  │     │
  │     └─► CMsiTransaction::SetEEUIDirectoryAndFilter @ 0x18018bb90  [VULNERABLE]
  │           ├─ IsValidCaller(this) — verifies calling thread is transaction owner
  │           ├─ StringCchCopyW(this+0xa4, 0x104, param_1) — copies attacker path
  │           ├─ *(this+0xa0) = param_2 — stores filter flags
  │           │
  │           └─► CMsiTransaction::ScheduleFileOrFolderDelete @ 0x1801af264  [VULNERABLE]
  │                 ├─ CElevate(true) — elevates to SYSTEM
  │                 ├─ OpenRegistryKey(HKLM, "Software\Microsoft\Windows\
  │                 │                  CurrentVersion\Installer\TempPackages")
  │                 ├─ MsiString(param_1) — wraps user-supplied path
  │                 ├─ If folder (param_2=true): builds "#2" flag string
  │                 ├─ CMsiRegKey::SetValue(path_string, "#2")
  │                 │   └─ Writes: HKLM\...\TempPackages\"C:\Config.Msi" = REG_DWORD 0x2
  │                 └─ NO VALIDATION that path was created by MSI service
  │
  └─► CMsiConfigurationManager::CleanupTempPackages @ 0x180184b90 (vtable offset 0x50)
        └─► CleanupTempPackagesInternal @ 0x180186c6c
              ├─ CElevate(true) — elevates to SYSTEM
              ├─ OpenRegistryKey(HKLM, "Software\Microsoft\Windows\
              │                  CurrentVersion\Installer\TempPackages")
              ├─ Enumerate all registry values
              │   ├─ GetIntegerValue() — checks if numeric (folder flag)
              │   ├─ MsiString::Remove(str, 3, 0x23) — strips "#" prefix
              │   ├─ GetInteger() → parses flag value
              │   └─ If (flag & 2) != 0: FOLDER deletion path
              │
              └─► FDeleteFolder @ 0x1801b29ac  [RUNS AS SYSTEM]
                    ├─ FindFirstFileW(path\*.*)
                    ├─ Loop: FindNextFileW
                    │   ├─ Files: DeleteFileW(child_path)
                    │   │   └─ If fails: LockdownPath() → SetFileAttributesW(0) → DeleteFileW()
                    │   └─ Subdirs: FDeleteFolder(child_path) [recursive]
                    ├─ RemoveDirectoryW(param_1)
                    │   └─ If fails: LockdownPath() → SetFileAttributesW(0) → RemoveDirectoryW()
                    └─ NO VALIDATION of path origin — blindly deletes
```

## Root Cause

The vulnerability is a **trust boundary violation** in the TempPackages registry mechanism:

1. **`CMsiTransaction::SetEEUIDirectoryAndFilter` (@ 0x18018bb90)** copies an attacker-supplied folder path and unconditionally calls `ScheduleFileOrFolderDelete`, which writes the path to `HKLM\Software\Microsoft\Windows\CurrentVersion\Installer\TempPackages` as a folder-delete entry (flag `0x2`).

2. **`CleanupTempPackagesInternal` (@ 0x180186c6c)** enumerates TempPackages and calls `FDeleteFolder` as SYSTEM on every entry with the folder flag set. It does **not validate** that the paths were created by the MSI service — it blindly trusts the registry contents.

3. The only access check is the `CreateFileW` call in `CMsiConfigurationManager::SetEEUIDirectoryAndFilter` (@ 0x18018ba10) which verifies the caller has `DELETE` permission on the folder. This is trivially satisfied for `C:\Config.Msi` because:
   - Any user can create folders at the root of `C:\`
   - User-created folders inherit permissive ACLs from the user
   - `FILE_FLAG_OPEN_REPARSE_POINT` prevents junction following, but this is irrelevant when the target is `C:\Config.Msi` itself

4. **`FDeleteFolder` (@ 0x1801b29ac)** recursively deletes all contents and the folder itself. If `RemoveDirectoryW` fails (restrictive ACLs), it calls `LockdownPath` to override ACLs and retries — meaning even folders with restrictive DACLs can be deleted.

## Exploitation Chain (C:\Config.Msi Delete → SYSTEM)

The folder-delete primitive becomes a full EoP via rollback script injection:

**Phase 0 — Register C:\Config.Msi for deletion:**
- Create `C:\Config.Msi` with permissive ACLs
- Open handle with `DELETE` permission
- Call `MsiBeginTransactionW()` → `SetEEUIDirectoryAndFilter("C:\\Config.Msi")` → `CleanupTempPackages()`
- `C:\Config.Msi` is deleted as SYSTEM via `FDeleteFolder`

**Phase 1 — Prepare Config.Msi with a locked rollback file:**
- Install a crafted `.msi` to create `C:\Config.Msi` with rollback data
- During uninstall, the installer moves the installed file into `C:\Config.Msi` as an `.rbf`
- Lock the `.rbf` to prevent the uninstaller from cleaning up
- Delete the `.rbf` via `FileDispositionInfo` after the uninstaller gives up
- `C:\Config.Msi` is now empty but registered in `HKLM\...\Installer\Folders`

**Phase 2 — Trigger the SYSTEM folder delete:**
- Call `CleanupTempPackages()` to delete `C:\Config.Msi` as SYSTEM
- The `Folders` registry entry persists

**Phase 3 — Plant malicious rollback scripts:**
- Re-create `C:\Config.Msi` with NULL DACL (any user can create root folders)
- Open a `WRITE_DAC` handle (NULL DACL grants full access)
- Start a failing MSI install — installer recognizes folder via `Folders` registry, writes `.rbs`
- Installer sets restrictive DACL, but exploit's handle retains `WRITE_DAC` (checked at open time)
- Re-apply NULL DACL via `NtSetSecurityObject`
- Swap `.rbs` with malicious rollback script
- Installer executes attacker's rollback script as SYSTEM

## Mitigations

The MSI service process (`msiexec.exe`) has **RedirectionGuard** enabled (`EnforceRedirectionTrust: True`), which blocks NTFS junction/symlink traversal by unprivileged users. This prevents generic junction-based attacks but does NOT mitigate the `C:\Config.Msi` attack path, since the attacker creates a real folder (not a junction) and the exploit operates on the folder's contents directly.

## Patch Analysis

Microsoft patched by adding a **feature flag check** in `CMsiTransaction::SetEEUIDirectoryAndFilter`:

```
Pre-patch (vulnerable):
  IsValidCaller(this)
  StringCchCopyW(this+0xa4, 0x104, param_1)
  *(this+0xa0) = param_2
  ScheduleFileOrFolderDelete(this, this+0xa4, true)  ← ALWAYS CALLED

Post-patch (fixed):
  IsValidCaller(this)
  StringCchCopyW(this+0xa4, 0x104, param_1)
  *(this+0xa0) = param_2
  if (Feature_1997029688::IsEnabled())               ← NEW CHECK
    return 0;                                         ← SUCCESS, but NO registry write
  else
    ScheduleFileOrFolderDelete(this, this+0xa4, true) ← kill-switch path only
```

The feature flag `Feature_1997029688` gates the call to `ScheduleFileOrFolderDelete`. When enabled (default in patched builds), `SetEEUIDirectoryAndFilter` returns success (`0`) without writing the folder path to `TempPackages`. This breaks the exploit chain at its root — `CleanupTempPackages` will never find an attacker-controlled path.

The kill-switch path (feature disabled) preserves the old behavior for controlled rollback capability — same gradual deployment pattern used in CLFS.sys and mqac.sys patches.

## Detection Rules

### YARA — Vulnerable msi.dll Binary Detection

```yara
rule CVE_2025_27727_Vulnerable_MSI_DLL
{
    meta:
        description = "Detects pre-patch msi.dll vulnerable to CVE-2025-27727 (missing Feature_1997029688 check in SetEEUIDirectoryAndFilter)"
        author = "OnlyFm252 Blue Team"
        date = "2025-04-08"
        cve = "CVE-2025-27727"
        reference = "https://blog.exodusintel.com/2026/07/06/microsoft-windows-installer-folder-delete-privilege-escalation/"

    strings:
        // "Software\Microsoft\Windows\CurrentVersion\Installer\TempPackages"
        $reg_temppackages = "TempPackages" wide

        // SetEEUIDirectoryAndFilter string reference
        $eeui_debug = "EEUI Directory path does not have a delete permissions by client process" wide

        // FDeleteFolder debug strings
        $fdel_file = "FDeleteFolder: Deleting file" wide
        $fdel_folder = "FDeleteFolder: Deleting folder" wide

        // CreateFileW with DELETE access (0x10000) + OPEN_EXISTING (3) + flags (0x2200000)
        // In vulnerable binary: no feature flag check before ScheduleFileOrFolderDelete
        $delete_access = { 00 00 01 00 }  // 0x10000 = DELETE

        // Windows Installer description
        $description = "Windows Installer" wide

    condition:
        uint16(0) == 0x5A4D and
        filesize > 2MB and filesize < 8MB and
        $description and
        $reg_temppackages and
        $eeui_debug and
        ($fdel_file or $fdel_folder) and
        $delete_access
}
```

### YARA — CVE-2025-27727 Exploit Artifact Detection

```yara
rule CVE_2025_27727_Exploit_Artifact
{
    meta:
        description = "Detects potential CVE-2025-27727 exploit tools targeting MSI TempPackages folder delete"
        author = "OnlyFm252 Blue Team"
        date = "2025-04-08"
        cve = "CVE-2025-27727"

    strings:
        // COM CLSID for MSI server
        $clsid = { 1C 10 0C 00 00 00 00 00 C0 00 00 00 00 00 00 46 }

        // MsiBeginTransactionW API
        $api_begin = "MsiBeginTransactionW" ascii wide

        // SetEEUIDirectoryAndFilter
        $api_eeui = "SetEEUIDirectoryAndFilter" ascii wide

        // CleanupTempPackages
        $api_cleanup = "CleanupTempPackages" ascii wide

        // Target path
        $config_msi = "C:\\Config.Msi" ascii wide nocase
        $config_msi2 = "Config.Msi" ascii wide nocase

        // TempPackages registry path
        $reg_path = "Installer\\TempPackages" ascii wide nocase

    condition:
        uint16(0) == 0x5A4D and
        ($clsid or $api_begin) and
        ($api_eeui or $api_cleanup) and
        ($config_msi or $config_msi2 or $reg_path)
}
```

### Sigma — CVE-2025-27727 Exploitation Indicators

```yaml
title: CVE-2025-27727 MSI Installer Folder Delete Exploitation
id: 8c3d4e2a-1f7b-4a9c-b6d5-e8f2a3c71094
status: experimental
description: |
    Detects indicators of CVE-2025-27727 exploitation where a low-privileged
    user leverages the MSI COM interface to delete C:\Config.Msi as SYSTEM,
    then plants malicious rollback scripts for SYSTEM code execution.
references:
    - https://blog.exodusintel.com/2026/07/06/microsoft-windows-installer-folder-delete-privilege-escalation/
    - https://msrc.microsoft.com/update-guide/vulnerability/CVE-2025-27727
author: OnlyFm252 Blue Team
date: 2025/04/08
tags:
    - attack.privilege_escalation
    - attack.t1574
    - attack.t1546
    - cve.2025.27727
logsource:
    category: registry_set
    product: windows
detection:
    selection_temppackages:
        TargetObject|contains: '\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\TempPackages'
        Details|contains: 'Config.Msi'
    condition: selection_temppackages
falsepositives:
    - Legitimate MSI installations that use C:\Config.Msi (however, the TempPackages
      registry value name should be an MSI-generated temp path, not C:\Config.Msi)
level: high
---
title: CVE-2025-27727 C:\Config.Msi Folder Recreation with Weak DACL
id: 9d4e5f3b-2a8c-4b0d-c7e6-f9a3b4d82105
status: experimental
description: |
    Detects creation of C:\Config.Msi folder by a non-SYSTEM process,
    which may indicate Phase 3 of CVE-2025-27727 exploitation where
    the attacker re-creates the folder with a NULL DACL.
author: OnlyFm252 Blue Team
date: 2025/04/08
tags:
    - attack.privilege_escalation
    - attack.t1574
    - cve.2025.27727
logsource:
    category: file_event
    product: windows
detection:
    selection_configmsi:
        TargetFilename|startswith: 'C:\Config.Msi'
    filter_system:
        User|contains:
            - 'SYSTEM'
            - 'TrustedInstaller'
    filter_msiexec:
        Image|endswith: '\msiexec.exe'
    condition: selection_configmsi and not (filter_system or filter_msiexec)
falsepositives:
    - Third-party MSI wrappers that pre-create C:\Config.Msi
level: high
---
title: CVE-2025-27727 Suspicious MSI COM Interface Abuse
id: ae5f6a4c-3b9d-4c1e-d8f7-0ab4c5e93216
status: experimental
description: |
    Detects a low-privileged process loading msi.dll and performing COM
    calls to the MSI server interface, potentially exploiting CVE-2025-27727.
author: OnlyFm252 Blue Team
date: 2025/04/08
tags:
    - attack.privilege_escalation
    - attack.t1559.001
    - cve.2025.27727
logsource:
    category: image_load
    product: windows
detection:
    selection_msi_load:
        ImageLoaded|endswith: '\msi.dll'
    filter_legitimate:
        Image|endswith:
            - '\msiexec.exe'
            - '\MsiExec.exe'
            - '\setup.exe'
            - '\installer.exe'
            - '\wusa.exe'
            - '\TiWorker.exe'
            - '\TrustedInstaller.exe'
            - '\svchost.exe'
            - '\dism.exe'
    condition: selection_msi_load and not filter_legitimate
falsepositives:
    - Custom application installers
    - System management tools
    - Software deployment agents
level: medium
```

### Sysmon Configuration

```xml
<!-- CVE-2025-27727: MSI Installer Folder Delete EoP -->

<!-- Rule 1: Monitor TempPackages registry writes -->
<RuleGroup name="CVE-2025-27727" groupRelation="or">
  <RegistryEvent onmatch="include">
    <!-- Event ID 12/13/14: Registry key/value create/modify -->
    <TargetObject condition="contains">Installer\TempPackages</TargetObject>
  </RegistryEvent>
</RuleGroup>

<!-- Rule 2: Monitor C:\Config.Msi file/folder operations by non-SYSTEM -->
<RuleGroup name="CVE-2025-27727-ConfigMsi" groupRelation="or">
  <FileCreate onmatch="include">
    <TargetFilename condition="begin with">C:\Config.Msi</TargetFilename>
  </FileCreate>
</RuleGroup>

<!-- Rule 3: Monitor DACL changes on C:\Config.Msi -->
<!-- Requires Windows Security Audit: Object Access → File System -->
<!-- Event ID 4670 (Permissions on an object were changed) -->

<!-- Rule 4: Monitor msi.dll loading by suspicious processes -->
<RuleGroup name="CVE-2025-27727-DLLLoad" groupRelation="or">
  <ImageLoad onmatch="include">
    <ImageLoaded condition="end with">\msi.dll</ImageLoaded>
  </ImageLoad>
  <ImageLoad onmatch="exclude">
    <Image condition="end with">\msiexec.exe</Image>
    <Image condition="end with">\svchost.exe</Image>
    <Image condition="end with">\TiWorker.exe</Image>
    <Image condition="end with">\TrustedInstaller.exe</Image>
    <Image condition="end with">\dism.exe</Image>
    <Image condition="end with">\wusa.exe</Image>
  </ImageLoad>
</RuleGroup>

<!-- Rule 5: Monitor for suspicious .rbs/.rbf file creation in C:\Config.Msi -->
<RuleGroup name="CVE-2025-27727-Rollback" groupRelation="or">
  <FileCreate onmatch="include">
    <TargetFilename condition="begin with">C:\Config.Msi</TargetFilename>
    <TargetFilename condition="end with">.rbs</TargetFilename>
  </FileCreate>
  <FileCreate onmatch="include">
    <TargetFilename condition="begin with">C:\Config.Msi</TargetFilename>
    <TargetFilename condition="end with">.rbf</TargetFilename>
  </FileCreate>
</RuleGroup>
```

## Key Addresses (Pre-Patch msi.dll 5.0.26100.3323)

| Function | Address | Role |
|----------|---------|------|
| `CreateMsiServer` | `0x180116420` | COM server instantiation |
| `CMsiConfigurationManager::SetEEUIDirectoryAndFilter` | `0x18018ba10` | COM entry point (vtable 0xC8) — DELETE permission check |
| `CMsiTransaction::SetEEUIDirectoryAndFilter` | `0x18018bb90` | **Vulnerable** — calls ScheduleFileOrFolderDelete without feature flag |
| `CMsiTransaction::ScheduleFileOrFolderDelete` | `0x1801af264` | Writes attacker path to TempPackages registry |
| `CMsiConfigurationManager::CleanupTempPackages` | `0x180184b90` | COM entry point (vtable 0x50) |
| `CleanupTempPackagesInternal` | `0x180186c6c` | Enumerates TempPackages, calls FDeleteFolder as SYSTEM |
| `FDeleteFolder` | `0x1801b29ac` | Recursive folder deletion with LockdownPath fallback |
| `LockdownPath` | `0x18000319c` | Overrides ACLs to force deletion |
| `CleanupTempPackagesOnTransactionCompletion` | `0x1801b10f4` | Alternative trigger path |

## References

- [Exodus Intelligence — Microsoft Windows Installer Folder Delete Privilege Escalation](https://blog.exodusintel.com/2026/07/06/microsoft-windows-installer-folder-delete-privilege-escalation/)
- [MSRC — CVE-2025-27727](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2025-27727)
- [NVD — CVE-2025-27727](https://nvd.nist.gov/vuln/detail/CVE-2025-27727)
