Although released under the GPL, DD-WRT is notoriously difficult to build from source. If you want to customize your DD-WRT installation, it is usually easier to extract files from the firmware image, change what you need, and then re-construct the image.
One exception here is the Web GUI. The DD-WRT Web pages (*.asp, *.htm, *.gif, *.css) in each firmware image are protected in order to prevent modification. Being able to customize the Web interface can be advantageous for those wishing to add compatibility with mobile/uncommon browsers, change themes, add links, etc.
And, despite claims to the contrary, that’s exactly what we’ll be doing.
Starting on this project, my first assumption was that the Web pages were built into the httpd binary itself. However, taking a look at the source code, we can see that the function getWebsFile actually reads data from the file /etc/www:
263 FILE *getWebsFile(char *path) 264 { 265 cprintf("opening %s\n", path); 266 int i = 0; 267 while (websRomPageIndex[i].path != NULL) { 268 if (!strcmp(websRomPageIndex[i].path, path)) { 269 FILE *web = fopen("/tmp/www.debug", "rb"); 270 if (!web) 271 web = fopen("/etc/www", "rb"); 272 if (web == NULL) 273 return NULL; 274 fseek(web, websRomPageIndex[i].offset, 0); 275 cprintf("found %s\n", path); 276 return web; 277 } 278 i++; 279 } 280 cprintf("not found %s\n", path); 281 282 return NULL; 283 }
At build time, all of the Web files are concatenated into the /etc/www file; websRomPageIndex is used by the httpd code to identify where each file is located inside of /etc/www.
websRomPageIndex points to an array of data structures that each contain three elements: a pointer to a Web URL string, the size of the file, and the file’s location inside /etc/www:
82 typedef struct { 83 char *path; /* Web page URL path */ 84 unsigned int offset; /* Web page data */ 85 unsigned int size; /* Size of web page in bytes */ 86 } websRomPageIndexType;
UPDATE:
Not long after this article was published, websRomPageIndexType was modified so that newer DD-WRT builds use the following structure:
82 typedef struct { 83 char *path; /* Web page URL path */ 84 unsigned int size; /* Size of web page in bytes */ 85 } websRomPageIndexType;The offset is not explicitly specified and must be inferred based on the sizes of the previous files. Both the old and new formats are supported by webdecomp.
If we can locate websRomPageIndex in the httpd binary, we will be able to identify and extract each Web page from the /etc/www file and associate the extracted data with the appropriate file name.
There are several ways to locate websRomPageIndex. First, IDA resolves the name properly, making it easy to identify the virtual address of websRomPageIndex:
For MIPS binaries, readelf can also be used to identify the websRomPageIndex virtual address:
$ readelf --arch-specific httpd | grep websRomPageIndex 004372e8 -31416(gp) <unknown> 004352c8 OBJECT 19 websRomPageIndex
These virtual addresses can be converted into file offsets by:
- Identifying the ELF program section where the address is located
- Subtracting the section virtual address and adding the section file offset to the address
Here, we see that the address 0x004352C8 is located in the second PT_LOAD section:
$ readelf --program-headers httpd Elf file type is EXEC (Executable file) Entry point 0x403950 There are 7 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x00400034 0x00400034 0x000e0 0x000e0 R E 0x4 INTERP 0x000114 0x00400114 0x00400114 0x00014 0x00014 R 0x1 [Requesting program interpreter: /lib/ld-uClibc.so.0] LOAD 0x000000 0x00400000 0x00400000 0x24e44 0x24e44 R E 0x10000 LOAD 0x025000 0x00435000 0x00435000 0x023ab 0x084bc RW 0x10000 DYNAMIC 0x000128 0x00400128 0x00400128 0x00128 0x00128 RWE 0x4 GNU_EH_FRAME 0x0023ab 0x00424e30 0x00424e30 0x00000 0x00014 R 0x4 NULL 0x000000 0x00000000 0x00000000 0x00000 0x00000 0x4
We can now calculate the file offset of websRomIndexPage:
$ echo "$((0x004352C8)) - $((0x00435000)) + $((0x025000))" | bc 152264
Since each structure in the websRomIndexPage array contains a pointer to the Web file path, another method of locating websRomIndexPage is to:
- Locate the offset of the first file path in the httpd binary (typically Alive.asp)
- Convert the physical offset of this string to a virtual address
- Search the binary for references to the virtual address
Once the websRomIndexPage location has been identified, we can simply walk through the structures and extract the corresponding file data from /etc/www until we find a structure with a NULL path, indicating the end of the structure array.
Looking at the first structure entry at offset 152264 (0x252C8), we see that the path pointer points to 0x0041F1F4, the offset into the /etc/www file is 0x00000000, and the file size is 0x00000C6C:
000252c0 04 3f 42 00 30 50 43 00 f4 f1 41 00 00 00 00 00 |.?B.0PC...A.....| 000252d0 6c 0c 00 00 00 f2 41 00 6c 0c 00 00 18 60 00 00 |l.....A.l....`..|
Converting the virtual pointer address 0x0041F1F4 to a physical file offset we get 0x1F1F4, which is where the string “Alive.asp” is located:
0001f1f0 25 3e 00 00 41 6c 69 76 65 2e 61 73 70 00 00 00 |%>..Alive.asp...|
We can now extract the contents of Alive.asp from /etc/www:
$ dd if=www bs=$((0xC6C)) count=1 of=Alive.asp 1+0 records in 1+0 records out 3180 bytes (3.2 kB) copied, 3.106e-05 s, 102 MB/s
And verify that the data looks correct:
<% do_pagehead("alive.titl"); %> {m} //<![CDATA[ function to_submit(F) { F.save_button.value = sbutton.saving; apply(F); } function to_apply(F) { F.save_button.value = sbutton.saving; applytake(F); } ... </div> {e}"info"><% tran("share.time"); %>: <span id="uptime"><% get_uptime(); %></span></div> {e}"info">WAN<span id="ipinfo"><% show_wanipinfo(); %></span></div> </div> </div> </div> </body> </html>
Looks good! We can now modify this file however we want, then copy it back into /etc/www. However, if we change the size of Alive.asp we will also need to update its file size, as well as the file offsets of all subsequent files, in the websRomPageIndex structure array.
Although this process is not terribly difficult, it is time consuming; obviously, some automation is in order. To that end, I’ve written webdecomp, a tool to automate the extraction and restoration of DD-WRT Web files. It has been added to the firmware-mod-kit, and allows you to change the Web pages however you wish, with the following restrictions:
- You cannot add files
- You cannot delete files (but you can have empty files)
So far it has been tested on various DD-WRT builds for ARMEB, MIPS and MIPSEL, but should work with most architectures and build versions without issue.
I don’t know whether this is the right place to ask… but I’m trying to dissect a firmware which is jungo’s openrg based. Have you guys dealt with those kind of firmwares ? Any plans to add them in the future to firmware-mod-kit ? Thanks.
acki
PS: If you want me to, I can upload a firmware sample for you to take a look (out of curiosity, of course).
PS2: Excuse me for the “cross post”
The OpenRG firmware usually provides a telnet shell, which is what I’ve always used. Obviously not useful if you don’t have the device though. Which OpenRG-based device are you looking at? The MI-424WR?
Craig,
Yes, it does provide a telnet shell. I even have supersuser rights. The device is a “Sagem F@st 3504”, rebranded as “Livebox 2”, used in Spain and France by that name and in Belgium and Italy (at least) by other names. I have run binwalk against a firmware -and also against a copy of the whole flash- and very little shows up. Just the u-boot and the kernel. No track of squashfs images or anything at all.
The point is: Have you guys ever tried to extract stuff from an OpenRG firmware ? Is it somehow in the roadmap of firmware-mod-kit ?
Thanks.
I forgot the say it, but I also ran latest firmware-mod-kit against the same files to no avail. (I guess it was implied, but just in case).
Another thing I forgot to mention, doing a “strings” to the firmware this line shows up:
root=/dev/mtdblock6 ro rootfstype=squashfs operational_start=0xbf760000 rescue_start=0x00000000 myfs_start=0xc0000000 type=operational
So I guess we have another “patched” squashfs suite. Isn’t it a GPL violation ?
Pingback: Modifying DD-WRT’s protected GUI - Hack a Day
Pingback: Modifying DD-WRT’s protected GUI | You've been blogged!
acki:
As far as I know, the FMK hasn’t been tested against a lot (any?) of the OpenRG firmware. I have a MI424WR lying around and I checked it out last night. It uses a CramFS file system, so it’s probably not the same OpenRG firmware as your router.
Patching squashfs is pretty common I’m afraid. I have no idea why, seems to be more trouble than it’s worth. Sometimes the modifications are simple, sometimes more complicated. But it’s only a GPL violation if they don’t provide you with the modified source code.
If you can provide links to the firmware image and/or GPL code, I can take a look at it. If GPL code is available, it’s usually pretty easy to add into the FMK.
Pingback: Modifying DD-WRT’s protected GUI | The Depot of Talk
Craig,
The firmware you can find it here.
http://www.megaupload.com/?d=0GH1FSBD
Regarding openrg gpl’d source code, you can read this:
http://www.jungo.com/openrg/download_gpl.html
As you can see they provide the gpl’d part upon paying $15 and then they mail a CD. But as soon as they change versions, that source code for sure will become useless. Not sure it is a complete GPL violation, but it could perfeclty be.
Regards.
Craig:
I don’t understand why, but my last message was removed. I’ll repeat it:
Firmware is here:
http://www.megaupload.com/?d=0GH1FSBD
And then, jungo offers their GPL’d source code upon paying 15$. See here:
http://www.jungo.com/openrg/download_gpl.html
And the worst part of it. You get the CD with the modified sources… and then, for next version, what do you do? Pay another $15 every time ? Plus the fact that we don’t know what openrg version was used to build that firmware. I still think that this is a GPL violation because source code is not exactly publicly available.
Craig,
My last two comments were “moderated” though I don’t understand the reason. I was speaking about a possible GPL violation and posted a link with a firmware to prove it. I apologize for any inconvenience.
If you want to discuss regarding this issue, you have my e-mail.
Regards.
Pingback: Modifying DD-WRT’s protected GUI | CisforComputers
Pingback: Modifying DD-WRT’s protected GUI - Free Plans, Hacks, Howto's and other DIY stuff - Free Plans Online
Pingback: Modifying DD-WRT’s protected GUI « FOOTBALL, SEX & ALCOHOL
@acki:
The filesystem in the firmware you’ve mentioned is not a squashfs. At offset 0x180 in the file openrg.img (http://www.megaupload.com/?d=0GH1FSBD) you’ll find a GZIP signature; crop the file from that point to the end of file and save as vmlinux.bin.gz. Then, decompress with ‘gunzip vmlinux.bin.gz’. The decompressed file (vmlinux.bin) contains a cramfs filesystem at offset 0x2f4000 (below you’ll see “Compressed ROMFS”); again, crop from that point to the end. Now you can extract its content using this utility: http://firmware-mod-kit.googlecode.com/issues/attachment?aid=-4083775365610407538&name=lzma-uncramfs.tar.gz&token=65209990128d32db53a91e866fe8de98
Regards.
Well there you to acki. 🙂
Sorry I haven’t gotten a chance to look at the firmware image yet, so thanks cbrown for jumping in and figuring it out!
i flashed ddwrt on dlink 615 bu i want to change the ddwrt to dlink in firmware. i downloaded the .bin file of ddwrt and when i try to extract its shows error “file not suppurted”..
i try to extract with power iso ned help plz
can u provide step by step guidies for newbies
@shiv:
What tool gave you the “file not supported” error? That string is not in the webdecomp tool nor the extract scripts from the firmware mod kit.
PowerISO is for working with ISO files. Firmware updates generally are not in ISO format.
There are step-by-step examples of how to extract the firmware, modify the DD-WRT GUI and put it all back together again in the firmware mod kit’s wiki page (see the ‘Examples’ section at the bottom of the page): http://code.google.com/p/firmware-mod-kit/wiki/Documentation
so that mean have work u linux based to modify firmware..thx a lot for help..if any very i stuck i ask question again..thx again m8…
You can have a look here, and you’ll see how to extract the firmware: http://fwhacking.blogspot.com/search/label/Livebox%202
uncramfs-lzma is required, and fortunately it’s found in firmware-mod-kit 🙂
I don’t know about building DD-WRT, but I didn’t have that much trouble building Open WRT.
It took about a weeks of on and off reading and a couple of days of setting up the build chain.
I was able to set up a working toolchain in Xbuntu in Virtual Box and had a working build for my router. And honestly that was the second time i’d ever build a kernal from source and the 1st time i’d ever cross compiled anything under *nix gcc toolchain.
The hardest part was that the dependencies scripts were using wget which refused to use anything other than IPv6 which at the time, the shitty OME firmware on my router failed to work with. So i ended up having locally host ever dependency and add entries in the /etc/network/hosts file. Just to get the configure script to complete.
Not sure if you guys would be willing to help but…..
Would it be possible to create a small webpage that would use the admin GUI webserver with redirect to the contents to the NAS?
I have the most current version of dd-wrt:
DD-WRT v24-sp2 (06/14/11) std
(SVN revision 17201)
I have a 1tb drive on the USB. Samba is enabled and I am able to see the share via my network. I have the share listed on my network as the z: drive and am able to read and write to it via the pc’S on my network.
The problem I am having is I just got a Roku2 XS streaming media box. I was watching movies via the USB port on the Roku. What I didn’t relize is that in order to be able to stream movies from the NAS on my router the Roku must access the NAS via an http:// webserver
Is there a simple way to webshare my NAS to my internal network?
I found something that might help:
http://www.dd-wrt.com/wiki/index.php/WEB_server
Any help with this would be very helpful. I am sure there are others with a Roku box that this may help as well. These seem to be becoming very popular.
The latest version of Firmware Modification Kit supports extracting/rebuilding the latest dd-wrt webui but it doesn’t support adding/deleting/renaming files.
Any tips on how to add/remove files from the web interface using this manual technique?
The FMK doesn’t support adding/deleting/renaming files, as that would (in all but a few cases), cause the size of the data and/or structure array in the httpd binary to change, which would almost certainly cause it to crash. You can have files of zero length though.
I found the comment http://www.devttys0.com/2011/09/modifying-the-dd-wrt-gui/#comment-1826 but Megaupload is off 🙁
Anybody have the firmware fast3yyy_69127a for livebox 2? Thanks
Everybody is searching the “fast3yyy_69127a” or any firmware from livebox2 for example: “fast3yyy_691288”. Please anybody could put a valid link, their help will be very apreciated.
Thanks.
very good post! 🙂
Download firmware here:
http://www.auditoriaswireless.net/index.php/topic,1790.msg19274.html#msg19274
i succely uncramfs a sagemfast3505’s image with the uncramfs-lzma , i did some modification , and i tried to rebuild the img , but i can’t find a reverse operation tool , i tried only to cramfs the modified directory , but the result image is bigger than the origin . does for exempe “mkcramfs-lzma” still not ready yet ? thnks .
Hi great article, really interesting.
Unfortunately this seems not to work with recent version of dd-wrt v24 preSP2..
Any progress on that?
Thank you
Please report any issues to the firmware-mod-kit project issues page, along with a link to the exact firmware image that you are having problems with.
Hi Craig, where can I download firmware_mod_kit?
Thank you.
Hi! It’s a very amazing post! I was also trying to unpack my httpd of an OpenRG firmware. I managed to unpack the actual firmware and to mount the file system with httpd.
Applying strings httpd I can see some variables and html code, but how to extract it and how to pack it back I have no idea. webdecomp doesnt work against it.
Actually there is no websRomPageIndex function I can find, thats where im stuck..
Hi. Is there a way to decompile the nikon dslr firmware and include some features of the high end cameras into the cheaper ones?
I don’t know about Nikon, but I know it’s been done with Canon cameras before.
http://chdk.wikia.com/
(Technically, it’s not modified firmware; it’s basically a program that runs on top of the existing, unmodified firmware.)
dear sir
i want hire your service if u intrested. i want to change logo of a firmware of ddwrt kindly contact me at the provided email address thanx n regards
raag
Hi, craig your work is amazing and i am using your fmk.
i have successfully extracted firmware i.e tp-link wr740n factory-to-dd-wrt.bin but when i tried to change the code in directory /etc/www
i only tried to rename label of “Router Name” to “Abc Name” in code and then i tried to build it again so the resultant image becomes larger like orignal 3.9mb after label changed 4.3mb and it can obviously brick the router.
please help me in this problem. Thankyou
***** Con esto puedo remover el Cartel de ” activacion” ??? ******