Do first commands refactoring
parent
52b41ab4f8
commit
80aef690a0
|
@ -12,11 +12,24 @@ module Msf
|
|||
module Exploit::Remote::SMB::Server
|
||||
# This mixin provides a minimal SMB server
|
||||
module Share
|
||||
require 'msf/core/exploit/smb/server/share/command'
|
||||
require 'msf/core/exploit/smb/server/share/information_level'
|
||||
require 'msf/core/exploit/smb/server/share/sub_command'
|
||||
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::Command::Close
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::Command::Negotiate
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::Command::NtCreateAndx
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::Command::ReadAndx
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::Command::SessionSetupAndx
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::InformationLevel::Find
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::InformationLevel::Query
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::SubCommand::Trans2
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::SubCommand::Trans2::FindFirst2
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::SubCommand::Trans2::QueryFileInformation
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::SubCommand::Trans2::QueryPathInformation
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::InformationLevel::Find
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::InformationLevel::Query
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::SubCommand::Trans2
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::SubCommand::Trans2::FindFirst2
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::SubCommand::Trans2::QueryFileInformation
|
||||
include Msf::Exploit::Remote::SMB::Server::Share::SubCommand::Trans2::QueryPathInformation
|
||||
|
@ -133,283 +146,6 @@ module Msf
|
|||
smb_error(cmd, c, CONST::SMB_STATUS_SUCCESS)
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Responds to a client CLOSE request
|
||||
#
|
||||
def smb_cmd_close(c, buff)
|
||||
dprint("[SMB_CMD_CLOSE]")
|
||||
pkt = CONST::SMB_CLOSE_PKT.make_struct
|
||||
pkt.from_s(buff)
|
||||
|
||||
pkt = CONST::SMB_CLOSE_RES_PKT.make_struct
|
||||
smb_set_defaults(c, pkt)
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_CLOSE
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x88
|
||||
pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 0
|
||||
|
||||
c.put(pkt.to_s)
|
||||
end
|
||||
|
||||
#
|
||||
# Negotiates a SHARE session with the client
|
||||
#
|
||||
def smb_cmd_negotiate(c, buff)
|
||||
dprint("[SMB_CMD_NEGOTIATE]")
|
||||
pkt = CONST::SMB_NEG_PKT.make_struct
|
||||
pkt.from_s(buff)
|
||||
|
||||
dialects = pkt['Payload'].v['Payload'].gsub(/\x00/, '').split(/\x02/).grep(/^\w+/)
|
||||
|
||||
dialect = dialects.index("NT LM 0.12") || dialects.length-1
|
||||
|
||||
pkt = CONST::SMB_NEG_RES_NT_PKT.make_struct
|
||||
smb_set_defaults(c, pkt)
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NEGOTIATE
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x88
|
||||
pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 17
|
||||
pkt['Payload'].v['Dialect'] = dialect
|
||||
pkt['Payload'].v['SecurityMode'] = 2 # SHARE Security Mode
|
||||
pkt['Payload'].v['MaxMPX'] = 50
|
||||
pkt['Payload'].v['MaxVCS'] = 1
|
||||
pkt['Payload'].v['MaxBuff'] = 4356
|
||||
pkt['Payload'].v['MaxRaw'] = 65536
|
||||
pkt['Payload'].v['SystemTimeLow'] = lo
|
||||
pkt['Payload'].v['SystemTimeHigh'] = hi
|
||||
pkt['Payload'].v['ServerTimeZone'] = 0x0
|
||||
pkt['Payload'].v['SessionKey'] = 0
|
||||
pkt['Payload'].v['Capabilities'] = 0x0080f3fd
|
||||
pkt['Payload'].v['KeyLength'] = 8
|
||||
pkt['Payload'].v['Payload'] = Rex::Text.rand_text_hex(8)
|
||||
|
||||
c.put(pkt.to_s)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets up an SMB session in response to a SESSION_SETUP_ANDX request
|
||||
#
|
||||
def smb_cmd_session_setup(c, buff)
|
||||
dprint("[SMB_CMD_SESSION_SETUP]")
|
||||
pkt = CONST::SMB_SETUP_RES_PKT.make_struct
|
||||
smb_set_defaults(c, pkt)
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_SESSION_SETUP_ANDX
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x88
|
||||
pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 3
|
||||
pkt['Payload'].v['AndX'] = 0x75
|
||||
pkt['Payload'].v['Reserved1'] = 00
|
||||
pkt['Payload'].v['AndXOffset'] = 96
|
||||
pkt['Payload'].v['Action'] = 0x1 # Logged in as Guest
|
||||
pkt['Payload'].v['Payload'] =
|
||||
Rex::Text.to_unicode("Unix", 'utf-16be') + "\x00\x00" + # Native OS # Samba signature
|
||||
Rex::Text.to_unicode("Samba 3.4.7", 'utf-16be') + "\x00\x00" + # Native LAN Manager # Samba signature
|
||||
Rex::Text.to_unicode("WORKGROUP", 'utf-16be') + "\x00\x00\x00" + # Primary DOMAIN # Samba signature
|
||||
tree_connect_response = ""
|
||||
tree_connect_response << [7].pack("C") # Tree Connect Response : WordCount
|
||||
tree_connect_response << [0xff].pack("C") # Tree Connect Response : AndXCommand
|
||||
tree_connect_response << [0].pack("C") # Tree Connect Response : Reserved
|
||||
tree_connect_response << [0].pack("v") # Tree Connect Response : AndXOffset
|
||||
tree_connect_response << [0x1].pack("v") # Tree Connect Response : Optional Support
|
||||
tree_connect_response << [0xa9].pack("C") # Access Mask for just Read and Exec
|
||||
tree_connect_response << [0x00].pack("C")
|
||||
tree_connect_response << [0x12].pack("C")
|
||||
tree_connect_response << [0x00].pack("C")
|
||||
tree_connect_response << [0].pack("v") # Tree Connect Response : Word Parameter
|
||||
tree_connect_response << [0].pack("v") # Tree Connect Response : Word Parameter
|
||||
tree_connect_response << [13].pack("v") # Tree Connect Response : ByteCount
|
||||
tree_connect_response << "A:\x00" # Service
|
||||
tree_connect_response << "#{Rex::Text.to_unicode("NTFS")}\x00\x00" # Extra byte parameters
|
||||
# Fix the Netbios Session Service Message Length
|
||||
# to have into account the tree_connect_response,
|
||||
# need to do this because there isn't support for
|
||||
# AndX still
|
||||
my_pkt = pkt.to_s + tree_connect_response
|
||||
original_length = my_pkt[2, 2].unpack("n").first
|
||||
original_length = original_length + tree_connect_response.length
|
||||
my_pkt[2, 2] = [original_length].pack("n")
|
||||
c.put(my_pkt)
|
||||
end
|
||||
|
||||
#
|
||||
# Responds to a client NT_CREATE_ANDX request
|
||||
#
|
||||
def smb_cmd_create(c, buff)
|
||||
dprint("[SMB_CMD_CREATE]")
|
||||
smb = @state[c]
|
||||
pkt = CONST::SMB_CREATE_PKT.make_struct
|
||||
pkt.from_s(buff)
|
||||
|
||||
# Tries to do CREATE and X
|
||||
payload = pkt['Payload'].v['Payload'].gsub(/\x00/, '').gsub(/.*\\/, '\\').chomp.strip.split('\\').last
|
||||
file = file_name
|
||||
path = path_name
|
||||
|
||||
if payload.nil?
|
||||
payload = file
|
||||
end
|
||||
|
||||
if payload.length.to_s.eql?('1') or payload.eql?(path)
|
||||
fid = smb[:dir_id].to_i
|
||||
attribs = 0x10 # Ordinary Dir
|
||||
eof = 0
|
||||
isdir = 1
|
||||
else
|
||||
fid = smb[:file_id].to_i
|
||||
attribs = 0x80 # File Attributes
|
||||
eof = exe_contents.length
|
||||
isdir = 0
|
||||
end
|
||||
|
||||
pkt = CONST::SMB_CREATE_RES_PKT.make_struct
|
||||
smb_set_defaults(c, pkt)
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_CREATE_ANDX
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x88
|
||||
pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 42
|
||||
pkt['Payload'].v['AndX'] = 0xff # no further commands
|
||||
pkt['Payload'].v['OpLock'] = 0x3 # Grant Oplock on File
|
||||
pkt['Payload'].v['FileID'] = fid
|
||||
pkt['Payload'].v['Action'] = 0x1 # The file existed and was opened
|
||||
pkt['Payload'].v['CreateTimeLow'] = lo
|
||||
pkt['Payload'].v['CreateTimeHigh'] = hi
|
||||
pkt['Payload'].v['AccessTimeLow'] = lo
|
||||
pkt['Payload'].v['AccessTimeHigh'] = hi
|
||||
pkt['Payload'].v['WriteTimeLow'] = lo
|
||||
pkt['Payload'].v['WriteTimeHigh'] = hi
|
||||
pkt['Payload'].v['ChangeTimeLow'] = lo
|
||||
pkt['Payload'].v['ChangeTimeHigh'] = hi
|
||||
pkt['Payload'].v['Attributes'] = attribs
|
||||
pkt['Payload'].v['AllocLow'] = 0x100000
|
||||
pkt['Payload'].v['AllocHigh'] = 0
|
||||
pkt['Payload'].v['EOFLow'] = eof
|
||||
pkt['Payload'].v['EOFHigh'] = 0
|
||||
pkt['Payload'].v['FileType'] = 0
|
||||
pkt['Payload'].v['IPCState'] = 0x7
|
||||
pkt['Payload'].v['IsDirectory'] = isdir
|
||||
|
||||
# As above, if payload is a file or "\" send found response
|
||||
if (payload.downcase.eql?(file.downcase)) or payload.length.to_s.eql?('1') or payload.eql?(path)
|
||||
connect_response = ""
|
||||
# GUID
|
||||
connect_response << ([0].pack("C") * 16)
|
||||
# File ID
|
||||
connect_response << ([0].pack("C") * 6)
|
||||
# Access Rights
|
||||
connect_response << [0xff].pack("C")
|
||||
connect_response << [0x01].pack("C")
|
||||
connect_response << [0x1f].pack("C")
|
||||
connect_response << [0].pack("C")
|
||||
connect_response << ([0].pack("C") * 4) # Guest access
|
||||
connect_response << ([0].pack("C") * 2) # Byte Count
|
||||
|
||||
my_pkt = pkt.to_s + connect_response
|
||||
original_length = my_pkt[2, 2].unpack("n").first
|
||||
original_length = original_length + connect_response.length
|
||||
my_pkt[2, 2] = [original_length].pack("n")
|
||||
c.put(my_pkt)
|
||||
else
|
||||
# Otherwise send not found
|
||||
pkt = CONST::SMB_CREATE_RES_PKT.make_struct
|
||||
smb_set_defaults(c, pkt)
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_CREATE_ANDX
|
||||
pkt['Payload']['SMB'].v['ErrorClass'] = 0xC0000034 # OBJECT_NAME_NOT_FOUND
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x88
|
||||
pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
|
||||
c.put(pkt.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Responds to a client READ_ANDX request
|
||||
# This function sends chunks of the payload to the client
|
||||
# by reading the offset and length requested by the client
|
||||
# and sending the appropriate chunk of the payload
|
||||
#
|
||||
def smb_cmd_read(c, buff)
|
||||
dprint("[SMB_CMD_READ]")
|
||||
pkt = CONST::SMB_READ_PKT.make_struct
|
||||
pkt.from_s(buff)
|
||||
|
||||
offset = pkt['Payload'].v['Offset']
|
||||
length = pkt['Payload'].v['MaxCountLow']
|
||||
|
||||
pkt = CONST::SMB_READ_RES_PKT.make_struct
|
||||
smb_set_defaults(c, pkt)
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_READ_ANDX
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x88
|
||||
pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 12
|
||||
pkt['Payload'].v['AndX'] = 0xff # no more commands
|
||||
pkt['Payload'].v['Remaining'] = 0xffff
|
||||
pkt['Payload'].v['DataLenLow'] = length
|
||||
pkt['Payload'].v['DataOffset'] = 59
|
||||
pkt['Payload'].v['DataLenHigh'] = 0
|
||||
pkt['Payload'].v['Reserved3'] = 0
|
||||
pkt['Payload'].v['Reserved4'] = 0x0a
|
||||
pkt['Payload'].v['ByteCount'] = length
|
||||
pkt['Payload'].v['Payload'] = exe_contents[offset, length]
|
||||
c.put(pkt.to_s)
|
||||
end
|
||||
|
||||
#
|
||||
# Responds to client TRANSACTION2 requests and dispatches the request off to
|
||||
# other functions dependent on what the sub_command is. Commands supported
|
||||
# include:
|
||||
# QUERY_FILE_INFO (Basic, Standard and Internal)
|
||||
# QUERY_PATH_INFO (Basic and Standard)
|
||||
#
|
||||
def smb_cmd_trans(c, buff)
|
||||
dprint("[SMB_CMD_TRANS]")
|
||||
# Client socket is c
|
||||
pkt = CONST::SMB_TRANS2_PKT.make_struct
|
||||
pkt.from_s(buff)
|
||||
|
||||
sub_command = pkt['Payload'].v['SetupData'].unpack("v").first
|
||||
ar = Rex::Text.to_hex(buff, '').to_s
|
||||
mdc = ar[86..89].unpack('n*').reverse.pack('n*').to_i(16)
|
||||
|
||||
case sub_command
|
||||
when CONST::TRANS2_QUERY_FILE_INFO_BASIC
|
||||
dprint("\t[query_file_info_basic]")
|
||||
smb_cmd_trans_query_path_info_standard(c, buff)
|
||||
when CONST::TRANS2_QUERY_FILE_INFO_STANDARD
|
||||
dprint("\t[query_file_info_standard]")
|
||||
loi = ar[148..151].unpack('n*').reverse.pack('n*').to_i(16)
|
||||
case loi
|
||||
when CONST::SMB_QUERY_PATH_STANDARD_INFO
|
||||
dprint("\t\t[smb_cmd_trans_query_path_info_standard]")
|
||||
smb_cmd_trans_query_path_info_standard(c, buff)
|
||||
when CONST::SMB_QUERY_FILE_STANDARD_INFO_BASIC
|
||||
dprint("\t\t[smb_cmd_trans_query_file_info_basic]")
|
||||
smb_cmd_trans_query_file_info_basic(c, buff)
|
||||
when CONST::SMB_QUERY_FILE_NETWORK_OPEN_INFO
|
||||
dprint("\t\t[smb_cmd_trans_query_file_info_network]")
|
||||
smb_cmd_trans_query_file_info_network(c, buff)
|
||||
else
|
||||
dprint("\t\tUnknown LOI [smb_cmd_trans_query_path_info_standard] - #{loi.to_s}")
|
||||
smb_cmd_trans_query_file_info_standard(c, buff)
|
||||
end
|
||||
when CONST::TRANS2_QUERY_PATH_INFO
|
||||
smb_cmd_trans2_query_path_information(c, buff)
|
||||
when CONST::TRANS2_FIND_FIRST2
|
||||
smb_cmd_trans2_find_first2(c, buff)
|
||||
else
|
||||
dprint("\t[UNKNOWN SUBCOMMAND]")
|
||||
pkt = CONST::SMB_TRANS_RES_PKT.make_struct
|
||||
smb_set_defaults(c, pkt)
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TRANSACTION2
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x88
|
||||
pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
|
||||
pkt['Payload']['SMB'].v['ErrorClass'] = 0xc0000225 # NT_STATUS_NOT_FOUND
|
||||
c.put(pkt.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Exploit::Remote::SMB::Server
|
||||
module Share
|
||||
module Command
|
||||
require 'msf/core/exploit/smb/server/share/command/close'
|
||||
require 'msf/core/exploit/smb/server/share/command/negotiate'
|
||||
require 'msf/core/exploit/smb/server/share/command/nt_create_andx'
|
||||
require 'msf/core/exploit/smb/server/share/command/read_andx'
|
||||
require 'msf/core/exploit/smb/server/share/command/session_setup_andx'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Exploit::Remote::SMB::Server
|
||||
module Share
|
||||
module Command
|
||||
module Close
|
||||
#
|
||||
# Responds to a client CLOSE request
|
||||
#
|
||||
def smb_cmd_close(c, buff)
|
||||
dprint("[SMB_CMD_CLOSE]")
|
||||
pkt = CONST::SMB_CLOSE_PKT.make_struct
|
||||
pkt.from_s(buff)
|
||||
|
||||
pkt = CONST::SMB_CLOSE_RES_PKT.make_struct
|
||||
smb_set_defaults(c, pkt)
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_CLOSE
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x88
|
||||
pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 0
|
||||
|
||||
c.put(pkt.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,47 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Exploit::Remote::SMB::Server
|
||||
module Share
|
||||
module Command
|
||||
module Negotiate
|
||||
#
|
||||
# Negotiates a SHARE session with the client
|
||||
#
|
||||
def smb_cmd_negotiate(c, buff)
|
||||
dprint("[SMB_CMD_NEGOTIATE]")
|
||||
pkt = CONST::SMB_NEG_PKT.make_struct
|
||||
pkt.from_s(buff)
|
||||
|
||||
dialects = pkt['Payload'].v['Payload'].gsub(/\x00/, '').split(/\x02/).grep(/^\w+/)
|
||||
|
||||
dialect = dialects.index("NT LM 0.12") || dialects.length-1
|
||||
|
||||
pkt = CONST::SMB_NEG_RES_NT_PKT.make_struct
|
||||
smb_set_defaults(c, pkt)
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NEGOTIATE
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x88
|
||||
pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 17
|
||||
pkt['Payload'].v['Dialect'] = dialect
|
||||
pkt['Payload'].v['SecurityMode'] = 2 # SHARE Security Mode
|
||||
pkt['Payload'].v['MaxMPX'] = 50
|
||||
pkt['Payload'].v['MaxVCS'] = 1
|
||||
pkt['Payload'].v['MaxBuff'] = 4356
|
||||
pkt['Payload'].v['MaxRaw'] = 65536
|
||||
pkt['Payload'].v['SystemTimeLow'] = lo
|
||||
pkt['Payload'].v['SystemTimeHigh'] = hi
|
||||
pkt['Payload'].v['ServerTimeZone'] = 0x0
|
||||
pkt['Payload'].v['SessionKey'] = 0
|
||||
pkt['Payload'].v['Capabilities'] = 0x0080f3fd
|
||||
pkt['Payload'].v['KeyLength'] = 8
|
||||
pkt['Payload'].v['Payload'] = Rex::Text.rand_text_hex(8)
|
||||
|
||||
c.put(pkt.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,100 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Exploit::Remote::SMB::Server
|
||||
module Share
|
||||
module Command
|
||||
module NtCreateAndx
|
||||
#
|
||||
# Responds to a client NT_CREATE_ANDX request
|
||||
#
|
||||
def smb_cmd_create(c, buff)
|
||||
dprint("[SMB_CMD_CREATE]")
|
||||
smb = @state[c]
|
||||
pkt = CONST::SMB_CREATE_PKT.make_struct
|
||||
pkt.from_s(buff)
|
||||
|
||||
# Tries to do CREATE and X
|
||||
payload = pkt['Payload'].v['Payload'].gsub(/\x00/, '').gsub(/.*\\/, '\\').chomp.strip.split('\\').last
|
||||
file = file_name
|
||||
path = path_name
|
||||
|
||||
if payload.nil?
|
||||
payload = file
|
||||
end
|
||||
|
||||
if payload.length.to_s.eql?('1') or payload.eql?(path)
|
||||
fid = smb[:dir_id].to_i
|
||||
attribs = 0x10 # Ordinary Dir
|
||||
eof = 0
|
||||
isdir = 1
|
||||
else
|
||||
fid = smb[:file_id].to_i
|
||||
attribs = 0x80 # File Attributes
|
||||
eof = exe_contents.length
|
||||
isdir = 0
|
||||
end
|
||||
|
||||
pkt = CONST::SMB_CREATE_RES_PKT.make_struct
|
||||
smb_set_defaults(c, pkt)
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_CREATE_ANDX
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x88
|
||||
pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 42
|
||||
pkt['Payload'].v['AndX'] = 0xff # no further commands
|
||||
pkt['Payload'].v['OpLock'] = 0x3 # Grant Oplock on File
|
||||
pkt['Payload'].v['FileID'] = fid
|
||||
pkt['Payload'].v['Action'] = 0x1 # The file existed and was opened
|
||||
pkt['Payload'].v['CreateTimeLow'] = lo
|
||||
pkt['Payload'].v['CreateTimeHigh'] = hi
|
||||
pkt['Payload'].v['AccessTimeLow'] = lo
|
||||
pkt['Payload'].v['AccessTimeHigh'] = hi
|
||||
pkt['Payload'].v['WriteTimeLow'] = lo
|
||||
pkt['Payload'].v['WriteTimeHigh'] = hi
|
||||
pkt['Payload'].v['ChangeTimeLow'] = lo
|
||||
pkt['Payload'].v['ChangeTimeHigh'] = hi
|
||||
pkt['Payload'].v['Attributes'] = attribs
|
||||
pkt['Payload'].v['AllocLow'] = 0x100000
|
||||
pkt['Payload'].v['AllocHigh'] = 0
|
||||
pkt['Payload'].v['EOFLow'] = eof
|
||||
pkt['Payload'].v['EOFHigh'] = 0
|
||||
pkt['Payload'].v['FileType'] = 0
|
||||
pkt['Payload'].v['IPCState'] = 0x7
|
||||
pkt['Payload'].v['IsDirectory'] = isdir
|
||||
|
||||
# As above, if payload is a file or "\" send found response
|
||||
if (payload.downcase.eql?(file.downcase)) or payload.length.to_s.eql?('1') or payload.eql?(path)
|
||||
connect_response = ""
|
||||
# GUID
|
||||
connect_response << ([0].pack("C") * 16)
|
||||
# File ID
|
||||
connect_response << ([0].pack("C") * 6)
|
||||
# Access Rights
|
||||
connect_response << [0xff].pack("C")
|
||||
connect_response << [0x01].pack("C")
|
||||
connect_response << [0x1f].pack("C")
|
||||
connect_response << [0].pack("C")
|
||||
connect_response << ([0].pack("C") * 4) # Guest access
|
||||
connect_response << ([0].pack("C") * 2) # Byte Count
|
||||
|
||||
my_pkt = pkt.to_s + connect_response
|
||||
original_length = my_pkt[2, 2].unpack("n").first
|
||||
original_length = original_length + connect_response.length
|
||||
my_pkt[2, 2] = [original_length].pack("n")
|
||||
c.put(my_pkt)
|
||||
else
|
||||
# Otherwise send not found
|
||||
pkt = CONST::SMB_CREATE_RES_PKT.make_struct
|
||||
smb_set_defaults(c, pkt)
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_CREATE_ANDX
|
||||
pkt['Payload']['SMB'].v['ErrorClass'] = 0xC0000034 # OBJECT_NAME_NOT_FOUND
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x88
|
||||
pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
|
||||
c.put(pkt.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,44 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Exploit::Remote::SMB::Server
|
||||
module Share
|
||||
module Command
|
||||
module ReadAndx
|
||||
#
|
||||
# Responds to a client READ_ANDX request
|
||||
# This function sends chunks of the payload to the client
|
||||
# by reading the offset and length requested by the client
|
||||
# and sending the appropriate chunk of the payload
|
||||
#
|
||||
def smb_cmd_read(c, buff)
|
||||
dprint("[SMB_CMD_READ]")
|
||||
pkt = CONST::SMB_READ_PKT.make_struct
|
||||
pkt.from_s(buff)
|
||||
|
||||
offset = pkt['Payload'].v['Offset']
|
||||
length = pkt['Payload'].v['MaxCountLow']
|
||||
|
||||
pkt = CONST::SMB_READ_RES_PKT.make_struct
|
||||
smb_set_defaults(c, pkt)
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_READ_ANDX
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x88
|
||||
pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 12
|
||||
pkt['Payload'].v['AndX'] = 0xff # no more commands
|
||||
pkt['Payload'].v['Remaining'] = 0xffff
|
||||
pkt['Payload'].v['DataLenLow'] = length
|
||||
pkt['Payload'].v['DataOffset'] = 59
|
||||
pkt['Payload'].v['DataLenHigh'] = 0
|
||||
pkt['Payload'].v['Reserved3'] = 0
|
||||
pkt['Payload'].v['Reserved4'] = 0x0a
|
||||
pkt['Payload'].v['ByteCount'] = length
|
||||
pkt['Payload'].v['Payload'] = exe_contents[offset, length]
|
||||
c.put(pkt.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,57 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
module Exploit::Remote::SMB::Server
|
||||
module Share
|
||||
module Command
|
||||
module SessionSetupAndx
|
||||
#
|
||||
# Sets up an SMB session in response to a SESSION_SETUP_ANDX request
|
||||
#
|
||||
def smb_cmd_session_setup(c, buff)
|
||||
dprint("[SMB_CMD_SESSION_SETUP]")
|
||||
pkt = CONST::SMB_SETUP_RES_PKT.make_struct
|
||||
smb_set_defaults(c, pkt)
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_SESSION_SETUP_ANDX
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x88
|
||||
pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 3
|
||||
pkt['Payload'].v['AndX'] = 0x75
|
||||
pkt['Payload'].v['Reserved1'] = 00
|
||||
pkt['Payload'].v['AndXOffset'] = 96
|
||||
pkt['Payload'].v['Action'] = 0x1 # Logged in as Guest
|
||||
pkt['Payload'].v['Payload'] =
|
||||
Rex::Text.to_unicode("Unix", 'utf-16be') + "\x00\x00" + # Native OS # Samba signature
|
||||
Rex::Text.to_unicode("Samba 3.4.7", 'utf-16be') + "\x00\x00" + # Native LAN Manager # Samba signature
|
||||
Rex::Text.to_unicode("WORKGROUP", 'utf-16be') + "\x00\x00\x00" + # Primary DOMAIN # Samba signature
|
||||
tree_connect_response = ""
|
||||
tree_connect_response << [7].pack("C") # Tree Connect Response : WordCount
|
||||
tree_connect_response << [0xff].pack("C") # Tree Connect Response : AndXCommand
|
||||
tree_connect_response << [0].pack("C") # Tree Connect Response : Reserved
|
||||
tree_connect_response << [0].pack("v") # Tree Connect Response : AndXOffset
|
||||
tree_connect_response << [0x1].pack("v") # Tree Connect Response : Optional Support
|
||||
tree_connect_response << [0xa9].pack("C") # Access Mask for just Read and Exec
|
||||
tree_connect_response << [0x00].pack("C")
|
||||
tree_connect_response << [0x12].pack("C")
|
||||
tree_connect_response << [0x00].pack("C")
|
||||
tree_connect_response << [0].pack("v") # Tree Connect Response : Word Parameter
|
||||
tree_connect_response << [0].pack("v") # Tree Connect Response : Word Parameter
|
||||
tree_connect_response << [13].pack("v") # Tree Connect Response : ByteCount
|
||||
tree_connect_response << "A:\x00" # Service
|
||||
tree_connect_response << "#{Rex::Text.to_unicode("NTFS")}\x00\x00" # Extra byte parameters
|
||||
# Fix the Netbios Session Service Message Length
|
||||
# to have into account the tree_connect_response,
|
||||
# need to do this because there isn't support for
|
||||
# AndX still
|
||||
my_pkt = pkt.to_s + tree_connect_response
|
||||
original_length = my_pkt[2, 2].unpack("n").first
|
||||
original_length = original_length + tree_connect_response.length
|
||||
my_pkt[2, 2] = [original_length].pack("n")
|
||||
c.put(my_pkt)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -8,6 +8,61 @@ module Msf
|
|||
require 'msf/core/exploit/smb/server/share/sub_command/trans2/find_first2'
|
||||
require 'msf/core/exploit/smb/server/share/sub_command/trans2/query_file_information'
|
||||
require 'msf/core/exploit/smb/server/share/sub_command/trans2/query_path_information'
|
||||
|
||||
#
|
||||
# Responds to client TRANSACTION2 requests and dispatches the request off to
|
||||
# other functions dependent on what the sub_command is. Commands supported
|
||||
# include:
|
||||
# QUERY_FILE_INFO (Basic, Standard and Internal)
|
||||
# QUERY_PATH_INFO (Basic and Standard)
|
||||
#
|
||||
def smb_cmd_trans(c, buff)
|
||||
dprint("[SMB_CMD_TRANS]")
|
||||
# Client socket is c
|
||||
pkt = CONST::SMB_TRANS2_PKT.make_struct
|
||||
pkt.from_s(buff)
|
||||
|
||||
sub_command = pkt['Payload'].v['SetupData'].unpack("v").first
|
||||
ar = Rex::Text.to_hex(buff, '').to_s
|
||||
mdc = ar[86..89].unpack('n*').reverse.pack('n*').to_i(16)
|
||||
|
||||
case sub_command
|
||||
when CONST::TRANS2_QUERY_FILE_INFO_BASIC
|
||||
dprint("\t[query_file_info_basic]")
|
||||
smb_cmd_trans_query_path_info_standard(c, buff)
|
||||
when CONST::TRANS2_QUERY_FILE_INFO_STANDARD
|
||||
dprint("\t[query_file_info_standard]")
|
||||
loi = ar[148..151].unpack('n*').reverse.pack('n*').to_i(16)
|
||||
case loi
|
||||
when CONST::SMB_QUERY_PATH_STANDARD_INFO
|
||||
dprint("\t\t[smb_cmd_trans_query_path_info_standard]")
|
||||
smb_cmd_trans_query_path_info_standard(c, buff)
|
||||
when CONST::SMB_QUERY_FILE_STANDARD_INFO_BASIC
|
||||
dprint("\t\t[smb_cmd_trans_query_file_info_basic]")
|
||||
smb_cmd_trans_query_file_info_basic(c, buff)
|
||||
when CONST::SMB_QUERY_FILE_NETWORK_OPEN_INFO
|
||||
dprint("\t\t[smb_cmd_trans_query_file_info_network]")
|
||||
smb_cmd_trans_query_file_info_network(c, buff)
|
||||
else
|
||||
dprint("\t\tUnknown LOI [smb_cmd_trans_query_path_info_standard] - #{loi.to_s}")
|
||||
smb_cmd_trans_query_file_info_standard(c, buff)
|
||||
end
|
||||
when CONST::TRANS2_QUERY_PATH_INFO
|
||||
smb_cmd_trans2_query_path_information(c, buff)
|
||||
when CONST::TRANS2_FIND_FIRST2
|
||||
smb_cmd_trans2_find_first2(c, buff)
|
||||
else
|
||||
dprint("\t[UNKNOWN SUBCOMMAND]")
|
||||
pkt = CONST::SMB_TRANS_RES_PKT.make_struct
|
||||
smb_set_defaults(c, pkt)
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TRANSACTION2
|
||||
pkt['Payload']['SMB'].v['Flags1'] = 0x88
|
||||
pkt['Payload']['SMB'].v['Flags2'] = FLAGS2
|
||||
pkt['Payload']['SMB'].v['ErrorClass'] = 0xc0000225 # NT_STATUS_NOT_FOUND
|
||||
c.put(pkt.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue