ruby_smb 1.0.5 → 2.0.3

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 (191) 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/anonymous_auth.rb +3 -3
  8. data/examples/append_file.rb +10 -8
  9. data/examples/authenticate.rb +9 -5
  10. data/examples/delete_file.rb +8 -6
  11. data/examples/enum_registry_key.rb +29 -0
  12. data/examples/enum_registry_values.rb +31 -0
  13. data/examples/list_directory.rb +8 -6
  14. data/examples/negotiate.rb +51 -8
  15. data/examples/negotiate_with_netbios_service.rb +9 -5
  16. data/examples/net_share_enum_all.rb +6 -4
  17. data/examples/pipes.rb +13 -13
  18. data/examples/query_service_status.rb +64 -0
  19. data/examples/read_file.rb +8 -6
  20. data/examples/read_file_encryption.rb +56 -0
  21. data/examples/read_registry_key_value.rb +33 -0
  22. data/examples/rename_file.rb +9 -7
  23. data/examples/tree_connect.rb +7 -5
  24. data/examples/write_file.rb +9 -7
  25. data/lib/ruby_smb.rb +4 -1
  26. data/lib/ruby_smb/client.rb +239 -21
  27. data/lib/ruby_smb/client/authentication.rb +27 -8
  28. data/lib/ruby_smb/client/encryption.rb +62 -0
  29. data/lib/ruby_smb/client/negotiation.rb +154 -12
  30. data/lib/ruby_smb/client/signing.rb +19 -0
  31. data/lib/ruby_smb/client/tree_connect.rb +4 -4
  32. data/lib/ruby_smb/client/utils.rb +8 -7
  33. data/lib/ruby_smb/client/winreg.rb +46 -0
  34. data/lib/ruby_smb/crypto.rb +30 -0
  35. data/lib/ruby_smb/dcerpc.rb +40 -0
  36. data/lib/ruby_smb/dcerpc/bind.rb +2 -2
  37. data/lib/ruby_smb/dcerpc/bind_ack.rb +2 -2
  38. data/lib/ruby_smb/dcerpc/error.rb +6 -0
  39. data/lib/ruby_smb/dcerpc/ndr.rb +260 -16
  40. data/lib/ruby_smb/dcerpc/pdu_header.rb +1 -1
  41. data/lib/ruby_smb/dcerpc/request.rb +41 -9
  42. data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +34 -0
  43. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +38 -0
  44. data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -0
  45. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +9 -0
  46. data/lib/ruby_smb/dcerpc/svcctl.rb +479 -0
  47. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +48 -0
  48. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +26 -0
  49. data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request.rb +25 -0
  50. data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +26 -0
  51. data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +26 -0
  52. data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +26 -0
  53. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +35 -0
  54. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +23 -0
  55. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +31 -0
  56. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +23 -0
  57. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +25 -0
  58. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +44 -0
  59. data/lib/ruby_smb/dcerpc/svcctl/query_service_status_request.rb +23 -0
  60. data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +27 -0
  61. data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +25 -0
  62. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +27 -0
  63. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +25 -0
  64. data/lib/ruby_smb/dcerpc/winreg.rb +421 -0
  65. data/lib/ruby_smb/dcerpc/winreg/close_key_request.rb +24 -0
  66. data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +27 -0
  67. data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +73 -0
  68. data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +36 -0
  69. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +45 -0
  70. data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +42 -0
  71. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +39 -0
  72. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +36 -0
  73. data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +34 -0
  74. data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +25 -0
  75. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +43 -0
  76. data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +35 -0
  77. data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +27 -0
  78. data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +40 -0
  79. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +40 -0
  80. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +57 -0
  81. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +40 -0
  82. data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +37 -0
  83. data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +23 -0
  84. data/lib/ruby_smb/dispatcher/base.rb +1 -1
  85. data/lib/ruby_smb/dispatcher/socket.rb +5 -4
  86. data/lib/ruby_smb/error.rb +28 -1
  87. data/lib/ruby_smb/field/stringz16.rb +17 -1
  88. data/lib/ruby_smb/nbss/session_header.rb +4 -4
  89. data/lib/ruby_smb/smb1/commands.rb +1 -1
  90. data/lib/ruby_smb/smb1/file.rb +8 -14
  91. data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +1 -1
  92. data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +2 -2
  93. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -1
  94. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +2 -2
  95. data/lib/ruby_smb/smb1/packet/write_andx_request.rb +1 -1
  96. data/lib/ruby_smb/smb1/pipe.rb +81 -3
  97. data/lib/ruby_smb/smb1/tree.rb +12 -3
  98. data/lib/ruby_smb/smb2/bit_field/session_flags.rb +2 -1
  99. data/lib/ruby_smb/smb2/bit_field/share_flags.rb +6 -4
  100. data/lib/ruby_smb/smb2/file.rb +51 -61
  101. data/lib/ruby_smb/smb2/negotiate_context.rb +108 -0
  102. data/lib/ruby_smb/smb2/packet.rb +2 -0
  103. data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +41 -0
  104. data/lib/ruby_smb/smb2/packet/error_packet.rb +2 -4
  105. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +51 -14
  106. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +50 -4
  107. data/lib/ruby_smb/smb2/packet/transform_header.rb +84 -0
  108. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +92 -6
  109. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +8 -26
  110. data/lib/ruby_smb/smb2/pipe.rb +80 -3
  111. data/lib/ruby_smb/smb2/smb2_header.rb +1 -1
  112. data/lib/ruby_smb/smb2/tree.rb +32 -20
  113. data/lib/ruby_smb/version.rb +1 -1
  114. data/ruby_smb.gemspec +5 -3
  115. data/spec/lib/ruby_smb/client_spec.rb +1583 -102
  116. data/spec/lib/ruby_smb/crypto_spec.rb +25 -0
  117. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +2 -2
  118. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +2 -2
  119. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +1729 -0
  120. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +50 -7
  121. data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +161 -0
  122. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +135 -0
  123. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +13 -0
  124. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +60 -0
  125. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +191 -0
  126. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +38 -0
  127. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request_spec.rb +30 -0
  128. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +38 -0
  129. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +39 -0
  130. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +38 -0
  131. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +78 -0
  132. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +38 -0
  133. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +59 -0
  134. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +38 -0
  135. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +38 -0
  136. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +152 -0
  137. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_request_spec.rb +30 -0
  138. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +38 -0
  139. data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +72 -0
  140. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +46 -0
  141. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +30 -0
  142. data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +512 -0
  143. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_request_spec.rb +28 -0
  144. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +36 -0
  145. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +110 -0
  146. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +44 -0
  147. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +104 -0
  148. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +97 -0
  149. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +94 -0
  150. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +82 -0
  151. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +74 -0
  152. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +35 -0
  153. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +95 -0
  154. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +38 -0
  155. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +35 -0
  156. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +113 -0
  157. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +88 -0
  158. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +138 -0
  159. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +32 -0
  160. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +57 -0
  161. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +22 -0
  162. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +884 -0
  163. data/spec/lib/ruby_smb/dcerpc_spec.rb +81 -0
  164. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +12 -12
  165. data/spec/lib/ruby_smb/error_spec.rb +59 -0
  166. data/spec/lib/ruby_smb/field/stringz16_spec.rb +12 -0
  167. data/spec/lib/ruby_smb/nbss/session_header_spec.rb +4 -11
  168. data/spec/lib/ruby_smb/smb1/file_spec.rb +9 -1
  169. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +2 -2
  170. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +2 -2
  171. data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +2 -2
  172. data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +1 -1
  173. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +216 -147
  174. data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +9 -0
  175. data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +27 -0
  176. data/spec/lib/ruby_smb/smb2/file_spec.rb +146 -68
  177. data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +332 -0
  178. data/spec/lib/ruby_smb/smb2/packet/compression_transform_header_spec.rb +108 -0
  179. data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +3 -24
  180. data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +138 -3
  181. data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +120 -2
  182. data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +220 -0
  183. data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +339 -9
  184. data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +3 -30
  185. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +226 -148
  186. data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +2 -2
  187. data/spec/lib/ruby_smb/smb2/tree_spec.rb +88 -9
  188. metadata +257 -81
  189. metadata.gz.sig +0 -0
  190. data/lib/ruby_smb/smb1/dcerpc.rb +0 -72
  191. data/lib/ruby_smb/smb2/dcerpc.rb +0 -75
@@ -0,0 +1,27 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Winreg
4
+
5
+ class RpcHkey < Ndr::NdrContextHandle; end
6
+
7
+ # This class represents a BaseRegQueryInfoKey Request Packet as defined in
8
+ # [3.1.5.16 BaseRegQueryInfoKey (Opnum 16)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/a886ba66-5c7b-4331-bacd-7c77edc95d85)
9
+ class QueryInfoKeyRequest < BinData::Record
10
+ attr_reader :opnum
11
+
12
+ endian :little
13
+
14
+ rpc_hkey :hkey
15
+ rrp_unicode_string :lp_class
16
+
17
+ def initialize_instance
18
+ super
19
+ @opnum = REG_QUERY_INFO_KEY
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+
27
+
@@ -0,0 +1,40 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Winreg
4
+ # This class represents a BaseRegQueryInfoKey Response Packet as defined in
5
+ # [3.1.5.16 BaseRegQueryInfoKey (Opnum 16)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/a886ba66-5c7b-4331-bacd-7c77edc95d85)
6
+ class QueryInfoKeyResponse < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ rrp_unicode_string :lp_class, initial_value: 0
12
+ string :pad, length: -> { pad_length }
13
+ uint32 :lpc_sub_keys
14
+ uint32 :lpc_max_sub_key_len
15
+ uint32 :lpc_max_class_len
16
+ uint32 :lpc_values
17
+ uint32 :lpcb_max_value_name_len
18
+ uint32 :lpcb_max_value_len
19
+ uint32 :lpcb_security_descriptor
20
+ file_time :lpft_last_write_time
21
+ uint32 :error_status
22
+
23
+ def initialize_instance
24
+ super
25
+ @opnum = REG_QUERY_INFO_KEY
26
+ end
27
+
28
+ # Determines the correct length for the padding in front of
29
+ # #lpc_sub_keys. It should always force a 4-byte alignment.
30
+ def pad_length
31
+ offset = (lp_class.abs_offset + lp_class.to_binary_s.length) % 4
32
+ (4 - offset) % 4
33
+ end
34
+ end
35
+
36
+ end
37
+ end
38
+ end
39
+
40
+
@@ -0,0 +1,40 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Winreg
4
+
5
+ class RpcHkey < Ndr::NdrContextHandle; end
6
+
7
+ # This class represents a BaseRegQueryValue Request Packet as defined in
8
+ # [3.1.5.17 BaseRegQueryValue (Opnum 17)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/8bc10aa3-2f91-44e8-aa33-b3263c49ab9d)
9
+ class QueryValueRequest < BinData::Record
10
+ attr_reader :opnum
11
+
12
+ endian :little
13
+
14
+ rpc_hkey :hkey
15
+ rrp_unicode_string :lp_value_name
16
+ string :pad1, length: -> { pad_length(self.lp_value_name) }
17
+ ndr_lp_dword :lp_type
18
+ ndr_lp_byte_array :lp_data
19
+ string :pad2, length: -> { pad_length(self.lp_data) }
20
+ ndr_lp_dword :lpcb_data
21
+ ndr_lp_dword :lpcb_len
22
+
23
+ def initialize_instance
24
+ super
25
+ @opnum = REG_QUERY_VALUE
26
+ end
27
+
28
+ # Determines the correct length for the padding, so that the next
29
+ # field is 4-byte aligned.
30
+ def pad_length(prev_element)
31
+ offset = (prev_element.abs_offset + prev_element.to_binary_s.length) % 4
32
+ (4 - offset) % 4
33
+ end
34
+ end
35
+
36
+ end
37
+ end
38
+ end
39
+
40
+
@@ -0,0 +1,57 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Winreg
4
+
5
+ # This class represents a BaseRegQueryValue Response Packet as defined in
6
+ # [3.1.5.17 BaseRegQueryValue (Opnum 17)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/8bc10aa3-2f91-44e8-aa33-b3263c49ab9d)
7
+ class QueryValueResponse < BinData::Record
8
+ attr_reader :opnum
9
+
10
+ endian :little
11
+
12
+ ndr_lp_dword :lp_type
13
+ ndr_lp_byte_array :lp_data
14
+ string :pad, length: -> { pad_length(self.lp_data) }
15
+ ndr_lp_dword :lpcb_data
16
+ ndr_lp_dword :lpcb_len
17
+ uint32 :error_status
18
+
19
+ def initialize_instance
20
+ super
21
+ @opnum = REG_QUERY_VALUE
22
+ end
23
+
24
+ # Determines the correct length for the padding, so that the next
25
+ # field is 4-byte aligned.
26
+ def pad_length(prev_element)
27
+ offset = (prev_element.abs_offset + prev_element.to_binary_s.length) % 4
28
+ (4 - offset) % 4
29
+ end
30
+
31
+ # Returns the data portion of the registry value formatted according to its type:
32
+ # [3.1.1.5 Values](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/3d64dbea-f016-4373-8cac-e43bf343837d)
33
+ def data
34
+ bytes = lp_data.bytes.to_a.pack('C*')
35
+ case lp_type
36
+ when 1,2
37
+ bytes.force_encoding('utf-16le').strip
38
+ when 3
39
+ bytes
40
+ when 4
41
+ bytes.unpack('V').first
42
+ when 5
43
+ bytes.unpack('N').first
44
+ when 7
45
+ str = bytes.force_encoding('utf-16le')
46
+ str.split("\0".encode('utf-16le'))
47
+ when 11
48
+ bytes.unpack('Q<').first
49
+ else
50
+ ""
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,40 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Winreg
4
+
5
+ # This class represents a REGSAM structure as defined in
6
+ # [2.2.3 REGSAM](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/fefbc801-b141-4bb1-9dcb-bf366da3ae7e)
7
+ # [2.4.3 ACCESS_MASK](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/7a53f60e-e730-4dfe-bbe9-b21b62eb790b)
8
+ class Regsam < BinData::Record
9
+ endian :little
10
+ bit2 :reserved, label: 'Reserved Space'
11
+ bit1 :key_create_link, label: 'Key Create Link'
12
+ bit1 :key_notify, label: 'Key Notify'
13
+ bit1 :key_enumerate_sub_keys, label: 'Key Enumerate Sub Keys'
14
+ bit1 :key_create_sub_key, label: 'Key Create Sub Key'
15
+ bit1 :key_set_value, label: 'Key Set Value'
16
+ bit1 :key_query_value, label: 'Key Query Value'
17
+ # byte boundary
18
+ bit6 :reserved2, label: 'Reserved Space'
19
+ bit1 :key_wow64_32key, label: 'Key Wow64 32key'
20
+ bit1 :key_wow64_64key, label: 'Key Wow64 64key'
21
+ # byte boundary
22
+ bit3 :reserved3, label: 'Reserved Space'
23
+ bit1 :synchronize, label: 'Synchronize'
24
+ bit1 :write_owner, label: 'Write Owner'
25
+ bit1 :write_dac, label: 'Write DAC'
26
+ bit1 :read_control, label: 'Read Control'
27
+ bit1 :delete_access, label: 'Delete'
28
+ # byte boundary
29
+ bit1 :generic_read, label: 'Generic Read'
30
+ bit1 :generic_write, label: 'Generic Write'
31
+ bit1 :generic_execute, label: 'Generic Execute'
32
+ bit1 :generic_all, label: 'Generic All'
33
+ bit2 :reserved4, label: 'Reserved Space'
34
+ bit1 :maximum, label: 'Maximum Allowed'
35
+ bit1 :system_security, label: 'System Security'
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,37 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Winreg
4
+
5
+ class RpcHkey < Ndr::NdrContextHandle; end
6
+
7
+ # This class represents a BaseRegSaveKey Request Packet as defined in
8
+ # [3.1.5.20 BaseRegSaveKey (Opnum 20)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/f022247d-6ef1-4f46-b195-7f60654f4a0d)
9
+ class SaveKeyRequest < BinData::Record
10
+ attr_reader :opnum
11
+
12
+ endian :little
13
+
14
+ rpc_hkey :hkey
15
+ rrp_unicode_string :lp_file
16
+ string :pad, length: -> { pad_length(self.lp_file) }
17
+ prpc_security_attributes :lp_security_attributes
18
+
19
+ def initialize_instance
20
+ super
21
+ @opnum = REG_SAVE_KEY
22
+ end
23
+
24
+ # Determines the correct length for the padding, so that the next
25
+ # field is 4-byte aligned.
26
+ def pad_length(prev_element)
27
+ offset = (prev_element.abs_offset + prev_element.to_binary_s.length) % 4
28
+ (4 - offset) % 4
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+
36
+
37
+
@@ -0,0 +1,23 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Winreg
4
+
5
+ # This class represents a BaseRegSaveKey Response Packet as defined in
6
+ # [3.1.5.20 BaseRegSaveKey (Opnum 20)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/f022247d-6ef1-4f46-b195-7f60654f4a0d)
7
+ class SaveKeyResponse < BinData::Record
8
+ attr_reader :opnum
9
+
10
+ endian :little
11
+
12
+ uint32 :error_status
13
+
14
+ def initialize_instance
15
+ super
16
+ @opnum = REG_CREATE_KEY
17
+ end
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+
@@ -9,7 +9,7 @@ module RubySMB
9
9
  def nbss(packet)
10
10
  nbss = RubySMB::Nbss::SessionHeader.new
11
11
  nbss.session_packet_type = RubySMB::Nbss::SESSION_MESSAGE
12
- nbss.packet_length = packet.do_num_bytes
12
+ nbss.stream_protocol_length = packet.do_num_bytes
13
13
  nbss.to_binary_s
14
14
  end
15
15
 
@@ -48,7 +48,7 @@ module RubySMB
48
48
  end
49
49
 
50
50
  rescue IOError, Errno::ECONNABORTED, Errno::ECONNRESET => e
51
- raise RubySMB::Error::CommunicationError, "An error occured writing to the Socket: #{e.message}"
51
+ raise RubySMB::Error::CommunicationError, "An error occurred writing to the Socket: #{e.message}"
52
52
  end
53
53
  nil
54
54
  end
@@ -61,19 +61,20 @@ module RubySMB
61
61
  # which are assumed to be the NetBiosSessionService header.
62
62
  # @raise [RubySMB::Error::CommunicationError] if the read timeout expires or an error occurs when reading the socket
63
63
  def recv_packet(full_response: false)
64
+ raise RubySMB::Error::CommunicationError, 'Connection has already been closed' if @tcp_socket.closed?
64
65
  if IO.select([@tcp_socket], nil, nil, @read_timeout).nil?
65
66
  raise RubySMB::Error::CommunicationError, "Read timeout expired when reading from the Socket (timeout=#{@read_timeout})"
66
67
  end
67
68
 
68
69
  begin
69
70
  nbss_data = @tcp_socket.read(4)
70
- raise IOError if nbss_data.nil?
71
+ raise RubySMB::Error::CommunicationError, 'Socket read returned nil' if nbss_data.nil?
71
72
  nbss_header = RubySMB::Nbss::SessionHeader.read(nbss_data)
72
73
  rescue IOError
73
74
  raise ::RubySMB::Error::NetBiosSessionService, 'NBSS Header is missing'
74
75
  end
75
76
 
76
- length = nbss_header.packet_length
77
+ length = nbss_header.stream_protocol_length
77
78
  data = full_response ? nbss_header.to_binary_s : ''
78
79
  if length > 0
79
80
  if IO.select([@tcp_socket], nil, nil, @read_timeout).nil?
@@ -84,7 +85,7 @@ module RubySMB
84
85
  end
85
86
  data
86
87
  rescue Errno::EINVAL, Errno::ECONNABORTED, Errno::ECONNRESET, TypeError, NoMethodError => e
87
- raise RubySMB::Error::CommunicationError, "An error occured reading from the Socket #{e.message}"
88
+ raise RubySMB::Error::CommunicationError, "An error occurred reading from the Socket #{e.message}"
88
89
  end
89
90
  end
90
91
  end
@@ -53,7 +53,28 @@ module RubySMB
53
53
  end
54
54
 
55
55
  # Raised when a response packet has a NTStatus code that was unexpected.
56
- class UnexpectedStatusCode < RubySMBError; end
56
+ class UnexpectedStatusCode < RubySMBError
57
+ attr_reader :status_code
58
+
59
+ def initialize(status_code)
60
+ case status_code
61
+ when WindowsError::ErrorCode
62
+ @status_code = status_code
63
+ when Integer
64
+ @status_code = WindowsError::NTStatus.find_by_retval(status_code).first
65
+ if @status_code.nil?
66
+ @status_code = WindowsError::ErrorCode.new("0x#{status_code.to_s(16)}", status_code, "Unknown 0x#{status_code.to_s(16)}")
67
+ end
68
+ else
69
+ raise ArgumentError, "Status code must be a WindowsError::ErrorCode or an Integer, got #{status_code.class}"
70
+ end
71
+ super
72
+ end
73
+
74
+ def to_s
75
+ "The server responded with an unexpected status code: #{status_code.name}"
76
+ end
77
+ end
57
78
 
58
79
  # Raised when an error occurs with the underlying socket.
59
80
  class CommunicationError < RubySMBError; end
@@ -65,5 +86,11 @@ module RubySMB
65
86
  # Raised when trying to parse raw binary into a BitField and the data
66
87
  # is invalid.
67
88
  class InvalidBitField < RubySMBError; end
89
+
90
+ # Raised when an encryption operation fails
91
+ class EncryptionError < RubySMBError; end
92
+
93
+ # Raised when an signing operation fails
94
+ class SigningError < RubySMBError; end
68
95
  end
69
96
  end
@@ -25,12 +25,17 @@ module RubySMB
25
25
  # @see BinData::Stringz
26
26
  def read_and_return_value(io)
27
27
  max_length = eval_parameter(:max_length)
28
+ if max_length && max_length % 2 != 0
29
+ raise ArgumentError, "[Stringz16] #max_length should be a multiple of "\
30
+ "two, since it is Unicode (got #{max_length})"
31
+ end
28
32
  str = ''
29
33
  i = 0
30
34
  ch = nil
31
35
 
32
36
  # read until double NULL-byte or we have read in the max number of bytes
33
- while (ch != "\0\0") && (i != max_length)
37
+ loop do
38
+ break if ch == "\0\0" || (max_length && i == max_length)
34
39
  ch = io.readbytes(2)
35
40
  str << ch
36
41
  i += 2
@@ -46,6 +51,17 @@ module RubySMB
46
51
  def truncate_after_first_zero_byte!(str)
47
52
  str.sub!(/([^\0]*\0\0\0).*/, '\1')
48
53
  end
54
+
55
+ def trim_to!(str, max_length = nil)
56
+ if max_length
57
+ max_length = 2 if max_length < 2
58
+ str.slice!(max_length..-1)
59
+ if str.length == max_length && str[-2, 2] != "\0\0"
60
+ str[-2, 2] = "\0\0"
61
+ end
62
+ end
63
+ end
64
+
49
65
  end
50
66
  end
51
67
  end
@@ -1,13 +1,13 @@
1
1
  module RubySMB
2
2
  module Nbss
3
3
  # Representation of the NetBIOS Session Service Header as defined in
4
- # [4.3.1 GENERAL FORMAT OF SESSION PACKETS](https://tools.ietf.org/html/rfc1002)
4
+ # SMB: [2.1 Transport](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb/f906c680-330c-43ae-9a71-f854e24aeee6)
5
+ # SMB2: [2.1 Transport](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/1dfacde4-b5c7-4494-8a14-a09d3ab4cc83)
5
6
  class SessionHeader < BinData::Record
6
7
  endian :big
7
8
 
8
- uint8 :session_packet_type, label: 'Session Packet Type'
9
- bit7 :flags, label: 'Flags', initial_value: 0
10
- bit17 :packet_length, label: 'Packet Length'
9
+ uint8 :session_packet_type, label: 'Session Packet Type', initial_value: 0
10
+ uint24 :stream_protocol_length, label: 'Stream Protocol Length'
11
11
  end
12
12
  end
13
13
  end
@@ -10,7 +10,7 @@ module RubySMB
10
10
  SMB_COM_TRANSACTION2_SECONDARY = 0x33
11
11
  SMB_COM_TREE_DISCONNECT = 0x71
12
12
  SMB_COM_NEGOTIATE = 0x72
13
- SMB_COM_SESSION_SETUP = 0x73
13
+ SMB_COM_SESSION_SETUP_ANDX = 0x73
14
14
  SMB_COM_LOGOFF = 0x74
15
15
  SMB_COM_TREE_CONNECT = 0x75
16
16
  SMB_COM_NT_TRANSACT = 0xA0
@@ -91,7 +91,7 @@ module RubySMB
91
91
  )
92
92
  end
93
93
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
94
- raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
94
+ raise RubySMB::Error::UnexpectedStatusCode, response.status_code
95
95
  end
96
96
  response.status_code
97
97
  end
@@ -106,11 +106,7 @@ module RubySMB
106
106
  # @raise [RubySMB::Error::InvalidPacket] if the response packet is not valid
107
107
  # @raise [RubySMB::Error::UnexpectedStatusCode] if the response NTStatus is not STATUS_SUCCESS
108
108
  def read(bytes: @size, offset: 0)
109
- atomic_read_size = if bytes > @tree.client.max_buffer_size
110
- @tree.client.max_buffer_size
111
- else
112
- bytes
113
- end
109
+ atomic_read_size = [bytes, @tree.client.max_buffer_size].min
114
110
  remaining_bytes = bytes
115
111
  data = ''
116
112
 
@@ -127,7 +123,7 @@ module RubySMB
127
123
  )
128
124
  end
129
125
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
130
- raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
126
+ raise RubySMB::Error::UnexpectedStatusCode, response.status_code
131
127
  end
132
128
 
133
129
  if response.is_a?(RubySMB::SMB1::Packet::ReadAndxResponse)
@@ -156,6 +152,8 @@ module RubySMB
156
152
  def read_packet(read_length: 0, offset: 0)
157
153
  read_request = set_header_fields(RubySMB::SMB1::Packet::ReadAndxRequest.new)
158
154
  read_request.parameter_block.max_count_of_bytes_to_return = read_length
155
+ read_request.parameter_block.min_count_of_bytes_to_return = read_length
156
+ read_request.parameter_block.remaining = read_length
159
157
  read_request.parameter_block.offset = offset
160
158
  read_request
161
159
  end
@@ -174,7 +172,7 @@ module RubySMB
174
172
  )
175
173
  end
176
174
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
177
- raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
175
+ raise RubySMB::Error::UnexpectedStatusCode, response.status_code
178
176
  end
179
177
 
180
178
  response.data_block.data.to_binary_s
@@ -225,11 +223,7 @@ module RubySMB
225
223
  total_bytes_written = 0
226
224
 
227
225
  loop do
228
- atomic_write_size = if bytes > @tree.client.max_buffer_size
229
- @tree.client.max_buffer_size
230
- else
231
- bytes
232
- end
226
+ atomic_write_size = [bytes, @tree.client.max_buffer_size].min
233
227
  write_request = write_packet(data: buffer.slice!(0, atomic_write_size), offset: offset)
234
228
  raw_response = @tree.client.send_recv(write_request)
235
229
  response = RubySMB::SMB1::Packet::WriteAndxResponse.read(raw_response)
@@ -242,7 +236,7 @@ module RubySMB
242
236
  )
243
237
  end
244
238
  unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
245
- raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
239
+ raise RubySMB::Error::UnexpectedStatusCode, response.status_code
246
240
  end
247
241
  bytes_written = response.parameter_block.count_low + (response.parameter_block.count_high << 16)
248
242
  total_bytes_written += bytes_written