Adventures in Linux: Reverse Engineering Firmware - This 8-Bit Life
***Update. I should note that I found SHA1 unsalted hashes in the filesystem. Unfortunately none of those passwords worked for my mysterious admin port. Gotta say thanks to all the folks in /r/hacking for the encouragement and helpful info. And many thanks to Hack a Day for posting my stuff!
I got home today after class with the intent to start playing around with some new network security tools in my lab, my classes are intellectually stimulating enough that I usually leave with ahead full of ideas and plans to break things in new an interesting ways. Today was no exception, except I never actually got to playing around with my new tools, and ended up learning how to reverse engineer binary firmware instead. I love when things take a turn for the organic!
So there I was, getting ready to hack around on my network. The first thing I did, as it occurred to me I never had before, was to port scan my external IP. I didn’t find much out of the ordinary open aside from one strange port, 4567. A few quick Google searches informed me that common belief was this was a port used by Verizon to automatically push firmware updates to customer premise equipment, namely that FiOS router (mine is a Westell 9100EM) you have sitting near your machine if you are one of the chosen. Well this piqued my interest, “Surely this would be password protected”, I thought.
Visiting my public IP with that port appended to it from a web browser returned a login prompt and sure enough my normal administrative login didn’t work. I found a few theories on the defaults for the account credentials in various forums but nothing concrete or functional. But this just wouldn’t do. I refuse to have a port exposed to the Internet that I don’t have access to. So I did what any self-respecting man would do. I tore apart the firmware for the router to look for the credentials by hand!
What follows serves as a pseudo tutorial/hacklog. I spend a number of hours learning from point zero how to do something that should ultimately take about 15 minutes. I know because I had to do it a second time to get all the screenshots. This project has been a ton of fun for me and it’s not over yet. I still have a lot more to learn here. But enough prattling, on to dirty work!
I began by pulling down a clean image of the router firmware from Verizon’s website.
I am a pretty regular listener of the PaulDotCom Security Podcast and have been hearing the hosts speak a lot about reverse engineering firmware for various embedded devices. They’ve mentioned that some of their first steps in understanding what you are dealing with is to run strings and hexdump against the binary in question. I had both tools place their output into files under a directory called “dumps”.
From here I opened each of the files up in the nano editor to get a look ate what might be in the header of the binary. Behold! It is Linux! Big surprise…
Luckily I also learned that this firmware is based on the OpenRG platform, that is to say that this firmware was developed by a third-party and customized by the manufacturer. **For more on OpenRG check out this link here.
So now we I knew I was dealing with a Linux-based firmware and I had a developer resource as well! Not much info but a place to start. Now it was time to fire up that binwalk tool I had heard so much about. I went ahead and gave the download its own directory in the interest of neatness.
Then took a look at the README which explained how to install with its handy little Python script. **Note to self, finish that damned book on Python and start learning it!
From here I went ahead and ran binwalk against my binary and got just a tiny step further. Looking at the screenshot below we can see that the last decimal (byte value location) of this uImage header is 171 bytes into the binary. Since all I wanted was the soft underbelly of the filesystem I needed to ignore this section. Using the dd command I was able to carve out the filesystem portion from the rest of the binary as shown below. And to verify that I got everything intact I ran the file command against this chunk to be sure it was a valid uImage file.
So what to do now? I have a binary filesystem that I can’t read from. A bunch of Googling an caffeine led me to a pretty nifty shell script that was built with the express purpose of automatically extracting uImage data. Thank goodness for people smarter than I!
I downloaded the script from the developer’s website and used chmod to make it executable, otherwise it would bitch at me.
After running this handy script (that saved me a TON of trial and error) I now had a gzip compressed file called Image. I made sure to run file against it to verify that it was a sane image. I also got some more useful data! The file command told me when this file was last updated! This could be useful if I ever decided to start hunting for exploits for the firmware as I now had a time frame from which to base my exploit inquiry.
Next I uncompressed the gzipped “Image” file and renamed it to “vmlinux.bin”.
Now that I had an uncompressed binary of just the filesystem binwalk might just give me some real information about the firmware. Sure enough it found 3 separate filesystems, one called “romfs” and 2 others called “CramFS”. Now I don’t know the first thing about these filesystems but I definitely intend to learn more about CramFS, you’ll see why in a moment.
A bit more dd magic and I had 1 readable filesystem and 2 compressed (crammed?) filesystems. So I mounted up the romfs first only to find that it contained kernel modules. Not quite what I was after…
There wasn’t much here for me but I’ll probably poke around a bit more later on.
So, onward to the CramFS stuff! Again I have no idea how this filesystem works so I Googled around until I found a tool called lzma-uncramfs. This tool is meant to uncompress a CramFS filesystem and provide you with the raw directory structure and hopefully its delicious insides. I pulled the tar down from this link https://github.com/digiampietro/lzma-uncramfs. Then I compiled it from source with the make command. Then I went ahead and ran it with a “./” to run it from the path I specified and inserted a period as the output directory. I repeated this process for both cramfs files I had previously created with dd.
And just like that I had a fully uncompressed firmware image to dig around in! I even found the image files used by the browser interface for the router.
But sadly I have hit a wall. I’ve found plenty of good data in here but it looks like all of the really interesting stuff was exported as broken symbolic links and I’m not sure what to do to fix them. I’m going to be doing more research online over the weekend to see what I can come up with. Oh and if anyone who reads this has an idea as to why this happened please feel free to comment and let me know!
Until next time guys!
**If you would like to take a look at the work I have done so far download THIS TAR FILE!