ruby_smb 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/.gitignore +21 -0
- data/.rspec +3 -0
- data/.simplecov +42 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/CONTRIBUTING.md +119 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +18 -0
- data/README.md +64 -0
- data/Rakefile +22 -0
- data/examples/authenticate.rb +30 -0
- data/examples/negotiate.rb +25 -0
- data/lib/ruby_smb/client/authentication.rb +236 -0
- data/lib/ruby_smb/client/negotiation.rb +126 -0
- data/lib/ruby_smb/client/signing.rb +48 -0
- data/lib/ruby_smb/client.rb +164 -0
- data/lib/ruby_smb/dispatcher/base.rb +18 -0
- data/lib/ruby_smb/dispatcher/socket.rb +53 -0
- data/lib/ruby_smb/dispatcher.rb +4 -0
- data/lib/ruby_smb/error.rb +17 -0
- data/lib/ruby_smb/field/file_time.rb +62 -0
- data/lib/ruby_smb/field/nt_status.rb +16 -0
- data/lib/ruby_smb/field/stringz16.rb +55 -0
- data/lib/ruby_smb/field.rb +7 -0
- data/lib/ruby_smb/generic_packet.rb +179 -0
- data/lib/ruby_smb/gss.rb +109 -0
- data/lib/ruby_smb/smb1/andx_block.rb +13 -0
- data/lib/ruby_smb/smb1/bit_field/capabilities.rb +39 -0
- data/lib/ruby_smb/smb1/bit_field/header_flags.rb +19 -0
- data/lib/ruby_smb/smb1/bit_field/header_flags2.rb +27 -0
- data/lib/ruby_smb/smb1/bit_field/security_mode.rb +16 -0
- data/lib/ruby_smb/smb1/bit_field.rb +10 -0
- data/lib/ruby_smb/smb1/commands.rb +9 -0
- data/lib/ruby_smb/smb1/data_block.rb +42 -0
- data/lib/ruby_smb/smb1/dialect.rb +11 -0
- data/lib/ruby_smb/smb1/packet/error_packet.rb +14 -0
- data/lib/ruby_smb/smb1/packet/negotiate_request.rb +52 -0
- data/lib/ruby_smb/smb1/packet/negotiate_response.rb +46 -0
- data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +47 -0
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +71 -0
- data/lib/ruby_smb/smb1/packet/session_setup_response.rb +48 -0
- data/lib/ruby_smb/smb1/packet.rb +12 -0
- data/lib/ruby_smb/smb1/parameter_block.rb +42 -0
- data/lib/ruby_smb/smb1/smb_header.rb +21 -0
- data/lib/ruby_smb/smb1.rb +16 -0
- data/lib/ruby_smb/smb2/bit_field/session_flags.rb +17 -0
- data/lib/ruby_smb/smb2/bit_field/smb2_capabailities.rb +23 -0
- data/lib/ruby_smb/smb2/bit_field/smb2_header_flags.rb +23 -0
- data/lib/ruby_smb/smb2/bit_field/smb2_security_mode.rb +15 -0
- data/lib/ruby_smb/smb2/bit_field/smb2_security_mode_single.rb +14 -0
- data/lib/ruby_smb/smb2/bit_field.rb +11 -0
- data/lib/ruby_smb/smb2/commands.rb +25 -0
- data/lib/ruby_smb/smb2/packet/negotiate_request.rb +50 -0
- data/lib/ruby_smb/smb2/packet/negotiate_response.rb +33 -0
- data/lib/ruby_smb/smb2/packet/session_setup_request.rb +53 -0
- data/lib/ruby_smb/smb2/packet/session_setup_response.rb +38 -0
- data/lib/ruby_smb/smb2/packet.rb +10 -0
- data/lib/ruby_smb/smb2/smb2_header.rb +22 -0
- data/lib/ruby_smb/smb2.rb +12 -0
- data/lib/ruby_smb/version.rb +3 -0
- data/lib/ruby_smb.rb +22 -0
- data/ruby_smb.gemspec +38 -0
- data/spec/lib/ruby_smb/client_spec.rb +638 -0
- data/spec/lib/ruby_smb/dispatcher/dispatcher_base_spec.rb +22 -0
- data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +60 -0
- data/spec/lib/ruby_smb/field/file_time_spec.rb +59 -0
- data/spec/lib/ruby_smb/field/nt_status_spec.rb +19 -0
- data/spec/lib/ruby_smb/field/stringz16_spec.rb +50 -0
- data/spec/lib/ruby_smb/generic_packet_spec.rb +58 -0
- data/spec/lib/ruby_smb/smb1/andx_block_spec.rb +41 -0
- data/spec/lib/ruby_smb/smb1/bit_field/capabilities_spec.rb +245 -0
- data/spec/lib/ruby_smb/smb1/bit_field/header_flags2_spec.rb +146 -0
- data/spec/lib/ruby_smb/smb1/bit_field/header_flags_spec.rb +102 -0
- data/spec/lib/ruby_smb/smb1/bit_field/security_mode_spec.rb +44 -0
- data/spec/lib/ruby_smb/smb1/data_block_spec.rb +26 -0
- data/spec/lib/ruby_smb/smb1/dialect_spec.rb +26 -0
- data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +39 -0
- data/spec/lib/ruby_smb/smb1/packet/negotiate_request_spec.rb +77 -0
- data/spec/lib/ruby_smb/smb1/packet/negotiate_response_extended_spec.rb +149 -0
- data/spec/lib/ruby_smb/smb1/packet/negotiate_response_spec.rb +150 -0
- data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +100 -0
- data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +72 -0
- data/spec/lib/ruby_smb/smb1/parameter_block_spec.rb +26 -0
- data/spec/lib/ruby_smb/smb1/smb_header_spec.rb +96 -0
- data/spec/lib/ruby_smb/smb2/bit_field/header_flags_spec.rb +81 -0
- data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +28 -0
- data/spec/lib/ruby_smb/smb2/bit_field/smb2_capabilities_spec.rb +72 -0
- data/spec/lib/ruby_smb/smb2/bit_field/smb_secruity_mode_spec.rb +22 -0
- data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +122 -0
- data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +147 -0
- data/spec/lib/ruby_smb/smb2/packet/session_setup_request_spec.rb +79 -0
- data/spec/lib/ruby_smb/smb2/packet/session_setup_response_spec.rb +54 -0
- data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +127 -0
- data/spec/lib/ruby_smb_spec.rb +2 -0
- data/spec/spec_helper.rb +100 -0
- data/spec/support/mock_socket_dispatcher.rb +8 -0
- data/spec/support/shared/examples/bit_field_single_flag.rb +14 -0
- data.tar.gz.sig +0 -0
- metadata +384 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB1
|
3
|
+
module Packet
|
4
|
+
|
5
|
+
# A SMB1 SMB_COM_SESSION_SETUP_ANDX Request Packet as defined in
|
6
|
+
# [2.2.4.6.1](https://msdn.microsoft.com/en-us/library/cc246328.aspx)
|
7
|
+
class SessionSetupRequest < RubySMB::GenericPacket
|
8
|
+
|
9
|
+
# A SMB1 Parameter Block as defined by the {SessionSetupRequest}
|
10
|
+
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
11
|
+
and_x_block :andx_block
|
12
|
+
uint16 :max_buffer_size, label: 'Max Buffer Size'
|
13
|
+
uint16 :max_mpx_count, label: 'Max Mpx Count'
|
14
|
+
uint16 :vc_number, label: 'VC Number'
|
15
|
+
uint32 :session_key, label: 'Session Key'
|
16
|
+
uint16 :security_blob_length, label: 'Security Blob Length'
|
17
|
+
uint32 :reserved
|
18
|
+
capabilities :capabilities
|
19
|
+
end
|
20
|
+
|
21
|
+
# Represents the specific layout of the DataBlock for a {SessionSetupRequest} Packet.
|
22
|
+
# Due to vagaries of character encoding and the way we currently handle NTLM authentication
|
23
|
+
# for the security blob, you must null-terminate the {native_os} and {native_lan_man} fields
|
24
|
+
# yourself if you set them away from their defaults.
|
25
|
+
class DataBlock < RubySMB::SMB1::DataBlock
|
26
|
+
string :security_blob, label: 'Security Blob (GSS-API)', length: lambda { self.parent.parameter_block.security_blob_length }
|
27
|
+
stringz :native_os, label: 'Native OS', initial_value: 'Windows 7 Ultimate N 7601 Service Pack 1'
|
28
|
+
stringz :native_lan_man, label: 'Native LAN Manager', initial_value: 'Windows 7 Ultimate N 6.1'
|
29
|
+
end
|
30
|
+
|
31
|
+
smb_header :smb_header
|
32
|
+
parameter_block :parameter_block
|
33
|
+
data_block :data_block
|
34
|
+
|
35
|
+
def initialize_instance
|
36
|
+
super
|
37
|
+
smb_header.command = RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
|
38
|
+
end
|
39
|
+
|
40
|
+
# Takes an NTLM Type 1 Message and creates the GSS Security Blob
|
41
|
+
# for it and sets it in the {RubySMB::SMB1::Packet::SessionSetupRequest::DataBlock#security_blob}
|
42
|
+
# field. It also automaticaly sets the length in
|
43
|
+
# {RubySMB::SMB1::Packet::SessionSetupRequest::ParameterBlock#security_blob_length}
|
44
|
+
#
|
45
|
+
# @param type1_message [String] the serialized Type 1 NTLM message
|
46
|
+
# @return [void]
|
47
|
+
def set_type1_blob(type1_message)
|
48
|
+
gss_blob = RubySMB::Gss.gss_type1(type1_message)
|
49
|
+
parameter_block.security_blob_length = gss_blob.length
|
50
|
+
data_block.security_blob = gss_blob
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
# Takes an NTLM Type 3 Message and creates the GSS Security Blob
|
55
|
+
# for it and sets it in the {RubySMB::SMB1::Packet::SessionSetupRequest::DataBlock#security_blob}
|
56
|
+
# field. It also automaticaly sets the length in
|
57
|
+
# {RubySMB::SMB1::Packet::SessionSetupRequest::ParameterBlock#security_blob_length}
|
58
|
+
#
|
59
|
+
# @param type3_message [String] the serialized Type 3 NTLM message
|
60
|
+
# @return [void]
|
61
|
+
def set_type3_blob(type3_message)
|
62
|
+
gss_blob = RubySMB::Gss.gss_type3(type3_message)
|
63
|
+
parameter_block.security_blob_length = gss_blob.length
|
64
|
+
data_block.security_blob = gss_blob
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB1
|
3
|
+
module Packet
|
4
|
+
|
5
|
+
# A SMB1 SMB_COM_SESSION_SETUP Response Packet as defined in
|
6
|
+
# [2.2.4.6.2](https://msdn.microsoft.com/en-us/library/cc246329.aspx)
|
7
|
+
class SessionSetupResponse < RubySMB::GenericPacket
|
8
|
+
|
9
|
+
# A SMB1 Parameter Block as defined by the {SessionSetupResponse}
|
10
|
+
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
11
|
+
and_x_block :andx_block
|
12
|
+
uint16 :action, label: 'Action'
|
13
|
+
uint16 :security_blob_length, label: 'Security Blob Length'
|
14
|
+
end
|
15
|
+
|
16
|
+
# Represents the specific layout of the DataBlock for a {SessionSetupResponse} Packet.
|
17
|
+
class DataBlock < RubySMB::SMB1::DataBlock
|
18
|
+
string :security_blob, label: 'Security Blob (GSS-API)', length: lambda { self.parent.parameter_block.security_blob_length }
|
19
|
+
stringz :native_os, label: 'Native OS'
|
20
|
+
stringz :native_lan_man, label: 'Native LAN Manager'
|
21
|
+
end
|
22
|
+
|
23
|
+
smb_header :smb_header
|
24
|
+
parameter_block :parameter_block
|
25
|
+
data_block :data_block
|
26
|
+
|
27
|
+
def initialize_instance
|
28
|
+
super
|
29
|
+
smb_header.command = RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
|
30
|
+
smb_header.flags.reply = 1
|
31
|
+
end
|
32
|
+
|
33
|
+
# Takes an NTLM Type 2 Message and creates the GSS Security Blob
|
34
|
+
# for it and sets it in the {RubySMB::SMB1::Packet::SessionSetupRequest::DataBlock#security_blob}
|
35
|
+
# field. It also automaticaly sets the length in
|
36
|
+
# {RubySMB::SMB1::Packet::SessionSetupRequest::ParameterBlock#security_blob_length}
|
37
|
+
#
|
38
|
+
# @param type2_message [String] the serialized Type 2 NTLM message
|
39
|
+
# @return [void]
|
40
|
+
def set_type2_blob(type2_message)
|
41
|
+
gss_blob = RubySMB::Gss.gss_type2(type2_message)
|
42
|
+
data_block.security_blob = gss_blob
|
43
|
+
parameter_block.security_blob_length = gss_blob.length
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB1
|
3
|
+
module Packet
|
4
|
+
require 'ruby_smb/smb1/packet/error_packet'
|
5
|
+
require 'ruby_smb/smb1/packet/negotiate_request'
|
6
|
+
require 'ruby_smb/smb1/packet/negotiate_response'
|
7
|
+
require 'ruby_smb/smb1/packet/negotiate_response_extended'
|
8
|
+
require 'ruby_smb/smb1/packet/session_setup_request'
|
9
|
+
require 'ruby_smb/smb1/packet/session_setup_response'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB1
|
3
|
+
# Represents the ParameterBlock portion of an SMB1 Packet. The ParameterBlock will
|
4
|
+
# always contain a word_count field that gives the size of the rest of
|
5
|
+
# the data block in words.
|
6
|
+
class ParameterBlock < BinData::Record
|
7
|
+
endian :little
|
8
|
+
|
9
|
+
uint8 :word_count, label: 'Word Count', value: -> { calculate_word_count }
|
10
|
+
|
11
|
+
# Class method to stub word count calculation during
|
12
|
+
# lazy evaluation.
|
13
|
+
#
|
14
|
+
# @param [Fixnum] will always return 0
|
15
|
+
def self.calculate_word_count
|
16
|
+
0
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns the name of all fields, other than word_count, in
|
20
|
+
# the ParameterBlock as symbols.
|
21
|
+
#
|
22
|
+
# @return [Array<Symbol>] the names of all other ParameterBlock fields
|
23
|
+
def self.parameter_fields
|
24
|
+
fields = self.fields.collect(&:name)
|
25
|
+
fields.reject { |field| field == :word_count }
|
26
|
+
end
|
27
|
+
|
28
|
+
# Calculates the size of the other fields in the ParameterBlock
|
29
|
+
# in Words.
|
30
|
+
#
|
31
|
+
# @return [Fixnum] The size of the ParameterBlock in Words
|
32
|
+
def calculate_word_count
|
33
|
+
total_count = 0
|
34
|
+
self.class.parameter_fields.each do |field_name|
|
35
|
+
field_value = send(field_name)
|
36
|
+
total_count += field_value.do_num_bytes
|
37
|
+
end
|
38
|
+
total_count.to_i / 2
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB1
|
3
|
+
# Represents the Header of an SMB1 packet as defined in
|
4
|
+
# [2.2.3.1 SMB Header Extensions](https://msdn.microsoft.com/en-us/library/cc246254.aspx)
|
5
|
+
class SMBHeader < BinData::Record
|
6
|
+
endian :little
|
7
|
+
bit32 :protocol, label: 'Protocol ID Field', initial_value: RubySMB::SMB1::SMB_PROTOCOL_ID
|
8
|
+
bit8 :command, label: 'SMB Command ID'
|
9
|
+
nt_status :nt_status, label: 'NTStatus Code'
|
10
|
+
header_flags :flags
|
11
|
+
header_flags2 :flags2
|
12
|
+
bit16 :pid_high, label: 'PID High Bytes'
|
13
|
+
string :security_features, label: 'Security Features', length: 8
|
14
|
+
bit16 :reserved, label: 'Reserved'
|
15
|
+
bit16 :tid, label: 'Tree ID'
|
16
|
+
bit16 :pid_low, label: 'PID Low Bytes'
|
17
|
+
bit16 :uid, label: 'User ID'
|
18
|
+
bit16 :mid, label: 'Multiplex ID'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# This module adds the namespace for version 1 of the SMB Protocol
|
2
|
+
# as defined in [MS-SMB](https://msdn.microsoft.com/en-us/library/cc246231.aspx)
|
3
|
+
module RubySMB::SMB1
|
4
|
+
# Protocol ID value. Translates to \xFFSMB
|
5
|
+
SMB_PROTOCOL_ID = 0xFF534D42
|
6
|
+
|
7
|
+
require 'ruby_smb/smb1/commands'
|
8
|
+
require 'ruby_smb/smb1/andx_block'
|
9
|
+
require 'ruby_smb/smb1/bit_field'
|
10
|
+
require 'ruby_smb/smb1/smb_header'
|
11
|
+
require 'ruby_smb/smb1/parameter_block'
|
12
|
+
require 'ruby_smb/smb1/data_block'
|
13
|
+
require 'ruby_smb/smb1/dialect'
|
14
|
+
require 'ruby_smb/smb1/packet'
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB2
|
3
|
+
module BitField
|
4
|
+
# The SessionsFlags bit-field for a {RubySMB::SMB2::Packet::SessionSetupResponse}
|
5
|
+
class SessionFlags < BinData::Record
|
6
|
+
endian :little
|
7
|
+
bit6 :reserved3, label: 'Reserved', value: 0
|
8
|
+
bit1 :null, label: 'ASYNC Command', initial_value: 0
|
9
|
+
bit1 :guest, label: 'Is Guest?', initial_value: 0
|
10
|
+
resume_byte_alignment
|
11
|
+
# byte border
|
12
|
+
uint8 :reserved1, label: 'Reserved', value: 0
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB2
|
3
|
+
module BitField
|
4
|
+
# Represents a Capabilities BitField as defined by
|
5
|
+
# [2.2.3 SMB2 NEGOTIATE Request](https://msdn.microsoft.com/en-us/library/cc246543.aspx)
|
6
|
+
class Smb2Capabilities < BinData::Record
|
7
|
+
endian :little
|
8
|
+
bit1 :reserved1, label: 'Reserved'
|
9
|
+
bit1 :encryption, label: 'Encryption'
|
10
|
+
bit1 :directory_leasing, label: 'Directory Leasing'
|
11
|
+
bit1 :persistent_handles, label: 'Persistent Handles'
|
12
|
+
bit1 :multi_channel, label: 'Multi Channel'
|
13
|
+
bit1 :large_mtu, label: 'Large MTU'
|
14
|
+
bit1 :leasing, label: 'Leasing'
|
15
|
+
bit1 :dfs, label: 'DFS'
|
16
|
+
# byte border
|
17
|
+
uint8 :reserved2, label: 'Reserved'
|
18
|
+
uint8 :reserved3, label: 'Reserved'
|
19
|
+
uint8 :reserved4, label: 'Reserved'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB2
|
3
|
+
module BitField
|
4
|
+
# The Flags bit-field for an SMB2 Header as defined in
|
5
|
+
# [2.2.1.2 SMB2 Packet Header - SYNC](https://msdn.microsoft.com/en-us/library/cc246529.aspx)
|
6
|
+
class Smb2HeaderFlags < BinData::Record
|
7
|
+
endian :little
|
8
|
+
bit4 :reserved3, label: 'Reserved', value: 0
|
9
|
+
bit1 :signed, label: 'Packet Signed'
|
10
|
+
bit1 :related_operations, label: 'Chained Request'
|
11
|
+
bit1 :async_command, label: 'ASYNC Command', value: 0
|
12
|
+
bit1 :reply, label: 'Response'
|
13
|
+
# byte border
|
14
|
+
uint16 :reserved2, label: 'Reserved', value: 0
|
15
|
+
# byte border
|
16
|
+
bit2 :reserved1, label: 'Reserved', value: 0
|
17
|
+
bit1 :replay_operation, label: 'Replay Operation'
|
18
|
+
bit1 :dfs_operation, label: 'DFS Operation'
|
19
|
+
resume_byte_alignment
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB2
|
3
|
+
module BitField
|
4
|
+
# Represents a Security Mode BitField as defined by
|
5
|
+
# [2.2.3 SMB2 NEGOTIATE Request](https://msdn.microsoft.com/en-us/library/cc246543.aspx)
|
6
|
+
class Smb2SecurityMode < BinData::Record
|
7
|
+
endian :little
|
8
|
+
bit6 :reserved, label: 'Reserved'
|
9
|
+
bit1 :signing_required, label: 'Signing Required'
|
10
|
+
bit1 :signing_enabled, label: 'Signing Enabled'
|
11
|
+
uint8 :reserved2, label: 'Reserved'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB2
|
3
|
+
module BitField
|
4
|
+
# Represents a Security Mode BitField as defined by
|
5
|
+
# [2.2.3 SMB2 NEGOTIATE Request](https://msdn.microsoft.com/en-us/library/cc246543.aspx)
|
6
|
+
class Smb2SecurityModeSingle < BinData::Record
|
7
|
+
endian :little
|
8
|
+
bit6 :reserved, label: 'Reserved'
|
9
|
+
bit1 :signing_required, label: 'Signing Required'
|
10
|
+
bit1 :signing_enabled, label: 'Signing Enabled'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB2
|
3
|
+
module BitField
|
4
|
+
require 'ruby_smb/smb2/bit_field/smb2_header_flags'
|
5
|
+
require 'ruby_smb/smb2/bit_field/smb2_security_mode'
|
6
|
+
require 'ruby_smb/smb2/bit_field/smb2_security_mode_single'
|
7
|
+
require 'ruby_smb/smb2/bit_field/smb2_capabailities'
|
8
|
+
require 'ruby_smb/smb2/bit_field/session_flags'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB2
|
3
|
+
# [[MS-SMB2] 2.2 Message Syntax](https://msdn.microsoft.com/en-us/library/cc246497.aspx)
|
4
|
+
module Commands
|
5
|
+
NEGOTIATE = 0x00
|
6
|
+
SESSION_SETUP = 0x01
|
7
|
+
LOGOFF = 0x02
|
8
|
+
TREE_CONNECT = 0x03
|
9
|
+
TREE_DISCONNECT = 0x04
|
10
|
+
CREATE = 0x05
|
11
|
+
CLOSE = 0x06
|
12
|
+
FLUSH = 0x07
|
13
|
+
READ = 0x08
|
14
|
+
WRITE = 0x09
|
15
|
+
LOCK = 0x0a
|
16
|
+
IOCTL = 0x0b
|
17
|
+
CANCEL = 0x0c
|
18
|
+
QUERY_DIRECTORY = 0x0e
|
19
|
+
ECHO = 0x0d
|
20
|
+
CHANGE_NOTIFY = 0x0f
|
21
|
+
QUERY_INFO = 0x10
|
22
|
+
SET_INFO = 0x11
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB2
|
3
|
+
module Packet
|
4
|
+
# An SMB2 NEGOTIATE Request packet as defined by
|
5
|
+
# [2.2.3 SMB2 NEGOTIATE Request](https://msdn.microsoft.com/en-us/library/cc246543.aspx)
|
6
|
+
class NegotiateRequest < RubySMB::GenericPacket
|
7
|
+
endian :little
|
8
|
+
smb2_header :smb2_header
|
9
|
+
uint16 :structure_size, label: 'Structure Size', initial_value: 36
|
10
|
+
uint16 :dialect_count, label: 'Dialect Count'
|
11
|
+
smb2_security_mode :security_mode
|
12
|
+
uint16 :reserved1, label: 'Reserved', initial_value: 0
|
13
|
+
smb2_capabilities :capabilities
|
14
|
+
string :client_guid, label: 'Client GUID', length: 16
|
15
|
+
file_time :client_start_time, label: 'Client Start Time', initial_value: 0
|
16
|
+
array :dialects, label: 'Dialects', type: :uint16, read_until: :eof
|
17
|
+
|
18
|
+
def initialize_instance
|
19
|
+
super
|
20
|
+
smb2_header.command = RubySMB::SMB2::Commands::NEGOTIATE
|
21
|
+
end
|
22
|
+
|
23
|
+
# Adds a dialect to the Dialects array and increments the dialect count
|
24
|
+
#
|
25
|
+
# @param [Fixnum] the numeric code for the dialect you wish to add
|
26
|
+
# @return [Array<Fixnum>] the array of all currently selected dialects
|
27
|
+
def add_dialect(dialect)
|
28
|
+
return ArgumentError, 'Must be a number' unless dialect.is_a? Fixnum
|
29
|
+
self.dialect_count += 1
|
30
|
+
dialects << dialect
|
31
|
+
end
|
32
|
+
|
33
|
+
# Takes an array of dialects and sets it on the packet. Also updates
|
34
|
+
# the dialect_count field appropriately. Will erase any previously set
|
35
|
+
# dialects.
|
36
|
+
#
|
37
|
+
# @param [Array<Fixnum>] the array of dialects to set
|
38
|
+
# @return [Array<Fixnum>] the current value of the dialects array
|
39
|
+
def set_dialects(add_dialects = [])
|
40
|
+
self.dialects = []
|
41
|
+
self.dialect_count = 0
|
42
|
+
add_dialects.each do |dialect|
|
43
|
+
add_dialect(dialect)
|
44
|
+
end
|
45
|
+
dialects
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB2
|
3
|
+
module Packet
|
4
|
+
# An SMB2 NEGOTIATE Response packet as defined by
|
5
|
+
# [2.2.4 SMB2 NEGOTIATE Response](https://msdn.microsoft.com/en-us/library/cc246561.aspx)
|
6
|
+
class NegotiateResponse < RubySMB::GenericPacket
|
7
|
+
endian :little
|
8
|
+
smb2_header :smb2_header
|
9
|
+
uint16 :structure_size, label: 'Structure Size', initial_value: 65
|
10
|
+
smb2_security_mode :security_mode
|
11
|
+
uint16 :dialect_revision, label: 'Dialect Revision'
|
12
|
+
uint16 :negotiate_context_count, label: 'Negotiate Context Count', initial_value: 0
|
13
|
+
string :server_guid, label: 'Server GUID', length: 16
|
14
|
+
smb2_capabilities :capabilities
|
15
|
+
uint32 :max_transact_size, label: 'Max Transaction Size'
|
16
|
+
uint32 :max_read_size, label: 'Max Read Size'
|
17
|
+
uint32 :max_write_size, label: 'Max Write Size'
|
18
|
+
file_time :system_time, label: 'Server System Time'
|
19
|
+
file_time :server_start_time, label: 'Server Start Time'
|
20
|
+
uint16 :security_buffer_offset, label: 'Offset to Security Buffer'
|
21
|
+
uint16 :security_buffer_length, label: 'Security Buffer Length', value: -> { security_buffer.length }
|
22
|
+
uint32 :negotiate_context_offset, label: 'Offset to Negotiate Context'
|
23
|
+
string :security_buffer, label: 'Security Buffer', read_length: :security_buffer_length
|
24
|
+
|
25
|
+
def initialize_instance
|
26
|
+
super
|
27
|
+
smb2_header.command = RubySMB::SMB2::Commands::NEGOTIATE
|
28
|
+
smb2_header.flags.reply = 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB2
|
3
|
+
module Packet
|
4
|
+
|
5
|
+
# An SMB2 SessionSetupRequest Packet as defined in
|
6
|
+
# [2.2.5 SMB2 SESSION_SETUP Request](https://msdn.microsoft.com/en-us/library/cc246563.aspx)
|
7
|
+
class SessionSetupRequest < RubySMB::GenericPacket
|
8
|
+
endian :little
|
9
|
+
smb2_header :smb2_header
|
10
|
+
uint16 :structure_size, label: 'Structure Size', initial_value: 25
|
11
|
+
uint8 :flags, label: 'Flags', initial_value: 0x00
|
12
|
+
smb2_security_mode_single :security_mode
|
13
|
+
smb2_capabilities :capabilities
|
14
|
+
uint32 :channel, label: 'Channel', initial_value: 0x00
|
15
|
+
uint16 :security_buffer_offset, label: 'Security Buffer Offset', initial_value: 0x58
|
16
|
+
uint16 :security_buffer_length, label: 'Security Buffer Length'
|
17
|
+
uint64 :previous_session_id, label: 'Previous Session ID'
|
18
|
+
string :buffer, label: 'Security Buffer', length: lambda { self.security_buffer_length }
|
19
|
+
|
20
|
+
|
21
|
+
def initialize_instance
|
22
|
+
super
|
23
|
+
smb2_header.command = RubySMB::SMB2::Commands::SESSION_SETUP
|
24
|
+
end
|
25
|
+
|
26
|
+
# Takes a serialized NTLM Type 1 message and wraps it in the GSS ASN1 encoding
|
27
|
+
# and inserts it into the {RubySMB::SMB2::Packet::SessionSetupRequest#buffer}
|
28
|
+
# as well as updating the {RubySMB::SMB2::Packet::SessionSetupRequest#security_buffer_length}
|
29
|
+
#
|
30
|
+
# @param type1_message [String] the serialized NTLM Type 1 message
|
31
|
+
# @return [void]
|
32
|
+
def set_type1_blob(type1_message)
|
33
|
+
gss_blob = RubySMB::Gss.gss_type1(type1_message)
|
34
|
+
self.security_buffer_length = gss_blob.length
|
35
|
+
self.buffer = gss_blob
|
36
|
+
end
|
37
|
+
|
38
|
+
# Takes a serialized NTLM Type 3 message and wraps it in the GSS ASN1 encoding
|
39
|
+
# and inserts it into the {RubySMB::SMB2::Packet::SessionSetupRequest#buffer}
|
40
|
+
# as well as updating the {RubySMB::SMB2::Packet::SessionSetupRequest#security_buffer_length}
|
41
|
+
#
|
42
|
+
# @param type3_message [String] the serialized NTLM Type 3 message
|
43
|
+
# @return [void]
|
44
|
+
def set_type3_blob(type3_message)
|
45
|
+
gss_blob = RubySMB::Gss.gss_type3(type3_message)
|
46
|
+
self.security_buffer_length = gss_blob.length
|
47
|
+
self.buffer = gss_blob
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB2
|
3
|
+
module Packet
|
4
|
+
|
5
|
+
# An SMB2 SessionSetupResponse Packet as defined in
|
6
|
+
# [2.2.6 SMB2 SESSION_SETUP Response](https://msdn.microsoft.com/en-us/library/cc246564.aspx)
|
7
|
+
class SessionSetupResponse < RubySMB::GenericPacket
|
8
|
+
endian :little
|
9
|
+
smb2_header :smb2_header
|
10
|
+
uint16 :structure_size, label: 'Structure Size', initial_value: 9
|
11
|
+
session_flags :session_flags
|
12
|
+
uint16 :security_buffer_offset, label: 'Security Buffer Offset', initial_value: 0x48
|
13
|
+
uint16 :security_buffer_length, label: 'Security Buffer Length'
|
14
|
+
string :buffer, label: 'Security Buffer', length: lambda { self.security_buffer_length }
|
15
|
+
|
16
|
+
|
17
|
+
def initialize_instance
|
18
|
+
super
|
19
|
+
smb2_header.command = RubySMB::SMB2::Commands::SESSION_SETUP
|
20
|
+
smb2_header.flags.reply = 1
|
21
|
+
end
|
22
|
+
|
23
|
+
# Takes a serialized NTLM Type 2 message and wraps it in the GSS ASN1 encoding
|
24
|
+
# and inserts it into the {RubySMB::SMB2::Packet::SessionSetupRequest#buffer}
|
25
|
+
# as well as updating the {RubySMB::SMB2::Packet::SessionSetupRequest#security_buffer_length}
|
26
|
+
#
|
27
|
+
# @param type1_message [String] the serialized NTLM Type 1 message
|
28
|
+
# @return [void]
|
29
|
+
def set_type2_blob(type1_message)
|
30
|
+
gss_blob = RubySMB::Gss.gss_type2(type1_message)
|
31
|
+
self.security_buffer_length = gss_blob.length
|
32
|
+
self.buffer = gss_blob
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB2
|
3
|
+
module Packet
|
4
|
+
require 'ruby_smb/smb2/packet/negotiate_request'
|
5
|
+
require 'ruby_smb/smb2/packet/negotiate_response'
|
6
|
+
require 'ruby_smb/smb2/packet/session_setup_request'
|
7
|
+
require 'ruby_smb/smb2/packet/session_setup_response'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB2
|
3
|
+
# Represents the Header of an SMB2 packet as defined in
|
4
|
+
# [2.2.1.2 SMB2 Packet Header - SYNC](https://msdn.microsoft.com/en-us/library/cc246529.aspx)
|
5
|
+
class SMB2Header < BinData::Record
|
6
|
+
endian :little
|
7
|
+
bit32 :protocol, label: 'Protocol ID Field', initial_value: RubySMB::SMB2::SMB2_PROTOCOL_ID
|
8
|
+
uint16 :structure_size, label: 'Header Structure Size', initial_value: 64
|
9
|
+
uint16 :credit_charge, label: 'Credit Charge', initial_value: 0
|
10
|
+
nt_status :nt_status, label: 'NT Status', initial_value: 0
|
11
|
+
uint16 :command, label: 'Command'
|
12
|
+
uint16 :credits, label: 'Credit Request/Response'
|
13
|
+
smb2_header_flags :flags, label: 'Flags'
|
14
|
+
uint32 :next_command, label: 'Command Chain Offset', initial_value: 0
|
15
|
+
uint64 :message_id, label: 'Message ID'
|
16
|
+
uint32 :process_id, label: 'Process ID', initial_value: 0x0000feff
|
17
|
+
uint32 :tree_id, label: 'Tree ID'
|
18
|
+
uint64 :session_id, label: 'Session ID'
|
19
|
+
string :signature, label: 'Signature', length: 16
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# A packet parsing and manipulation library for the SMB2 protocol
|
2
|
+
#
|
3
|
+
# [[MS-SMB2] Server Mesage Block (SMB) Protocol Versions 2 and 3](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
|
4
|
+
module RubySMB::SMB2
|
5
|
+
# Protocol ID value. Translates to \xFESMB
|
6
|
+
SMB2_PROTOCOL_ID = 0xFE534D42
|
7
|
+
|
8
|
+
require 'ruby_smb/smb2/commands'
|
9
|
+
require 'ruby_smb/smb2/bit_field'
|
10
|
+
require 'ruby_smb/smb2/smb2_header'
|
11
|
+
require 'ruby_smb/smb2/packet'
|
12
|
+
end
|
data/lib/ruby_smb.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'bit-struct'
|
2
|
+
require 'bindata'
|
3
|
+
require 'net/ntlm'
|
4
|
+
require 'net/ntlm/client'
|
5
|
+
require 'windows_error'
|
6
|
+
require 'windows_error/nt_status'
|
7
|
+
# A packet parsing and manipulation library for the SMB1 and SMB2 protocols
|
8
|
+
#
|
9
|
+
# [[MS-SMB] Server Mesage Block (SMB) Protocol Version 1](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
|
10
|
+
# [[MS-SMB2] Server Mesage Block (SMB) Protocol Versions 2 and 3](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
|
11
|
+
module RubySMB
|
12
|
+
require 'ruby_smb/gss'
|
13
|
+
require 'ruby_smb/field'
|
14
|
+
require 'ruby_smb/generic_packet'
|
15
|
+
require 'ruby_smb/dispatcher'
|
16
|
+
require 'ruby_smb/error'
|
17
|
+
require 'ruby_smb/version'
|
18
|
+
require 'ruby_smb/version'
|
19
|
+
require 'ruby_smb/smb2'
|
20
|
+
require 'ruby_smb/smb1'
|
21
|
+
require 'ruby_smb/client'
|
22
|
+
end
|
data/ruby_smb.gemspec
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ruby_smb/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'ruby_smb'
|
8
|
+
spec.version = RubySMB::VERSION
|
9
|
+
spec.authors = ['David Maloney', 'James Lee']
|
10
|
+
spec.email = ['DMaloney@rapid7.com', 'egypt@metasploit.com']
|
11
|
+
spec.summary = 'A message creator and parser for the SMB protocol family'
|
12
|
+
spec.description = ''
|
13
|
+
spec.homepage = 'http://www.metasploit.com'
|
14
|
+
spec.license = 'BSD-3-clause'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
if RUBY_PLATFORM =~ /java/
|
22
|
+
spec.add_development_dependency 'kramdown'
|
23
|
+
spec.platform = Gem::Platform::JAVA
|
24
|
+
else
|
25
|
+
spec.add_development_dependency 'redcarpet'
|
26
|
+
spec.platform = Gem::Platform::RUBY
|
27
|
+
end
|
28
|
+
|
29
|
+
spec.add_development_dependency 'bundler'
|
30
|
+
spec.add_development_dependency 'fivemat'
|
31
|
+
spec.add_development_dependency 'rake'
|
32
|
+
spec.add_development_dependency 'yard'
|
33
|
+
|
34
|
+
spec.add_runtime_dependency 'rubyntlm', '~> 0.5'
|
35
|
+
spec.add_runtime_dependency 'bit-struct'
|
36
|
+
spec.add_runtime_dependency 'windows_error'
|
37
|
+
spec.add_runtime_dependency 'bindata'
|
38
|
+
end
|