1
0
mirror of https://github.com/chylex/Blog.git synced 2025-05-23 15:34:04 +02:00

Add post - Open Executables Without Saving In Firefox 57+

This commit is contained in:
chylex 2020-03-26 02:25:43 +01:00
parent f544ac868d
commit cc17ad3f40
4 changed files with 186 additions and 0 deletions
_posts
assets
download/firefox-open-exe
img/firefox-open-exe

View File

@ -0,0 +1,50 @@
---
title: "Open Executables Without Saving In Firefox 57+"
subtitle: "%pub"
date: 2020-03-25
commentid: 3
---
Since Firefox 57, extensions such as OpenDownload² can no longer modify the Download dialog, removing the option to run executables without manually saving them first. Here is a PowerShell script to fix that.
### Before
![Download dialog before the patch.](/assets/img/firefox-open-exe/before.png)
### After
![Download dialog after the patch.](/assets/img/firefox-open-exe/after.png)
# How to Use
1. [Download the script](/assets/download/firefox-open-exe/FirefoxOpenExePatch.ps1)
2. Close Firefox
3. Open PowerShell in the folder with the downloaded script
- If you installed Firefox into a protected location (such as Program Files), you will need to run PowerShell as Administrator, and navigate to the script folder using `cd "<folder>"`
- Otherwise, you can simply open the script folder in Windows Explorer and type `powershell` into the address bar
4. Type `.\FirefoxOpenExePatch.ps1 "<firefox-folder>"` into PowerShell and press Enter
- For ex.: `.\FirefoxOpenExePatch.ps1 "C:\Program Files\Mozilla Firefox"`
5. After the patching completes, make sure it says `Applied 4 patches`
- If it's fewer, it may still work but not 100%
- If it's more, it probably touched something it shouldn't have
6. Delete `compatibility.ini` from your Firefox profile folder to regenerate the download dialog
- For non-portable installs, your profile is in `%APPDATA%\Mozilla\Firefox\Profiles\<profile-id>`
- For portable installs, your profile is in `<installation-folder>\Data\profile`
7. Repeat when Firefox updates
If you cannot run PowerShell scripts, follow [this guide](https://social.technet.microsoft.com/wiki/contents/articles/38496.unblock-downloaded-powershell-scripts.aspx).
If you see an error message, read it, most times you should be able to figure out what's wrong. If the patch succeeds but Firefox doesn't work, revert the patch by renaming `omni.ja.old` to `omni.ja`.
Please let me know in the comments if a Firefox update breaks the patch. If this guide works for you, I'd appreciate if you [bought me a coffee](https://ko-fi.com/chylex).
# How it Works
In the Firefox installation folder, `omni.ja` is a ZIP file with no compression. The archive contains `modules\HelperAppDlg.jsm` (or `components/nsHelperAppDlg.js` in older versions) with JavaScript logic for the download dialog.
The patch does 2 things:
1. It replaces `this.mLauncher.targetFileIsExecutable` with `false` in 3 places to make executables pretend they are normal files, so they will not trigger the "simple" download dialog.
2. It modifies a condition that checks which option (`Open with` or `Save File`) is checked by default, to make executables default to `Open with`.
Because the ZIP file has no compression, the script treats it as a binary file and simply searches it for byte sequences to replace. The replacement bytes are written so that they don't affect the file size. Changing the ZIP file bytes *corrupts* it because the CRC checksum no longer matches the contents, but Firefox doesn't care.

View File

@ -0,0 +1,136 @@
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true, Position = 0)]
[System.IO.FileInfo] $FirefoxFolder
)
$ErrorActionPreference = "Stop"
if (-Not (Test-Path -Path $FirefoxFolder -PathType Container)){
throw "Folder does not exist."
}
$OmniJa = Join-Path -Path $FirefoxFolder -ChildPath "omni.ja"
$OmniJaOld = "$OmniJa.old"
if (-Not (Test-Path -Path $OmniJa -PathType Leaf)){
throw "File 'omni.ja' was not found in the folder."
}
function Apply-Patch {
Param(
[Parameter(Mandatory = $true, Position = 0)]
[Byte[]] $Data,
[Parameter(Mandatory = $true, Position = 1)]
[Byte[]] $Search,
[Parameter(Mandatory = $true, Position = 2)]
[Byte[]] $Replace
)
$Occurrences = 0
$SearchLength = $Search.Length
$CheckLength = $Data.Length - $SearchLength
for($i = 0; $i -lt $CheckLength; $i++){
if ($Data[$i] -ne $Search[0]){
continue
}
$Matches = $true
for($o = 1; $o -lt $SearchLength; $o++){
if ($Data[$i + $o] -ne $Search[$o]){
$Matches = $false
break
}
}
if ($Matches){
for($o = 0; $o -lt $Replace.Length; $o++){
$Data[$i + $o] = $Replace[$o]
}
$i += $Replace.Length
$Occurrences++
}
}
return $Occurrences
}
Write-Host ""
Write-Host "Patching omni.ja..."
Write-Host ""
[Byte[]] $Data = [System.IO.File]::ReadAllBytes($OmniJa)
$Occurrences = 0
$BytesSearch1 = [Byte[]](
0x74, 0x68, 0x69, 0x73, 0x2E, 0x6D, 0x4C, 0x61, 0x75, 0x6E, 0x63, 0x68, 0x65, 0x72, 0x2E, 0x74, # this.mLauncher.t
0x61, 0x72, 0x67, 0x65, 0x74, 0x46, 0x69, 0x6C, 0x65, 0x49, 0x73, 0x45, 0x78, 0x65, 0x63, 0x75, # argetFileIsExecu
0x74, 0x61, 0x62, 0x6C, 0x65 # table
)
$BytesReplace1 = [Byte[]](
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, #
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, #
0x66, 0x61, 0x6C, 0x73, 0x65 # false
)
$Attempt = Apply-Patch $Data $BytesSearch1 $BytesReplace1
$Occurrences += $Attempt
if ($Attempt -eq 1){ # most likely the occurrence added by second patch
Write-Host "It appears this installation is already patched."
exit
}
if ($Attempt -eq 0){
Write-Host "Found nothing to patch."
exit
}
$BytesSearch2a = [Byte[]](
0x0A, 0x20, 0x20, 0x20, 0x20, 0x29, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2F, # \n ){\n /
0x2F, 0x20, 0x4F, 0x70, 0x65, 0x6E, 0x20, 0x28, 0x75, 0x73, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x79, # / Open (using sy
0x73, 0x74, 0x65, 0x6D, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6C # stem defaul
)
$BytesReplace2a = [Byte[]](
0x7C, 0x7C, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x6D, 0x4C, 0x61, 0x75, 0x6E, 0x63, 0x68, 0x65, 0x72, # ||this.mLauncher
0x2E, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x46, 0x69, 0x6C, 0x65, 0x49, 0x73, 0x45, 0x78, 0x65, # .targetFileIsExe
0x63, 0x75, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x29, 0x7B, 0x2F, 0x2F # cutable){//
)
$BytesSearch2b = [Byte[]](
0x29, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2F, 0x2F, 0x20, 0x4F, 0x70, 0x65, # ) {\n // Ope
0x6E, 0x20, 0x28, 0x75, 0x73, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x20, # n (using system
0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x29, 0x2E # default).
)
$BytesReplace2b = [Byte[]](
0x7C, 0x7C, 0x74, 0x68, 0x69, 0x73, 0x2E, 0x6D, 0x4C, 0x61, 0x75, 0x6E, 0x63, 0x68, 0x65, 0x72, # ||this.mLauncher
0x2E, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x46, 0x69, 0x6C, 0x65, 0x49, 0x73, 0x45, 0x78, 0x65, # .targetFileIsExe
0x63, 0x75, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x29, 0x7B # cutable){
)
$Attempt = Apply-Patch $Data $BytesSearch2a $BytesReplace2a
if ($Attempt -eq 0){ # older versions
$Attempt = Apply-Patch $Data $BytesSearch2b $BytesReplace2b
}
$Occurrences += $Attempt
if ($Occurrences -gt 0){
Move-Item -Path $OmniJa -Destination $OmniJaOld -Force
[System.IO.File]::WriteAllBytes($OmniJa, $Data)
Write-Host "Applied $Occurrences patches."
Write-Host "Delete 'compatibility.ini' from your Firefox profile folder to regenerate the download dialog."
Write-Host "The original 'omni.ja' file is backed up as 'omni.ja.old'."
}
else{
Write-Host "Found nothing to patch."
}

Binary file not shown.

After

(image error) Size: 25 KiB

Binary file not shown.

After

(image error) Size: 20 KiB