655 lines
16 KiB
Ruby
655 lines
16 KiB
Ruby
require 'rex/proto/smb'
|
||
require 'rex/proto/dcerpc'
|
||
require 'rex/encoder/ndr'
|
||
|
||
module Msf
|
||
|
||
###
|
||
#
|
||
# This mixin provides utility methods for interacting with a SMB/CIFS service on
|
||
# a remote machine. These methods may generally be useful in the context of
|
||
# exploitation. This mixin extends the Tcp exploit mixin. Only one SMB
|
||
# service can be accessed at a time using this class.
|
||
#
|
||
###
|
||
|
||
module Exploit::Remote::SMB
|
||
|
||
include Exploit::Remote::Tcp
|
||
SIMPLE = Rex::Proto::SMB::SimpleClient
|
||
XCEPT = Rex::Proto::SMB::Exceptions
|
||
CONST = Rex::Proto::SMB::Constants
|
||
|
||
# Alias over the Rex DCERPC protocol modules
|
||
DCERPCPacket = Rex::Proto::DCERPC::Packet
|
||
DCERPCClient = Rex::Proto::DCERPC::Client
|
||
DCERPCResponse = Rex::Proto::DCERPC::Response
|
||
DCERPCUUID = Rex::Proto::DCERPC::UUID
|
||
NDR = Rex::Encoder::NDR
|
||
|
||
def initialize(info = {})
|
||
super
|
||
|
||
register_evasion_options(
|
||
[
|
||
OptBool.new('SMB::pipe_evasion', [ true, 'Enable segmented read/writes for SMB Pipes', 'False']),
|
||
OptInt.new('SMB::pipe_write_min_size', [ true, 'Minimum buffer size for pipe writes', 1]),
|
||
OptInt.new('SMB::pipe_write_max_size', [ true, 'Maximum buffer size for pipe writes', 1024]),
|
||
OptInt.new('SMB::pipe_read_min_size', [ true, 'Minimum buffer size for pipe reads', 1]),
|
||
OptInt.new('SMB::pipe_read_max_size', [ true, 'Maximum buffer size for pipe reads', 1024]),
|
||
OptInt.new('SMB::pad_data_level', [ true, 'Place extra padding between headers and data (level 0-3)', 0]),
|
||
OptInt.new('SMB::pad_file_level', [ true, 'Obscure path names used in open/create (level 0-3)', 0]),
|
||
OptInt.new('SMB::obscure_trans_pipe_level', [ true, 'Obscure PIPE string in TransNamedPipe (level 0-3)', 0]),
|
||
|
||
], Msf::Exploit::Remote::SMB)
|
||
|
||
register_advanced_options(
|
||
[
|
||
OptBool.new('SMBDirect', [ true, 'The target port is a raw SMB service (not NetBIOS)', 'True' ]),
|
||
OptString.new('SMBUser', [ false, 'The username to authenticate as', '']),
|
||
OptString.new('SMBPass', [ false, 'The password for the specified username', '']),
|
||
OptString.new('SMBDomain', [ false, 'The Windows domain to use for authentication', 'WORKGROUP']),
|
||
OptString.new('SMBName', [ true, 'The NetBIOS hostname (required for port 139 connections)', '*SMBSERVER'])
|
||
], Msf::Exploit::Remote::SMB)
|
||
|
||
register_options(
|
||
[
|
||
Opt::RHOST,
|
||
OptInt.new('RPORT', [ true, 'Set the SMB service port', 445])
|
||
], Msf::Exploit::Remote::SMB)
|
||
end
|
||
|
||
def connect()
|
||
|
||
disconnect()
|
||
|
||
super
|
||
|
||
self.simple = SIMPLE.new(self.sock, self.smb_direct)
|
||
|
||
# setup pipe evasion foo
|
||
if datastore['SMB::pipe_evasion']
|
||
# XXX - insert code to change the instance of the read/write functions to do segmentation
|
||
end
|
||
|
||
if (datastore['SMB::pad_data_level'])
|
||
self.simple.client.evasion_opts['pad_data'] = datastore['SMB::pad_data_level']
|
||
end
|
||
|
||
if (datastore['SMB::pad_file_level'])
|
||
self.simple.client.evasion_opts['pad_file'] = datastore['SMB::pad_file_level']
|
||
end
|
||
|
||
if (datastore['SMB::obscure_trans_pipe_level'])
|
||
self.simple.client.evasion_opts['obscure_trans_pipe'] = datastore['SMB::obscure_trans_pipe_level']
|
||
end
|
||
end
|
||
|
||
# Convert a standard ASCII string to 16-bit Unicode
|
||
def unicode(str)
|
||
Rex::Text.to_unicode(str)
|
||
end
|
||
|
||
# This method establishes a SMB session over the default socket
|
||
def smb_login
|
||
simple.login(
|
||
datastore['SMBName'],
|
||
datastore['SMBUser'],
|
||
datastore['SMBPass'],
|
||
datastore['SMBDomain']
|
||
)
|
||
|
||
simple.connect("\\\\#{datastore['RHOST']}\\IPC$")
|
||
end
|
||
|
||
# This method returns the native operating system of the peer
|
||
def smb_peer_os
|
||
self.simple.client.peer_native_os
|
||
end
|
||
|
||
# This method returns the native lanman version of the peer
|
||
def smb_peer_lm
|
||
self.simple.client.peer_native_lm
|
||
end
|
||
|
||
# This method opens a handle to an IPC pipe
|
||
def smb_create(pipe)
|
||
self.simple.create_pipe(pipe)
|
||
end
|
||
|
||
def smb_hostname
|
||
datastore['SMBName'] || '*SMBSERVER'
|
||
end
|
||
|
||
def smb_direct
|
||
datastore['SMBDirect']
|
||
end
|
||
|
||
|
||
#
|
||
# Fingerprinting methods
|
||
#
|
||
|
||
|
||
# This method the EnumPrinters() function of the spooler service
|
||
def smb_enumprinters(flags, name, level, blen)
|
||
stub =
|
||
NDR.long(flags) +
|
||
(name ? NDR.uwstring(name) : NDR.long(0)) +
|
||
NDR.long(level) +
|
||
NDR.long(rand(0xffffffff)+1)+
|
||
NDR.long(blen) +
|
||
"\x00" * blen +
|
||
NDR.long(blen)
|
||
|
||
handle = dcerpc_handle(
|
||
'12345678-1234-abcd-ef00-0123456789ab', '1.0',
|
||
'ncacn_np', ["\\SPOOLSS"]
|
||
)
|
||
|
||
begin
|
||
dcerpc_bind(handle)
|
||
dcerpc.call(0x00, stub)
|
||
return dcerpc.last_response.stub_data
|
||
rescue ::Interrupt
|
||
raise $!
|
||
rescue ::Exception => e
|
||
return nil
|
||
end
|
||
end
|
||
|
||
# This method dumps the print provider strings from the spooler
|
||
def smb_enumprintproviders
|
||
resp = smb_enumprinters(8, nil, 1, 0)
|
||
return nil if not resp
|
||
rptr, tmp, blen = resp.unpack("V*")
|
||
|
||
resp = smb_enumprinters(8, nil, 1, blen)
|
||
return nil if not resp
|
||
|
||
bcnt,pcnt,stat = resp[-12, 12].unpack("VVV")
|
||
return nil if stat != 0
|
||
return nil if pcnt == 0
|
||
return nil if bcnt > blen
|
||
return nil if pcnt < 3
|
||
|
||
return resp
|
||
|
||
#
|
||
# The correct way, which leads to invalid offsets :-(
|
||
#
|
||
providers = []
|
||
|
||
0.upto(pcnt-1) do |i|
|
||
flags,desc_o,name_o,comm_o = resp[8 + (i*16), 16].unpack("VVVV")
|
||
|
||
#desc = read_unicode(resp,8+desc_o).gsub("\x00", '')
|
||
#name = read_unicode(resp,8+name_o).gsub("\x00", '')
|
||
#comm = read_unicode(resp,8+comm_o).gsub("\x00", '')
|
||
#providers << [flags,desc,name,comm]
|
||
end
|
||
|
||
providers
|
||
end
|
||
|
||
# This method performs an extensive set of fingerprinting operations
|
||
def smb_fingerprint
|
||
fprint = {}
|
||
|
||
# Connect to the server if needed
|
||
if(not self.simple)
|
||
connect()
|
||
smb_login()
|
||
end
|
||
|
||
os = 'Unknown'
|
||
sp = ''
|
||
|
||
case smb_peer_os()
|
||
when 'Windows NT 4.0'
|
||
os = 'Windows NT 4.0'
|
||
|
||
when 'Windows 5.0'
|
||
os = 'Windows 2000'
|
||
|
||
when 'Windows 5.1'
|
||
os = 'Windows XP'
|
||
|
||
when /Windows XP (\d+) Service Pack (\d+)/
|
||
os = 'Windows XP'
|
||
sp = 'Service Pack ' + $2
|
||
|
||
when /Windows Server 2003 (\d+)$/
|
||
os = 'Windows 2003'
|
||
sp = 'No Service Pack'
|
||
|
||
when /Windows Server 2003 (\d+) Service Pack (\d+)/
|
||
os = 'Windows 2003'
|
||
sp = 'Service Pack ' + $2
|
||
|
||
when /Windows Server 2003 R2 (\d+) Service Pack (\d+)/
|
||
os = 'Windows 2003 R2'
|
||
sp = 'Service Pack ' + $2
|
||
|
||
when /Windows Vista \(TM\) (\w+|\w+ \w+) (\d+) Service Pack (\d+)/
|
||
os = 'Windows Vista ' + $1
|
||
sp = 'Service Pack ' + $3
|
||
|
||
when /Windows Vista \(TM\) (\w+|\w+ \w+) (\d+)/
|
||
os = 'Windows Vista ' + $1
|
||
sp = '(Build ' + $2 + ')'
|
||
|
||
when /Windows Server \(R\) 2008 (\w+|\w+ \w+) (\d+) Service Pack (\d+)/
|
||
os = 'Windows 2008 ' + $1
|
||
sp = 'Service Pack ' + $3
|
||
|
||
when /Windows Server \(R\) 2008 (\w+|\w+ \w+) (\d+)/
|
||
os = 'Windows 2008 ' + $1
|
||
sp = '(Build ' + $2 + ')'
|
||
|
||
when 'Unix'
|
||
os = 'Unix'
|
||
sv = smb_peer_lm()
|
||
case sv
|
||
when /Samba\s+(.*)/i
|
||
sp = 'Samba ' + $1
|
||
end
|
||
end
|
||
|
||
|
||
if (os == 'Windows XP' and sp.length == 0)
|
||
# SRVSVC was blocked in SP2
|
||
begin
|
||
smb_create("\\SRVSVC")
|
||
sp = 'Service Pack 0 / 1'
|
||
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e
|
||
if (e.error_code == 0xc0000022)
|
||
sp = 'Service Pack 2+'
|
||
end
|
||
end
|
||
end
|
||
|
||
if (os == 'Windows 2000' and sp.length == 0)
|
||
# LLSRPC was blocked in a post-SP4 update
|
||
begin
|
||
smb_create("\\LLSRPC")
|
||
sp = 'Service Pack 0 - 4'
|
||
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e
|
||
if (e.error_code == 0xc0000022)
|
||
sp = 'Service Pack 4 with MS05-010+'
|
||
end
|
||
end
|
||
end
|
||
|
||
#
|
||
# Perform granular XP SP checks if LSARPC is exposed
|
||
#
|
||
if (os == 'Windows XP')
|
||
|
||
#
|
||
# Service Pack 2 added a range(0,64000) to opnum 0x22 in SRVSVC
|
||
# Credit to spoonm for first use of unbounded [out] buffers
|
||
#
|
||
handle = dcerpc_handle(
|
||
'4b324fc8-1670-01d3-1278-5a47bf6ee188', '3.0',
|
||
'ncacn_np', ["\\BROWSER"]
|
||
)
|
||
|
||
begin
|
||
dcerpc_bind(handle)
|
||
|
||
stub =
|
||
NDR.uwstring(Rex::Text.rand_text_alpha(rand(10)+1)) +
|
||
NDR.wstring(Rex::Text.rand_text_alpha(rand(10)+1)) +
|
||
NDR.long(64001) +
|
||
NDR.long(0) +
|
||
NDR.long(0)
|
||
|
||
dcerpc.call(0x22, stub)
|
||
sp = "Service Pack 0 / 1"
|
||
|
||
rescue ::Interrupt
|
||
raise $!
|
||
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode
|
||
rescue ::Rex::Proto::SMB::Exceptions::ReadPacket
|
||
rescue ::Rex::Proto::DCERPC::Exceptions::Fault
|
||
sp = "Service Pack 2+"
|
||
rescue ::Exception
|
||
end
|
||
|
||
|
||
#
|
||
# Service Pack 3 fixed information leaks via [unique][out] pointers
|
||
# Call SRVSVC::NetRemoteTOD() to return [out] [ref] [unique]
|
||
# Credit:
|
||
# Pointer leak is well known, but Immunity also covered in a paper
|
||
# Silent fix of pointer leak in SP3 and detection method by Rhys Kidd
|
||
#
|
||
handle = dcerpc_handle(
|
||
'4b324fc8-1670-01d3-1278-5a47bf6ee188', '3.0',
|
||
'ncacn_np', ["\\BROWSER"]
|
||
)
|
||
|
||
begin
|
||
dcerpc_bind(handle)
|
||
|
||
stub = NDR.uwstring(Rex::Text.rand_text_alpha(rand(8)+1))
|
||
resp = dcerpc.call(0x1c, stub)
|
||
|
||
if(resp and resp[0,4] == "\x00\x00\x02\x00")
|
||
sp = "Service Pack 3"
|
||
else
|
||
if(resp and sp =~ /Service Pack 2\+/)
|
||
sp = "Service Pack 2"
|
||
end
|
||
end
|
||
|
||
rescue ::Interrupt
|
||
raise $!
|
||
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode
|
||
rescue ::Rex::Proto::SMB::Exceptions::ReadPacket
|
||
rescue ::Exception
|
||
end
|
||
end
|
||
|
||
|
||
#
|
||
# Remote language detection via Print Providers
|
||
# Credit: http://immunityinc.com/downloads/Remote_Language_Detection_in_Immunity_CANVAS.odt
|
||
#
|
||
|
||
lang = 'Unknown'
|
||
|
||
sigs =
|
||
{
|
||
'English' =>
|
||
[
|
||
Rex::Text.to_unicode('Windows NT Remote Printers'),
|
||
Rex::Text.to_unicode('LanMan Print Services')
|
||
],
|
||
'Spanish' =>
|
||
[
|
||
Rex::Text.to_unicode('Impresoras remotas Windows NT'),
|
||
Rex::Text.to_unicode('Impresoras remotas de Windows NT')
|
||
],
|
||
'Italian' =>
|
||
[
|
||
Rex::Text.to_unicode('Stampanti remote di Windows NT'),
|
||
Rex::Text.to_unicode('Servizi di stampa LanMan')
|
||
],
|
||
'French' =>
|
||
[
|
||
Rex::Text.to_unicode('Imprimantes distantes NT'),
|
||
Rex::Text.to_unicode('Imprimantes distantes pour Windows NT'),
|
||
Rex::Text.to_unicode("Services d'impression LanMan")
|
||
],
|
||
'German' =>
|
||
[
|
||
Rex::Text.to_unicode('Remotedrucker')
|
||
],
|
||
'Portuguese - Brazilian' =>
|
||
[
|
||
Rex::Text.to_unicode('Impr. remotas Windows NT'),
|
||
Rex::Text.to_unicode('Impressoras remotas do Windows NT')
|
||
],
|
||
'Portuguese' =>
|
||
[
|
||
Rex::Text.to_unicode('Imp. remotas do Windows NT')
|
||
],
|
||
'Hungarian' =>
|
||
[
|
||
Rex::Text.to_unicode('T<>voli nyomtat<61>k')
|
||
],
|
||
'Finnish' =>
|
||
[
|
||
Rex::Text.to_unicode('Et<45>tulostimet')
|
||
],
|
||
'Dutch' =>
|
||
[
|
||
Rex::Text.to_unicode('Externe printers voor NT')
|
||
],
|
||
'Danish' =>
|
||
[
|
||
Rex::Text.to_unicode('Fjernprintere')
|
||
],
|
||
'Swedish' =>
|
||
[
|
||
Rex::Text.to_unicode('Fj<46>rrskrivare')
|
||
],
|
||
'Polish' =>
|
||
[
|
||
Rex::Text.to_unicode('Zdalne drukarki')
|
||
],
|
||
'Czech' =>
|
||
[
|
||
Rex::Text.to_unicode('Vzd<7A>len<65> tisk<73>rny')
|
||
],
|
||
'Turkish' =>
|
||
[
|
||
"\x59\x00\x61\x00\x7a\x00\x31\x01\x63\x00\x31\x01\x6c\x00\x61\x00\x72\x00"
|
||
],
|
||
'Japanese' =>
|
||
[
|
||
"\xea\x30\xe2\x30\xfc\x30\xc8\x30\x20\x00\xd7\x30\xea\x30\xf3\x30\xbf\x30"
|
||
],
|
||
'Chinese - Traditional' =>
|
||
[
|
||
"\xdc\x8f\x0b\x7a\x53\x62\x70\x53\x3a\x67"
|
||
],
|
||
'Chinese - Traditional / Taiwan' =>
|
||
[
|
||
"\x60\x90\xef\x7a\x70\x53\x68\x88\x5f\x6a",
|
||
],
|
||
'Korean' =>
|
||
[
|
||
"\xd0\xc6\xa9\xac\x20\x00\x04\xd5\xb0\xb9\x30\xd1",
|
||
],
|
||
'Russian' =>
|
||
[
|
||
"\x1f\x04\x40\x04\x38\x04\x3d\x04\x42\x04\x35\x04\x40\x04\x4b\x04\x20\x00\x43\x04\x34\x04\x30\x04\x3b\x04\x35\x04\x3d\x04\x3d\x04\x3e\x04\x33\x04\x3e\x04\x20\x00\x34\x04\x3e\x04\x41\x04\x42\x04\x43\x04\x3f\x04\x30\x04",
|
||
],
|
||
|
||
}
|
||
|
||
begin
|
||
prov = smb_enumprintproviders()
|
||
if(prov)
|
||
sigs.each_key do |k|
|
||
sigs[k].each do |s|
|
||
if(prov.index(s))
|
||
lang = k
|
||
break
|
||
end
|
||
break if lang != 'Unknown'
|
||
end
|
||
break if lang != 'Unknown'
|
||
end
|
||
|
||
if(lang == 'Unknown')
|
||
|
||
@fpcache ||= {}
|
||
mhash = ::Digest::MD5.hexdigest(prov[4,prov.length-4])
|
||
|
||
if(not @fpcache[mhash])
|
||
|
||
buff = "\n"
|
||
buff << "*** NEW FINGERPRINT: PLEASE SEND TO [ msfdev[at]metasploit.com ]\n"
|
||
buff << " VERS: $Revision$\n"
|
||
buff << " HOST: #{rhost}\n"
|
||
buff << " OS: #{os}\n"
|
||
buff << " SP: #{sp}\n"
|
||
|
||
prov.unpack("H*")[0].scan(/.{64}|.*/).each do |line|
|
||
next if line.length == 0
|
||
buff << " FP: #{line}\n"
|
||
end
|
||
|
||
prov.split(/\x00\x00+/).each do |line|
|
||
line.gsub!("\x00",'')
|
||
line.strip!
|
||
next if line.length < 6
|
||
|
||
buff << " TXT: #{line}\n"
|
||
end
|
||
|
||
buff << "*** END FINGERPRINT\n"
|
||
|
||
print_line(buff)
|
||
|
||
@fpcache[mhash] = true
|
||
end
|
||
|
||
end
|
||
end
|
||
rescue ::Interrupt
|
||
raise $!
|
||
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode
|
||
end
|
||
|
||
fprint['os'] = os
|
||
fprint['sp'] = sp
|
||
fprint['lang'] = lang
|
||
|
||
fprint
|
||
end
|
||
|
||
#
|
||
# Accessors
|
||
#
|
||
|
||
attr_accessor :simple
|
||
|
||
end
|
||
|
||
###
|
||
#
|
||
# This mixin provides a minimal SMB server
|
||
#
|
||
###
|
||
|
||
module Exploit::Remote::SMBServer
|
||
include Exploit::Remote::TcpServer
|
||
CONST = ::Rex::Proto::SMB::Constants
|
||
CRYPT = ::Rex::Proto::SMB::Crypt
|
||
UTILS = ::Rex::Proto::SMB::Utils
|
||
XCEPT = ::Rex::Proto::SMB::Exceptions
|
||
EVADE = ::Rex::Proto::SMB::Evasions
|
||
|
||
def initialize(info = {})
|
||
super
|
||
|
||
register_options(
|
||
[
|
||
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 139 ])
|
||
], self.class)
|
||
end
|
||
|
||
def setup
|
||
super
|
||
@state = {}
|
||
end
|
||
|
||
def on_client_connect(client)
|
||
# print_status("New SMB connection from #{client.peerhost}:#{client.peerport}")
|
||
smb_conn(client)
|
||
end
|
||
|
||
def on_client_data(client)
|
||
# print_status("New data from #{client.peerhost}:#{client.peerport}")
|
||
smb_recv(client)
|
||
true
|
||
end
|
||
|
||
def on_client_close(client)
|
||
smb_stop(client)
|
||
end
|
||
|
||
def smb_conn(c)
|
||
@state[c] = {:name => "#{c.peerhost}:#{c.peerport}", :ip => c.peerhost, :port => c.peerport}
|
||
end
|
||
|
||
def smb_stop(c)
|
||
@state.delete(c)
|
||
end
|
||
|
||
def smb_recv(c)
|
||
smb = @state[c]
|
||
smb[:data] ||= ''
|
||
smb[:data] << c.get_once
|
||
|
||
while(smb[:data].length > 0)
|
||
|
||
return if smb[:data].length < 4
|
||
|
||
plen = smb[:data][2,2].unpack('n')[0]
|
||
|
||
return if smb[:data].length < plen+4
|
||
|
||
buff = smb[:data].slice!(0, plen+4)
|
||
|
||
pkt_nbs = CONST::NBRAW_PKT.make_struct
|
||
pkt_nbs.from_s(buff)
|
||
|
||
# print_status("NetBIOS request from #{smb[:name]} #{pkt_nbs.v['Type']} #{pkt_nbs.v['Flags']} #{buff.inspect}")
|
||
|
||
# Check for a NetBIOS name request
|
||
if (pkt_nbs.v['Type'] == 0x81)
|
||
# Accept any name they happen to send
|
||
|
||
host_dst = UTILS.nbname_decode(pkt_nbs.v['Payload'][1,32]).gsub(/[\x00\x20]+$/, '')
|
||
host_src = UTILS.nbname_decode(pkt_nbs.v['Payload'][35,32]).gsub(/[\x00\x20]+$/, '')
|
||
|
||
smb[:nbdst] = host_dst
|
||
smb[:nbsrc] = host_src
|
||
|
||
# print_status("NetBIOS session request from #{smb[:name]} (asking for #{host_dst} from #{host_src})")
|
||
c.write("\x82\x00\x00\x00")
|
||
next
|
||
end
|
||
|
||
|
||
#
|
||
# TODO: Support AndX parameters
|
||
#
|
||
|
||
|
||
# Cast this to a generic SMB structure
|
||
pkt = CONST::SMB_BASE_PKT.make_struct
|
||
pkt.from_s(buff)
|
||
|
||
# Only response to requests, ignore server replies
|
||
if (pkt['Payload']['SMB'].v['Flags1'] & 128 != 0)
|
||
print_status("Ignoring server response from #{smb[:name]}")
|
||
next
|
||
end
|
||
|
||
cmd = pkt['Payload']['SMB'].v['Command']
|
||
begin
|
||
smb_cmd_dispatch(cmd, c, buff)
|
||
rescue ::Interrupt
|
||
raise $!
|
||
rescue ::Exception => e
|
||
print_status("Error processing request from #{smb[:name]} (#{cmd}): #{e.class} #{e.to_s} #{e.backtrace.to_s}")
|
||
next
|
||
end
|
||
end
|
||
end
|
||
|
||
def smb_cmd_dispatch(cmd, c, buff)
|
||
smb = @state[c]
|
||
print_status("Received command #{cmd} from #{smb[:name]}")
|
||
end
|
||
|
||
def smb_set_defaults(c, pkt)
|
||
smb = @state[c]
|
||
pkt['Payload']['SMB'].v['ProcessID'] = smb[:process_id].to_i
|
||
pkt['Payload']['SMB'].v['UserID'] = smb[:user_id].to_i
|
||
pkt['Payload']['SMB'].v['TreeID'] = smb[:tree_id].to_i
|
||
pkt['Payload']['SMB'].v['MultiplexID'] = smb[:multiplex_id].to_i
|
||
end
|
||
|
||
end
|
||
|
||
|
||
end
|