Skip to content

Instantly share code, notes, and snippets.

@aplocher
Last active May 20, 2021 20:19
Show Gist options
  • Save aplocher/7d717925fe00c6602bed to your computer and use it in GitHub Desktop.
Save aplocher/7d717925fe00c6602bed to your computer and use it in GitHub Desktop.
Patch router firmware files for WNDR3800SW (SureWest specific) router model. Can convert any Netgear WNDR3800 firmware img to work with WNDR3800SW. Requires perl.exe currently.
== patch3800sw.ps1 ==
Requires perl.exe to be in the same folder or in the environment PATH (for generating checksum)!
Patch firmware .img files used for Netgear WNDR3800 routers to work with Netgear WNDR3800SW
The SW model routers are specfic to SureWest Communications (ISP from northern CA)
The routers are identical, but require a different header on the .img file. This should work with any
.img file that works with a WNDR3800, including DD-WRT, OpenWRT, and the Netgear factory firmware
-- Example Command (PowerShell):
PS C:\Temp> .\patch3800sw.ps1 "C:\users\adam\Downloads\openwrt-ar71xx-generic-wndr3800-squashfs-factory(2).img" "C:\temp\test333.img"
-- Example Result:
===========================================================
PATCHING INPUT FILE FOR SUREWEST NETGEAR WNDR3800SW ROUTERS
===========================================================
-Reading input file
-Removing existing checksum byte
-Patching first 128 bytes of file with WNDR3800SW signature
-Attempting to generate new checksum byte
-Perl.exe found, generating and executing script
* Append checksum => file : C:\Users\adam\AppData\Local\Temp\tmp5794.tmp, len : 0x340084, checksum : 0x63
-Finished
-New file - C:\temp\test333.img
-Patched and ready to flash on WNDR3800SW (if there weren't any errors)
# REQUIRES PERL.EXE!
#
# Patch firmware .img files used for Netgear WNDR3800 routers to work with Netgear WNDR3800SW
# The SW model routers are specfic to SureWest Communications (ISP from northern CA)
# The routers are identical, but require a different header on the .img file. This should work with any
# .img file that works with a WNDR3800, including DD-WRT, OpenWRT, and the Netgear factory firmware
#
## Usage: .\patch3800sw <input img file path> <output img file path>
#
## Example: .\patch3800sw openwrt-ar71xx-generic-wndr3800-squashfs-factory.img openwrt-wndr3800sw.img
#
## Requires: perl.exe must be installed or in the same folder as this script!
#
## Find updates at http://gist.github.com/aplocher
#
## All actual reverse engineering/hacking/whatevering was done by the folks over at OpenWRT.org. They
## deserve all the real credit https://forum.openwrt.org/viewtopic.php?id=39142
#
## If anyone would like to port the perl script portion over to PowerShell, I would be happy to update
## this with your contributions. I hate requiring perl.exe!
Param(
[string]$fwImgInputPath,
[string]$fwImgOutputPath
)
Write-Output "==========================================================="
Write-Output "PATCHING INPUT FILE FOR SUREWEST NETGEAR WNDR3800SW ROUTERS"
Write-Output "==========================================================="
$fwImgInputPath = Convert-Path $fwImgInputPath
if ($fwImgInputPath -eq $null -or $fwImgInputPath -eq "" -or -not (Test-Path $fwImgInputPath)) { Write-Error "File not found"; Exit; }
$newBytes = 0x64,0x65,0x76,0x69,0x63,0x65,0x3A,0x57,0x4E,0x44,0x52,0x33,0x38,0x30,0x30,0x53,0x57,0x0A,0x76,0x65,0x72,0x73,0x69,0x6F,0x6E,0x3A,0x56,0x31,
0x2E,0x30,0x2E,0x30,0x2E,0x39,0x39,0x53,0x57,0x0A,0x72,0x65,0x67,0x69,0x6F,0x6E,0x3A,0x0A,0x68,0x64,0x5F,0x69,0x64,0x3A,0x32,0x39,0x37,0x36,
0x33,0x36,0x35,0x34,0x2B,0x31,0x36,0x2B,0x31,0x32,0x38,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
Write-Output "-Reading input file"
$inputFileBytes = [System.IO.File]::ReadAllBytes($fwImgInputPath)
$bytes = $inputFileBytes[1..($inputFileBytes.Length-1)]
Write-Output "-Removing existing checksum byte"
[array]::Copy($inputFileBytes, $bytes, $bytes.Length)
Write-Output "-Patching first 128 bytes of file with WNDR3800SW signature"
[array]::Copy($newBytes,0,$bytes,0,128)
New-Item $fwImgOutputPath -Force -ea SilentlyContinue | Out-Null
$fwImgOutputPath = Convert-Path $fwImgOutputPath
[System.IO.File]::WriteAllBytes($fwImgOutputPath, $bytes)
Write-Output "-Attempting to generate new checksum byte"
$perlExe = "perl.exe"
if (Get-Command ".\perl.exe" -ea SilentlyContinue) {$perlExe = ".\perl.exe"}
if ((Get-Command "$($perlExe)" -ea SilentlyContinue) -ne $null) {
Write-Output "-Perl.exe found, generating and executing script"
$perlPath = (Get-Command $perlExe).Path
$perlScript = "#!/usr/bin/perl -w`
`
use strict;`
`
my `$TempCompFileName = shift(@ARGV);`
my `$OutFileName = shift(@ARGV);`
`
my (`$start_addr, `$appd_cks, `$appd_len) = (0);`
`
sub appendCks`
{`
my (`$fileName) = @_;`
my (`$cks, `$len) = (0, 0);`
`
open APPENDCKS_FH, `"+<`$fileName`" or die `"fail to open file `$fileName : `$!`";`
until ( eof APPENDCKS_FH ) {`
`$cks = ( `$cks + ord( getc( APPENDCKS_FH )) ) % 0x100 ;`
`$len++ ;`
}`
`
`$cks = 0xFF - `$cks;`
close APPENDCKS_FH;`
`
printf (`" * Append checksum => file : %s, len : 0x%X, checksum : 0x%X \n`", , `$fileName, `$len, `$cks);`
`$appd_cks =`$cks;`
`$appd_len =`$len;`
}`
`
`
appendCks(`$TempCompFileName);`
`
# Then append Checksum (include the 4bytes starting address) `
open INS_FH, `"`$TempCompFileName`" or die `"fail to open file `$TempCompFileName : `$!`";`
open OUT_FH, `">`$OutFileName`" or die `"fail to Append file `$OutFileName: `$!`";`
while (<INS_FH>)`
{`
print OUT_FH `$_;`
}`
print OUT_FH chr(`$appd_cks); `
close INS_FH;`
close OUT_FH;"
$checksumPlPath = Join-Path $env:TEMP "GenChecksum.pl"
$newPerlPath = Join-Path $env:TEMP "newperl.exe"
Copy-Item -Force $perlPath $newPerlPath
$perlScript | Out-File $checksumPlPath -Force
$tmp = New-TemporaryFile
Move-Item "$($fwImgOutputPath)" "$($tmp)" -Force
c:\windows\system32\cmd.exe /c ""$perlPath" "$($checksumPlPath)" "$($tmp)" "$($fwImgOutputPath)""
Write-Output "-Finished"
Write-Output "-New file - $($fwImgOutputPath)"
Write-Output "-Patched and ready to flash on WNDR3800SW (if there weren't any errors)"
}
else {
Write-Warning "-Perl.exe not found. New file generated but no valid checksum byte created"
Write-Output "-New file: $($fwImgOutputPath)"
}
@uragit
Copy link

uragit commented May 20, 2021

Nice! I used geoffch's C version. Saved my ass when I ended up with a used WNDR3800 from ebay that turned out to be a WNDR3800SW. Worked flawlessly. Thanks guys!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment