# How to reverse engineering a DLINK ADSL Modem firmware I have a `DLINK DSL-2750U - HW:V1` and I would like to reverse its frimware. for start I search for a `frimware` version that could matched with my device I found some image to download. you can also find this image on the `DLINK` website. this url might help you if you want do it step by step with us. ``` https://dlinkmea.com/index.php/site/SupportResource ``` In above url I search for `DSL-2750U` then I select a proper version for my device for me the lastest version that I could install on my device was `H/W Ver. V1/V2 F/W Ver.1.16_ME`. you can also could select right version for yourself. when you downloaded a proper `Frimware`. carfully follow these steps. ## Prerequest : when you decide to reverse engineering a frimeware you should have some tools there is some tools that in follow help us 1. binwalk 2. mksquash, unsquash 3. lzma, lzmainfo, unlzma 4. dd -> `installed by default :)` 5. file -> `installed by default :)` to install them please follow these instraction > Install binwalk : Tool library for analyzing binary blobs and executable code ```bash sudo apt-get update sudo apt-get upgrade sudo apt-get install binwalk ``` > Install squash tool : Tool to create and append to squashfs filesystems ```bash sudo apt-get install squashfs-tools ``` > Install lzma : Compression and decompression in the LZMA format - command line utility ```bash sudo apt-get install lzma ``` ## First Step : Analysis with binwalk I use `BinkWalk` to check and analysis my downloaded frimware. to do it we could use this below command : ```bash binwalk GAN9.ET235B-B-DL-DSL2750U-R5B028-ME.EN_2T2R_update_1.16.img ``` Note : you might curious about `GAN9.ET235B-B-DL-DSL2750U-R5B028-ME.EN_2T2R_update_1.16.img`. I want say this was frimware that we download from `DLINK` website. when you download proper `frimware` and unzip it you could find inside it a image like `GAN9.ET235B-B-DL-DSL2750U-R5B028-ME.EN_2T2R_update_1.16.img` when you use `binwalk` command you can see result something like this ```bash DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 5746840 bytes 1800448 0x1B7900 Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 4922146 bytes, 1161 inodes, blocksize: 262144 bytes, created: 2016-10-20 00:25:24 ``` in above result we could see we have two part of data that contained inside our `GAN9.ET235B-B-DL-DSL2750U-R5B028-ME.EN_2T2R_update_1.16.img` file as a binery. to extract all data like `LZMA compressed data` and `Squashfs filesystem` we could use `dd` command line tool. but why ? because all this data store inside a binery file (.img file). ## Secound step : extract data from image file To extract data from `.img` file we use `dd` like this : ```bash dd if=GAN9.ET235B-B-DL-DSL2750U-R5B028-ME.EN_2T2R_update_1.16.img bs=1 skip=1800448 of=sq-filesystem ``` `dd` command help use to read a binry file and select a partof it then write selected part on the hard disk. in above example we use `dd` and its options : - if= this option get binery input file - bs= this option number of block that we should count ? - skip= this option indicated how much byte `dd` should skip to start read `squashfs file system`. in above example `dd` will skip from `0` to `1800448` then it start read data from `1800448` to end - of= this option help use to write extracted data to a binery file Note : you should curious about `skip=1800448`.`1800448` is number that binwalk show us in last step. binwalk show us where we should start to read to extract `Squashfs filesystem`. when you run above `dd` command you should have this result : ```bash 4923552+0 records in 4923552+0 records out 4923552 bytes (4.9 MB, 4.7 MiB) copied, 18.5036 s, 266 kB/s ``` and a package of frimware file system same as `sq-filesystem`. to ensure extracted data work right I check exported file with this below command : ``` file sq-filesystem ``` and result should like this below : ``` sq-filesystem: Squashfs filesystem, little endian, version 1024.0, compressed, 2457640485032820736 bytes, -1996226560 inodes, blocksize: 1024 bytes, created: Thu Oct 1 17:52:24 2099 ``` ok we extract frimware filesystem. `sq-filesystem` is binery file like `GAN9.ET235B-B-DL-DSL2750U-R5B028-ME.EN_2T2R_update_1.16.img ` to unpack it we need `unsquashfs` tool that so far in `prerequest` section we talk about it. Ok lets unpack this `sq-filesystem` with `unsquashfs` : ```bash sudo unsquashfs sq-filesystem ``` if everything was ok result should like somethings : ```bash Parallel unsquashfs: Using 4 processors 1102 inodes (1126 blocks) to write [============================================================================|] 1126/1126 100% created 696 files created 59 directories created 125 symlinks created 281 devices created 0 fifos ``` Then you should have a `squashfs-root` folder inside your work directory. now you can jump in to it and research about whole file inside it :). you might curious about,`web interface file, ftp, ssh, http server, samba ...` and another service that runned inside your Modem. you can find all of them inside `squashfs-root` folder. but as we know `GAN9.ET235B-B-DL-DSL2750U-R5B028-ME.EN_2T2R_update_1.16.img` had two parts. 1. LZMA compressed data 2. Squashfs filesystem we extracted `Squashfs filesystem`. but how we could extract part 1 `LZMA compressed data` from `GAN9.ET235B-B-DL-DSL2750U-R5B028-ME.EN_2T2R_update_1.16.img` file. this is really good question ? as we saw we used `dd` tool. for `LZMA compressed data` also we use it. this is command that we are use to extract `LZMA` part from `GAN9.ET235B-B-DL-DSL2750U-R5B028-ME.EN_2T2R_update_1.16.img` : ```bash dd if=GAN9.ET235B-B-DL-DSL2750U-R5B028-ME.EN_2T2R_update_1.16.img count=1800448 bs=1 of=lzma-data.lzma ``` above command is a bit diffrent from lastest command. in this command we use `count=1800448` and don't use `skip`. but why ? because we need extract `lzma` part and this part contained from `0` to `1800448`. binwalk help us to know how each part contain inside a binary file. binwalk show us first part containd from `0` to `1800448`. and second part contained from `1800448` to end. ok when `dd` extract lzma part we could check it with `file` command : ```bash file lizma-data.lzma ``` and file result is : ```bash DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 5746840 bytes ``` to extract this file we could use `ulzma` tools that so far we talk about it. lets extract lzma file with this below command : ```bash unlzma -d -k -f -v lzma-data.lzma ``` when `unlzma` decompress `lzma-data.lzma` we could check exported data with `file` command but before we check output file I want expine some unlzma option that we use in above command : 1. -d : this option decompress a input file 2. -k : keep input file when process completed 3. -f : this help forcly export data 4. -v : and this option show all task that `unlzma` do to decompress file. now lets check output file : ```bash file lzma-data ``` and output : ```bash lzma-data: data ``` to check `lzma-data` exported file I also use binwalk to check this file. because this file also is a binery file that could contained same part. excatly like `GAN9.ET235B-B-DL-DSL2750U-R5B028-ME.EN_2T2R_update_1.16.img` we check `lzma-data` with binwalk : ```bash binwalk lzma-data ``` And this is result : ```bash DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 4333600 0x422020 Linux kernel version 2.6.30 4533248 0x452C00 CRC32 polynomial table, little endian 4545752 0x455CD8 CRC32 polynomial table, big endian 5167416 0x4ED938 Neighborly text, "NeighborSolicitstunnel6 init(): can't add protocol" 5167436 0x4ED94C Neighborly text, "NeighborAdvertisementst add protocol" 5171123 0x4EE7B3 Neighborly text, "neighbor %.2x%.2x.%.2x:%.2x:%.2x:%.2x:%.2x:%.2x lost on port %d(%s)(%s)" ``` As you can see our `lzma-data` file separated to multiple part like ` Linux kernel version 2.6.30` , `CRC32 polynomial table` and etc. to extract each part we can use `dd` tools againe for example if I want extract `Linux kernel version 2.6.30` I should use this below command : ```bash dd if=lzma-data bs=1 skip=4333600 count=199648 of=linux-kernel-version-2-6-30 ``` and for first CRC32 : ```bash dd if=lzma-data bs=1 skip=4533248 count=12504 of=CRC32-t ``` and so on.