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
@@ -1,15 +1,55 @@
1
1
  module RubySMB
2
2
  module Dcerpc
3
+ MAX_XMIT_FRAG = 4280
4
+ MAX_RECV_FRAG = 4280
5
+
6
+ require 'windows_error/win32'
3
7
  require 'ruby_smb/dcerpc/error'
4
8
  require 'ruby_smb/dcerpc/uuid'
5
9
  require 'ruby_smb/dcerpc/ndr'
6
10
  require 'ruby_smb/dcerpc/ptypes'
7
11
  require 'ruby_smb/dcerpc/p_syntax_id_t'
12
+ require 'ruby_smb/dcerpc/rrp_unicode_string'
13
+ require 'ruby_smb/dcerpc/rpc_security_attributes'
8
14
  require 'ruby_smb/dcerpc/pdu_header'
9
15
  require 'ruby_smb/dcerpc/srvsvc'
16
+ require 'ruby_smb/dcerpc/winreg'
17
+ require 'ruby_smb/dcerpc/svcctl'
10
18
  require 'ruby_smb/dcerpc/request'
11
19
  require 'ruby_smb/dcerpc/response'
12
20
  require 'ruby_smb/dcerpc/bind'
13
21
  require 'ruby_smb/dcerpc/bind_ack'
22
+
23
+
24
+ # Bind to the remote server interface endpoint.
25
+ #
26
+ # @param options [Hash] the options to pass to the Bind request packet. At least, :endpoint must but provided with an existing Dcerpc class
27
+ # @return [RubySMB::Dcerpc::BindAck] the BindAck response packet
28
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if an invalid packet is received
29
+ # @raise [RubySMB::Dcerpc::Error::BindError] if the response is not a BindAck packet or if the Bind result code is not ACCEPTANCE
30
+ def bind(options={})
31
+ bind_req = RubySMB::Dcerpc::Bind.new(options)
32
+ write(data: bind_req.to_binary_s)
33
+ @size = 1024
34
+ dcerpc_raw_response = read()
35
+ begin
36
+ dcerpc_response = RubySMB::Dcerpc::BindAck.read(dcerpc_raw_response)
37
+ rescue IOError
38
+ raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the DCERPC response"
39
+ end
40
+ unless dcerpc_response.pdu_header.ptype == RubySMB::Dcerpc::PTypes::BIND_ACK
41
+ raise RubySMB::Dcerpc::Error::BindError, "Not a BindAck packet"
42
+ end
43
+
44
+ res_list = dcerpc_response.p_result_list
45
+ if res_list.n_results == 0 ||
46
+ res_list.p_results[0].result != RubySMB::Dcerpc::BindAck::ACCEPTANCE
47
+ raise RubySMB::Dcerpc::Error::BindError,
48
+ "Bind Failed (Result: #{res_list.p_results[0].result}, Reason: #{res_list.p_results[0].reason})"
49
+ end
50
+ @tree.client.max_buffer_size = dcerpc_response.max_xmit_frag
51
+ dcerpc_response
52
+ end
53
+
14
54
  end
15
55
  end
@@ -35,8 +35,8 @@ module RubySMB
35
35
 
36
36
  pdu_header :pdu_header, label: 'PDU header'
37
37
 
38
- uint16 :max_xmit_frag, label: 'max transmit frag size', initial_value: 0xFFFF
39
- uint16 :max_recv_frag, label: 'max receive frag size', initial_value: 0xFFFF
38
+ uint16 :max_xmit_frag, label: 'max transmit frag size', initial_value: RubySMB::Dcerpc::MAX_XMIT_FRAG
39
+ uint16 :max_recv_frag, label: 'max receive frag size', initial_value: RubySMB::Dcerpc::MAX_RECV_FRAG
40
40
  uint32 :assoc_group_id, label: 'ncarnation of client-server assoc group'
41
41
 
42
42
  p_cont_list_t :p_context_list, label: 'Presentation context list', endpoint: -> { endpoint }
@@ -46,8 +46,8 @@ module RubySMB
46
46
 
47
47
  pdu_header :pdu_header, label: 'PDU header'
48
48
 
49
- uint16 :max_xmit_frag, label: 'Max transmit frag size', initial_value: 0xFFFF
50
- uint16 :max_recv_frag, label: 'Max receive frag size', initial_value: 0xFFFF
49
+ uint16 :max_xmit_frag, label: 'Max transmit frag size', initial_value: RubySMB::Dcerpc::MAX_XMIT_FRAG
50
+ uint16 :max_recv_frag, label: 'Max receive frag size', initial_value: RubySMB::Dcerpc::MAX_RECV_FRAG
51
51
  uint32 :assoc_group_id, label: 'Association group ID'
52
52
  port_any_t :sec_addr, label: 'Secondary address'
53
53
  string :pad, length: -> { pad_length }
@@ -10,6 +10,12 @@ module RubySMB
10
10
 
11
11
  # Raised when an invalid packet is received
12
12
  class InvalidPacket < DcerpcError; end
13
+
14
+ # Raised when an error is returned during a Winreg operation
15
+ class WinregError < DcerpcError; end
16
+
17
+ # Raised when an error is returned during a Svcctl operation
18
+ class SvcctlError < DcerpcError; end
13
19
  end
14
20
  end
15
21
  end
@@ -7,36 +7,280 @@ module RubySMB
7
7
  VER_MAJOR = 2
8
8
  VER_MINOR = 0
9
9
 
10
- class NdrString < BinData::Record
10
+
11
+ # An NDR Conformant and Varying String representation as defined in
12
+ # [Transfer Syntax NDR - Conformant and Varying Strings](http://pubs.opengroup.org/onlinepubs/9629399/chap14.htm#tagcjh_19_03_04_02)
13
+ # The string elements are Stringz16 (unicode)
14
+ class NdrString < BinData::Primitive
11
15
  endian :little
12
16
 
13
- uint32 :max_count, initial_value: -> { str.length }
17
+ uint32 :max_count
14
18
  uint32 :offset, initial_value: 0
15
- uint32 :actual_count, initial_value: -> { str.length }
16
- stringz16 :str, read_length: -> { actual_count }
19
+ uint32 :actual_count
20
+ stringz16 :str, max_length: -> { actual_count * 2 }, onlyif: -> { actual_count > 0 }
21
+
22
+ def get
23
+ self.actual_count == 0 ? 0 : self.str
24
+ end
25
+
26
+ def set(v)
27
+ if v == 0
28
+ self.str.clear
29
+ self.actual_count = 0
30
+ else
31
+ v = v.str if v.is_a?(self.class)
32
+ unless self.str.equal?(v)
33
+ if v.empty?
34
+ self.actual_count = 0
35
+ else
36
+ self.actual_count = v.to_s.size + 1
37
+ self.max_count = self.actual_count
38
+ end
39
+ end
40
+ self.str = v.to_s
41
+ end
42
+ end
17
43
 
18
- def assign(v)
19
- self.max_count = v.size
20
- self.actual_count = v.size
21
- self.str = v
44
+ def clear
45
+ # Make sure #max_count and #offset are not cleared out
46
+ self.str.clear
47
+ self.actual_count.clear
48
+ end
49
+
50
+ def to_s
51
+ self.str.to_s
22
52
  end
23
53
  end
24
54
 
25
- class NdrLpStr < BinData::Record
55
+ # An NDR Uni-dimensional Conformant Array of Bytes representation as defined in
56
+ # [Transfer Syntax NDR - Uni-dimensional Conformant Arrays](https://pubs.opengroup.org/onlinepubs/9629399/chap14.htm#tagcjh_19_03_03_02)
57
+ class NdrLpByte < BinData::Primitive
26
58
  endian :little
27
59
 
28
- uint32 :referent_identifier
29
- ndr_string :ndr_str
60
+ uint32 :max_count, initial_value: -> { self.elements.size }
61
+ array :elements, type: :uint8, read_until: -> { index == self.max_count - 1 }, onlyif: -> { self.max_count > 0 }
30
62
 
31
- def assign(v)
32
- self.ndr_str = v
63
+ def get
64
+ self.elements
33
65
  end
34
66
 
35
- def to_s
36
- self.ndr_str.str
67
+ def set(v)
68
+ v = v.elements if v.is_a?(self.class)
69
+ self.elements = v.to_ary
70
+ self.max_count = self.elements.size unless self.elements.equal?(v)
71
+ end
72
+ end
73
+
74
+ # An NDR Uni-dimensional Conformant-varying Arrays of bytes representation as defined in:
75
+ # [Transfer Syntax NDR - NDR Constructed Types](http://pubs.opengroup.org/onlinepubs/9629399/chap14.htm#tagcjh_19_03_03_04)
76
+ class NdrByteArray < BinData::Primitive
77
+ endian :little
78
+
79
+ uint32 :max_count, initial_value: -> { self.actual_count }
80
+ uint32 :offset, initial_value: 0
81
+ uint32 :actual_count, initial_value: -> { self.bytes.size }
82
+ array :bytes, :type => :uint8, initial_length: -> { self.actual_count }
83
+
84
+ def get
85
+ self.bytes
86
+ end
87
+
88
+ def set(v)
89
+ v = v.bytes if v.is_a?(self.class)
90
+ self.bytes = v.to_ary
91
+ self.max_count = self.bytes.size unless self.bytes.equal?(v)
92
+ end
93
+ end
94
+
95
+ # An NDR Context Handle representation as defined in
96
+ # [IDL Data Type Declarations - Basic Type Declarations](http://pubs.opengroup.org/onlinepubs/9629399/apdxn.htm#tagcjh_34_01)
97
+ class NdrContextHandle < BinData::Primitive
98
+ endian :little
99
+
100
+ uint32 :context_handle_attributes
101
+ uuid :context_handle_uuid
102
+
103
+ def get
104
+ {:context_handle_attributes => context_handle_attributes, :context_handle_uuid => context_handle_uuid}
105
+ end
106
+
107
+ def set(handle)
108
+ if handle.is_a?(Hash)
109
+ self.context_handle_attributes = handle[:context_handle_attributes]
110
+ self.context_handle_uuid = handle[:context_handle_uuid]
111
+ elsif handle.is_a?(NdrContextHandle)
112
+ read(handle.to_binary_s)
113
+ else
114
+ read(handle.to_s)
115
+ end
116
+ end
117
+ end
118
+
119
+ # An NDR Top-level Full Pointers representation as defined in
120
+ # [Transfer Syntax NDR - Top-level Full Pointers](http://pubs.opengroup.org/onlinepubs/9629399/chap14.htm#tagcjh_19_03_11_01)
121
+ # This class must be inherited and the subclass must have a #referent property
122
+ class NdrPointer < BinData::Primitive
123
+ endian :little
124
+
125
+ uint32 :referent_id, initial_value: 0
126
+
127
+ def do_read(io)
128
+ self.referent_id.do_read(io)
129
+ if process_referent?
130
+ self.referent.do_read(io) unless self.referent_id == 0
131
+ end
132
+ end
133
+
134
+ def do_write(io)
135
+ self.referent_id.do_write(io)
136
+ if process_referent?
137
+ self.referent.do_write(io) unless self.referent_id == 0
138
+ end
139
+ end
140
+
141
+ def set(v)
142
+ if v == :null
143
+ self.referent.clear
144
+ self.referent_id = 0
145
+ else
146
+ if self.referent.respond_to?(:set)
147
+ self.referent.set(v)
148
+ else
149
+ self.referent = v
150
+ end
151
+ self.referent_id = rand(0xFFFFFFFF) if self.referent_id == 0
152
+ end
153
+ end
154
+
155
+ def get
156
+ if self.referent_id == 0
157
+ :null
158
+ else
159
+ self.referent
160
+ end
161
+ end
162
+
163
+ def process_referent?
164
+ current_parent = parent
165
+ loop do
166
+ return true unless current_parent
167
+ return false if current_parent.is_a?(NdrStruct)
168
+ current_parent = current_parent.parent
169
+ end
170
+ end
171
+ end
172
+
173
+ # A pointer to a NdrString structure
174
+ class NdrLpStr < NdrPointer
175
+ endian :little
176
+
177
+ ndr_string :referent, onlyif: -> { self.referent_id != 0 }
178
+ end
179
+
180
+ class NdrLpDword < NdrPointer
181
+ endian :little
182
+
183
+ uint32 :referent, onlyif: -> { self.referent_id != 0 }
184
+ end
185
+
186
+ # A pointer to an NDR Uni-dimensional Conformant-varying Arrays of bytes
187
+ class NdrLpByteArray < NdrPointer
188
+ endian :little
189
+
190
+ ndr_byte_array :referent, onlyif: -> { self.referent_id != 0 }
191
+
192
+ def set(v)
193
+ if v != :null && v.is_a?(NdrLpByteArray)
194
+ super(v.referent)
195
+ else
196
+ super(v)
197
+ end
198
+ end
199
+ end
200
+
201
+ # A pointer to a Windows FILETIME structure
202
+ class NdrLpFileTime < NdrPointer
203
+ endian :little
204
+
205
+ file_time :referent, onlyif: -> { self.referent_id != 0 }
206
+ end
207
+
208
+ # A generic NDR structure that implements logic to #read and #write
209
+ # (#to_binary_s) in case the structure contains BinData::Array or
210
+ # NdrPointer fields. This class must be inherited.
211
+ class NdrStruct < BinData::Record
212
+
213
+ def do_read(io)
214
+ super(io)
215
+ each_pair do |_name, field|
216
+ case field
217
+ when BinData::Array
218
+ field.each do |element|
219
+ next unless element.is_a?(NdrPointer)
220
+ next if element.referent_id == 0
221
+ pad = (4 - io.offset % 4) % 4
222
+ io.seekbytes(pad) if pad > 0
223
+ element.referent.do_read(io)
224
+ end
225
+ when NdrPointer
226
+ next if field.referent_id == 0
227
+ pad = (4 - io.offset % 4) % 4
228
+ io.seekbytes(pad) if pad > 0
229
+ field.referent.do_read(io)
230
+ end
231
+ end
232
+ end
233
+
234
+ def do_write(io)
235
+ super(io)
236
+ each_pair do |_name, field|
237
+ case field
238
+ when BinData::Array
239
+ field.each do |element|
240
+ next unless element.is_a?(NdrPointer)
241
+ next if element.referent_id == 0
242
+ pad = (4 - io.offset % 4) % 4
243
+ io.writebytes("\x00" * pad + element.referent.to_binary_s)
244
+ end
245
+ when NdrPointer
246
+ next if field.referent_id == 0
247
+ pad = (4 - io.offset % 4) % 4
248
+ io.writebytes("\x00" * pad + field.referent.to_binary_s)
249
+ end
250
+ end
251
+ end
252
+ end
253
+
254
+ class NdrStringPtrsw < NdrStruct
255
+ endian :little
256
+
257
+ uint32 :max_count, initial_value: -> { self.elements.size }
258
+ array :elements, type: :ndr_lp_str, read_until: -> { index == self.max_count - 1 }, onlyif: -> { self.max_count > 0 }
259
+
260
+ def get
261
+ self.elements
262
+ end
263
+
264
+ def set(v)
265
+ v = v.elements if v.is_a?(self.class)
266
+ self.elements = v.to_ary
267
+ self.max_count = self.elements.size unless self.elements.equal?(v)
268
+ end
269
+
270
+ def do_num_bytes
271
+ to_binary_s.size
272
+ end
273
+ end
274
+
275
+ class NdrLpStringPtrsw < NdrPointer
276
+ endian :little
277
+
278
+ ndr_string_ptrsw :referent, onlyif: -> { self.referent_id != 0 }
279
+
280
+ def set(v)
281
+ super(v.respond_to?(:to_ary) ? v.to_ary : v)
37
282
  end
38
283
  end
39
284
  end
40
285
  end
41
-
42
286
  end
@@ -21,7 +21,7 @@ module RubySMB
21
21
  end
22
22
 
23
23
  uint32 :packed_drep, label: 'NDR data representation format label', initial_value: 0x10
24
- uint16 :frag_length, label: 'Total length of fragment', initial_value: -> { parent.do_num_bytes }
24
+ uint16 :frag_length, label: 'Total length of fragment', initial_value: -> { parent.num_bytes }
25
25
  uint16 :auth_length, label: 'Length of auth_value'
26
26
  uint32 :call_id, label: 'Call identifier', initial_value: 1
27
27
  end
@@ -6,19 +6,51 @@ module RubySMB
6
6
  endian :little
7
7
 
8
8
  pdu_header :pdu_header, label: 'PDU header'
9
+ uint32 :alloc_hint, label: 'Allocation hint', initial_value: -> { stub.num_bytes }
10
+ uint16 :p_cont_id, label: 'Presentation context identification'
11
+ uint16 :opnum, label: 'Operation Number'
12
+ uuid :object, label: 'Object UID', onlyif: -> { pdu_header.pfc_flags.object_uuid == 1 }
9
13
 
10
- uint32 :alloc_hint, label: 'Allocation hint', initial_value: -> { stub.do_num_bytes }
11
- uint16 :p_cont_id, label: 'Presentation context identification'
12
- uint16 :opnum, label: 'Operation Number'
13
-
14
- uuid :object, label: 'Object UID', onlyif: -> { pdu_header.pfc_flags.object_uuid == 1 }
15
-
16
- choice :stub, label: 'Stub', selection: -> { opnum } do
17
- net_share_enum_all RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL, host: -> { host }
14
+ choice :stub, label: 'Stub', selection: -> { @obj.parent.get_parameter(:endpoint) || '' } do
15
+ choice 'Winreg', selection: -> { opnum } do
16
+ open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKCR, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKCR
17
+ open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKCU, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKCU
18
+ open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKLM, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKLM
19
+ open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKPD, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKPD
20
+ open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKU, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKU
21
+ open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKCC, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKCC
22
+ open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKPT, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKPT
23
+ open_root_key_request RubySMB::Dcerpc::Winreg::OPEN_HKPN, opnum: RubySMB::Dcerpc::Winreg::OPEN_HKPN
24
+ close_key_request RubySMB::Dcerpc::Winreg::REG_CLOSE_KEY
25
+ enum_key_request RubySMB::Dcerpc::Winreg::REG_ENUM_KEY
26
+ enum_value_request RubySMB::Dcerpc::Winreg::REG_ENUM_VALUE
27
+ open_key_request RubySMB::Dcerpc::Winreg::REG_OPEN_KEY
28
+ query_info_key_request RubySMB::Dcerpc::Winreg::REG_QUERY_INFO_KEY
29
+ query_value_request RubySMB::Dcerpc::Winreg::REG_QUERY_VALUE
30
+ create_key_request RubySMB::Dcerpc::Winreg::REG_CREATE_KEY
31
+ save_key_request RubySMB::Dcerpc::Winreg::REG_SAVE_KEY
32
+ string :default
33
+ end
34
+ choice 'Srvsvc', selection: -> { opnum } do
35
+ net_share_enum_all RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL, host: -> { host rescue '' }
36
+ string :default
37
+ end
38
+ choice 'Svcctl', selection: -> { opnum } do
39
+ open_sc_manager_w_request RubySMB::Dcerpc::Svcctl::OPEN_SC_MANAGER_W
40
+ open_service_w_request RubySMB::Dcerpc::Svcctl::OPEN_SERVICE_W
41
+ query_service_status_request RubySMB::Dcerpc::Svcctl::QUERY_SERVICE_STATUS
42
+ query_service_config_w_request RubySMB::Dcerpc::Svcctl::QUERY_SERVICE_CONFIG_W
43
+ change_service_config_w_request RubySMB::Dcerpc::Svcctl::CHANGE_SERVICE_CONFIG_W
44
+ start_service_w_request RubySMB::Dcerpc::Svcctl::START_SERVICE_W
45
+ control_service_request RubySMB::Dcerpc::Svcctl::CONTROL_SERVICE
46
+ close_service_handle_request RubySMB::Dcerpc::Svcctl::CLOSE_SERVICE_HANDLE
47
+ string :default
48
+ end
49
+ string :default
18
50
  end
19
51
 
20
52
  string :auth_verifier, label: 'Authentication verifier',
21
- onlyif: -> { pdu_header.auth_length > 0 },
53
+ onlyif: -> { pdu_header.auth_length > 0 },
22
54
  read_length: -> { pdu_header.auth_length }
23
55
 
24
56
  def initialize_instance