Dlink固件
Dlink固件:
DIR-2640_REVA_FIRMWARE_1.11B02
binwalk提取固件后将prog.cgi拖入ida分析:
在函数sub_481FC8中,可以看到一个变量count,来控制for循环的次数,循环中,使用strcpy函数把haystack复制到ptr中,而count并没有经过验证,所以当count足够大时,可以造成堆溢出。
checksec查看保护:
发现啥保护都没开,先在qemu用户态下测试一下,运行prog.cgi
大概是有些设备没挂载,所以我们先启动一个chroot容器,运行一下rcS
1 | chroot . ./qemu-mipsel-static ./bin/ash |
虽然有些问题,但还是挂载了一些盘上去,再运行prog.cgi试试
报错,经过调试,发现程序在函数sub_42D2DC退出,该函数是一个注册表函数,其在调用函数trace时,会触发ioctl的报错,所以我们把它patch掉,成功进入主循环
后来发现这个程序并不是通过网络来通信,而是利用getenv函数,通过环境变量来与web应用通信。而启动整个web应用,作者做过诸多尝试,但还是不行,所以得换个思路。
关于如何让程序崩溃:
需要攻击的代码如下
1 | ptr = malloc(0xFFF0u); |
我们需要让循环跑到strcpy那里,需要满足两个约束:webGetVarString返回有效值
,*haystack不为空
,只要满足这两个条件,就会在循环中调用strcpy函数,将haystack中0x888长度的内容copy到ptr中;除此之外,我们要让循环继续执行下去,往下看看代码:
1 | memset(v50, 0, sizeof(v50)); |
为了简化模型,我们控制v46为0,不进入if分支,后续进入else后程序会进入下一次循环,这样我们的目的就达到了。
调试方法:
将qemu-mipsel-static复制到固件根目录下,chroot启动容器,运行以下命令
1 | cp /usr/bin/qemu-mipsel-static . |
再另起一个终端,启动gdb-multiarch
1 | gdb-multiarch |
hook到sub_481FC8函数:
编写一个main_hook.so,利用libc_start_main函数,hook到sub_481FC8函数,随意编写一个输入,count定为64,以下是seeds.bin:
1 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
io钩子函数如下
64个大写的A,先把LD_PRELOAD设为main_hook.so,运行以下指令:
1 | chroot . ./qemu-mipsel-static -L . -E LD_PRELOAD=/lib/libdl.so.0:./stack_hook.so -g 1234 ./bin/prog-cgi seeds.b |
往下调试发现报了一个段错误:
检查发现是haystack这个字符串把下面的ptr给覆盖了,所以在解引用ptr时,出现了报错,简单来说,这里有个缓冲区溢出,并且能够实现任意地址写的原语。
栈结构如下: