Cisco Cook常用方法与技巧
在之前公众号的文章中对Cisco IOS整体进行了一些介绍(https://mp.weixin.qq.com/s/L030HpZGX_JglySsin7WzA),今天介绍一下具体的一些常用方法与技巧。
一、介绍
1.Cisco近几年的安全漏洞:
Cisco近几年披露了诸多的安全漏洞。The Holy Grail Cisco IOS Shellcode And Exploitaion Techniques---Michael Lynn:披露如何绕过Cisco堆检查;GeekPwn大会上的相关内容;以及众多主要的漏洞:IKEv2 Exploit(cve-2016-1287)、EXTRABACON(snmp协议)、IKEv1 Exploit(cve-2016-1287)、Cisco Cluster Management Protocol(CMP)(cve-2017-3881)…..

2.Cisco diversity
Cisco的多样性是其一项标志性特征,主要分为系统多样性和指令架构多样性。
系统多样化:Cisco IOS、Cisco IOS XE、Cisco NX-OS、Cisco IOS XR、ASA OS ?
指令架构多样化:PowerPC、MIPS、x86_64
3.常见目标特征:
(1)需要对Cisco IOS固件进行逆向分析??
(2)通常镜像都是一个大型二进制文件,需要静态分析??
(3)在IOS中,所有代码都是在提权模式下进行,因此可以使用特权指令??
(4)在IOS中,好几段虚拟内存可能映射的是同一段物理空间(例如20000000与80000000)??
(5)溢出执行完shellcode要将控制流返回至正常服务??
(6)当IOS服务触发异常时,Cisco IOS会重启设备(dos攻击很简单,RCE需要再构造)??
Cisco IOS没有其他的API函数或者指令支持,因此如果想调用里面的一些功能(比如tcp连接),需要去定位相关的功能函数
4.常见防护:
(1)DEP:栈、堆等内存中不可执行,要做ROP攻击
(2)ASLR:栈、堆具有随机化特征,要绕过地址随机化
(3)堆检查:IOS会在固定时间检查堆结构,在堆释放的时候也会进行堆检查(具体的检查方法在之前的公众号文章里有讲),而且IOS的栈的空间也是在堆中的,因此栈溢出和堆溢出利用都可能被检查
(4)代码完整性检查:完整性检查会是否在镜像文件里植入了后门或者shellcode(一般利用签名)
(5)计时器:如果shellcode运行时间太久,计时器会触发然后终止攻击进程
(6)Cisco多样化:思科镜像多样性,exp在镜像间的移植需要时间
(7)I-cache、D-cache防护:Powerpc架构的处理器会隔离代码区域和数据区域,因此有时候将控制流劫持到数据区域是无法执行的
5.Cisco IOS漏洞利用整体思路:

二、常用cook方法:
1.Exploit Debugging:
想要实现漏洞利用首先是需要能执行漏洞调试,这里主要介绍两种调试方式。
虚拟平台调试:
①安装Cisco dynamips调试平台(并支持gdb调试版本):
git?clone?https://github.com/Groundworkstech/dynamips-gdb-mod
cd?dynamips-gdb-mod/src
updatedb
locate?libelf.a
②利用dynamips启动对应的模拟调试:
dynamips?-Z?+连接的端口?-j(禁用JIT编译器)?-P?+模拟的硬件平台?-t?2621?-s?0:0:tap:tap1?-s?0:1:linux_eth:eth0?+镜像文件
③利用gdb连接调试:
注意,这里用的gdb连接调试需要使用对应架构的gdb,有两种解决方案:
一是利用gdb-multiarch;二是利用buildroot或者交叉编译工具链交叉编译一个对应架构的gdb调试工具。
gdb$?target?remote?192.168.9.1:6666
虚拟调试平台脚本:https://github.com/Groundworkstech/dynamips-gdb-mod
实体设备调试:
虽然虚拟平台调试比较方便,但是有很多版本以及型号的限制,因此最好使用实体设备进行调试。实体设备调试需要利用cisco设备自带的调试栈开启调试。
①实体设备连接:
首先进行串口调试配置,对于Linux系统,需要指定串口驱动程序。因此需要先查找相应串口驱动模块:
lenovo@ubuntu:~$?dmesg?l?grep?ttyS*
[??????0.00000]?console?[tty0]enabled
[838830.952225]?usb?2-2.1:FTDI?USB?serial?Device?converter?now?attached?to?ttyUSB1
[844005.477214]?ftdi_sio?ttyUsB0:?FTDI?USB?Serial?Device?converter?now?disconnected?fron?ttyUSB1
[1471721.288079]?usb?2-2.1:FTDI?USB?serial?Device?converter?now?attached?to?ttyUSB1
利用串口通信工具连接至指定串口驱动模块,并设置Cisco IOS串口通信的硬件信息,即可建立连接:
lenovo@ubuntu:~$?sudo?picocom?-b?9600?/dev/ttyUSB1
picocom?v1.7
port?is???:?/dev?/ttyUSB1
flowcontrol???:?none
baudrate?is???:?9600
parity?is???:?none
databits?are???:?8
②使用gdb kernel在实体设备上启动gdb调试模式:

对于Cisco IOS新版本,会屏蔽相应调试功能,需要进入ROMMON中开启调试功能。
rommon1>confreg?0x2100
C1921(config)#config-register?0x2100
MIPS:?break?‘0000000d’
PPC:trap?‘7fe00008’
③利用调试脚本连接对应串口,实现调试功能:
python?调试脚本.py?/dev/ttyUSB1

调试脚本参考:
https://github.com/klsecservices/ios_mips_gdb
https://gist.github.com/nstarke/50a1519067f62c223e39a98ba32ed7d5
??????? mips、arm和ppc的调试脚本其实都大同小异,甚至可以自己编写修改调试脚本,注意对应不同的架构时,要修改capstone的对应架构,以及设置断点时的寄存器数值。
2.获取控制流:
通常利用栈溢出漏洞获取控制流(Phrack Magazine Burning the bridge Cisco IOS exploits (2002))
3.DEP绕过:
利用ROP攻击绕过DEP防护,对于ppc指令,可以通过常见返回指令去找gadgets:blr blrl bctr bctrl
常见ROP利用技巧:??
(1)利用ROP gadgets直接构造shellcode(cve-2017-3881)
(2)利用gadgets直接重写指定数据甚至代码,看能不能起到效果
(3)利用gadgets去禁掉DEP防护,然后在栈上执行shellcode
(4)开启在代码段的写权限
ROP攻击限制:ROP攻击可能导致在栈上存放过多的数据(因为shellcode长的话,要在栈上构造很多个gadgets的地址),这样容易触发堆检查机制或者是影响其他的正常数据,因此在栈上不能构造太长的ROP攻击。
4.Gadgets构造的拓展技巧:
(1)Write-4 Primitive
(参考34c3交流会议)因为前面所说,不方便构造太多的gadgets,因此可以利用几个简短的gadgets(这几个gadgets的功能就是向内存写一段在栈上存放的4字节的数据),将想执行的shellcode每4字节逐次写到内存中,最后再劫持控制流到内存中即可。这样的话shellcode不论长短,都可以写到内存中,因此不需要在栈上构造过长的gadgets。
在mips和ppc上都有这种类似的write-4的gadgets:
lwz?????r0,0x14(r1)
mtlr????r0
lwz?????r30,8(r1)?????#value
lwz?????r31,0xC(r1)???#dst?address
addi????r1,r1,0x10
blr
stw?????r30,0(r31)????#store?value
lwz?????r0,0x14(r1)
mtlr????r0
lmw?????r30,8(r1)
addi????r1,r1,0x10
blr
(2)Blrl Gadgets
由于C语言和PowerPC架构的调用约定,想找到从栈向r3-r17寄存器加载的gadget比较难,但是此类gadget又很常用,因为从r3开始的低号寄存器是PPC架构的传参寄存器,经常需要利用这种gadget向调用函数传参。
解决方法一:可以分几个阶段,先初始化寄存器,再向大号寄存器进行传参(这种gadget很多),然后利用大号寄存器向小号寄存器进行赋值操作。这种办法可以,但是有点麻烦,浪费堆栈空间。
解决方法二:利用blrl gadget,blrl gadget通常具有几个特点:通常都结合低号寄存器使用,而且通常比较多样,因此可以利用blrl gadget,节省堆栈空间。
lwz?????r5,0xC(r1)????#Load?Word?and?Zero
mr??????r6,r20????????#Move?Register
mtlr????r27???????????#Move?to?link?register
blrl??????????????????#Branch?unconditionally
(3)Indirect Call Gadgets
有时候ROP攻击的shellcode比较复杂,需要调用各类函数,比如memcpy函数,或者是禁止安全机制的函数,或者是调用另一个shellcode,特别是当这些函数位于其他区段时,利用Indirect Call Gadget可以解决。
1.mtlr????r28????????#Move?to?link?register
??blrl???????????????#Branch?unconditionally
??lwz?????r0,0x1C(r1)
??mtlr????r0
2.mtctr???r0?????????#Move?to?count?register
??bctr
3.mtctr???r31????????#Move?to?count?register
??mr??????r3,r30?????#Move?Register
??bctrl??????????????#Branch?unconditionally
??lwz?????r0,0x10+arg_4(r1)
??mtlr????r0
(4)Multitask Gadget
有些一个Gadget可以执行多个功能,例如在栈上存储数据,下面就是一个例子,可以同时执行3个功能:
mtctr????r29??????????#Move?to?count?register
bctrl?????????????????#1st?task
mtlr?????r28??????????#Move?to?link?register
blrl??????????????????#2nd?task
lwz??????r0,0x1C(r1)
mtlr?????r0???????????#Move?to?link?register
lwz??????r28,8(r1)????#3rd?task
lwz??????r29,0xC(r1)
lwz??????r30,0x10(r1)
lwz??????r31,0x14(r1)
addi?????r1,r1,0x18???#Add?Immediate
blr
(5)Stack Keeper
功能就是保存一下当前的栈指针,其实就是对r1寄存器进行一下赋值操作:
mr?????r3,r1?????#Move?Register
blr??????????????#Branch?unconditionally
(6)Debug Gadget
Debug gadget是用来调用调试器的。
trap?????????#Trap?Word?Unconditionally
blr??????????#Branch?unconditionally
上述只是对一些重要gadgets的举例,其中Write-4 Primitive是重要的构造技巧,因为可以实现很多shellcode的写入与执行。
5.调试中的地址随机化问题:
Cisco IOS固件在IDA的解析中基址固定不变,但是某些型号的设备其IOS加载地址随机变化,但是可以通过指令计算IOS加载偏移:

根据show region得出的加载基址,同IDA加载基址进行偏移的计算,即可得出偏移量,然后对比IDA和实体设备gdb调试得到的汇编代码,解决ASLR问题。
6.漏洞利用中的代码随机化问题:
前面讲到,Cisco IOS具有DEP防护机制,这种机制可以通过ROP攻击绕过,但是当代码段也存在地址随机化时,无法直接在栈上布置指定地址的Gadgets,但是这个问题可以通过ROMMON解决。
ROMMON在内存中的加载地址一直不会变化,因此可以利用ROMMON中的代码构造ROP攻击。整体流程可以分为以下三步:
(1)首先利用栈溢出,劫持返回地址进入ROMMON部分,构造ROP链。
利用ROP攻击,通过write-4 primitive方法将shellcode写入内存。
将shellcode写入内存段后,再构造栈溢出,控制流劫持到该内存区域,执行shellcode。
7.利用路由器崩溃
Cisco IOS可以将崩溃信息写道内存卡里或者闪存里,也可以通过TFTP服务器传到远端。不同版本路由器可能提供的转储信息记录功能不相同,但是基本信息都是可以记录的,可以通过路由器crash文件追踪漏洞所在位置。崩溃转储功能要进行一下配置。
radio#conf?t
Enter?configuration?commands,one?per?line.?End?with?CNTL/Z.
radio?(config)?#exception?core-file?radio-core
radio?(config)?#exception?dump?192.168.2.5
radio?(config)?#^2
三、cook实例
2017年,Cisco官网披露并修复了SNMP协议中存在的漏洞,漏洞使得攻击者发送构造好的SNMP数据包,实现Dos攻击或RCE攻击。
以C1900系列路由器为例,该漏洞位于SNMP服务处理函数中:

其调用子函数sub_23BEC474进行处理,子函数主要功能为对v19地址进行赋值操纵,v19在子函数中为参数a1,主要功能为对a1地址进行赋值,写入长度由a3控制。

在子函数sub_23BEC474函数中,存在栈溢出漏洞。父函数的v19是长度为16的数组,存放在栈空间上,而子函数的赋值操作的次数可以人为控制,并且该函数的赋值操作没有额外的检查,因此会造成栈溢出。该函数赋值操作过长,会使栈上的v19所在地址的栈空间溢出,影响栈结构,造成溢出,因此可以覆盖父函数返回地址实现ROP攻击。
我们首先利用前面所讲方法解决调试中的ASLR防护,通过show region计算出动态与静态加载基址的偏移量,解决地址随机化问题。通过检查汇编代码是否一致,来判断是否正确计算代码段偏移,可知整体偏移量为0x5160。


验证漏洞,利用scapy构造并发送超长的SNMP数据包:
>>>?oid?=?"1.3.6.1.2.1.1.1.0'+".55'*100
>>>sr1(IP(dst='192.168.88.1'?)/UDP(sport=161,dport=161)/SNMP(community-"public"?,PDU-SNMPget(varbindlist=[?SNMPvarbind(oid=oid)])?))
Begin?emission?:
Finished?to?send?1?packets.
根据代码偏移量,在父函数的返回地址处设置断点,查看返回地址的覆盖情况,成功实现栈溢出攻击。

继续执行,路由器崩溃重启。

因为C1900系列存在ASLR防护,如果想实现RCE攻击,可以利用ROMMON构造ROP chain,注意一点,ROMMON中的汇编代码具有非连续特点,因此需要编写IDA python脚本进行批量刷写。
四、参考
https://www.powerofcommunity.net/poc2017/george.pdf
结束
招新小广告
ChaMd5?Venom?招收大佬入圈
新成立组IOT+工控+样本分析?长期招新
欢迎联系admin@chamd5.org

关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号随时掌握互联网精彩
- 1 习近平将发表二〇二六年新年贺词 7904141
- 2 2026年国补政策来了 7808738
- 3 东部战区:开火!开火!全部命中! 7712893
- 4 2026年这些民生政策将惠及百姓 7616985
- 5 小学食堂米线过期2.5小时被罚5万 7519709
- 6 解放军喊话驱离台军 原声曝光 7428214
- 7 为博流量直播踩烈士陵墓?绝不姑息 7327605
- 8 每月最高800元!多地发放养老消费券 7238391
- 9 数字人民币升级 1月1日起将计付利息 7141831
- 10 2026年1月1日起 一批新规将施行 7040675



![晚苏susu[XiuRen秀人网] 2024.03.29 No.8312](https://imgs.knowsafe.com:8087/img/aideep/2024/4/14/a68b50257bace74712d6eca8e655c7de.webp?w=250)




Chamd5安全团队
