MCPcopy Create free account
hub / github.com/KingOfTheNOPs/CDP-Enable-BOF

github.com/KingOfTheNOPs/CDP-Enable-BOF @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
62 symbols 190 edges 6 files ⚖ GPL-3.0 27 documented · 44% updated 10d ago★ 126

Browse by type

Functions 58 Types & classes 4
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

CDP-Enable-BOF

CDP-Enable-BOF enables the Chrome DevTools Protocol in a running x64 Chrome or Edge browser. It includes separate execution paths for ordinary browser processes and Chrome's Windows Process Isolation boundary.

Based on CDP-Enable and Modern Session Hijacking by Living off the DevTools Protocol by Cedric Van Bockhaven

Usage

cdp-enable <edge|chrome|chrome-iso> [port]

The default port is 9222.

cdp-enable chrome
cdp-enable chrome-iso
cdp-enable edge 9301

Use chrome for an ordinary Chrome process and chrome-iso for Chrome running with Process Isolation.

How It Works

The normal chrome and edge modes:

  • finds the requested live browser process and its top-level window
  • locates the loaded browser module (msedge.dll or chrome.dll)
  • reads the module’s PE headers and sections from the remote process
  • resolves these internal symbols at runtime using masked byte signatures:
  • StartRemoteDebuggingServer
  • operator new
  • TCPServerSocketFactory::CreateForHttpServer
  • TCPServerSocketFactory vtable
  • allocates two small remote stubs plus a context block
  • temporarily installs a remote window procedure
  • triggers that window procedure on the browser UI thread
  • calls StartRemoteDebuggingServer on the requested port

Running the final internal call on the browser UI thread is the key trick that makes this reliable in the presence of CFG / TLS / CET-sensitive execution.

chrome-iso uses only query-limited handles to the isolated process. It:

  • enumerates visible Chrome windows and identifies Chrome rather than Edge
  • resolves the installation root with QueryFullProcessImageNameW
  • selects the versioned chrome.dll whose PE image size matches the live process
  • resolves the CDP symbols from masked signatures in that local image
  • uses Chrome's WindowImpl dispatch and a synchronous WM_COPYDATA buffer to make its UI-thread stack executable
  • transfers execution to the buffer with an existing-image User32 hook
  • restores the affected window state and calls StartRemoteDebuggingServer

Both modes reject execution unless the server, allocator, factory-method, and final vtable resolutions each produce exactly one candidate.

Build

mingw32-make

This produces cdp_enable_bof.o and cdp_enable_iso_bof.o. Load cdp_enable_bof.cna from Cobalt Strike → Script Manager; the script chooses the correct object for each command.

Validate

Use the bundled Python script to prove CDP is up and reachable:

python .\grab_cookies.py --port 9222 --output cookies.json

If CDP is working, the script will:

  • resolve the browser websocket from http://127.0.0.1:9222/json/version
  • connect to the websocket
  • dump cookies to cookies.json

Optional domain filter:

python .\grab_cookies.py --port 9001 --domain microsoft.com --output ms_cookies.json

Common Issue

Issue: "Failed to resolve symbol signatures"

Cause: Edge version mismatch - signatures are version-specific Solution: See "Finding New Signatures" below

Tested ordinary Chrome version: 151.0.7922.174 Tested process-isolated Chrome version: 151.0.7922.174 Tested Edge versions: 151.0.4129.101

Finding New Signatures

These scripts are used to find new signatures and supporting runtime inputs for updated browser versions:

  • StartRemoteDebuggingServer
  • operator new
  • TCPServerSocketFactory::CreateForHttpServer
  • derived TCPServerSocketFactory vtable information

Pull the DLLs

Copy the DLL from the browser build you are targeting into the working directory. On this machine, the installed DLLs live under versioned subdirectories:

Copy-Item "C:\Program Files\Google\Chrome\Application\<version>\chrome.dll" .
Copy-Item "C:\Program Files (x86)\Microsoft\Edge\Application\<version>\msedge.dll" .

Pull the matching PDBs

For Chrome:

& 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\symchk.exe' /v chrome.dll /s srv*C:\symbols*https://chromium-browser-symsrv.commondatastorage.googleapis.com

For Edge:

symchk /v /ocx edge-symchk.txt /s SRV*c:\symbols*https://msdl.microsoft.com/download/symbols .\msedge.dll

Run the scripts

Find StartRemoteDebuggingServer:

python .\find_start_server.py .\chrome.dll <full path to chrome.dll.pdb>
python .\find_start_server.py .\msedge.dll <full path to msedge.dll.pdb>

For the chrome-iso object, validate every embedded masked signature against a candidate Chrome DLL with:

python .\find_cdp_inputs.py .\chrome.dll --validate-bof-signatures

start, new, and entry1 should report exactly one hit. entry0 is an optional destructor aid: zero hits selects the unique executable-vtable fallback, while up to 32 hits are resolved by their relationship to entry1. Pass an explicit BOF source path after --validate-bof-signatures when needed. To derive a candidate mask after identifying the symbol RVAs in two builds:

python .\find_cdp_inputs.py .\new\chrome.dll --diff-mask .\old\chrome.dll <old-rva> <new-rva> <length>

Example Edge output:

{
  "binary": "C:\\Users\\antrovmp\\Desktop\\CDP-Enable-BOF\\msedge.dll",
  "pdb": "c:\\symbols\\msedge.dll.pdb\\23DB3E4A1AB4F3B44C4C44205044422E1\\msedge.dll.pdb",
  "symbol": "?StartRemoteDebuggingServer@DevToolsAgentHost@content@@SAXV?$unique_ptr@VDevToolsSocketFactory@content@@U?$default_delete@VDevToolsSocketFactory@content@@@__Cr@std@@@__Cr@std@@AEBVFilePath@base@@1W4RemoteDebuggingServerMode@12@@Z",
  "signature_rva": "0x0321EAC2",
  "signature_va": "0x000000018321EAC2",
  "signature_length": 30,
  "signature_hex": "41 57 41 56 41 54 56 57 55 53 48 83 EC 50 44 89 CD 4C 89 C3 48 89 D7 48 89 CE 48 8B 05 5D",
  "signature_c_initializer": "0x41, 0x57, 0x41, 0x56, 0x41, 0x54, 0x56, 0x57, 0x55, 0x53, 0x48, 0x83, 0xEC, 0x50, 0x44, 0x89, 0xCD, 0x4C, 0x89, 0xC3, 0x48, 0x89, 0xD7, 0x48, 0x89, 0xCE, 0x48, 0x8B, 0x05, 0x5D",
  "copy_to_code": "Use this for EDGE_START_SIG if analyzing msedge.dll, or CHROME_START_SIG if analyzing chrome.dll.",
  "text_hits": 1
}

Copy signature_c_initializer into the start signature array in cdp_enable_bof.c:

  • Edge: EDGE_START_SIG at line 168
  • Edge mask: EDGE_START_MASK at line 181
  • Chrome: CHROME_START_SIG at line 194
  • Chrome mask: CHROME_START_MASK at line 207

For Edge, replace the bytes in EDGE_START_SIG with the new signature_c_initializer. For Chrome, do the same with CHROME_START_SIG.

Find the supporting inputs:

python .\find_cdp_inputs.py .\chrome.dll <full path to chrome.dll.pdb>
python .\find_cdp_inputs.py .\msedge.dll <full path to msedge.dll.pdb>

Example Edge output:

{
  "binary": "msedge.dll",
  "operator_new": {
    "rva": "0x036335D8",
    "va": "0x00000001836335D8",
    "signature": "40 53 48 83 EC 20 48 8B D9 EB ?? 48 8B CB E8 ?? ?? ?? ?? 85 C0 74 ?? 48 8B CB",
    "copy_to_code": "OPERATOR_NEW_SIG"
  },
  "tcp_server_socket_factory": {
    "create_for_http_server": {
      "rva": "0x016C7310",
      "va": "0x00000001816C7310",
      "signature_hex": "48 89 D0 0F B7 51 08 48",
      "signature_c_initializer": "0x48, 0x89, 0xD0, 0x0F, 0xB7, 0x51, 0x08, 0x48",
      "copy_to_code": "EDGE_ENTRY1_SIG",
      "vtable_rva": "0x0FBDCA70",
      "vtable_va": "0x000000018FBDCA70"
    },
    "layout": {
      "size": 16,
      "vtable_offset": 0,
      "port_offset": 8
    }
  }
}

Important fields and where they go:

  • operator_new.copy_to_code -> OPERATOR_NEW_SIG at line 221
  • tcp_server_socket_factory.create_for_http_server.copy_to_code -> EDGE_ENTRY1_SIG at line 242 or CHROME_ENTRY1_SIG at line 246
  • tcp_server_socket_factory.layout is a sanity check for the object layout the BOF expects: size 16, vtable offset 0, port offset 8

The script also derives the TCPServerSocketFactory vtable location. The BOF still resolves that through the VTABLE_ENTRY0_SIG / VTABLE_ENTRY0_MASK helper at lines 228 and 234 if that helper drifts.

Notes

  • x64 only
  • tested with both msedge.exe and chrome.exe
  • the BOF only targets the browser mode explicitly passed as an argument
  • the current Chrome resolver uses a stronger masked CreateForHttpServer signature to avoid false positives across patch-level browser changes

Core symbols most depended-on inside this repo

browse all functions →

Shape

Function 35
Method 23
Class 4

Languages

Python74%
C26%

Modules by API surface

pe_signature_finder.py32 symbols
cdp_enable_bof.c16 symbols
grab_cookies.py5 symbols
find_cdp_inputs.py5 symbols
find_start_server.py4 symbols

For agents

$ claude mcp add CDP-Enable-BOF \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page