Last month I posted a portion of a ridiculous conversation with NETGEAR over source code it withheld to unpack the filesystem on one of its routers. I would like to announce that against all expectations, NETGEAR actually pulled through and sent me the source code I was looking for!
As mentioned previously, I posted a detailed explanation of my situation over on the OpenWRT forum. To avoid any unnecessary re-explaining of background information, I’ll copy/paste it here:
Hey guys,
I’m trying to unpack SquashFS on the WNR1000v3 1.0.2.26 but have been running into lots of issues.
The firmware image is available here: http://www.downloads.netgear.com/files/WNR1000v3-V1.0.2.26_51.0.59NA.chk
The source for it is available here: http://www.downloads.netgear.com/files/GPL/WNR1000v3-V1.0.2.26_51.0.59NAWW_src.tar.zip
binwalk 0.4.2 provides the following output:
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------
58 0x3A TRX firmware header, little endian, header size: 28 bytes, image size: 2584576 bytes, CRC32: 0x9861D9FF flags/version: 0x10000
86 0x56 LZMA compressed data, properties: 0x5D, dictionary size: 65536 bytes, uncompressed size: 1634304 bytes
592666 0x90B1A Squashfs filesystem, little endian, non-standard signature, version 3.0, size: 1988809 bytes, 421 inodes, blocksize: 65536 bytes, created: Fri Jul 16 06:30:19 2010
Extract the filesystem at offset 592666:
$ dd if=WNR1000v3-V1.0.2.26_51.0.59NA.chk of=filesystem.bin bs=592666 skip=1
3+1 records in
3+1 records out
1991968 bytes (2.0 MB) copied, 0.0391462 s, 50.9 MB/s
As noted by binwalk, the filesystem has a non-standard magic number:
$ hexdump -C filesystem.bin | head -n2
00000000 73 68 73 71 a5 01 00 00 84 7a 00 37 dc 7c 00 de |shsq.....z.7.|..|
00000010 8a 04 08 40 06 01 40 02 00 63 00 09 03 00 00 00 |...@..@..c......|
Trying to unpackage it immediately returns the following error:
$ unsquashfs filesystem.bin
Can't find a SQUASHFS superblock on filesystem.bin
…which is to be expected. Correct the magic number to “hsqs” and now:
$ unsquashfs filesystem.bin
Parallel unsquashfs: Using 2 processors
gzip uncompress failed with error code -3
read_block: failed to read block @0x1e547f
read_fragment_table: failed to read fragment table block
FATAL ERROR aborting: failed to read fragment table
A little sleuthing returns that the filesystem is actually compressed using lzma, not gzip, so try a different compilation:
$ ../../../firmware-mod-kit-read-only/trunk/src/others/squashfs-4.0-lzma/unsquashfs-lzma filesystem.bin
Parallel unsquashfs: Using 2 processors
uncompress failed, unknown error -3
read_block: failed to read block @0x1e547f
read_fragment_table: failed to read fragment table block
FATAL ERROR aborting: failed to read fragment table
I can confirm that none of the publicly available unsquashfs utilities I can find are able to unpackage the file. I’ve tried using every version of unsquashfs, every variant of it, in every package that incorporates it (e.g., firmware-mod-kit). firmware-mod-kit’s scripts are unsuccessful as well.
Looking through the firmware source code, I see:
$ find . -name *squash*
./src/router/mipsel-uclibc/target.squashfs
./src/router/squashfs
./src/router/squashfs/mksquashfs.c
./src/router/squashfs/mksquashfs.h
./src/linux/linux/scripts/squashfs
./src/linux/linux/scripts/squashfs/mksquashfs
./src/linux/linux/scripts/squashfs/mksquashfs.c
./src/linux/linux/scripts/squashfs/mksquashfs.h
./src/linux/linux/scripts/squashfs/squashfs_fs.h
./src/linux/linux/fs/squashfs
./src/linux/linux/fs/squashfs/.squashfs2_0.o.flags
./src/linux/linux/fs/squashfs/squashfs2_0.o
./src/linux/linux/fs/squashfs/squashfs.o
./src/linux/linux/fs/squashfs/squashfs.h
./src/linux/linux/fs/squashfs/squashfs2_0.c
./src/linux/linux/fs/squashfs/.squashfs.o.flags
./src/linux/linux/include/linux/squashfs_fs_i.h
./src/linux/linux/include/linux/squashfs_fs.h
./src/linux/linux/include/linux/squashfs_fs_sb.h
./src/linux/linux/include/config/squashfs.h
./src/linux/linux/include/config/squashfs
…and unfortunately no unsquashfs.c code. In the meantime, I’ve contacted Netgear asking if they have it available.
The exact version they’re using is a bit confusing:
$ grep "mksquashfs version" -r .
./src/router/mipsel-uclibc/target/lib/modules/2.4.20/build/scripts/squashfs/mksquashfs.c: printf("mksquashfs version 2.2-r2n");
./src/router/squashfs/mksquashfs.c: printf("mksquashfs version 3.2-r2 (2007/01/15)n");
./src/linux/linux/scripts/squashfs/mksquashfs.c: printf("mksquashfs version 2.2-r2n");
Grepping for our non-standard magic number reveals:
$ grep 0x73687371 -r .
./src/router/mipsel-uclibc/target/lib/modules/2.4.20/build/include/linux/squashfs_fs.h:#define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371
./src/linux/linux/include/linux/squashfs_fs.h:#define SQUASHFS_MAGIC_LZMA_SWAP 0x73687371
Okay, great. Some Googling and it seems that this patch should do the trick: https://dev.openwrt.org/browser/trunk/tools/squashfs4/patches/170-add_support_for_LZMA_MAGIC_to_unsqashfs.patch?rev=28489
Patch unsquashfs, rebuild, and:
$ ./unsquashfs ../../filesystem.bin
Parallel unsquashfs: Using 2 processors
lzma uncompress failed with error code 1
read_block: failed to read block @0x1e547f
read_fragment_table: failed to read fragment table block
FATAL ERROR aborting: failed to read fragment table
Would anyone have any advice to offer, or mind lending a hand trying to get this filesystem unpackaged? Thank you in advance.
After about a month of back and forth conversation with their technical support team, I finally received a message linking me to the unsquashfs.c file I was looking for (download link is at the end of this post).
The following steps outline how to compile:
- Download and extract http://www.downloads.netgear.com/files/GPL/WNR1000v3-V1.0.2.26_51.0.59NAWW_src.tar.zip
- Copy unsquashfs.c into bcm5356/src/router/squashfs
- `cd bcm5356/src/router/squashfs; make`
sh-4.1$ ./unsquashfs
SYNTAX: ./unsquashfs [options] filesystem [directory or file to extract]
-v[ersion] print version, licence and copyright information
-i[nfo] print files as they are unsquashed
-l[s] list filesystem only
-d[est] unsquash to , default "squashfs-root"
-f[orce] if file already exists then overwrite
sh-4.1$ ./unsquashfs -version
unsquashfs version 1.3 (2007/01/02)
copyright (C) 2007 Phillip Lougher
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2,
or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
sh-4.1$
And to demonstrate its functionality:
sh-4.1$ dd if=WNR1000v3-V1.0.2.26_51.0.59NA.chk of=filesystem.bin bs=592666 skip=1
3+1 records in
3+1 records out
1991968 bytes (2.0 MB) copied, 0.0060848 s, 327 MB/s
sh-4.1$ ./unsquashfs filesystem.bin
created 327 files
created 35 directories
created 59 symlinks
created 0 devices
created 0 fifos
sh-4.1$ ls -R squashfs-root/
squashfs-root/:
bin dev etc lib media mnt proc sbin sys tmp usr var www
squashfs-root/bin:
busybox cp gunzip ls mount ps rmdir wps_ap
cat eapd gzip mkdir msh pwd sh wps_monitor
chmod echo kill mknod ping rm umount zcat
squashfs-root/dev:
squashfs-root/etc:
icon.ico large.ico ld.so.conf ppp small.ico
iproute2 ld.so.cache lld2d.conf resolv.conf
squashfs-root/etc/iproute2:
squashfs-root/etc/ppp:
squashfs-root/lib:
ld-uClibc.so.0 libc.so.0 libgcc_s.so.1 libpthread.so.0 libutil.so.0
libcrypt.so.0 libdl.so.0 libm.so.0 libresolv.so.0 modules
squashfs-root/lib/modules:
2.4.20
squashfs-root/lib/modules/2.4.20:
build kernel pcmcia
squashfs-root/lib/modules/2.4.20/kernel:
drivers net
squashfs-root/lib/modules/2.4.20/kernel/drivers:
net
squashfs-root/lib/modules/2.4.20/kernel/drivers/net:
emf et igs wl
squashfs-root/lib/modules/2.4.20/kernel/drivers/net/emf:
emf.o
squashfs-root/lib/modules/2.4.20/kernel/drivers/net/et:
et.o
squashfs-root/lib/modules/2.4.20/kernel/drivers/net/igs:
igs.o
squashfs-root/lib/modules/2.4.20/kernel/drivers/net/wl:
wl.o
squashfs-root/lib/modules/2.4.20/kernel/net:
ipv4
squashfs-root/lib/modules/2.4.20/kernel/net/ipv4:
acos_nat l7_filter multissidcontrol opendns ubd
squashfs-root/lib/modules/2.4.20/kernel/net/ipv4/acos_nat:
acos_nat.o
squashfs-root/lib/modules/2.4.20/kernel/net/ipv4/l7_filter:
l7_filter.o
squashfs-root/lib/modules/2.4.20/kernel/net/ipv4/multissidcontrol:
MultiSsidControl.o
squashfs-root/lib/modules/2.4.20/kernel/net/ipv4/opendns:
openDNS_hijack.o
squashfs-root/lib/modules/2.4.20/kernel/net/ipv4/ubd:
ubd.o
squashfs-root/lib/modules/2.4.20/pcmcia:
squashfs-root/mnt:
squashfs-root/proc:
squashfs-root/sbin:
acos_init burnrf ifconfig ntpclient reset_no_reboot version
acos_service burnsn init pppd restart_all_processes write
bd erase insmod preinit rmmod
burnboardid getchksum leddown rc routerinfo
burnethermac gpio ledup read_bd ubdcmd
burnpin hotplug lsmod reboot uptime
squashfs-root/sys:
squashfs-root/tmp:
squashfs-root/usr:
bin lib sbin tmp
squashfs-root/usr/bin:
free killall route telnetd tftp wget
squashfs-root/usr/lib:
libacos_shared.so libbcm.so libnvram.so libwpscom.so
libbcmcrypto.so libnat.so libshared.so tc
squashfs-root/usr/lib/tc:
q_netem.so
squashfs-root/usr/sbin:
acl_logd email lld2d swresetd upnpd wlconf
bpalogin emf nas tc upnpnat wpsd
bpa_monitor epi_ttcp nvram telnetenabled vconfig zebra
brctl et outputimage tfmeter wan_debug
cli ftpc pot timesync wandetect
ddnsd heartbeat pppoecd udhcpc wanled
dnsmasq httpd pptp udhcpd wl
dnsRedirectReplyd igs ripd upnp wlanconfigd
squashfs-root/www:
Add_WPS_Client.htm PWD_password.htm
backpage2.htm QOS_check_uplink_band_width.htm
backpage.htm QOS_main_h.htm
BAK_backup_h.htm QOS_main.htm
BAK_backup.htm QOS_ruletab.htm
BAK_cfm.htm QOS_service.htm
BAS_basic.htm redbull.gif
BAS_basictop.htm router-info.htm
BAS_bpa_h.htm RST_interval.htm
BAS_bpa.htm RST_statistics.htm
BAS_ether_h.htm RST_stattbl.htm
BAS_ether.htm RST_status_h.htm
BAS_pppoe_basic.htm RST_status.htm
BAS_pppoe_basictop.htm RST_st_bpa.htm
BAS_pppoe_flet2.htm RST_st_dhcp.htm
BAS_pppoe_flet.htm RST_st_fix.htm
BAS_pppoe_h.htm RST_st_poe.htm
BAS_pppoe.htm RST_st_pptp.htm
BAS_pppoe_other.htm RST_wanstat.htm
BAS_pptp_h.htm settings_wnr1000v3.jpg
BAS_pptp.htm spacer.gif
BAS_wtest_d.htm SRV_response.htm
BAS_wtest_l.htm start.htm
BAS_wtest_ppp2.htm start_update.htm
BKS_err.htm STR_add.htm
BKS_keyword_h.htm StringTableUpload.html
BKS_keyword.htm string_table_wnr1000v3
BKS_keyword_ppp2.htm STR_routes_h.htm
BKS_service_add_h.htm STR_routes.htm
BKS_service_add.htm style.css
BKS_service_edit.htm traffic_important_update.htm
BKS_service_h.htm traffic_interval.htm
BKS_service.htm traffic_meter_h.htm
BKS_service_ppp2.htm traffic_meter.htm
browser.js traffic_start_update.htm
CheckNewFW.html traffic_stattbl.htm
currentsetting.htm traffic_status.htm
darkblue.gif traffic_warning.htm
debuginfo.htm UPG_fw_check.htm
DEV_device_h.htm UPG_upgrade_h.htm
DEV_device.htm UPG_upgrade.htm
DIG_reboot2.htm upload.gif
DIG_reboot3.htm UPNP_upnp_h.htm
DIG_reboot4.htm UPNP_upnp.htm
DIG_reboot.htm utility.js
DIG_update.htm VER_check_h.htm
DNS_ddns_h.htm VER_check.htm
DNS_ddns.htm VER_download_h.htm
DNS_ddns_st.htm VER_download.htm
form.css VER_fw_found.htm
func.js VER_fwlang_found.htm
FW_check.htm VER_fw_not_found.htm
FW_email_h.htm VER_result_h.htm
FW_email.htm VER_sel_h.htm
FW_forward_h.htm VER_sel.htm
FW_forward.htm VER_write2.htm
FW_forward_service_h.htm VER_write_h.htm
FW_forward_service.htm VER_write.htm
FW_log_h.htm WAN_wan_h.htm
FW_log.htm WAN_wan.htm
FW_pt_h.htm WiFi_HiddenPage.htm
FW_pt.htm WIZ_bpa_h.htm
FW_pt_service.htm WIZ_bpa.htm
FW_remote_h.htm WIZ_cfm_h.htm
FW_remote.htm WIZ_cfm.htm
FW_schedule_h.htm WIZ_det_fix_h.htm
FW_schedule.htm WIZ_det_fix.htm
FW_schedule_ppp2.htm WIZ_detwan.htm
help.css WIZ_dyn_h.htm
IA_IP_SUBNET.htm WIZ_dyn.htm
important_update.htm WIZ_fix_h.htm
index.htm WIZ_fix.htm
LANG_brs_conflict_h.htm WIZ_ph_fail_h.htm
LANG_brs_conflict.htm WIZ_ph_fail.htm
LANG_check_brslang.htm WIZ_pppoe_fleteast.htm
LANG_check.htm WIZ_pppoe_fletother.htm
LANG_check_top.htm WIZ_pppoe_fletwest.htm
LANG_download.htm WIZ_pppoe_h.htm
LANG_failed.htm WIZ_pppoe.htm
LANG_found.htm WIZ_pptp_h.htm
LANG_lang_h.htm WIZ_pptp.htm
LANG_lang.htm WIZ_result.htm
LANG_no_connection.htm WIZ_sel_h.htm
LANG_not_found.htm WIZ_sel.htm
LANG_upgrade.htm WLG_acl_add_h.htm
LANG_write.htm WLG_acl_add.htm
LAN_lan_h.htm WLG_acl_edit.htm
LAN_lan.htm WLG_acl_h.htm
LAN_reserv_add_h.htm WLG_acl.htm
LAN_reserv_add.htm WLG_adv_h.htm
LAN_reserv_edit_h.htm WLG_adv.htm
LAN_reserv_edit.htm WLG_wds_h.htm
LGO_logout.htm WLG_wds.htm
liteblue.gif WLG_wireless1_2.htm
md5.js WLG_wireless1.htm
menublue.gif WLG_wireless2_2.htm
mimo_logo_wnr1000v3.jpg WLG_wireless_2_h.htm
MNU_access_failure.htm WLG_wireless_2.htm
MNU_access_unauthorized.htm WLG_wireless2.htm
MNU_blank.htm WLG_wireless3_2.htm
MNU_login.htm WLG_wireless3.htm
MNU_menu.htm WLG_wireless4_2.htm
MNU_menu_no_link.htm WLG_wireless_h.htm
MNU_top.htm WLG_wireless.htm
msg.js WPS_Add_Client_FAIL_Cancel_Change.htm
NoInternetConn.html WPS_Add_Client_FAIL_Cancel.htm
NoInternet.html WPS_Add_Client_FAIL_ErrorPIN.htm
POT.htm WPS_Add_Client_FAIL_PBC_Conflict_Change.htm
pppoe2_domain_add.htm WPS_Add_Client_FAIL_PBC_Conflict.htm
pppoe2_domain_edit.htm WPS_Add_Client_FAIL_PIN_Change.htm
pppoe2_ip_add.htm WPS_Add_Client_FAIL_PIN.htm
pppoe2_ip_edit.htm WPS_Add_Client_FAIL_Timeout_Change.htm
pppoe2_port_add.htm WPS_Add_Client_FAIL_Timeout.htm
pppoe2_port_edit.htm WPS_Add_Client_OK_Change.htm
Public_UPNP_gatedesc.xml WPS_Add_Client_OK.htm
Public_UPNP_LANHostCfgMag.xml WPS_Add_Client_PBC.htm
Public_UPNP_Layer3F.xml WPS_Add_Client_PIN.htm
Public_UPNP_WAND.xml WPS_h.htm
Public_UPNP_WANEtherLinkCfg.xml WPS.htm
Public_UPNP_WANIPConn.xml wps_icon_off.bmp
Public_UPNP_WANPPPConn.xml wps_icon_on.bmp
PWD_passwd_h.htm WPS_PIN.htm
sh-4.1$
In summary, the following code has been verified to unpack SquashFS filesystems on the following NETGEAR devices:
- WNR1000v3 1.0.26NA
- WGR614v10 1.0.26NA
The unsquashfs code may be downloaded here: unsquashfs-1.3.c
If there is one lesson to be learned from this experience, it’s amazing what you can receive if you are polite and simply choose to ask.