-
-
Save tophf/3fac58988fb94bd83aef69c9f18d1948 to your computer and use it in GitHub Desktop.
| <# 1. To patch dll in a protected folder like "c:\program files" run this script as Administrator. | |
| 2. If your Windows isn't configured to run ps1 files, you can run it from command prompt like this: | |
| powershell -ep bypass -noprofile "patch-chrome-mv2.ps1" | |
| #> | |
| param([string]$dll, [string]$dir = $pwd) | |
| function doPatch([string]$path, [string]$pathLabel = '') { | |
| $dll = $script:dll = if ($path.EndsWith('\')) { Join-Path $path chrome.dll } else { $path } | |
| if (!(Test-Path -literal $dll)) { return } | |
| $localAppData = [Environment]::GetFolderPath('LocalApplicationData') | |
| write-host -f yellow "`n$(@($pathLabel, (split-path $dll).Replace($localAppData, '%LocalAppData%')) -join ' ')" | |
| $script:stream = [IO.File]::Open($dll, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::ReadWrite) | |
| $reader = [IO.BinaryReader]$stream | |
| $enc = [Text.Encoding]::GetEncoding(28591) | |
| $features = @( | |
| '-ExtensionManifestV2Unsupported' | |
| '-ExtensionManifestV2Disabled' | |
| '-ExtensionsManifestV3Only' | |
| '+AllowLegacyMV2Extensions' | |
| ) | |
| write-host -f DarkGray "`tREADING Chrome.dll..." | |
| $stream.seek(0x3C, 0) >$null | |
| $coff = $reader.ReadUint32() + 4 | |
| $coffSize = 20 | |
| $stream.seek($coff, 0) >$null | |
| $bytes = $reader.ReadBytes($coffSize + 2) | |
| $is64 = [BitConverter]::ToUInt16($bytes, 0) -eq 0x8664 | |
| $isPE32 = [BitConverter]::ToUInt16($bytes, $coffSize) -eq 0x010b | |
| $stream.seek($coff + $coffSize + 24 + 4 * $isPE32, 0) >$null | |
| $imageBase = if ($isPE32) { $reader.ReadUInt32() } else { $reader.ReadUInt64() } | |
| # find sections | |
| $extraHeaderSize = [BitConverter]::ToUInt16($bytes, 16) | |
| $numSections = [BitConverter]::ToUInt16($bytes, 2) | |
| $stream.seek($coff + $coffSize + $extraHeaderSize, 0) >$null | |
| $sections = @{} | |
| foreach ($i in 1..$numSections) { | |
| $sec = $reader.ReadBytes(40) | |
| $i = $sec.IndexOf([byte]0) | |
| $name = $enc.GetString($sec, 0, $(if ($i -lt 0) { 8 } else { [math]::min(8, $i) })) | |
| if ($name -eq '.rdata' -or $name -eq '.data') { | |
| $sections[$name.substring(1)] = @{ | |
| addr = $imageBase + [uint64][BitConverter]::ToUInt32($sec, 12); | |
| size = [BitConverter]::ToUInt32($sec, 16); | |
| filePos = [BitConverter]::ToUInt32($sec, 20); | |
| } | |
| if ($sections.count -eq 2) { break } | |
| } | |
| } | |
| # .rdata section | |
| if (!$sections.rdata) { | |
| return "Could not find .rdata section" | |
| } | |
| $stream.seek($sections.rdata.filePos, 0) >$null | |
| $cur = 0 | |
| $step = 1MB | |
| $featArea = 1kB | |
| $featData = [ordered]@{} | |
| while ($cur -lt $sections.rdata.size) { | |
| $bytes = $reader.ReadBytes($step) | |
| $str = $enc.GetString($bytes) | |
| foreach ($feat in $features) { | |
| if ($featData[$feat]) { continue } | |
| $pos = $str.indexOf($feat.substring(1)) | |
| if ($pos -lt 0) { continue } | |
| $featData[$feat] = $sections.rdata.addr + $cur + $pos | |
| } | |
| if ($featData.count -eq $features.length) { break } | |
| $cur += $step - $featArea | |
| $stream.seek(-$featArea, [IO.SeekOrigin]::Current) >$null | |
| } | |
| if (!$sections.data) { | |
| return "Could not find .data section" | |
| } | |
| # .data section | |
| $stream.seek($sections.data.filePos, 0) >$null | |
| $len = $sections.data.size | |
| $bytes = $reader.ReadBytes($len) | |
| if ($is64) { $words = [uint64[]]::new($len -shr 3) } | |
| else { $words = [uint32[]]::new($len -shr 2) } | |
| [Buffer]::BlockCopy($bytes, 0, $words, 0, $len) | |
| $bytes = $null | |
| $copied = $false | |
| $wordType = $words[0].getType() | |
| foreach ($feat in $featData.Keys) { | |
| $needle = $featData[$feat] | |
| $needle = $needle -as $wordType | |
| $val = ($feat[0] -eq '+') -as $wordType | |
| $feat = $feat.substring(1) | |
| $i = $words.indexOf($needle) | |
| while ($i -ge 0 -and !($words[$i + 1] -in 0,1)) { | |
| $i = [Array]::IndexOf($words, $needle, $i + 1) | |
| } | |
| if (!++$i) { | |
| return "Could not find $feat pointer in .data section" | |
| } | |
| if ($words[$i] -eq $val) { | |
| write-host -f darkcyan "`tAlready patched $feat" | |
| continue | |
| } | |
| if (!$copied) { | |
| $copied = $true | |
| $stream.close() | |
| $script:stream = [IO.File]::Open($dll, [IO.FileMode]::Open, [IO.FileAccess]::ReadWrite, [IO.FileShare]::Read) | |
| if (test-path -literal "$dll.BAK") { | |
| write-host -f darkgray "`tFound an existing backup of the original dll." | |
| } else { | |
| write-host -f darkgray "`tBacking up the original dll..." | |
| [IO.File]::Copy($dll, "$dll.BAK") | |
| } | |
| } | |
| write-host -f cyan "`tPatching $feat..." | |
| $stream.seek($sections.data.filePos + $i * (4 + 4 * $is64), 0) >$null | |
| $stream.WriteByte($val) | |
| } | |
| write-host -f green "`tDONE." | |
| } | |
| function tryPatch($a, $b) { | |
| try { | |
| $err = doPatch $a $b | |
| } catch { | |
| $a = ([regex]'\): "(.+)"').match($Error[0]).Groups[1].Value | |
| $err = if ($a) { $a.Replace($dll, 'chrome.dll') } else { $Error[0] } | |
| } | |
| if ($stream) { | |
| $stream.close() | |
| $script:stream = $null | |
| } | |
| if ($err) { | |
| if ($err -is [string]) { write-host -f red "`t$err" } else { $err } | |
| $script:err = $true | |
| } | |
| [GC]::Collect() | |
| } | |
| $err = $false | |
| if ($dll) { | |
| tryPatch $dll | |
| } else { | |
| $pathsDone = @{} | |
| tryPatch ((gi -literal $dir).fullName + '\') 'CURRENT DIRECTORY' | |
| ('HKLM', 'HKCU') | %{ | |
| $hive = $_ | |
| ('', '\Wow6432Node') | %{ | |
| $key = "${hive}:\SOFTWARE$_\Google\Update\Clients" | |
| gci -ea silentlycontinue $key -r | gp | ?{ $_.CommandLine } | %{ | |
| $path = $_.CommandLine -replace '"(.+?\\\d+\.\d+\.\d+\.\d+\\).+', '$1' | |
| if (!$pathsDone[$path.toLower()]) { | |
| tryPatch $path REGISTRY | |
| $pathsDone[$path.toLower()] = $true | |
| } | |
| } | |
| } | |
| } | |
| } | |
| if ($err) { read-host "Press Enter key to exit" } |
i wonder if this same script would work on edge if i change the "chrome.dll" lines to "msedge.dll" :/
It's probably not that simple; it's already crashing on the Chromium DLL (changes are supposedly made to the file, but they're ignored as if they were just irrelevant noise), so the others would need fixes specific to non-branded versions and Edge (though my Edge doesn't seem to be picky and doesn't need that).
It still works today. Thank you a lot OP! ^_^
Anyway to do same on Linux?
I don't how but anyway it's already obsolete because Chrome 150 has removed these flags.
As a casual user, I’d like to ask: How do I run this program on a Windows laptop? Also, can it be implemented on Chromium-based browsers like Brave? Thank you.
This patch doesn't work on new Chromium-based browsers because they removed the underlying features.
Are there any other workarounds?
No, and Chrome doesn't show it anyway.