Unpacking Trendnet IP camera firmware
Auch wenn ich normalerweise meine Blog-Einträge auf Deutsch schreibe, so werde ich diesen Artikel ausnahmsweise in Englisch verfassen, da er möglicherweise auch für andere Leute interessant sein könnte:
Recently, I had a little project which involved video streaming from IP cameras. I checked various cameramodels whether they suit my needs. So I also tried to check their linux-based firmware and find out how the cameras are working.
The cameras I evaluated can be controlled by the NIPCA API.
I found some interesting blogs that deal with some Trendnet camera models, i.e.:
http://hackingthetrendnet312w.blogspot.co.at/
This blog describes how you can compile your own programs for the Trendnet 312W and how to even modify the image using overlays. Great read!
Another interesting blog entry deals with the D-Link 2121 which also seems
to be based on the same subsystem exposing the NIPCA API:
http://newsoft-tech.blogspot.co.at/2010/09/d-link-dcs-2121-and-state-of-embedded.html
As for me, I wanted to unpack the firmware of a Trendnet TV-IP572PI camera.
As I learned from other firmware reversing sites, there is a nice little utility called binwalk, which analyzed images for potential signtures of emebdded files (i.e. CramFS filesytems etc.). However using binwalk on this firmware image, which you can download from their website, didn’t reveal anything. When I had a look at it, I saw that it containd a shellscript as a loader, which in turn calls an embedded utility called ddPack, like it is also mentioned in the DCS-2121 blog post. This utility basically uses the firmware, which starts after the marker “=== Firmware Boundary ===” in the file.
I found out that the text string in the real firmware image looked “crippled” somehow. After taking a closer look, I realized, that the image is in Big Endian format, so every 32bit doubleword is swapped.
So in order to analyze and unpack it, you first have to swap the bytes in the image first. The dd utility offers an option to swap words, but not doublewords (some versions may have an option for this, however the version shipped with Debian Linux doesn’t have one).
So I wrote a few lines of C-code to swap the image.
After that, binwalk analysis succeeds and finds a gzipped image in it. If you extract and unzip it, you find another gzipped image in the resulting file. If you unzip that one too, you finally end up with a cpio-archive which you can unpack and voilá: Here is the filesystem from the firmware image.
This all also applies to the D-Link DCS-942L camera, which is also based on that firmware.
I wrote a litte shellscript to unpack the firmware: unp_fw_TV-IP572PI.sh
I also have a TV-IP512P available. The firmware in there seems to be easier to unpack, the image isn’t in Big Endian format and just contains a cramfs that you can extract and mount.
Here is the unpacker script for that one: unp_fw_DCS-56×5.sh
I hope that this information is useful to anyone who is messing around with Trendnet camera firmware. For further information about unpacking various camera firmwares, please visit my site about this topic.
Comments
Trying to re-use your unpacker without success. zImage seem to not have a gzip header (folowin binwalk)…
pap: Just provide a link to the firmware you want to unpack and I’ll check…
I’m just tried to unpack the dcs-942l firmware but without success, here’s a log:
root@Sergey-PC:~/942l# ./unp_fw_TV-IP572PI.sh update_DCS-942L_1.12_1608_WW.bin
Trendnet TV-IP572PI, D-Link DCS-942L, DCS-5211L, DCS-5222L Firmware unpacker
http://www.hardwarefetish.com
zImage written.
repack-zImage.sh: Can’t find a gzip header in file ‘zImage’
./unp_fw_TV-IP572PI.sh: строка 128: 2468 Завершено ./repack-zImage.sh -u zImage
The firmware was taken from D-Link’s official russian FTP-server (ftp://ftp.dlink.ru/pub/Multimedia/DCS-942L/Firmware/update_DCS-942L_1.12_1608_WW.bin). Could you please check this? Thanks in advance!
evilslon: Works perfectly fine here. Maybe you are using an outdated version of repack-zimage.sh or your image is incomplete/corrupted?
The one that I’m using and that is working fine is:
version=”Version 6, by mizch
Time-stamp:
Output:
# wget ftp://ftp.dlink.ru/pub/Multimedia/DCS-942L/Firmware/update_DCS-942L_1.12_1608_WW.bin
…
# ./unp_fw_TV-IP572PI.sh update_DCS-942L_1.12_1608_WW.bin
Trendnet TV-IP572PI, D-Link DCS-942L, DCS-5211L, DCS-5222L Firmware unpacker
http://www.hardwarefetish.com
zImage written.
Separating gzipped part from trailer in ‘piggy.gz+piggy_trailer’
Trying size: 5088862 7633293 8905509 9541617 9859671 10018698 9939184 9978941 9998820 10008760 10003790 10001305 10002548 10001926 10001615 10001459 10001537 10001498 10001478./repack-zImage.sh: Zeile 284: [: : Ganzzahliger Ausdruck erwartet.
padding check (may take some time): 3
Found gzip compressed ramdisk.
Separating gzipped part from trailer in ‘initramfs.cpio+part3′
Trying size: 5919048 8878572 7398810 8138691 8508632 8323661 8231175 8277418 8300540 8312101./repack-zImage.sh: Zeile 284: [: : Ganzzahliger Ausdruck erwartet.
padding check (may take some time): 5143
Unpacking initramfs
36248 blocks
cpio: Removing leading `/’ from member names
36248 blocks
Success.
The unpacked files and the initramfs directory are in ‘./zImage_unpacked’.
—-
Hm, strange thing, i just tried to unpack this firmware again, but still no success. Image file is not corrupted (i was redownload this file with Steadyflow download manager), i’m using repack-zimage.sh ver.6, my machine running Ubuntu 12.10 x64.
I’ve found that you’re using simple code written in C, i’m not a C specialist (it’s like Mayan alphabet to me), but this code is using 2 header files (#include
#include ). Where are they located? Maybe the problem is somewhere there?
upd:
Argh, the parser was eaten filenames: #include stdio.h
#include byteswap.h
Ah, sorry, i found these files, but i’m still think that root of the problem is in C code…
Hm, maybe you have a 64bit machine, I haven’t tested my C-coe on 64bits, there may be some problem with data alignment there. You can check if the zImage generated by the C-Program is correct by erifying that
strings zImage | grep “zImage”
returns zImage, as this string should be in the resulting binary image. If it causes problems, you may want to compile the c-program with a 32bit compiler to ensure proper alignment.
I’m installed 32-bit version of Ubuntu on the Virtual Box and script is ended successfully and i already have unpacked filesystem! Thank you for your work and your help! Happy New Year!
If you add a -m32 to your gcc line it will always compile 32bit code, which seems to have worked for my firmware unpack
Karcaw: Thanks for this hint, I added it to my scripts now 🙂
I am working on a DVR firmware trying to add another DDNS server to their list. Firmware Mod Kit wouldn’t work with the file but Binwalk was able to extract the 3 cramfs images from it. Then I used FMK’s uncramfs_all script to extract them and I was able to find the XML files with those entries and edit them. Now my question is how to I reverse the process, convert this directory back to a cramfs file and repack the 3 images back into a FW file?
Trackbacks