ruby_smb 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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