For those who are interested and found the article interesting there are additional posts in this series. The second[0] and third[1] posts are quite neat.
Cool! One question: I wonder why they didn’t just use GHIDRA to reverse engineer the MIPS binary? GHIDRA can decompile MIPS and does quite a passable job. IDA is an awesome tool (and still edges out GHIDRA for ARM/x86 if you have the decompiler), but my experience is that GHIDRA is way nicer for pretty much any other architecture. YMMV.
I appreciated the writeup, especially since I’ve done some firmware decryption and repacking myself (although in my case, the encryption was just repeating-XOR!).
Hi,
As much as I have to give credit to Ghidra and its capabilities and I just don't like using it. I find the UI/UX very awful. So I decided to just reverse it in IDA.
After I was done with everything I double-checked what I had re-constructed from the disassembly with what Ghidra suggested the decompilation may look like. To be honest they were pretty similar. So again, Ghidra is really powerful tool, I just dislike it :)
At least a few models of Linksys/Cisco home routers I own had their firmware "encrypted" using GnuPG. They had the extension .gpg.img but could simply be decrypted with:
It looks like they mainly did this for verification, as there is an RSA public key embedded on the device. It unfortunately does make it nearly impossible to flash any modified firmware such as OpenWRT, which is very frustrating. I say nearly as I haven't fully investigated the models that I own. Some routers have a emergency recovery flash method that may bypass the PGP check, I recall older D-Link models having a web flasher integrated into u-boot.
They make use of /etc_ro/public.pem to verify the integrity of a firmware update. So flashing a custom firmware (e.g.: OpenWRT) will fail all checks they put in place.
I did not investigate how one could circumvent the update mechanism yet but if you're interested in doing so for these particular models my GitHub repo (https://github.com/0xricksanchez/dlink-decrypt) has a decryption script for these firmware images so you can snoop around the file system for further clues.
I think they were replying to me about the Linksys/Cisco routers, but it is similar in that the public key is contained on the filesystem and prevents flashing any firmware not signed with it. What's worse is they added this after the fact to several models in later firmware versions, making it impossible to downgrade to older unsigned versions.
Unlike with yours, no decryption script is required, gnupg can decrypt them as-is.
Sorry, poor choice of words I guess. I mean it's embedded within the filesystem. If you had root or serial access to the device, then you could probably very easily replace it, but at that point you could also just write the firmware anyway. The checks are only important for flashing via the Web UI.
> the firmware encryption that was put in place to prevent tampering and static analysis
Code signing is enough to prevent tampering, so D-Link obviously doesn't want their users to know how their own hardware works. Does D-Link view their users as the adversary? If so, should the users view D-Link as hostile?
I'm not an expert (so I might be wrong here question-wise), but it seems to me that using the same type of encryption "key" to lock down firmware on various devices sounds like a very ill-advised way to do things.
It seems like it would be possible that once you find the "key" for one router, you could potentially exploit a bunch of other router/switch models as well. Am I incorrect in this thinking?
Encryption for firmware updates is only to obscure the contents. The imgdecrypt binary here also references RSA_verify and similarly public-key cryptography sounding names so I assume they are using that to authenticate the firmware images (checking for a D-Link signature).
Of course this is D-Link and the product is an embedded garbage router, so chances are high they are doing it entirely wrong.
You're right with your assumptions! If you go to part 3 pretty much to the bottom of the article there's a good summary of what fields are included in their firmware verification headers.
TL;DR: They verify the length of the encrypted and decrypted firmware as well as multiple RSA signatures.
As much as I like pushing security vectors on embedded/IoT devices... This approach of obscuring what is being pushed in an update may not be the right approach imo.
I was able to finally extract the squashfs file from my routers firmware using dd and program I found on github called “sasquash” which patches decompression tools and can also flip endianness.
[0]: https://0x434b.dev/breaking-the-d-link-dir3060-firmware-encr...
[1]: https://0x434b.dev/breaking-the-d-link-dir3060-firmware-encr...