ruby_smb 1.0.0 → 1.1.0

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 (171) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.travis.yml +4 -1
  4. data/README.md +35 -47
  5. data/examples/enum_registry_key.rb +28 -0
  6. data/examples/enum_registry_values.rb +30 -0
  7. data/examples/pipes.rb +2 -1
  8. data/examples/read_registry_key_value.rb +32 -0
  9. data/lib/ruby_smb/client/authentication.rb +43 -25
  10. data/lib/ruby_smb/client/echo.rb +20 -2
  11. data/lib/ruby_smb/client/negotiation.rb +27 -12
  12. data/lib/ruby_smb/client/tree_connect.rb +20 -14
  13. data/lib/ruby_smb/client/utils.rb +2 -2
  14. data/lib/ruby_smb/client/winreg.rb +46 -0
  15. data/lib/ruby_smb/client.rb +28 -4
  16. data/lib/ruby_smb/dcerpc/bind.rb +2 -2
  17. data/lib/ruby_smb/dcerpc/bind_ack.rb +2 -2
  18. data/lib/ruby_smb/dcerpc/error.rb +3 -0
  19. data/lib/ruby_smb/dcerpc/ndr.rb +95 -16
  20. data/lib/ruby_smb/dcerpc/pdu_header.rb +1 -1
  21. data/lib/ruby_smb/dcerpc/request.rb +28 -9
  22. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +35 -0
  23. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +9 -0
  24. data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -0
  25. data/lib/ruby_smb/dcerpc/winreg/close_key_request.rb +24 -0
  26. data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +27 -0
  27. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +45 -0
  28. data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +42 -0
  29. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +39 -0
  30. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +36 -0
  31. data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +34 -0
  32. data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +25 -0
  33. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +43 -0
  34. data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +35 -0
  35. data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +27 -0
  36. data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +40 -0
  37. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +39 -0
  38. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +57 -0
  39. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +40 -0
  40. data/lib/ruby_smb/dcerpc/winreg.rb +340 -0
  41. data/lib/ruby_smb/dcerpc.rb +38 -0
  42. data/lib/ruby_smb/dispatcher/socket.rb +3 -1
  43. data/lib/ruby_smb/error.rb +40 -1
  44. data/lib/ruby_smb/generic_packet.rb +33 -4
  45. data/lib/ruby_smb/smb1/file.rb +67 -11
  46. data/lib/ruby_smb/smb1/packet/close_request.rb +2 -5
  47. data/lib/ruby_smb/smb1/packet/close_response.rb +2 -1
  48. data/lib/ruby_smb/smb1/packet/echo_request.rb +2 -4
  49. data/lib/ruby_smb/smb1/packet/echo_response.rb +2 -1
  50. data/lib/ruby_smb/smb1/packet/empty_packet.rb +10 -1
  51. data/lib/ruby_smb/smb1/packet/logoff_request.rb +2 -4
  52. data/lib/ruby_smb/smb1/packet/logoff_response.rb +2 -1
  53. data/lib/ruby_smb/smb1/packet/negotiate_request.rb +2 -5
  54. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +3 -7
  55. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +4 -4
  56. data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +2 -4
  57. data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +2 -1
  58. data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +2 -1
  59. data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +2 -1
  60. data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +2 -4
  61. data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +2 -1
  62. data/lib/ruby_smb/smb1/packet/read_andx_request.rb +2 -5
  63. data/lib/ruby_smb/smb1/packet/read_andx_response.rb +2 -1
  64. data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -1
  65. data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +2 -1
  66. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +2 -5
  67. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +2 -1
  68. data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_request.rb +0 -1
  69. data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_response.rb +3 -2
  70. data/lib/ruby_smb/smb1/packet/trans/request.rb +2 -5
  71. data/lib/ruby_smb/smb1/packet/trans/response.rb +2 -1
  72. data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_request.rb +1 -1
  73. data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_response.rb +1 -1
  74. data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +2 -1
  75. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +8 -2
  76. data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +2 -1
  77. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +8 -2
  78. data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +2 -1
  79. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +2 -1
  80. data/lib/ruby_smb/smb1/packet/trans2/request.rb +2 -4
  81. data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +2 -4
  82. data/lib/ruby_smb/smb1/packet/trans2/response.rb +2 -1
  83. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +2 -1
  84. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +2 -1
  85. data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +2 -4
  86. data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +13 -3
  87. data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
  88. data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -1
  89. data/lib/ruby_smb/smb1/packet/write_andx_request.rb +2 -5
  90. data/lib/ruby_smb/smb1/packet/write_andx_response.rb +2 -1
  91. data/lib/ruby_smb/smb1/pipe.rb +86 -5
  92. data/lib/ruby_smb/smb1/tree.rb +40 -2
  93. data/lib/ruby_smb/smb2/file.rb +97 -1
  94. data/lib/ruby_smb/smb2/packet/close_request.rb +2 -4
  95. data/lib/ruby_smb/smb2/packet/close_response.rb +2 -1
  96. data/lib/ruby_smb/smb2/packet/create_request.rb +2 -4
  97. data/lib/ruby_smb/smb2/packet/create_response.rb +2 -1
  98. data/lib/ruby_smb/smb2/packet/echo_request.rb +2 -4
  99. data/lib/ruby_smb/smb2/packet/echo_response.rb +2 -1
  100. data/lib/ruby_smb/smb2/packet/error_packet.rb +15 -3
  101. data/lib/ruby_smb/smb2/packet/ioctl_request.rb +2 -5
  102. data/lib/ruby_smb/smb2/packet/ioctl_response.rb +2 -1
  103. data/lib/ruby_smb/smb2/packet/logoff_request.rb +2 -4
  104. data/lib/ruby_smb/smb2/packet/logoff_response.rb +2 -1
  105. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +2 -5
  106. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +2 -1
  107. data/lib/ruby_smb/smb2/packet/query_directory_request.rb +2 -4
  108. data/lib/ruby_smb/smb2/packet/query_directory_response.rb +8 -2
  109. data/lib/ruby_smb/smb2/packet/read_request.rb +2 -4
  110. data/lib/ruby_smb/smb2/packet/read_response.rb +2 -1
  111. data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
  112. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -1
  113. data/lib/ruby_smb/smb2/packet/set_info_request.rb +2 -4
  114. data/lib/ruby_smb/smb2/packet/set_info_response.rb +2 -1
  115. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +2 -5
  116. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +8 -2
  117. data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +2 -4
  118. data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +2 -1
  119. data/lib/ruby_smb/smb2/packet/write_request.rb +2 -4
  120. data/lib/ruby_smb/smb2/packet/write_response.rb +2 -1
  121. data/lib/ruby_smb/smb2/pipe.rb +98 -11
  122. data/lib/ruby_smb/smb2/tree.rb +44 -6
  123. data/lib/ruby_smb/version.rb +1 -1
  124. data/lib/ruby_smb.rb +0 -1
  125. data/ruby_smb.gemspec +3 -3
  126. data/spec/lib/ruby_smb/client_spec.rb +271 -11
  127. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +2 -2
  128. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +2 -2
  129. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +410 -0
  130. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +50 -7
  131. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +98 -0
  132. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +13 -0
  133. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +60 -0
  134. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_request_spec.rb +28 -0
  135. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +36 -0
  136. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +108 -0
  137. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +97 -0
  138. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +94 -0
  139. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +82 -0
  140. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +74 -0
  141. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +35 -0
  142. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +90 -0
  143. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +38 -0
  144. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +39 -0
  145. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +113 -0
  146. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +88 -0
  147. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +150 -0
  148. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +32 -0
  149. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +710 -0
  150. data/spec/lib/ruby_smb/dcerpc_spec.rb +81 -0
  151. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +3 -1
  152. data/spec/lib/ruby_smb/generic_packet_spec.rb +52 -4
  153. data/spec/lib/ruby_smb/smb1/file_spec.rb +191 -2
  154. data/spec/lib/ruby_smb/smb1/packet/empty_packet_spec.rb +68 -0
  155. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +11 -2
  156. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +11 -2
  157. data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +40 -0
  158. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +272 -149
  159. data/spec/lib/ruby_smb/smb1/tree_spec.rb +44 -7
  160. data/spec/lib/ruby_smb/smb2/file_spec.rb +295 -2
  161. data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +78 -0
  162. data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +8 -0
  163. data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +8 -0
  164. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +322 -145
  165. data/spec/lib/ruby_smb/smb2/tree_spec.rb +214 -0
  166. data.tar.gz.sig +0 -0
  167. metadata +70 -11
  168. metadata.gz.sig +0 -0
  169. data/lib/ruby_smb/smb1/dcerpc.rb +0 -67
  170. data/lib/ruby_smb/smb2/dcerpc.rb +0 -70
  171. data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +0 -37
@@ -0,0 +1,46 @@
1
+ module RubySMB
2
+ class Client
3
+ module Winreg
4
+
5
+ def connect_to_winreg(host)
6
+ share = "\\\\#{host}\\IPC$"
7
+ tree = @tree_connects.find {|tree| tree.share == share}
8
+ tree = tree_connect(share) unless tree
9
+ named_pipe = tree.open_file(filename: "winreg", write: true, read: true)
10
+ if block_given?
11
+ res = yield named_pipe
12
+ named_pipe.close
13
+ res
14
+ else
15
+ named_pipe
16
+ end
17
+ end
18
+
19
+ def has_registry_key?(host, key)
20
+ connect_to_winreg(host) do |named_pipe|
21
+ named_pipe.has_registry_key?(key)
22
+ end
23
+ end
24
+
25
+ def read_registry_key_value(host, key, value_name)
26
+ connect_to_winreg(host) do |named_pipe|
27
+ named_pipe.read_registry_key_value(key, value_name)
28
+ end
29
+ end
30
+
31
+ def enum_registry_key(host, key)
32
+ connect_to_winreg(host) do |named_pipe|
33
+ named_pipe.enum_registry_key(key)
34
+ end
35
+ end
36
+
37
+ def enum_registry_values(host, key)
38
+ connect_to_winreg(host) do |named_pipe|
39
+ named_pipe.enum_registry_values(key)
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+
@@ -8,6 +8,7 @@ module RubySMB
8
8
  require 'ruby_smb/client/tree_connect'
9
9
  require 'ruby_smb/client/echo'
10
10
  require 'ruby_smb/client/utils'
11
+ require 'ruby_smb/client/winreg'
11
12
 
12
13
  include RubySMB::Client::Negotiation
13
14
  include RubySMB::Client::Authentication
@@ -15,6 +16,7 @@ module RubySMB
15
16
  include RubySMB::Client::TreeConnect
16
17
  include RubySMB::Client::Echo
17
18
  include RubySMB::Client::Utils
19
+ include RubySMB::Client::Winreg
18
20
 
19
21
  # The Default SMB1 Dialect string used in an SMB1 Negotiate Request
20
22
  SMB1_DIALECT_SMB1_DEFAULT = 'NT LM 0.12'.freeze
@@ -297,15 +299,32 @@ module RubySMB
297
299
  # Sends a LOGOFF command to the remote server to terminate the session
298
300
  #
299
301
  # @return [WindowsError::ErrorCode] the NTStatus of the response
302
+ # @raise [RubySMB::Error::InvalidPacket] if the response packet is not a LogoffResponse packet
300
303
  def logoff!
301
304
  if smb2
302
305
  request = RubySMB::SMB2::Packet::LogoffRequest.new
303
306
  raw_response = send_recv(request)
304
307
  response = RubySMB::SMB2::Packet::LogoffResponse.read(raw_response)
308
+ unless response.valid?
309
+ raise RubySMB::Error::InvalidPacket.new(
310
+ expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
311
+ expected_cmd: RubySMB::SMB2::Packet::LogoffResponse::COMMAND,
312
+ received_proto: response.smb2_header.protocol,
313
+ received_cmd: response.smb2_header.command
314
+ )
315
+ end
305
316
  else
306
317
  request = RubySMB::SMB1::Packet::LogoffRequest.new
307
318
  raw_response = send_recv(request)
308
319
  response = RubySMB::SMB1::Packet::LogoffResponse.read(raw_response)
320
+ unless response.valid?
321
+ raise RubySMB::Error::InvalidPacket.new(
322
+ expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
323
+ expected_cmd: RubySMB::SMB1::Packet::LogoffResponse::COMMAND,
324
+ received_proto: response.smb_header.protocol,
325
+ received_cmd: response.smb_header.command
326
+ )
327
+ end
309
328
  end
310
329
  wipe_state!
311
330
  response.status_code
@@ -380,14 +399,19 @@ module RubySMB
380
399
  # @param name [String] the NetBIOS name to request
381
400
  # @return [TrueClass] if session request is granted
382
401
  # @raise [RubySMB::Error::NetBiosSessionService] if session request is refused
402
+ # @raise [RubySMB::Error::InvalidPacket] if the response packet is not a NBSS packet
383
403
  def session_request(name = '*SMBSERVER')
384
404
  session_request = session_request_packet(name)
385
405
  dispatcher.send_packet(session_request, nbss_header: false)
386
406
  raw_response = dispatcher.recv_packet(full_response: true)
387
- session_header = RubySMB::Nbss::SessionHeader.read(raw_response)
388
- if session_header.session_packet_type == RubySMB::Nbss::NEGATIVE_SESSION_RESPONSE
389
- negative_session_response = RubySMB::Nbss::NegativeSessionResponse.read(raw_response)
390
- raise RubySMB::Error::NetBiosSessionService, "Session Request failed: #{negative_session_response.error_msg}"
407
+ begin
408
+ session_header = RubySMB::Nbss::SessionHeader.read(raw_response)
409
+ if session_header.session_packet_type == RubySMB::Nbss::NEGATIVE_SESSION_RESPONSE
410
+ negative_session_response = RubySMB::Nbss::NegativeSessionResponse.read(raw_response)
411
+ raise RubySMB::Error::NetBiosSessionService, "Session Request failed: #{negative_session_response.error_msg}"
412
+ end
413
+ rescue IOError
414
+ raise RubySMB::Error::InvalidPacket, 'Not a NBSS packet'
391
415
  end
392
416
 
393
417
  return true
@@ -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,9 @@ 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
13
16
  end
14
17
  end
15
18
  end
@@ -7,36 +7,115 @@ module RubySMB
7
7
  VER_MAJOR = 2
8
8
  VER_MINOR = 0
9
9
 
10
- class NdrString < BinData::Record
10
+ # An NDR Top-level Full Pointers representation as defined in
11
+ # [Transfer Syntax NDR - Top-level Full Pointers](http://pubs.opengroup.org/onlinepubs/9629399/chap14.htm#tagcjh_19_03_11_01)
12
+ # This class must be inherited and the subclass must have a #referent protperty
13
+ class NdrTopLevelFullPointer < BinData::Primitive
11
14
  endian :little
12
15
 
13
- uint32 :max_count, initial_value: -> { str.length }
14
- uint32 :offset, initial_value: 0
15
- uint32 :actual_count, initial_value: -> { str.length }
16
- stringz16 :str, read_length: -> { actual_count }
16
+ uint32 :referent_identifier, initial_value: 0x00020000
17
17
 
18
- def assign(v)
19
- self.max_count = v.size
20
- self.actual_count = v.size
21
- self.str = v
18
+ def get
19
+ is_a_null_pointer? ? 0 : self.referent
20
+ end
21
+
22
+ def set(v)
23
+ if v.is_a?(Integer) && v == 0
24
+ self.referent_identifier = 0
25
+ else
26
+ self.referent = v
27
+ end
28
+ end
29
+
30
+ def is_a_null_pointer?
31
+ self.referent_identifier == 0
22
32
  end
23
33
  end
24
34
 
25
- class NdrLpStr < BinData::Record
35
+ # An NDR Conformant and Varying String representation as defined in
36
+ # [Transfer Syntax NDR - Conformant and Varying Strings](http://pubs.opengroup.org/onlinepubs/9629399/chap14.htm#tagcjh_19_03_04_02)
37
+ # The string elements are Stringz16 (unicode)
38
+ class NdrString < BinData::Primitive
26
39
  endian :little
27
40
 
28
- uint32 :referent_identifier
29
- ndr_string :ndr_str
41
+ uint32 :max_count
42
+ uint32 :offset, initial_value: 0
43
+ uint32 :actual_count
44
+ stringz16 :str, read_length: -> { actual_count }, onlyif: -> { actual_count > 0 }
30
45
 
31
- def assign(v)
32
- self.ndr_str = v
46
+ def get
47
+ self.actual_count == 0 ? 0 : self.str
33
48
  end
34
49
 
50
+ def set(v)
51
+ if v.is_a?(Integer) && v == 0
52
+ self.actual_count = 0
53
+ else
54
+ self.str = v
55
+ self.max_count = self.actual_count = str.to_binary_s.size / 2
56
+ end
57
+ end
58
+ end
59
+
60
+ # A pointer to a NdrString structure
61
+ class NdrLpStr < NdrTopLevelFullPointer
62
+ endian :little
63
+
64
+ ndr_string :referent, onlyif: -> { !is_a_null_pointer? }
65
+
35
66
  def to_s
36
- self.ndr_str.str
67
+ is_a_null_pointer? ? "\0" : self.referent
68
+ end
69
+ end
70
+
71
+ # An NDR Context Handle representation as defined in
72
+ # [IDL Data Type Declarations - Basic Type Declarations](http://pubs.opengroup.org/onlinepubs/9629399/apdxn.htm#tagcjh_34_01)
73
+ class NdrContextHandle < BinData::Primitive
74
+ endian :little
75
+ uint32 :context_handle_attributes
76
+ uuid :context_handle_uuid
77
+
78
+ def get
79
+ {:context_handle_attributes => context_handle_attributes, :context_handle_uuid => context_handle_uuid}
37
80
  end
81
+
82
+ def set(handle)
83
+ if handle.is_a?(Hash)
84
+ self.context_handle_attributes = handle[:context_handle_attributes]
85
+ self.context_handle_uuid = handle[:context_handle_uuid]
86
+ elsif handle.is_a?(NdrContextHandle)
87
+ read(handle.to_binary_s)
88
+ else
89
+ read(handle.to_s)
90
+ end
91
+ end
92
+ end
93
+
94
+ # A pointer to a DWORD
95
+ class NdrLpDword < NdrTopLevelFullPointer
96
+ endian :little
97
+
98
+ uint32 :referent, onlyif: -> { !is_a_null_pointer? }
99
+ end
100
+
101
+ # An NDR Uni-dimensional Conformant-varying Arrays representation as defined in:
102
+ # [Transfer Syntax NDR - NDR Constructed Types](http://pubs.opengroup.org/onlinepubs/9629399/chap14.htm#tagcjh_19_03_03_04)
103
+ class NdrLpByte < BinData::Record
104
+ endian :little
105
+
106
+ uint32 :referent_identifier, initial_value: 0x00020000
107
+ uint32 :max_count, initial_value: -> { actual_count }, onlyif: -> { referent_identifier != 0 }
108
+ uint32 :offset, initial_value: 0, onlyif: -> { referent_identifier != 0 }
109
+ uint32 :actual_count, initial_value: -> { bytes.size }, onlyif: -> { referent_identifier != 0 }
110
+ array :bytes, :type => :uint8, initial_length: -> { actual_count }, onlyif: -> { referent_identifier != 0 }
111
+ end
112
+
113
+ # A pointer to a Windows FILETIME structure
114
+ class NdrLpFileTime < NdrTopLevelFullPointer
115
+ endian :little
116
+
117
+ file_time :referent, onlyif: -> { !is_a_null_pointer? }
38
118
  end
39
119
  end
40
120
  end
41
-
42
121
  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,38 @@ 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
+ string :default
31
+ end
32
+ choice 'Srvsvc', selection: -> { opnum } do
33
+ net_share_enum_all RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL, host: -> { host rescue '' }
34
+ string :default
35
+ end
36
+ string :default
18
37
  end
19
38
 
20
39
  string :auth_verifier, label: 'Authentication verifier',
21
- onlyif: -> { pdu_header.auth_length > 0 },
40
+ onlyif: -> { pdu_header.auth_length > 0 },
22
41
  read_length: -> { pdu_header.auth_length }
23
42
 
24
43
  def initialize_instance
@@ -0,0 +1,35 @@
1
+ require 'ruby_smb/dcerpc/ndr'
2
+
3
+ module RubySMB
4
+ module Dcerpc
5
+
6
+ # A RRP_UNICODE_STRING structure as defined in
7
+ # [2.2.4 RRP_UNICODE_STRING](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/c0c90f11-a4c4-496a-ac09-8a8a3697ceef)
8
+ class RrpUnicodeString < BinData::Primitive
9
+ endian :little
10
+
11
+ uint16 :buffer_length, initial_value: -> { buffer.to_s == "\0" ? 0 : buffer.actual_count * 2 }
12
+ uint16 :maximum_length, initial_value: -> { buffer.to_s == "\0" ? 0 : buffer.max_count * 2 }
13
+ ndr_lp_str :buffer
14
+
15
+ def get
16
+ self.buffer
17
+ end
18
+
19
+ def set(buf)
20
+ self.buffer = buf
21
+ self.buffer_length = self.buffer.to_s == "\0" ? 0 : self.buffer.actual_count * 2
22
+ self.maximum_length = self.buffer.to_s == "\0" ? 0 : self.buffer.max_count * 2
23
+ end
24
+ end
25
+
26
+ # A pointer to a RRP_UNICODE_STRING structure
27
+ class PrrpUnicodeString < Ndr::NdrTopLevelFullPointer
28
+ endian :little
29
+
30
+ rrp_unicode_string :referent, onlyif: -> { !is_a_null_pointer? }
31
+ end
32
+
33
+ end
34
+ end
35
+
@@ -5,6 +5,10 @@ module RubySMB
5
5
  #https://msdn.microsoft.com/en-us/library/cc247293.aspx
6
6
 
7
7
  class NetShareEnumAll < BinData::Record
8
+ attr_reader :opnum
9
+
10
+ mandatory_parameter :host
11
+
8
12
  endian :little
9
13
 
10
14
  uint32 :referent_id, initial_value: 0x00000001
@@ -27,6 +31,11 @@ module RubySMB
27
31
  uint32 :resume_referent_id, initial_value: 0x00000001
28
32
  uint32 :resume_handle, initial_value: 0
29
33
 
34
+ def initialize_instance
35
+ super
36
+ @opnum = NET_SHARE_ENUM_ALL
37
+ end
38
+
30
39
  def pad_length
31
40
  offset = (server_unc.abs_offset + server_unc.to_binary_s.length) % 4
32
41
  (4 - offset) % 4
@@ -10,6 +10,16 @@ module RubySMB
10
10
  NET_SHARE_ENUM_ALL = 0xF
11
11
 
12
12
  require 'ruby_smb/dcerpc/srvsvc/net_share_enum_all'
13
+
14
+ def net_share_enum_all(host)
15
+ bind(endpoint: RubySMB::Dcerpc::Srvsvc)
16
+
17
+ net_share_enum_all_request_packet = RubySMB::Dcerpc::Srvsvc::NetShareEnumAll.new(host: host)
18
+ response = dcerpc_request(net_share_enum_all_request_packet)
19
+
20
+ shares = RubySMB::Dcerpc::Srvsvc::NetShareEnumAll.parse_response(response)
21
+ shares.map{|s|{name: s[0], type: s[1], comment: s[2]}}
22
+ end
13
23
  end
14
24
  end
15
25
  end
@@ -0,0 +1,24 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Winreg
4
+
5
+ class RpcHkey < Ndr::NdrContextHandle; end
6
+
7
+ # This class represents a BaseRegCloseKey Request Packet as defined in
8
+ # [3.1.5.6 BaseRegCloseKey (Opnum 5)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/bc7545ff-0a54-4465-a95a-396b5c2995df)
9
+ class CloseKeyRequest < BinData::Record
10
+ attr_reader :opnum
11
+
12
+ endian :little
13
+
14
+ rpc_hkey :hkey
15
+
16
+ def initialize_instance
17
+ super
18
+ @opnum = REG_CLOSE_KEY
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -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 BaseRegCloseKey Response Packet as defined in
8
+ # [3.1.5.6 BaseRegCloseKey (Opnum 5)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/bc7545ff-0a54-4465-a95a-396b5c2995df)
9
+ class CloseKeyResponse < BinData::Record
10
+ attr_reader :opnum
11
+
12
+ endian :little
13
+
14
+ rpc_hkey :hkey
15
+ uint32 :error_status
16
+
17
+ def initialize_instance
18
+ super
19
+ @opnum = REG_CLOSE_KEY
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+
27
+
@@ -0,0 +1,45 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Winreg
4
+
5
+ class RpcHkey < Ndr::NdrContextHandle; end
6
+
7
+ # This class represents a BaseRegEnumKey Request Packet as defined in
8
+ # [3.1.5.10 BaseRegEnumKey (Opnum 9)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/668627e9-e0eb-4ab1-911f-0af589beeac3)
9
+ class EnumKeyRequest < BinData::Record
10
+ attr_reader :opnum
11
+
12
+ endian :little
13
+
14
+ rpc_hkey :hkey
15
+ uint32 :dw_index
16
+ rrp_unicode_string :lp_name
17
+ string :pad1, length: -> { pad_length1 }
18
+ prrp_unicode_string :lp_class
19
+ string :pad2, length: -> { pad_length2 }
20
+ ndr_lp_file_time :lpft_last_write_time
21
+
22
+ def initialize_instance
23
+ super
24
+ @opnum = REG_ENUM_KEY
25
+ end
26
+
27
+ # Determines the correct length for the padding in front of
28
+ # #lp_class. It should always force a 4-byte alignment.
29
+ def pad_length1
30
+ offset = (lp_name.abs_offset + lp_name.to_binary_s.length) % 4
31
+ (4 - offset) % 4
32
+ end
33
+
34
+ # Determines the correct length for the padding in front of
35
+ # #lpft_last_write_time. It should always force a 4-byte alignment.
36
+ def pad_length2
37
+ offset = (lp_class.abs_offset + lp_class.to_binary_s.length) % 4
38
+ (4 - offset) % 4
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+
@@ -0,0 +1,42 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Winreg
4
+
5
+ # This class represents a BaseRegEnumKey Response Packet as defined in
6
+ # [3.1.5.10 BaseRegEnumKey (Opnum 9)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/668627e9-e0eb-4ab1-911f-0af589beeac3)
7
+ class EnumKeyResponse < BinData::Record
8
+ attr_reader :opnum
9
+
10
+ endian :little
11
+
12
+ rrp_unicode_string :lp_name
13
+ string :pad1, length: -> { pad_length1 }
14
+ prrp_unicode_string :lp_class, initial_value: 0
15
+ string :pad2, length: -> { pad_length2 }
16
+ ndr_lp_file_time :lpft_last_write_time
17
+ uint32 :error_status
18
+
19
+ def initialize_instance
20
+ super
21
+ @opnum = REG_ENUM_KEY
22
+ end
23
+
24
+ # Determines the correct length for the padding in front of
25
+ # #lp_class. It should always force a 4-byte alignment.
26
+ def pad_length1
27
+ offset = (lp_name.abs_offset + lp_name.to_binary_s.length) % 4
28
+ (4 - offset) % 4
29
+ end
30
+
31
+ # Determines the correct length for the padding in front of
32
+ # #lpft_last_write_time. It should always force a 4-byte alignment.
33
+ def pad_length2
34
+ offset = (lp_class.abs_offset + lp_class.to_binary_s.length) % 4
35
+ (4 - offset) % 4
36
+ end
37
+ end
38
+
39
+ end
40
+ end
41
+ end
42
+
@@ -0,0 +1,39 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Winreg
4
+
5
+ class RpcHkey < Ndr::NdrContextHandle; end
6
+
7
+ # This class represents a BaseRegEnumValue Request Packet as defined in
8
+ # [3.1.5.11 BaseRegEnumValue (Opnum 10)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/56e99ef3-05dc-4f24-bcf5-9cff00412945)
9
+ class EnumValueRequest < BinData::Record
10
+ attr_reader :opnum
11
+
12
+ endian :little
13
+
14
+ rpc_hkey :hkey
15
+ uint32 :dw_index
16
+ rrp_unicode_string :lp_value_name
17
+ string :pad, length: -> { pad_length }
18
+ ndr_lp_dword :lp_type
19
+ ndr_lp_byte :lp_data
20
+ ndr_lp_dword :lpcb_data
21
+ ndr_lp_dword :lpcb_len
22
+
23
+ def initialize_instance
24
+ super
25
+ @opnum = REG_ENUM_VALUE
26
+ end
27
+
28
+ # Determines the correct length for the padding in front of
29
+ # #lp_type. It should always force a 4-byte alignment.
30
+ def pad_length
31
+ offset = (lp_value_name.abs_offset + lp_value_name.to_binary_s.length) % 4
32
+ (4 - offset) % 4
33
+ end
34
+ end
35
+
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,36 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Winreg
4
+
5
+ # This class represents a BaseRegEnumValue Response Packet as defined in
6
+ # [3.1.5.11 BaseRegEnumValue (Opnum 10)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/56e99ef3-05dc-4f24-bcf5-9cff00412945)
7
+ class EnumValueResponse < BinData::Record
8
+ attr_reader :opnum
9
+
10
+ endian :little
11
+
12
+ rrp_unicode_string :lp_value_name
13
+ string :pad, length: -> { pad_length }
14
+ ndr_lp_dword :lp_type
15
+ ndr_lp_byte :lp_data
16
+ ndr_lp_dword :lpcb_data
17
+ ndr_lp_dword :lpcb_len
18
+ uint32 :error_status
19
+
20
+ def initialize_instance
21
+ super
22
+ @opnum = REG_ENUM_VALUE
23
+ end
24
+
25
+ # Determines the correct length for the padding in front of
26
+ # #lp_type. It should always force a 4-byte alignment.
27
+ def pad_length
28
+ offset = (lp_value_name.abs_offset + lp_value_name.to_binary_s.length) % 4
29
+ (4 - offset) % 4
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+