ruby_smb 1.0.3 → 2.0.1

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 (200) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.travis.yml +3 -2
  5. data/Gemfile +6 -2
  6. data/README.md +35 -47
  7. data/examples/enum_registry_key.rb +28 -0
  8. data/examples/enum_registry_values.rb +30 -0
  9. data/examples/negotiate.rb +51 -8
  10. data/examples/pipes.rb +2 -1
  11. data/examples/read_file_encryption.rb +56 -0
  12. data/examples/read_registry_key_value.rb +32 -0
  13. data/lib/ruby_smb.rb +4 -1
  14. data/lib/ruby_smb/client.rb +233 -22
  15. data/lib/ruby_smb/client/authentication.rb +70 -33
  16. data/lib/ruby_smb/client/echo.rb +20 -2
  17. data/lib/ruby_smb/client/encryption.rb +62 -0
  18. data/lib/ruby_smb/client/negotiation.rb +172 -24
  19. data/lib/ruby_smb/client/signing.rb +19 -0
  20. data/lib/ruby_smb/client/tree_connect.rb +24 -18
  21. data/lib/ruby_smb/client/utils.rb +8 -7
  22. data/lib/ruby_smb/client/winreg.rb +46 -0
  23. data/lib/ruby_smb/crypto.rb +30 -0
  24. data/lib/ruby_smb/dcerpc.rb +38 -0
  25. data/lib/ruby_smb/dcerpc/bind.rb +2 -2
  26. data/lib/ruby_smb/dcerpc/bind_ack.rb +2 -2
  27. data/lib/ruby_smb/dcerpc/error.rb +3 -0
  28. data/lib/ruby_smb/dcerpc/ndr.rb +95 -16
  29. data/lib/ruby_smb/dcerpc/pdu_header.rb +1 -1
  30. data/lib/ruby_smb/dcerpc/request.rb +28 -9
  31. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +35 -0
  32. data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -0
  33. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +9 -0
  34. data/lib/ruby_smb/dcerpc/winreg.rb +340 -0
  35. data/lib/ruby_smb/dcerpc/winreg/close_key_request.rb +24 -0
  36. data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +27 -0
  37. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +45 -0
  38. data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +42 -0
  39. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +39 -0
  40. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +36 -0
  41. data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +34 -0
  42. data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +25 -0
  43. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +43 -0
  44. data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +35 -0
  45. data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +27 -0
  46. data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +40 -0
  47. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +39 -0
  48. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +57 -0
  49. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +40 -0
  50. data/lib/ruby_smb/dispatcher/socket.rb +4 -3
  51. data/lib/ruby_smb/error.rb +68 -2
  52. data/lib/ruby_smb/generic_packet.rb +33 -4
  53. data/lib/ruby_smb/smb1/commands.rb +1 -1
  54. data/lib/ruby_smb/smb1/file.rb +66 -15
  55. data/lib/ruby_smb/smb1/packet/close_request.rb +2 -5
  56. data/lib/ruby_smb/smb1/packet/close_response.rb +2 -1
  57. data/lib/ruby_smb/smb1/packet/echo_request.rb +2 -4
  58. data/lib/ruby_smb/smb1/packet/echo_response.rb +2 -1
  59. data/lib/ruby_smb/smb1/packet/empty_packet.rb +10 -1
  60. data/lib/ruby_smb/smb1/packet/logoff_request.rb +2 -4
  61. data/lib/ruby_smb/smb1/packet/logoff_response.rb +2 -1
  62. data/lib/ruby_smb/smb1/packet/negotiate_request.rb +2 -5
  63. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +3 -7
  64. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +4 -4
  65. data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +2 -4
  66. data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +2 -1
  67. data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +2 -1
  68. data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +2 -1
  69. data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +2 -4
  70. data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +2 -1
  71. data/lib/ruby_smb/smb1/packet/read_andx_request.rb +2 -5
  72. data/lib/ruby_smb/smb1/packet/read_andx_response.rb +2 -1
  73. data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -1
  74. data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +3 -2
  75. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +2 -5
  76. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +3 -2
  77. data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_request.rb +0 -1
  78. data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_response.rb +3 -2
  79. data/lib/ruby_smb/smb1/packet/trans/request.rb +2 -5
  80. data/lib/ruby_smb/smb1/packet/trans/response.rb +2 -1
  81. data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_request.rb +1 -1
  82. data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_response.rb +1 -1
  83. data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +2 -1
  84. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +8 -2
  85. data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +2 -1
  86. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +8 -2
  87. data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +2 -1
  88. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +2 -1
  89. data/lib/ruby_smb/smb1/packet/trans2/request.rb +2 -4
  90. data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +2 -4
  91. data/lib/ruby_smb/smb1/packet/trans2/response.rb +2 -1
  92. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +2 -1
  93. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +2 -1
  94. data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +2 -4
  95. data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +13 -3
  96. data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
  97. data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -1
  98. data/lib/ruby_smb/smb1/packet/write_andx_request.rb +3 -6
  99. data/lib/ruby_smb/smb1/packet/write_andx_response.rb +2 -1
  100. data/lib/ruby_smb/smb1/pipe.rb +87 -6
  101. data/lib/ruby_smb/smb1/tree.rb +50 -3
  102. data/lib/ruby_smb/smb2/bit_field/session_flags.rb +2 -1
  103. data/lib/ruby_smb/smb2/bit_field/share_flags.rb +6 -4
  104. data/lib/ruby_smb/smb2/file.rb +103 -25
  105. data/lib/ruby_smb/smb2/negotiate_context.rb +108 -0
  106. data/lib/ruby_smb/smb2/packet.rb +2 -0
  107. data/lib/ruby_smb/smb2/packet/close_request.rb +2 -4
  108. data/lib/ruby_smb/smb2/packet/close_response.rb +2 -1
  109. data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +41 -0
  110. data/lib/ruby_smb/smb2/packet/create_request.rb +2 -4
  111. data/lib/ruby_smb/smb2/packet/create_response.rb +2 -1
  112. data/lib/ruby_smb/smb2/packet/echo_request.rb +2 -4
  113. data/lib/ruby_smb/smb2/packet/echo_response.rb +2 -1
  114. data/lib/ruby_smb/smb2/packet/error_packet.rb +15 -3
  115. data/lib/ruby_smb/smb2/packet/ioctl_request.rb +2 -5
  116. data/lib/ruby_smb/smb2/packet/ioctl_response.rb +2 -1
  117. data/lib/ruby_smb/smb2/packet/logoff_request.rb +2 -4
  118. data/lib/ruby_smb/smb2/packet/logoff_response.rb +2 -1
  119. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +51 -17
  120. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +52 -5
  121. data/lib/ruby_smb/smb2/packet/query_directory_request.rb +2 -4
  122. data/lib/ruby_smb/smb2/packet/query_directory_response.rb +8 -2
  123. data/lib/ruby_smb/smb2/packet/read_request.rb +2 -4
  124. data/lib/ruby_smb/smb2/packet/read_response.rb +2 -1
  125. data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
  126. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -1
  127. data/lib/ruby_smb/smb2/packet/set_info_request.rb +2 -4
  128. data/lib/ruby_smb/smb2/packet/set_info_response.rb +2 -1
  129. data/lib/ruby_smb/smb2/packet/transform_header.rb +84 -0
  130. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +93 -10
  131. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +10 -22
  132. data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +2 -4
  133. data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +2 -1
  134. data/lib/ruby_smb/smb2/packet/write_request.rb +2 -4
  135. data/lib/ruby_smb/smb2/packet/write_response.rb +2 -1
  136. data/lib/ruby_smb/smb2/pipe.rb +86 -12
  137. data/lib/ruby_smb/smb2/smb2_header.rb +1 -1
  138. data/lib/ruby_smb/smb2/tree.rb +65 -21
  139. data/lib/ruby_smb/version.rb +1 -1
  140. data/ruby_smb.gemspec +5 -3
  141. data/spec/lib/ruby_smb/client_spec.rb +1612 -108
  142. data/spec/lib/ruby_smb/crypto_spec.rb +25 -0
  143. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +2 -2
  144. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +2 -2
  145. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +410 -0
  146. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +50 -7
  147. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +98 -0
  148. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +13 -0
  149. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +60 -0
  150. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_request_spec.rb +28 -0
  151. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +36 -0
  152. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +108 -0
  153. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +97 -0
  154. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +94 -0
  155. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +82 -0
  156. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +74 -0
  157. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +35 -0
  158. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +90 -0
  159. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +38 -0
  160. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +39 -0
  161. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +113 -0
  162. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +88 -0
  163. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +150 -0
  164. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +32 -0
  165. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +710 -0
  166. data/spec/lib/ruby_smb/dcerpc_spec.rb +81 -0
  167. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +2 -2
  168. data/spec/lib/ruby_smb/error_spec.rb +59 -0
  169. data/spec/lib/ruby_smb/generic_packet_spec.rb +52 -4
  170. data/spec/lib/ruby_smb/smb1/file_spec.rb +191 -2
  171. data/spec/lib/ruby_smb/smb1/packet/empty_packet_spec.rb +68 -0
  172. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +2 -2
  173. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +2 -2
  174. data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +2 -2
  175. data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +1 -1
  176. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +11 -2
  177. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +11 -2
  178. data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +40 -0
  179. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +272 -149
  180. data/spec/lib/ruby_smb/smb1/tree_spec.rb +44 -7
  181. data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +9 -0
  182. data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +27 -0
  183. data/spec/lib/ruby_smb/smb2/file_spec.rb +323 -6
  184. data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +332 -0
  185. data/spec/lib/ruby_smb/smb2/packet/compression_transform_header_spec.rb +108 -0
  186. data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +78 -0
  187. data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +138 -3
  188. data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +120 -2
  189. data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +8 -0
  190. data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +220 -0
  191. data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +339 -9
  192. data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +3 -22
  193. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +286 -149
  194. data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +2 -2
  195. data/spec/lib/ruby_smb/smb2/tree_spec.rb +261 -2
  196. metadata +191 -83
  197. metadata.gz.sig +0 -0
  198. data/lib/ruby_smb/smb1/dcerpc.rb +0 -67
  199. data/lib/ruby_smb/smb2/dcerpc.rb +0 -70
  200. data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +0 -37
@@ -5,6 +5,8 @@ module RubySMB
5
5
  # This class represents an SMB1 Trans2 FIND_FIRST2 Response Packet as defined in
6
6
  # [2.2.6.2.2 Response](https://msdn.microsoft.com/en-us/library/ee441704.aspx)
7
7
  class FindFirst2Response < RubySMB::GenericPacket
8
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
9
+
8
10
  class ParameterBlock < RubySMB::SMB1::Packet::Trans2::Response::ParameterBlock
9
11
  end
10
12
 
@@ -51,7 +53,6 @@ module RubySMB
51
53
 
52
54
  def initialize_instance
53
55
  super
54
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
55
56
  parameter_block.setup << RubySMB::SMB1::Packet::Trans2::Subcommands::FIND_FIRST2
56
57
  smb_header.flags.reply = 1
57
58
  end
@@ -62,6 +63,7 @@ module RubySMB
62
63
  #
63
64
  # @param klass [Class] the FileInformationClass class to read the data as
64
65
  # @return [array<BinData::Record>] An array of structs holding the requested information
66
+ # @raise [RubySMB::Error::InvalidPacket] if the string buffer is not a valid File Information packet
65
67
  def results(klass, unicode:)
66
68
  information_classes = []
67
69
  blob = data_block.trans2_data.buffer.to_binary_s.dup
@@ -76,7 +78,11 @@ module RubySMB
76
78
 
77
79
  file_info = klass.new
78
80
  file_info.unicode = unicode
79
- information_classes << file_info.read(data)
81
+ begin
82
+ information_classes << file_info.read(data)
83
+ rescue IOError
84
+ raise RubySMB::Error::InvalidPacket, "Invalid #{klass} File Information packet in the string buffer"
85
+ end
80
86
  end
81
87
  information_classes
82
88
  end
@@ -5,6 +5,8 @@ module RubySMB
5
5
  # A Trans2 FIND_NEXT2 Request Packet as defined in
6
6
  # [2.2.6.3.1 Request](https://msdn.microsoft.com/en-us/library/ee441844.aspx)
7
7
  class FindNext2Request < RubySMB::GenericPacket
8
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
9
+
8
10
  class ParameterBlock < RubySMB::SMB1::Packet::Trans2::Request::ParameterBlock
9
11
  end
10
12
 
@@ -67,7 +69,6 @@ module RubySMB
67
69
 
68
70
  def initialize_instance
69
71
  super
70
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
71
72
  parameter_block.setup << RubySMB::SMB1::Packet::Trans2::Subcommands::FIND_NEXT2
72
73
  end
73
74
  end
@@ -5,6 +5,8 @@ module RubySMB
5
5
  # This class represents an SMB1 Trans2 FIND_NEXT2 Response Packet as defined in
6
6
  # [2.2.6.3.2 Response](https://msdn.microsoft.com/en-us/library/ee441871.aspx)
7
7
  class FindNext2Response < RubySMB::GenericPacket
8
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
9
+
8
10
  class ParameterBlock < RubySMB::SMB1::Packet::Trans2::Response::ParameterBlock
9
11
  end
10
12
 
@@ -50,7 +52,6 @@ module RubySMB
50
52
 
51
53
  def initialize_instance
52
54
  super
53
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
54
55
  parameter_block.setup << RubySMB::SMB1::Packet::Trans2::Subcommands::FIND_NEXT2
55
56
  smb_header.flags.reply = 1
56
57
  end
@@ -61,6 +62,7 @@ module RubySMB
61
62
  #
62
63
  # @param klass [Class] the FileInformationClass class to read the data as
63
64
  # @return [array<BinData::Record>] An array of structs holding the requested information
65
+ # @raise [RubySMB::Error::InvalidPacket] if the string buffer is not a valid File Information packet
64
66
  def results(klass, unicode:)
65
67
  information_classes = []
66
68
  blob = data_block.trans2_data.buffer.to_binary_s.dup
@@ -75,7 +77,11 @@ module RubySMB
75
77
 
76
78
  file_info = klass.new
77
79
  file_info.unicode = unicode
78
- information_classes << file_info.read(data)
80
+ begin
81
+ information_classes << file_info.read(data)
82
+ rescue IOError
83
+ raise RubySMB::Error::InvalidPacket, "Invalid #{klass} File Information packet in the string buffer"
84
+ end
79
85
  end
80
86
  information_classes
81
87
  end
@@ -5,6 +5,8 @@ module RubySMB
5
5
  # A Trans2 OPEN2 Request Packet as defined in
6
6
  # [2.2.6.1.1 Request](https://msdn.microsoft.com/en-us/library/ee441733.aspx)
7
7
  class Open2Request < RubySMB::GenericPacket
8
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
9
+
8
10
  class ParameterBlock < RubySMB::SMB1::Packet::Trans2::Request::ParameterBlock
9
11
  end
10
12
 
@@ -50,7 +52,6 @@ module RubySMB
50
52
 
51
53
  def initialize_instance
52
54
  super
53
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
54
55
  parameter_block.setup << RubySMB::SMB1::Packet::Trans2::Subcommands::OPEN2
55
56
  end
56
57
  end
@@ -5,6 +5,8 @@ module RubySMB
5
5
  # This class represents an SMB1 Trans2 Open2 Response Packet as defined in
6
6
  # [2.2.6.1.2 Response](https://msdn.microsoft.com/en-us/library/ee441545.aspx)
7
7
  class Open2Response < RubySMB::GenericPacket
8
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
9
+
8
10
  class ParameterBlock < RubySMB::SMB1::Packet::Trans2::Response::ParameterBlock
9
11
  end
10
12
 
@@ -52,7 +54,6 @@ module RubySMB
52
54
 
53
55
  def initialize_instance
54
56
  super
55
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
56
57
  parameter_block.setup << RubySMB::SMB1::Packet::Trans2::Subcommands::OPEN2
57
58
  smb_header.flags.reply = 1
58
59
  end
@@ -5,6 +5,8 @@ module RubySMB
5
5
  # This class represents a generic SMB1 Trans2 Request Packet as defined in
6
6
  # [2.2.4.46.1 Request](https://msdn.microsoft.com/en-us/library/ee442192.aspx)
7
7
  class Request < RubySMB::GenericPacket
8
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
9
+
8
10
  # The {RubySMB::SMB1::ParameterBlock} specific to this packet type.
9
11
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
10
12
  uint16 :total_parameter_count, label: 'Total Parameter Count(bytes)'
@@ -39,10 +41,6 @@ module RubySMB
39
41
  parameter_block :parameter_block
40
42
  data_block :data_block
41
43
 
42
- def initialize_instance
43
- super
44
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
45
- end
46
44
  end
47
45
  end
48
46
  end
@@ -5,6 +5,8 @@ module RubySMB
5
5
  # This class represents a generic SMB1 Trans2 Secondary Request Packet as defined in
6
6
  # [2.2.4.47.1 Request](https://msdn.microsoft.com/en-us/library/ee442105.aspx)
7
7
  class RequestSecondary < RubySMB::GenericPacket
8
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2_SECONDARY
9
+
8
10
  # The {RubySMB::SMB1::ParameterBlock} specific to this packet type.
9
11
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
10
12
  uint16 :total_parameter_count, label: 'Total Parameter Count(bytes)'
@@ -26,10 +28,6 @@ module RubySMB
26
28
  parameter_block :parameter_block
27
29
  data_block :data_block
28
30
 
29
- def initialize_instance
30
- super
31
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2_SECONDARY
32
- end
33
31
  end
34
32
  end
35
33
  end
@@ -5,6 +5,8 @@ module RubySMB
5
5
  # This class represents a generic SMB1 Trans2 Response Packet as defined in
6
6
  # [2.2.4.46.2 Response](https://msdn.microsoft.com/en-us/library/ee441550.aspx)
7
7
  class Response < RubySMB::GenericPacket
8
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
9
+
8
10
  # The {RubySMB::SMB1::ParameterBlock} specific to this packet type.
9
11
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
10
12
  uint16 :total_parameter_count, label: 'Total Parameter Count(bytes)'
@@ -36,7 +38,6 @@ module RubySMB
36
38
 
37
39
  def initialize_instance
38
40
  super
39
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
40
41
  smb_header.flags.reply = 1
41
42
  end
42
43
  end
@@ -5,6 +5,8 @@ module RubySMB
5
5
  # A Trans2 SET_FILE_INFORMATION Request Packet as defined in
6
6
  # [2.2.6.9.1 Request](https://msdn.microsoft.com/en-us/library/ee441527.aspx)
7
7
  class SetFileInformationRequest < RubySMB::GenericPacket
8
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
9
+
8
10
  class ParameterBlock < RubySMB::SMB1::Packet::Trans2::Request::ParameterBlock
9
11
  end
10
12
 
@@ -56,7 +58,6 @@ module RubySMB
56
58
 
57
59
  def initialize_instance
58
60
  super
59
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
60
61
  parameter_block.setup << RubySMB::SMB1::Packet::Trans2::Subcommands::SET_FILE_INFORMATION
61
62
  end
62
63
  end
@@ -5,6 +5,8 @@ module RubySMB
5
5
  # A Trans2 SET_FILE_INFORMATION Response Packet as defined in
6
6
  # [2.2.6.9.2 Response](https://msdn.microsoft.com/en-us/library/ff469853.aspx)
7
7
  class SetFileInformationResponse < RubySMB::GenericPacket
8
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
9
+
8
10
  class ParameterBlock < RubySMB::SMB1::Packet::Trans2::Response::ParameterBlock
9
11
  end
10
12
 
@@ -46,7 +48,6 @@ module RubySMB
46
48
 
47
49
  def initialize_instance
48
50
  super
49
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2
50
51
  parameter_block.setup << RubySMB::SMB1::Packet::Trans2::Subcommands::SET_FILE_INFORMATION
51
52
  smb_header.flags.reply = 1
52
53
  end
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # This class represents an SMB1 TreeConnect Request Packet as defined in
5
5
  # [2.2.4.7.1 Client Request Extensions](https://msdn.microsoft.com/en-us/library/cc246330.aspx)
6
6
  class TreeConnectRequest < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
8
+
7
9
  # A SMB1 Parameter Block as defined by the {TreeConnectRequest}
8
10
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
9
11
  and_x_block :andx_block
@@ -22,10 +24,6 @@ module RubySMB
22
24
  parameter_block :parameter_block
23
25
  data_block :data_block
24
26
 
25
- def initialize_instance
26
- super
27
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
28
- end
29
27
  end
30
28
  end
31
29
  end
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # A SMB1 TreeConnect Response Packet as defined in
5
5
  # [2.2.4.7.2 Server Response Extensions](https://msdn.microsoft.com/en-us/library/cc246331.aspx)
6
6
  class TreeConnectResponse < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
8
+
7
9
  # A SMB1 Parameter Block as defined by the {SessionSetupResponse}
8
10
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
9
11
  and_x_block :andx_block
@@ -24,7 +26,6 @@ module RubySMB
24
26
 
25
27
  def initialize_instance
26
28
  super
27
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
28
29
  smb_header.flags.reply = 1
29
30
  end
30
31
 
@@ -34,12 +35,17 @@ module RubySMB
34
35
  #
35
36
  # @return [RubySMB::SMB1::BitField::DirectoryAccessMask] if a directory was connected to
36
37
  # @return [RubySMB::SMB1::BitField::FileAccessMask] if anything else was connected to
38
+ # @raise [RubySMB::Error::InvalidBitField] if ACCESS_MASK bit field is not valid
37
39
  def access_rights
38
40
  if is_directory?
39
41
  parameter_block.access_rights
40
42
  else
41
43
  mask = parameter_block.access_rights.to_binary_s
42
- RubySMB::SMB1::BitField::FileAccessMask.read(mask)
44
+ begin
45
+ RubySMB::SMB1::BitField::FileAccessMask.read(mask)
46
+ rescue IOError
47
+ raise RubySMB::Error::InvalidBitField, 'Invalid ACCESS_MASK for the Maximal Share Access Rights'
48
+ end
43
49
  end
44
50
  end
45
51
 
@@ -54,7 +60,11 @@ module RubySMB
54
60
  parameter_block.guest_access_rights
55
61
  else
56
62
  mask = parameter_block.guest_access_rights.to_binary_s
57
- RubySMB::SMB1::BitField::FileAccessMask.read(mask)
63
+ begin
64
+ RubySMB::SMB1::BitField::FileAccessMask.read(mask)
65
+ rescue IOError
66
+ raise RubySMB::Error::InvalidBitField, 'Invalid ACCESS_MASK for the Guest Share Access Rights'
67
+ end
58
68
  end
59
69
  end
60
70
 
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # This class represents an SMB1 TreeDisonnect Request Packet as defined in
5
5
  # [2.2.4.51.1 Request](https://msdn.microsoft.com/en-us/library/ee441622.aspx)
6
6
  class TreeDisconnectRequest < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TREE_DISCONNECT
8
+
7
9
  # The Parameter Block for this packet is empty save the Word Count
8
10
  # The {RubySMB::SMB1::ParameterBlock} specific to this packet type.
9
11
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
@@ -17,10 +19,6 @@ module RubySMB
17
19
  parameter_block :parameter_block
18
20
  data_block :data_block
19
21
 
20
- def initialize_instance
21
- super
22
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_DISCONNECT
23
- end
24
22
  end
25
23
  end
26
24
  end
@@ -4,6 +4,8 @@ module RubySMB
4
4
  # This class represents an SMB1 TreeDisonnect Response Packet as defined in
5
5
  # [2.2.4.51.2 Response](https://msdn.microsoft.com/en-us/library/ee441823.aspx)
6
6
  class TreeDisconnectResponse < RubySMB::GenericPacket
7
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_TREE_DISCONNECT
8
+
7
9
  # The Parameter Block for this packet is empty save the Word Count
8
10
  # The {RubySMB::SMB1::ParameterBlock} specific to this packet type.
9
11
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
@@ -19,7 +21,6 @@ module RubySMB
19
21
 
20
22
  def initialize_instance
21
23
  super
22
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_DISCONNECT
23
24
  smb_header.flags.reply = 1
24
25
  end
25
26
  end
@@ -5,6 +5,8 @@ module RubySMB
5
5
  # [2.2.4.43.1 Request](https://msdn.microsoft.com/en-us/library/ee441954.aspx)
6
6
  # [2.2.4.3.1 Client Request Extensions](https://msdn.microsoft.com/en-us/library/ff469893.aspx)
7
7
  class WriteAndxRequest < RubySMB::GenericPacket
8
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_WRITE_ANDX
9
+
8
10
  # A SMB1 Parameter Block as defined by the {WriteAndxRequest}
9
11
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
10
12
  endian :little
@@ -41,7 +43,7 @@ module RubySMB
41
43
 
42
44
  # Represents the specific layout of the DataBlock for a {WriteAndxRequest} Packet.
43
45
  class DataBlock < RubySMB::SMB1::DataBlock
44
- uint8 :pad, label: 'Pad'
46
+ string :pad, label: 'Pad', length: 1
45
47
  string :data, label: 'Data'
46
48
  end
47
49
 
@@ -49,11 +51,6 @@ module RubySMB
49
51
  parameter_block :parameter_block
50
52
  data_block :data_block
51
53
 
52
- def initialize_instance
53
- super
54
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_WRITE_ANDX
55
- end
56
-
57
54
  # Specifies whether the offset is a 32-bit (default) or 64-bit value. When `is_64_bit`
58
55
  # is true, a 64-bit offset will be used and the OffsetHigh field will be added to the structure.
59
56
  #
@@ -5,6 +5,8 @@ module RubySMB
5
5
  # [2.2.4.43.2 Response](https://msdn.microsoft.com/en-us/library/ee441673.aspx)
6
6
  # [2.2.4.3.2 Server Response Extensions](https://msdn.microsoft.com/en-us/library/ff469858.aspx)
7
7
  class WriteAndxResponse < RubySMB::GenericPacket
8
+ COMMAND = RubySMB::SMB1::Commands::SMB_COM_WRITE_ANDX
9
+
8
10
  # A SMB1 Parameter Block as defined by the {WriteAndxResponse}
9
11
  class ParameterBlock < RubySMB::SMB1::ParameterBlock
10
12
  endian :little
@@ -26,7 +28,6 @@ module RubySMB
26
28
 
27
29
  def initialize_instance
28
30
  super
29
- smb_header.command = RubySMB::SMB1::Commands::SMB_COM_WRITE_ANDX
30
31
  smb_header.flags.reply = 1
31
32
  end
32
33
  end
@@ -3,9 +3,9 @@ module RubySMB
3
3
  # Represents a pipe on the Remote server that we can perform
4
4
  # various I/O operations on.
5
5
  class Pipe < File
6
- require 'ruby_smb/smb1/dcerpc'
6
+ require 'ruby_smb/dcerpc'
7
7
 
8
- include RubySMB::SMB1::Dcerpc
8
+ include RubySMB::Dcerpc
9
9
 
10
10
  # Reference: https://msdn.microsoft.com/en-us/library/ee441883.aspx
11
11
  STATUS_DISCONNECTED = 0x0001
@@ -13,6 +13,17 @@ module RubySMB
13
13
  STATUS_OK = 0x0003
14
14
  STATUS_CLOSED = 0x0004
15
15
 
16
+ def initialize(tree:, response:, name:)
17
+ raise ArgumentError, 'No Name Provided' if name.nil?
18
+ case name
19
+ when 'srvsvc'
20
+ extend RubySMB::Dcerpc::Srvsvc
21
+ when 'winreg'
22
+ extend RubySMB::Dcerpc::Winreg
23
+ end
24
+ super(tree: tree, response: response, name: name)
25
+ end
26
+
16
27
  # Performs a peek operation on the named pipe
17
28
  #
18
29
  # @param peek_size [Integer] Amount of data to peek
@@ -26,14 +37,19 @@ module RubySMB
26
37
  packet = @tree.set_header_fields(packet)
27
38
  raw_response = @tree.client.send_recv(packet)
28
39
  response = RubySMB::SMB1::Packet::Trans::PeekNmpipeResponse.read(raw_response)
40
+ unless response.valid?
41
+ raise RubySMB::Error::InvalidPacket.new(
42
+ expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
43
+ expected_cmd: RubySMB::SMB1::Packet::Trans::PeekNmpipeRequest::COMMAND,
44
+ received_proto: response.smb_header.protocol,
45
+ received_cmd: response.smb_header.command
46
+ )
47
+ end
29
48
 
30
49
  unless response.status_code == WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW or response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
31
- raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
50
+ raise RubySMB::Error::UnexpectedStatusCode, response.status_code
32
51
  end
33
52
 
34
- unless response.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_TRANSACTION
35
- raise RubySMB::Error::InvalidPacket, 'Not a TransResponse packet'
36
- end
37
53
  response
38
54
  end
39
55
 
@@ -63,6 +79,71 @@ module RubySMB
63
79
  state == STATUS_OK
64
80
  end
65
81
 
82
+ # Send a DCERPC request with the provided stub packet.
83
+ #
84
+ # @params stub_packet [#opnum] the stub packet to add to the DCERPC request
85
+ # @return [String] the raw DCERPC response stub
86
+ # @raise [RubySMB::Error::InvalidPacket] if the response is not valid
87
+ # @raise [RubySMB::Error::UnexpectedStatusCode] if the response status code is different than STATUS_SUCCESS or STATUS_BUFFER_OVERFLOW
88
+ def dcerpc_request(stub_packet, options={})
89
+ options.merge!(endpoint: stub_packet.class.name.split('::').at(-2))
90
+ dcerpc_request = RubySMB::Dcerpc::Request.new({ opnum: stub_packet.opnum }, options)
91
+ dcerpc_request.stub.read(stub_packet.to_binary_s)
92
+ trans_nmpipe_request = RubySMB::SMB1::Packet::Trans::TransactNmpipeRequest.new(options)
93
+ @tree.set_header_fields(trans_nmpipe_request)
94
+ trans_nmpipe_request.set_fid(@fid)
95
+ trans_nmpipe_request.data_block.trans_data.write_data = dcerpc_request.to_binary_s
96
+
97
+ trans_nmpipe_raw_response = @tree.client.send_recv(trans_nmpipe_request)
98
+ trans_nmpipe_response = RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse.read(trans_nmpipe_raw_response)
99
+ unless trans_nmpipe_response.valid?
100
+ raise RubySMB::Error::InvalidPacket.new(
101
+ expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
102
+ expected_cmd: RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse::COMMAND,
103
+ received_proto: trans_nmpipe_response.smb_header.protocol,
104
+ received_cmd: trans_nmpipe_response.smb_header.command
105
+ )
106
+ end
107
+ unless [WindowsError::NTStatus::STATUS_SUCCESS,
108
+ WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW].include?(trans_nmpipe_response.status_code)
109
+ raise RubySMB::Error::UnexpectedStatusCode, trans_nmpipe_response.status_code
110
+ end
111
+
112
+ raw_data = trans_nmpipe_response.data_block.trans_data.read_data.to_binary_s
113
+ if trans_nmpipe_response.status_code == WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW
114
+ raw_data << read(bytes: @tree.client.max_buffer_size - trans_nmpipe_response.parameter_block.data_count)
115
+ dcerpc_response = dcerpc_response_from_raw_response(raw_data)
116
+ unless dcerpc_response.pdu_header.pfc_flags.first_frag == 1
117
+ raise RubySMB::Dcerpc::Error::InvalidPacket, "Not the first fragment"
118
+ end
119
+ stub_data = dcerpc_response.stub.to_s
120
+
121
+ loop do
122
+ break if dcerpc_response.pdu_header.pfc_flags.last_frag == 1
123
+ raw_data = read(bytes: @tree.client.max_buffer_size)
124
+ dcerpc_response = dcerpc_response_from_raw_response(raw_data)
125
+ stub_data << dcerpc_response.stub.to_s
126
+ end
127
+ stub_data
128
+ else
129
+ dcerpc_response = dcerpc_response_from_raw_response(raw_data)
130
+ dcerpc_response.stub.to_s
131
+ end
132
+ end
133
+
134
+
135
+ private
136
+
137
+ def dcerpc_response_from_raw_response(raw_data)
138
+ dcerpc_response = RubySMB::Dcerpc::Response.read(raw_data)
139
+ unless dcerpc_response.pdu_header.ptype == RubySMB::Dcerpc::PTypes::RESPONSE
140
+ raise RubySMB::Dcerpc::Error::InvalidPacket, "Not a Response packet"
141
+ end
142
+ dcerpc_response
143
+ rescue IOError
144
+ raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the DCERPC response"
145
+ end
146
+
66
147
  end
67
148
  end
68
149
  end