22nd Survey Division
Browser Security Credential Access Process Hollowing COM Injection

ChromElevator: ABE Bypass via Target-Context COM Injection

Research: Chrome ABE COM Injection Author: George Wu Updated: October 2026

T1539 — Steal Web Session Cookie

T1555.003 — Credentials from Web Browsers

T1055 — Process Injection

// What is this?
Chrome's App-Bound Encryption has a guard that only hands the vault key to Chrome itself. ChromElevator doesn't break the guard — it runs as Chrome.

In July 2024, Google deployed ABE to make browser credential theft impossible without admin rights. The old DPAPI approach broke overnight. The naive CDP workaround (debug port) is noisy and leaves a detectable network socket open. ChromElevator takes the opposite path: process hollowing + reflective injection + direct syscalls. The COM service validates the caller path, sees Chrome, and hands over the AES master key. No debug ports. No admin required. No disk writes. Confirmed working: Chrome 144, Brave, Edge, Avast.

What App-Bound Encryption Actually Does

Before July 2024, stealing Chrome credentials required three steps: copy the SQLite cookie database, call Windows's DPAPI decryption API, read the plaintext. Any program running as the logged-in user could do it. That's why infostealers were so effective.

Google's fix introduced a security guard. Imagine Chrome's AES master key is locked in a vault. A COM service — a separate Windows process called the Chrome Elevation Service — holds the combination. Its rule: I only open the vault for processes that can prove they are the real Chrome browser.

The proof is path validation. When a process asks the Elevation Service to decrypt the key, the service checks: "What executable file is making this request? Does its install path match Chrome?" If the path normalises to C:\Program Files\Google\Chrome\Application, the key is returned. Any other path gets rejected.

// Why DPAPI-in-DPAPI

The ABE key is actually wrapped in two layers of DPAPI encryption simultaneously: one using the calling user's credentials, one using the Windows SYSTEM account. Both layers are only unwrapped by the Elevation Service — which runs as SYSTEM and can impersonate the current user. A regular user-level process can't replicate this without cracking SYSTEM first.

Two Ways Past the Guard

Once ABE shipped, researchers found two categories of bypass:

Approach 1 — CDP (Debug Port): Don't touch the vault. Make Chrome unlock it for you. Launch Chrome with --remote-debugging-port=9222 Connect via WebSocket Send Storage.getCookies() Chrome decrypts its own data, returns plaintext ────────────────────────────────────────── Detection: network socket on 9222, Chrome killed & relaunched, hidden window at -32000,-32000, non-explorer parent Approach 2 — COM Injection (ChromElevator): Become Chrome. Ask the guard directly. Hollow a new chrome.exe process Inject encrypted payload via reflective DLL Payload calls IElevator::DecryptData from inside Chrome's address space Guard checks path → sees Chrome → returns AES key ────────────────────────────────────────── Detection: COM call from unexpected chrome.exe instance, process creation with suspended flag, unusual thread origin

CDP is the simpler technique and widely documented. ChromElevator is the surgical approach: no debug ports, no Chrome restart, no localhost socket. The attack surface for defenders is narrower and the COM call looks like normal browser behaviour.

ChromElevator: How It Works (Layman)

Step 1 — The Hollow Shell

ChromElevator creates a new chrome.exe process in a suspended state before any Chrome code runs. At this point Windows has already loaded the legitimate Chrome executable and set the process's identity — path, headers, everything. From Windows's perspective, this is Chrome.

The tool then unmaps Chrome's actual code from the process's memory and writes its own payload into that space. When the process resumes, it runs the payload. The process still shows as chrome.exe at the correct install path.

Step 2 — The Encrypted Payload

The DLL that performs the credential extraction is never stored on disk. It lives inside the main binary as an encrypted blob, encrypted with ChaCha20 at compile time. There are no readable strings, no recognisable API names, no patterns that signature-based detection can match against. The payload is decrypted into memory at runtime only.

Step 3 — Hell's Gate

Normal Windows programs call system functions like CreateProcess or VirtualAllocEx through Windows's official library (ntdll.dll). Security software instruments these calls to log and alert on suspicious behaviour.

ChromElevator uses a technique called Hell's Gate: instead of calling ntdll's functions by name, it reads ntdll's memory to find the actual syscall numbers, then calls the kernel directly. EDR hooks in ntdll are completely skipped. The calls are invisible to most endpoint security tools.

Step 4 — Reflective DLL Injection

The payload loads itself. Rather than using Windows's standard DLL loader (which creates filesystem traces and is monitored by security tools), the DLL contains its own mini-loader that maps it into Chrome's memory from scratch. After it runs, the DLL destroys its own PE headers in memory — so even a memory-scanning tool looking for loaded modules has less to find.

Step 5 — The COM Call

Now running inside a process that Windows identifies as chrome.exe at Chrome's real install path, the payload calls the Chrome Elevation Service's IElevator::DecryptData COM method. The Elevation Service performs path validation, normalises the caller's path, compares it — and finds Chrome. The 32-byte AES master key is returned.

With the master key, every v20-prefixed value in Chrome's databases is AES-256-GCM decryptable: session cookies, saved passwords, payment card data.

Research Output

ChromElevator tool output showing extracted browser credentials

ChromElevator extraction output — AES master key recovered, credential databases decrypted

ChromElevator showing multi-browser support across Chrome Brave Edge and Avast

Multi-browser run — same COM injection technique, different CLSIDs/IIDs per vendor

ChromElevator process hollowing and injection flow

Process hollowing chain — suspended chrome.exe, payload mapped, COM call issued from within Chrome's address space

// Validated — October 2026

Confirmed working across all Chromium-based browsers that implement ABE:

No administrator privileges required on any of the above. x64 and ARM64 verified.

Chrome 144: The Guard Gets a Promotion

In November 2025, Chromium commit 49620496b8f0b7c0c63e2666a82e01180df3f4c3 landed: "Add two new interfaces on IElevator." Chrome 144 ships with a second interface family — IElevator2 alongside the original IElevator.

The original IElevator chain had six interfaces: one base, five browser-specific flavours (Chrome Stable, Beta, Dev, Canary, Chromium). Chrome 144 doubles this to twelve by adding a parallel IElevator2 tree, each member inheriting the two new methods RunIsolatedChrome and AcceptInvitation.

IElevator (original — Chrome 127-143): IUnknown └─ IElevator ← DecryptData at vtable slot 5 ├─ IElevatorChrome ├─ IElevatorChromeBeta └─ IElevatorChromeCanary IElevator2 (new — Chrome 144+): IUnknown └─ IElevator ← DecryptData still at slot 5 └─ IElevator2 ← RunIsolatedChrome slot 6, AcceptInvitation slot 7 ├─ IElevator2Chrome (IID: {1BF5208B-295F-4992-B5F4-3A9BB6494838}) ├─ IElevator2ChromeBeta └─ IElevator2ChromeCanary

The important detail: DecryptData is still at the same vtable offset in IElevator2. The inheritance chain is IUnknown → IElevator → IElevator2 → IElevator2Chrome, so the first six method slots are identical to the old interface. Tools that statically hardcode the IElevatorChrome IID fail on Chrome 144 — not because the vtable layout changed, but because the registered interface has changed. Tools that dynamically resolve the CLSID and IID from the type library, or detect the Chrome 144 boundary and switch IIDs, continue to work.

The RunIsolatedChrome and AcceptInvitation methods appear to be groundwork for Mojo-based communication between elevated and non-elevated Chrome processes — a signal that future ABE hardening may involve verifying the calling process through Mojo IPC rather than path string matching alone.

Bypass Approaches Compared

Method Admin Required Network Artefacts Disk Writes EDR Visibility
DPAPI direct
Pre-Chrome 127
No None None Low — API call only
CDP debug port
Chrome 127+
No TCP 9222 on loopback, WebSocket None High — process args, port, parent chain
COM injection (ChromElevator)
Chrome 127–144+
No None None Medium — process hollowing detectable if telemetry covers it
Admin SYSTEM DPAPI
Requires elevation
Yes None None Low — standard system call

Detection

PowerShell — COM Injection Detection (ChromElevator)
# Chrome processes created in SUSPENDED state (hollowing indicator)
# Look for chrome.exe with unusual parent (not explorer, not chrome itself)
Get-CimInstance Win32_Process -Filter "Name='chrome.exe'" | ForEach-Object {
  $parent = Get-CimInstance Win32_Process -Filter "ProcessId=$($_.ParentProcessId)"
  if ($parent.Name -notmatch "explorer|chrome|GoogleUpdate") {
    [PSCustomObject]@{
      ChromePID   = $_.ProcessId
      Parent      = $parent.Name
      ParentPID   = $_.ParentProcessId
      CommandLine = $_.CommandLine
    }
  }
}

# COM calls to ChromeElevationService from unexpected callers
# Event ID 4688 with ProcessName=elevation_service.exe + unusual parent
Get-WinEvent -FilterHashtable @{LogName='Security';Id=4688} -MaxEvents 500 |
  Where-Object { $_.Message -match 'elevation_service' } |
  Select-Object TimeCreated, Message
If this flags: A chrome.exe process with a non-browser parent is a strong hollowing indicator. Elevation Service calls from unexpectedly-created chrome.exe instances confirm COM injection. Cross-reference with Sysmon Event ID 8 (CreateRemoteThread) or Event ID 25 (ProcessTampering) for memory injection confirmation.
Detection Type Indicator Applies To
Process chrome.exe with non-browser parent (not explorer.exe, not chrome.exe) COM injection + CDP
Process chrome.exe created with CREATE_SUSPENDED flag (Sysmon) COM injection
Memory chrome.exe with no PE headers mapped (Sysmon Event 25) COM injection (post-hollow)
COM elevation_service.exe serving DecryptData to unusual chrome.exe instance COM injection
Process chrome.exe with --remote-debugging-port flag CDP only
Network TCP 9222 listening on loopback CDP only
Behavioral Chrome killed → Chrome relaunched hidden → localhost WebSocket CDP only

What Doesn't Catch It

Signature-based AV scanning the ChromElevator binary sees only a ChaCha20-encrypted blob. No recognisable API names, no plaintext strings, no known shellcode patterns. The syscalls bypass ntdll hooks, so user-mode EDR telemetry misses the allocation and injection calls unless the EDR instruments at kernel level (minifilter or ETW kernel provider). The COM call to the Elevation Service looks identical to a legitimate Chrome startup sequence.

Defensive Recommendations

For Endpoint Security Teams

For Web Application Developers

Related Research

Research conducted for defensive purposes. All testing on owned infrastructure. Understanding injection-based credential access enables detection engineers to build telemetry that catches the technique rather than its artefacts.