ruby_smb 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/.gitignore +21 -0
  4. data/.rspec +3 -0
  5. data/.simplecov +42 -0
  6. data/.travis.yml +5 -0
  7. data/.yardopts +1 -0
  8. data/CONTRIBUTING.md +119 -0
  9. data/Gemfile +13 -0
  10. data/LICENSE.txt +18 -0
  11. data/README.md +64 -0
  12. data/Rakefile +22 -0
  13. data/examples/authenticate.rb +30 -0
  14. data/examples/negotiate.rb +25 -0
  15. data/lib/ruby_smb/client/authentication.rb +236 -0
  16. data/lib/ruby_smb/client/negotiation.rb +126 -0
  17. data/lib/ruby_smb/client/signing.rb +48 -0
  18. data/lib/ruby_smb/client.rb +164 -0
  19. data/lib/ruby_smb/dispatcher/base.rb +18 -0
  20. data/lib/ruby_smb/dispatcher/socket.rb +53 -0
  21. data/lib/ruby_smb/dispatcher.rb +4 -0
  22. data/lib/ruby_smb/error.rb +17 -0
  23. data/lib/ruby_smb/field/file_time.rb +62 -0
  24. data/lib/ruby_smb/field/nt_status.rb +16 -0
  25. data/lib/ruby_smb/field/stringz16.rb +55 -0
  26. data/lib/ruby_smb/field.rb +7 -0
  27. data/lib/ruby_smb/generic_packet.rb +179 -0
  28. data/lib/ruby_smb/gss.rb +109 -0
  29. data/lib/ruby_smb/smb1/andx_block.rb +13 -0
  30. data/lib/ruby_smb/smb1/bit_field/capabilities.rb +39 -0
  31. data/lib/ruby_smb/smb1/bit_field/header_flags.rb +19 -0
  32. data/lib/ruby_smb/smb1/bit_field/header_flags2.rb +27 -0
  33. data/lib/ruby_smb/smb1/bit_field/security_mode.rb +16 -0
  34. data/lib/ruby_smb/smb1/bit_field.rb +10 -0
  35. data/lib/ruby_smb/smb1/commands.rb +9 -0
  36. data/lib/ruby_smb/smb1/data_block.rb +42 -0
  37. data/lib/ruby_smb/smb1/dialect.rb +11 -0
  38. data/lib/ruby_smb/smb1/packet/error_packet.rb +14 -0
  39. data/lib/ruby_smb/smb1/packet/negotiate_request.rb +52 -0
  40. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +46 -0
  41. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +47 -0
  42. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +71 -0
  43. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +48 -0
  44. data/lib/ruby_smb/smb1/packet.rb +12 -0
  45. data/lib/ruby_smb/smb1/parameter_block.rb +42 -0
  46. data/lib/ruby_smb/smb1/smb_header.rb +21 -0
  47. data/lib/ruby_smb/smb1.rb +16 -0
  48. data/lib/ruby_smb/smb2/bit_field/session_flags.rb +17 -0
  49. data/lib/ruby_smb/smb2/bit_field/smb2_capabailities.rb +23 -0
  50. data/lib/ruby_smb/smb2/bit_field/smb2_header_flags.rb +23 -0
  51. data/lib/ruby_smb/smb2/bit_field/smb2_security_mode.rb +15 -0
  52. data/lib/ruby_smb/smb2/bit_field/smb2_security_mode_single.rb +14 -0
  53. data/lib/ruby_smb/smb2/bit_field.rb +11 -0
  54. data/lib/ruby_smb/smb2/commands.rb +25 -0
  55. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +50 -0
  56. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +33 -0
  57. data/lib/ruby_smb/smb2/packet/session_setup_request.rb +53 -0
  58. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +38 -0
  59. data/lib/ruby_smb/smb2/packet.rb +10 -0
  60. data/lib/ruby_smb/smb2/smb2_header.rb +22 -0
  61. data/lib/ruby_smb/smb2.rb +12 -0
  62. data/lib/ruby_smb/version.rb +3 -0
  63. data/lib/ruby_smb.rb +22 -0
  64. data/ruby_smb.gemspec +38 -0
  65. data/spec/lib/ruby_smb/client_spec.rb +638 -0
  66. data/spec/lib/ruby_smb/dispatcher/dispatcher_base_spec.rb +22 -0
  67. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +60 -0
  68. data/spec/lib/ruby_smb/field/file_time_spec.rb +59 -0
  69. data/spec/lib/ruby_smb/field/nt_status_spec.rb +19 -0
  70. data/spec/lib/ruby_smb/field/stringz16_spec.rb +50 -0
  71. data/spec/lib/ruby_smb/generic_packet_spec.rb +58 -0
  72. data/spec/lib/ruby_smb/smb1/andx_block_spec.rb +41 -0
  73. data/spec/lib/ruby_smb/smb1/bit_field/capabilities_spec.rb +245 -0
  74. data/spec/lib/ruby_smb/smb1/bit_field/header_flags2_spec.rb +146 -0
  75. data/spec/lib/ruby_smb/smb1/bit_field/header_flags_spec.rb +102 -0
  76. data/spec/lib/ruby_smb/smb1/bit_field/security_mode_spec.rb +44 -0
  77. data/spec/lib/ruby_smb/smb1/data_block_spec.rb +26 -0
  78. data/spec/lib/ruby_smb/smb1/dialect_spec.rb +26 -0
  79. data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +39 -0
  80. data/spec/lib/ruby_smb/smb1/packet/negotiate_request_spec.rb +77 -0
  81. data/spec/lib/ruby_smb/smb1/packet/negotiate_response_extended_spec.rb +149 -0
  82. data/spec/lib/ruby_smb/smb1/packet/negotiate_response_spec.rb +150 -0
  83. data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +100 -0
  84. data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +72 -0
  85. data/spec/lib/ruby_smb/smb1/parameter_block_spec.rb +26 -0
  86. data/spec/lib/ruby_smb/smb1/smb_header_spec.rb +96 -0
  87. data/spec/lib/ruby_smb/smb2/bit_field/header_flags_spec.rb +81 -0
  88. data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +28 -0
  89. data/spec/lib/ruby_smb/smb2/bit_field/smb2_capabilities_spec.rb +72 -0
  90. data/spec/lib/ruby_smb/smb2/bit_field/smb_secruity_mode_spec.rb +22 -0
  91. data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +122 -0
  92. data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +147 -0
  93. data/spec/lib/ruby_smb/smb2/packet/session_setup_request_spec.rb +79 -0
  94. data/spec/lib/ruby_smb/smb2/packet/session_setup_response_spec.rb +54 -0
  95. data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +127 -0
  96. data/spec/lib/ruby_smb_spec.rb +2 -0
  97. data/spec/spec_helper.rb +100 -0
  98. data/spec/support/mock_socket_dispatcher.rb +8 -0
  99. data/spec/support/shared/examples/bit_field_single_flag.rb +14 -0
  100. data.tar.gz.sig +0 -0
  101. metadata +384 -0
  102. 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
@@ -0,0 +1,3 @@
1
+ module RubySMB
2
+ VERSION = '0.0.8'.freeze
3
+ 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