-
-
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..." | |
| [void]$stream.seek(0x3C, 0) | |
| $coff = $reader.ReadUint32() + 4 | |
| $coffSize = 20 | |
| [void]$stream.seek($coff, 0) | |
| $bytes = $reader.ReadBytes($coffSize + 2) | |
| $is64 = [BitConverter]::ToUInt16($bytes, 0) -eq 0x8664 | |
| $isPE32 = [BitConverter]::ToUInt16($bytes, $coffSize) -eq 0x010b | |
| [void]$stream.seek($coff + $coffSize + 24 + 4 * $isPE32, 0) | |
| $imageBase = if ($isPE32) { $reader.ReadUInt32() } else { $reader.ReadUInt64() } | |
| # find sections | |
| $extraHeaderSize = [BitConverter]::ToUInt16($bytes, 16) | |
| $numSections = [BitConverter]::ToUInt16($bytes, 2) | |
| [void]$stream.seek($coff + $coffSize + $extraHeaderSize, 0) | |
| $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" | |
| } | |
| [void]$stream.seek($sections.rdata.filePos, 0) | |
| $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) { break } | |
| $featData[$feat] = $sections.rdata.addr + $cur + $pos | |
| } | |
| if ($featData.count -eq $features.length) { break } | |
| $cur += $step - $featArea | |
| [void]$stream.seek(-$featArea, [IO.SeekOrigin]::Current) | |
| } | |
| if (!$sections.data) { | |
| return "Could not find .data section" | |
| } | |
| # .data section | |
| [void]$stream.seek($sections.data.filePos, 0) | |
| $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..." | |
| [void]$stream.seek($sections.data.filePos + $i * (4 + 4 * $is64), 0) | |
| $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 | |
| if ($a) { $err = $a.Replace($dll, 'chrome.dll') } else { $Error[0] } | |
| } | |
| if ($stream) { | |
| $stream.close() | |
| $script:stream = $null | |
| } | |
| if ($err) { | |
| write-host -f red "`t$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" } |
Maybe ESET allows adding this dll to exceptions the way Defender does.
my dad would probably use this since for some reason, the OG patcher isn't working on his setup (or at least the "Warning, dev extension" popup keeps happening somehow), but would this be a "run once then it auto-runs every computer startup" thing, or would he have to manually run it every time he shuts down/restarts his computer?
@MonfGeiger, this patcher doesn't schedule itself, you run it manually one time and that's it.
- make sure Chrome doesn't auto-update itself: https://www.google.com/search?q=disable+auto-update+in+google+chrome
- update Chrome manually in menu -> Help -> About
- exit the browser, don't restart it, otherwise it'll delete MV2 extensions and their data
- run the patcher in admin mode so it patches the dll file and makes a BAK copy of the original dll
- run Chrome
don't restart it, otherwise it'll delete MV2 extensions and their data
Is it already so bad that you can lose your extension configuration?
@MonfGeiger, this patcher doesn't schedule itself, you run it manually one time and that's it.
1. make sure Chrome doesn't auto-update itself: https://www.google.com/search?q=disable+auto-update+in+google+chrome 2. update Chrome manually in menu -> Help -> About 3. exit the browser, don't restart it, otherwise it'll delete MV2 extensions and their data 4. run the patcher in admin mode so it patches the dll file and makes a BAK copy of the original dll 5. run Chrome
if i want to update his google chrome (or microsoft edge), i'd have to download their respective install files since i deleted the task scheduler entries, disabled & deleted the update services for edge and chrome, and manually deleted the folders containing the update programs for edge & chrome so it'd stop auto-updating the browsers and give him (or myself) manual control over if i want to update or not
his google chrome is at a few version numbers below the cutoff for the MV2 Extensions, so would "reinstalling" then using this break anything with his google chrome? or would it work just fine? this would also assume that i make backups of his ublock origin settings just incase. also, i should've clarified, the dev extension warning is happening on his microsoft edge, not google chrome, my bad
Edit: oh, i also, usually, make sure to have the GPO policy files for edge & chrome downloaded and applied in "C:\Windows\PolicyDefinitions" as a precautionary measure. now if i could only figure out how i permanently conquered the "Disable dev extension" warning in microsoft edge on my computer and do the same to his, then i'd apply it to his install, but for the life of me, i cannot remember how i did it originally. then again, that's a separate issue to figure out later
If it is too old, the script may not work and you should use older activation methods (e.g. flags in about://flags)
It may require a nerf of protection in the ESET Internet Security settings.