# Root Cause Analysis — CVE-2024-43626

## Metadata

| Field | Value |
|---|---|
| **CVE** | CVE-2024-43626 |
| **Binary** | tapisrv.dll (Windows Telephony Service) |
| **Severity** | Important (CVSS 7.8) |
| **Impact** | Elevation of Privilege |
| **Bug Class** | CWE-122: Heap-based Buffer Overflow (missing null terminator validation) |
| **Patch** | November 2024 Patch Tuesday |
| **Discoverers** | Chen Le Qi, Nguyen Dang Nguyen (STAR Labs SG) |

## 1. Executive Summary

CVE-2024-43626 is a heap OOB read/write vulnerability in the Windows Telephony Service (`tapisrv.dll`) caused by missing null terminator validation when reading a user-controlled registry value. The `GetPriorityList` function reads a string value from the current user's registry hive and passes it to `_wcsupr()`, which relies on a null terminator to determine string length. An attacker who writes a value without a null terminator causes `_wcsupr()` to read and modify adjacent heap chunks in the `svchost.exe` process running as SYSTEM.

A secondary info leak exists: `SetPriorityList` calls `lstrlenW()` on the same unterminated buffer, reading past the allocation into adjacent chunks. The resulting data (including heap pointers) is written back to the registry, allowing the attacker to query it and break ASLR.

## 2. Vulnerable Functions

### GetPriorityList

```c
void GetPriorityList(HKEY hKey, LPCWSTR RequestMediaCallName, wchar_t **pOutput)
{
    if (RegQueryValueExW(hKey, RequestMediaCallName, 0, &Type, 0, &cbData) || !cbData)
    {
        *pOutput = 0;
    }
    else
    {
        v6 = HeapAlloc(ghTapisrvHeap, HEAP_ZERO_MEMORY, cbData + 2);
        v7 = (wchar_t *)v6;
        if (v6)
        {
            *(_WORD *)v6 = '"';
            if (!RegQueryValueExW(hKey, RequestMediaCallName, 0, &Type, (LPBYTE)v6 + 2, &cbData))
            {
                _wcsupr(v7);    // BUG: no null terminator check
                *pOutput = v7;
            }
        }
    }
}
```

### GetPriorityListTReqCall

```c
void GetPriorityListTReqCall(wchar_t **pOutput)
{
    if (!RegOpenCurrentUser(KEY_ALL_ACCESS, &hkCU))
    {
        if (!RegOpenKeyExW(hkCU,
                L"Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\HandoffPriorities",
                0, KEY_READ, &hkHandOffPriority))
        {
            GetPriorityList(hkHandOffPriority, L"RequestMakeCall", pOutput);
            RegCloseKey(hkHandOffPriority);
        }
        RegCloseKey(hkCU);
    }
}
```

### SetPriorityList (info leak)

```c
LSTATUS SetPriorityList(HKEY hKey, LPCWSTR lpValueName, LPCWSTR lpString)
{
    if (!lpString)
        return RegDeleteValueW(hKey, lpValueName);
    v7 = lstrlenW(lpString);  // BUG: reads past allocation without null terminator
    return RegSetValueExW(hKey, lpValueName, 0, REG_SZ, (const BYTE *)lpString + 2, 2 * v7);
}
```

## 3. Root Cause

The vulnerability has two aspects:

### OOB Write

`_wcsupr()` converts a wide string to uppercase by iterating character-by-character until it finds a null terminator (L'\0'). When the registry value lacks a null terminator, `_wcsupr()` continues past the allocation boundary into adjacent heap chunks, modifying any lowercase ASCII characters it encounters.

### Info Leak (OOB Read)

`lstrlenW()` scans for a null terminator to determine string length. Without one, it reads past the allocation into adjacent heap data. `RegSetValueExW` then writes this extended data (which may include heap metadata and pointers) back to the registry. The attacker reads the registry value to obtain leaked heap addresses.

The info leak can be performed safely (without the OOB write) by starting the registry value with a non-ASCII character. Since `_wcsupr()` stops processing at non-ASCII characters, the OOB write is avoided while `lstrlenW()` still reads past the buffer.

### Recommended fix

Replace `RegQueryValueExW()` with `RegGetValueW()`, which enforces data types and automatically appends null terminators for string values (REG_SZ).

## 4. Reachability / Attack Surface

### RPC interface

The Telephony Service exposes three RPC functions:
- `ClientAttach` (opnum 0): Returns a context handle
- `ClientRequest` (opnum 1): Dispatcher — sub-opnum 69 = `LSetAppPriority`
- `ClientDetach` (opnum 2): Cleanup

### Attack path

```
Attacker writes to HKCU\...\Telephony\HandOffPriorities\RequestMakeCall
  (REG_BINARY or REG_SZ without null terminator)
  -> RPC call: ClientAttach() to get context handle
  -> RPC call: ClientRequest(opnum 69 = LSetAppPriority)
    -> GetPriorityListTReqCall
      -> RegOpenCurrentUser(attacker's hive)
        -> GetPriorityList
          -> RegQueryValueExW (reads unterminated value)
          -> _wcsupr() reads/writes past allocation  // OOB WRITE
        -> SetPriorityList
          -> lstrlenW() reads past allocation  // OOB READ (INFO LEAK)
          -> RegSetValueExW writes leaked data back to registry
  -> Attacker reads RequestMakeCall value to extract heap pointers
```

### Service context

The Telephony Service runs as `NT AUTHORITY\SYSTEM` inside `svchost.exe`. The heap corruption occurs in this SYSTEM-privileged process.

### Privilege required

Low (any authenticated local user can write to their own HKCU registry and make RPC calls to the Telephony Service).

## 5. Exploitation Strategy

1. **Info leak phase**: Write non-ASCII-prefixed REG_BINARY value without null terminator. Trigger RPC call. Read back the registry value — it now contains heap pointers from adjacent svchost.exe chunks. This gives the attacker a heap address in the SYSTEM process, breaking ASLR.

2. **Heap shaping**: Use the Telephony Service's own operations to create a predictable heap layout. Position a useful structure (e.g., function pointer, ACL, token reference) adjacent to the allocation.

3. **OOB write phase**: Write an ASCII-character-containing value without null terminator. Trigger RPC call. `_wcsupr()` corrupts adjacent heap data by uppercasing characters. With careful heap shaping, this can modify a controlled field.

4. **Code execution**: Chain the corrupted field (e.g., hijacked function pointer or corrupted security descriptor) to achieve code execution as SYSTEM.

## 6. Detection

### YARA rule

```yara
rule CVE_2024_43626_tapisrv_heap_oob {
    meta:
        description = "Detects exploit artifacts for CVE-2024-43626 (tapisrv.dll heap OOB)"
        cve = "CVE-2024-43626"
        author = "OnlyFm252"
    strings:
        $reg_path = "HandoffPriorities" wide
        $reg_value = "RequestMakeCall" wide
        $rpc_uuid = { 20 65 5F 2F 46 CA 67 10 B3 19 00 DD 01 06 62 DA }
        $tapi_attach = "ClientAttach" ascii
        $reg_binary = "RegSetValueExW" ascii
    condition:
        uint16(0) == 0x5A4D and
        $reg_path and $reg_value and
        2 of ($rpc_uuid, $tapi_attach, $reg_binary)
}
```

### Sigma rule

```yaml
title: CVE-2024-43626 Telephony Service Registry Manipulation
id: d9e8f5a2-2024-43626-tapisrv-heap
status: experimental
description: Detects writes to Telephony HandOffPriorities registry key without proper null termination
references:
    - https://starlabs.sg/advisories/24/24-43626/
    - https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-43626
logsource:
    product: windows
    category: registry_set
detection:
    selection:
        TargetObject|contains: '\Telephony\HandoffPriorities\RequestMakeCall'
    filter_normal:
        Image|endswith: '\svchost.exe'
    condition: selection and not filter_normal
falsepositives:
    - Legitimate telephony applications modifying handoff priorities
level: high
```

### Sysmon config

```xml
<!-- CVE-2024-43626: Telephony Service registry abuse -->
<RuleGroup groupRelation="or">
  <RegistryEvent onmatch="include">
    <Rule groupRelation="and">
      <TargetObject condition="contains">Telephony\HandoffPriorities</TargetObject>
      <Image condition="excludes">svchost.exe</Image>
    </Rule>
  </RegistryEvent>
</RuleGroup>
```

## 7. References

- STAR Labs advisory: https://starlabs.sg/advisories/24/24-43626/
- MSRC: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-43626
