ruby_smb 1.0.5 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
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