I'm trying to reverse engineering the router's TP-Link TD-W8961N V3 firmware. After following the same question here i used the script zynos.py for unpacking the firmware and i got some files

-rw-r--r-- 1 root root    2048 Sep 30 03:33 CertFile.rom
-rw-r--r-- 1 root root  350208 Sep 30 03:33 fmmudata
-rw-r--r-- 1 root root    1024 Sep 30 03:33 headmmu
-rw-r--r-- 1 root root      28 Sep 30 03:33 HTPCode
-rw-r--r-- 1 root root   32768 Sep 30 03:33 HTPCode.rom
drwxr-xr-x 2 root root    4096 Sep 30 15:54 _HTPCode.rom.extracted
-rw-r--r-- 1 root root    2048 Sep 30 03:33 huffmmu
-rw-r--r-- 1 root root    1024 Sep 30 03:33 LedDefi
-rw-r--r-- 1 root root    8192 Sep 30 03:33 LogoImg
-rw-r--r-- 1 root root    8192 Sep 30 03:33 LogoImg2
-rw-r--r-- 1 root root    3072 Sep 30 03:33 MemMapT
-rw-r--r-- 1 root root      28 Sep 30 03:33 RasCode
-rw-r--r-- 1 root root 1163194 Sep 30 03:33 RasCode.rom
drwxr-xr-x 2 root root    4096 Oct  1 18:39 _RasCode.rom.extracted
-rw-r--r-- 1 root root    8192 Sep 30 03:33 RomDefa
-rw-r--r-- 1 root root    1024 Sep 30 03:33 Rt11nE2p
-rw-r--r-- 1 root root     512 Sep 30 03:33 SIDList.rom
-rw-r--r-- 1 root root    4096 Sep 30 03:33 SKUTBL.rom
-rw-r--r-- 1 root root  245760 Sep 30 03:33 StrImag
-rw-r--r-- 1 root root    1024 Sep 30 03:33 termcap

I used binwalk to extract the files HTPCode.rom and RasCode.rom. After looking at the zynos.md, i find more informations about the extracted files

Memory mapping and objects
All inspected devices so far contain at least these objects: MemMapT, BootBas, BootExt, RasCode, RomDefa, termcap.

The MemMapT object maps the memory mapping table -- its actual location and size in ROM.
The BootBas object maps the BootBase code -- the initial program loader for the device. It is not actually contained within the firmware update image, but I have seen a few firmware releases from ZyXEL that contain BootBase update in a separate file. Apart from boot code, BootBase contains vendor and model names. BootBase is rather small, typically 16K, but then, it does not need to do much except loading stage 2.
The BootExt object maps the BootExtension code -- stage 2 program loader. It also contains rudimentary debugging facilities allowing to recover the device in case of e.g. problems with configuration. BootExtension is responsible to load actual ZyNOS code.
The RasCode object contains the OS image (named RAS -- acronym?) -- the final stage.
The RomDefa object contains ROMFILE with default configuration settings.
The termcap object contains what looks like, well, termcap description. I am not sure this is actually used anywhere in code.
Objects with unknown contents:

Depending on the device, the following objects may be present:

The HTPCode object contains Hardware Test Program, which can be loaded via BootExtension

So the file that containg OS image is RasCode i used binwalk to get more info about the file

1225740       0x12B40C        TP-Link firmware header, firmware version: -24640.27395.-4500, image version: " Co., Ltd.", product ID: 0x65737320, product version: 1349478766, kernel load address: 0x11F50, kernel entry point: 0xEFFFFFFF, kernel offset: 1693673252, kernel length: 4156967956, rootfs offset: 3556796160, rootfs length: 469800426, bootloader offset: 3573675958, bootloader length: 1106012034
2162096       0x20FDB0        Neighborly text, "neighbor loss) fail"
2165188       0x2109C4        ZyXEL rom-0 configuration block, name: "autoexec.net", compressed size: 25972, uncompressed size: 11886, data offset from start of block: 8313
2178704       0x213E90        Neighborly text, "neighbordown: can't shutdown OSPF task completely"
2189282       0x2167E2        ZyXEL rom-0 configuration block, name: "spt.dat", compressed size: 769, uncompressed size: 259, data offset from start of block: 28805
2270236       0x22A41C        HTML document footer
2270553       0x22A559        HTML document header
2274256       0x22B3D0        XML document, version: "1.0"
2340561       0x23B6D1        Base64 standard index table
2353193       0x23E829        ZyXEL rom-0 configuration block, name: "autoexec.net", compressed size: 25972, uncompressed size: 11886, data offset from start of block: 131
2353305       0x23E899        Copyright string: "Copyright (c) 1994 - 2004 ZyXEL Communications Corp."
2353358       0x23E8CE        Copyright string: "Copyright (c) 2001 - 2006 TrendChip Technologies Corp."
2353413       0x23E905        Copyright string: "Copyright (c) 2001 - 2006 "
2353807       0x23EA8F        ZyXEL rom-0 configuration block, name: "dbgarea", compressed size: 0, uncompressed size: 0, data offset from start of block: 16
2365690       0x2418FA        eCos RTOS string reference: "ecost"
2419868       0x24EC9C        SHA256 hash constants, big endian
2421932       0x24F4AC        Base64 standard index table
2422880       0x24F860        DES PC1 table
2422936       0x24F898        DES PC2 table
2423096       0x24F938        DES SP1, big endian
2423352       0x24FA38        DES SP2, big endian
2462937       0x2594D9        ZyXEL rom-0 configuration block, name: "autoexec.net", compressed size: 25972, uncompressed size: 11886, data offset from start of block: 135
2480824       0x25DAB8        ZyXEL rom-0 configuration block, name: "autoexec.net", compressed size: 25972, uncompressed size: 11886, data offset from start of block: 131
2521748       0x267A94        Base64 standard index table
2564056       0x271FD8        XML document, version: "1.0"
2570560       0x273940        XML document, version: "1.0"
2571748       0x273DE4        XML document, version: "1.0"
2572716       0x2741AC        XML document, version: "1.0"
2577536       0x275480        XML document, version: "1.0"
2581712       0x2764D0        XML document, version: "1.0"
2584984       0x277198        XML document, version: "1.0"
2590372       0x2786A4        XML document, version: "1.0"
2596352       0x279E00        XML document, version: "1.0"
2598488       0x27A658        XML document, version: "1.0"
2605596       0x27C21C        XML document, version: "1.0"
2622128       0x2802B0        XML document, version: "1.0"
2631608       0x2827B8        XML document, version: "1.0"
2640368       0x2849F0        XML document, version: "1.0"
2641804       0x284F8C        XML document, version: "1.0"
2654188       0x287FEC        XML document, version: "1.0"
2674971       0x28D11B        Copyright string: "copyright"
2684587       0x28F6AB        Copyright string: "copyright" >"
2786992       0x2A86B0        CRC32 polynomial table, big endian
2880544       0x2BF420        Copyright string: "Copyright (c) 1996-2010 Express Logic Inc. * ThreadX MIPS32_34Kx/Green Hills Version G5.4.5.0 SN: 3182-197-0401 *"

binwalk -A show that the file have MIPS instructions and the binwalk output before show that it's a RTOS ThreadX MIPS32_34Kx/Green Hills Version G5.4.5.0

I tried to load the file into IDA but without success

So my question is how can i work with this RTOS image to understand more about the firmware and find more informations.

The firmware can be downloaded at : https://www.tp-link.com/en/support/download/td-w8961n/v3/#Firmware


  • Did you try their offer on your link for a direct download of the sources of some of their software? They use GPL licenced SW in their products, thus - in these parts - have to provide their sources as well.
    – josh
    Oct 4, 2020 at 0:43
  • @josh i checked the GPL code center i didn't find the same router TD-8961N i find a source code for the TD-8960N i don't know if the same source code used for both Oct 5, 2020 at 2:56
  • Did you find an answer for this? I'm very interested in a solution...
    – drsnooker
    Jul 1 at 20:19

2 Answers 2


I think this isn't a filesystem but a memory of compiled functions and resources that are used in the OS. I would suggest you opening up the file in ghidra with MIPS instruction set (either 32bit or 64, depending on the router)


Yes Ghidra is the ticket! First you might want to re-extract RasCode (it's too small, and probably a text message saying LZMA error) I'm thinking that is now resolved so perhaps download dev-zzo/router-tools again to get the actual RasCode.

I am looking at a different router, but I'll go through the steps here. In my case it was a 32bit MIPS, big endian with the rest defaults. Do a search for 10 32 xx xx 54 76 and for 54 76 xx xx 10 32. This will give you the locations of MD5init and SHA1init.

The functions directly below the init is the MD5update (and SHA1update) usually. That's convenient because the update function usually has two function calls to itself. So look at the addresses of those function calls and the hex address of the update function. Subtract the two and now you have the base address.

Exit, delete RasCode from the imported files and re-import into Ghidra, with the added option of the base address and Bob's your uncle! All functions now properly reference eachother so you can step through the code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.