反编译D-Link路由器固件,找出Backdoor

October 30th, 2013 by JasonLe's Tech Leave a reply »

指导文章 http://blog.jobbole.com/49959/
最近DLink爆出固件存在后门,正好最近在看汇编,所以花了一晚上时间,按照这篇的提示实践了一下。

分析流程:
1.use Binwalk to identify different parts of a firmware image by their magic
2.use dd to split the firmware image apart
3.unpack parts / mount/extract the filesystem(s)
4.find interesting config files/binaries
5.load ELF binaries into your favorite disassembler
6.start looking at beautiful MIPS/ARM/PPC ASM首先我们使用binwalk。

Binwalk0.4.5 不用额外 dd if=xxx.img bs=1 skip=18204 count=853764 of=part1.gz $ binwalk firmware.bin –dd=gzip:gz 提取 gzip 档案存在 gz 檔.可自定义
$ binwalk firmware.bin –dd=lzma:lzma
$ binwalk firmware.bin –dd=Squashfs:Squashfs
$ binwalk firmware.bin –dd=all:dat

根据步骤然后导入这个固件
我们可以根据提示,找到这个firmware中的各个部分。

2013-10-29 22:26:15的屏幕截图

下面我们使用firmware-mod-kit
安装firmware-mod-kit
svn checkout http://firmware-mod-kit.googlecode.com/svn/ firmware-mod-kit-read-only
apt-get install subversion build-essential zlib1g-dev liblzma-dev
https://code.google.com/p/firmware-mod-kit/wiki/Documentation?tm=6

然后 遇到 Auto extract: 如果遇到 auto 会卡住,就手动解 ./extract_firmware.sh /root/Desktop/firmware.bin

036C17E2-D426-4B09-B2F5-E60C2EC1789E

Squashfs(.sfs)是一套供Linux核心使用的GPL开源只读压缩文件系统。Squashfs能够为文件系统内的文件、inode及目录结构进行压缩,并支持最大1024千字节的区段,以提供更大的压缩比。
Squashfs的设计是专门为一般的只读文件系统的使用而设计,它可应用于数据备份,或是系统资源紧张的电脑上使用。标准版的Squashfs采用gzip的数据压缩。
然后我们就会解出squashfs文件系统,打开这个文件系统,可以看到一个linux文件树,我们在/bin/webs找到了一个httpd,然后我们将这个webs的二进制代码加载进IDA 我们可以反汇编出一堆汇编代码,和一堆函数名。
我们果断发现了以alpha_开头的http得函数名,然后我们定位到alpha_auth_check()
我们发现了传说中的回文字符。
Unnamed QQ Screenshot20131029221634

这段代码理解出来的含义就是

#define AUTH_OK 1
#define AUTH_FAIL -1
 
int alpha_auth_check(struct http_request_t *request)
{
    if(strstr(request->url, "graphic/") ||
       strstr(request->url, "public/") ||
       strcmp(request->user_agent, "xmlset_roodkcableoj28840ybtide") == 0)
    {
        return AUTH_OK;
    }
    else
    {
        // These arguments are probably user/pass or session info
        if(check_login(request->0xC, request->0xE0) != 0)
        {
            return AUTH_OK;
        }
    }
 
    return AUTH_FAIL;
}

正如文中说的,如果遇到了user_agent = xmlset_roodkcableoj28840ybtide 就会通过验证。
这次我通过assemble的每一步,发现了程序变量和函数的跳转。
这样才能发现问题。