mv2ctl finds Chrome's Manifest V2 deprecation gates and applies verified in-memory edits after chrome.dll is loaded. It does not modify chrome.dll on disk.
If Chrome previously persisted the MV2-only disable reason (8388608), launch removes only that reason before startup, preserves unrelated disable reasons, and restamps Chrome's protected preferences. It creates a one-time Secure Preferences.mv2ctl.bak backup.
Version 3.8.0 adds the Chrome 156 rule and an opt-in restart option for an unpatched running browser (#13). The Chrome 156 rule was validated on Chrome for Testing 156.0.8078.12 x64, including MV2 installation and persistence after restart. Installed Google Chrome 155.0.8059.40 and the older Chrome 151-154 rules remain supported. Unknown layouts are accepted only when their complete rule-specific semantic signature passes; otherwise the analyzer fails closed.
Vietnamese instructions: README.vi.md
The recommended self-contained WinUI 3 GUI is:
.\artifacts\win-x64-gui\ChromeMv2Launcher.exeIt analyzes Chrome on startup, monitors whether Chrome is running, repairs persisted MV2 profile state when necessary, and exposes the verified RAM launch as one primary button. GitHub Releases use a normal ZIP containing the self-contained app rather than a self-extracting executable, reducing opaque packaging and making every runtime file inspectable.
Use Create one-click shortcut to add a Desktop shortcut that analyzes and launches Chrome with the RAM patch in one action. The app checks GitHub Releases at startup. When a newer version is published, Install update downloads the GUI ZIP, checks its SHA-256 digest, extracts it into a per-user versioned directory, updates the Desktop shortcut, and opens the new app. Open Chrome normally remains available if the current Chrome build has no verified patch.
After a successful patched or normal launch, the GUI exits immediately while Chrome keeps running. This applies to both the launch button and the Desktop shortcut. If analysis or launch fails, the GUI stays open to display the error. Advanced users can pass Chrome arguments after --, for example ChromeMv2Launcher.exe --auto-launch -- --user-data-dir=E:\Chrome-MV2-Profile.
When Chrome is already running, both the one-click shortcut and the executable itself first verify every RAM patch byte in the browser root process. Only a fully verified session with the same user-data directory is reused. The check analyzes that process's loaded chrome.dll, including an older version still running after an on-disk Chrome update. Unpatched, partially patched, inaccessible, or unsupported sessions are not reused or modified. URLs and profile arguments are forwarded, with or without the -- separator. Use ChromeMv2Launcher.exe --show-ui to open settings and update controls without taking this shortcut; the windowless reuse path does not run the GUI update check.
Close and restart unpatched Chrome is off by default. Enable it in the GUI (use --show-ui if necessary); the preference is saved per user and also applies to the one-click shortcut. Each restart requires confirmation. The launcher first verifies the complete original-byte patch set, executable, Windows user/session, and user-data directory; partial, unsupported, inaccessible, or unrelated sessions are not closed. Normal window closure is tried first. Background Chrome or a cancelled unload prompt requires a separate Force close confirmation, with Cancel as the default. Unsaved work may be lost; cancelling either dialog does not force termination. All windows/profiles sharing that browser session are affected. The consent is bound to the process ID and creation time, and the current on-disk Chrome is analyzed before closing and again before relaunching. The final launch guard still requires all Chrome processes to be gone.
The GUI supports Vietnamese, English, and Simplified Chinese. It selects the Windows UI language on first run and persists the user's choice under %LOCALAPPDATA%\ChromeMv2Launcher.
The self-contained Windows x64 build is at artifacts\win-x64-self-contained\mv2ctl.exe. It does not require a separately installed .NET runtime.
.\artifacts\win-x64-self-contained\mv2ctl.exe analyze
.\artifacts\win-x64-self-contained\mv2ctl.exe launch- Scans only the executable
.textPE section. - Does not use an expected file offset or RVA.
- Enumerates every byte-pattern candidate and applies structural checks.
mv2ctl probelists possible MV2 checker/clone sites using a broader read-only heuristic. Probe results never authorize a patch.- Requires the exact rule-specific set of semantic matches; missing or extra candidates abort.
- Chrome 152 rule v5, Chrome 153 rule v6, Chrome 154 rule v7, and Chrome 155 rule v8 locate both split
Extension&checker copies, the integer-argument checker, and the compiler-generated install/disable/re-enable clones. - Rules v8/v9 verify the normal policy call, the relocated unsupported-manifest error path, and their shared callback before accepting the Chrome 155/156 install gate. Chrome 155 requires localized error resource 8129; Chrome 156 requires 8121. Neither rule accepts an arbitrary resource ID.
- Locates and neutralizes the startup branch whose verified target constructs disable reason
0x800000. - Verifies every original byte in the remote process before writing any target.
- Reads every byte back after writing and flushes the instruction cache.
- Never writes to
chrome.dllon disk. - New patched launches still require Chrome to be fully closed. The GUI may open another window only in an existing browser session whose complete RAM patch set has been verified; it never patches that session during the check.
dotnet build .\ManifestV2.slnx -c Release
dotnet test .\ManifestV2.slnx -c Release
dotnet run --project .\src\Mv2Enabler -c Release -- analyze
dotnet run --project .\src\Mv2Enabler -c Release -- smoke-test
dotnet run --project .\src\Mv2Enabler -c Release -- functional-ui-test --extension .\test-extensionThe patch engine lives in src\Mv2Enabler.Core; both the CLI and WinUI 3 app reference the same implementation.
The automated smoke test creates a uniquely named profile below %TEMP%\mv2ctl-smoke, launches headless Chrome, applies and verifies the RAM patch, confirms Chrome remains alive, stops only the process tree it created, and removes that temporary profile.
The functional UI test uses Chrome's normal Load unpacked workflow, selects test-extension, and requires a DevTools target whose chrome-extension:// host exactly matches the ID derived from the test manifest's fixed public key. It then closes Chrome, launches the same temporary profile again through the RAM patcher, and requires the persistent MV2 background page to return. Its profile is uniquely named and removed afterward. The test briefly opens a Chrome window and restores the clipboard text it temporarily uses for the native folder picker.
After packaging, run .\scripts\test-gui-launch.ps1 to verify automatic shortcut launch, manual launch, normal Chrome launch, windowless reuse with URL forwarding, explicit GUI access, and rejection of unpatched or mismatched-profile sessions. It uses temporary profiles and checks that the launcher exits while Chrome's DevTools endpoint remains available.
The GUI test also covers restart opt-in, graceful confirmation/cancellation, background force-close confirmation/cancellation, and verified patched reuse after restart. It backs up and restores the restart preference. RestartSessionIntegrationTests uses owned temporary headless sessions to test refusal of wrong-profile, partially patched, stale-consent, and already-patched browsers. Close your own Chrome before running integration tests; they never terminate a pre-existing browser as test setup.
Close every Chrome window and background process, then run:
dotnet run --project .\src\Mv2Enabler -c Release -- launchChrome arguments can be passed after --:
dotnet run --project .\src\Mv2Enabler -c Release -- launch -- --user-data-dir=E:\Chrome-MV2-ProfileEvery new browser session must start through mv2ctl; the in-memory change disappears when Chrome exits. An MV2 extension only needs to be loaded once: later patched launches preserve the installed entry and prevent Chrome from persisting the unsupported-manifest disable reason again.
-
Launch Chrome through
mv2ctl. -
Open
chrome://extensionsand enable Developer mode. -
Choose Load unpacked and select the repository's
test-extensiondirectory. -
Confirm MV2 Gate Smoke Test remains enabled and its toolbar badge reads
MV2. -
Open
https://example.comand run this in DevTools:document.documentElement.dataset.mv2GateSmokeTest
The result should be
"running".
The test extension exercises a persistent MV2 background page, browser_action, a blocking webRequest listener, storage, and a content script.
mv2ctl analyze [--chrome PATH] [--dll PATH] [--json]
mv2ctl probe [--chrome PATH] [--dll PATH] [--json]
mv2ctl launch [--chrome PATH] [--timeout SECONDS] [--json] [-- CHROME_ARGS]
mv2ctl smoke-test [--chrome PATH] [--timeout SECONDS] [--json]
mv2ctl functional-ui-test --extension PATH [--chrome PATH] [--timeout SECONDS] [--json]
The launcher never modifies Google-signed binaries. Profile recovery is deliberately narrow: it removes only the MV2 disable bit, preserves other disable reasons, discovers the current preference MAC seed from resources.pak by validating existing MACs, and updates Chrome's protected preference hashes.