ruby_smb 1.0.3 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.travis.yml +3 -2
  5. data/Gemfile +6 -2
  6. data/README.md +35 -47
  7. data/examples/enum_registry_key.rb +28 -0
  8. data/examples/enum_registry_values.rb +30 -0
  9. data/examples/negotiate.rb +51 -8
  10. data/examples/pipes.rb +2 -1
  11. data/examples/read_file_encryption.rb +56 -0
  12. data/examples/read_registry_key_value.rb +32 -0
  13. data/lib/ruby_smb.rb +4 -1
  14. data/lib/ruby_smb/client.rb +233 -22
  15. data/lib/ruby_smb/client/authentication.rb +70 -33
  16. data/lib/ruby_smb/client/echo.rb +20 -2
  17. data/lib/ruby_smb/client/encryption.rb +62 -0
  18. data/lib/ruby_smb/client/negotiation.rb +172 -24
  19. data/lib/ruby_smb/client/signing.rb +19 -0
  20. data/lib/ruby_smb/client/tree_connect.rb +24 -18
  21. data/lib/ruby_smb/client/utils.rb +8 -7
  22. data/lib/ruby_smb/client/winreg.rb +46 -0
  23. data/lib/ruby_smb/crypto.rb +30 -0
  24. data/lib/ruby_smb/dcerpc.rb +38 -0
  25. data/lib/ruby_smb/dcerpc/bind.rb +2 -2
  26. data/lib/ruby_smb/dcerpc/bind_ack.rb +2 -2
  27. data/lib/ruby_smb/dcerpc/error.rb +3 -0
  28. data/lib/ruby_smb/dcerpc/ndr.rb +95 -16
  29. data/lib/ruby_smb/dcerpc/pdu_header.rb +1 -1
  30. data/lib/ruby_smb/dcerpc/request.rb +28 -9
  31. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +35 -0
  32. data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -0
  33. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +9 -0
  34. data/lib/ruby_smb/dcerpc/winreg.rb +340 -0
  35. data/lib/ruby_smb/dcerpc/winreg/close_key_request.rb +24 -0
  36. data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +27 -0
  37. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +45 -0
  38. data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +42 -0
  39. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +39 -0
  40. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +36 -0
  41. data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +34 -0
  42. data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +25 -0
  43. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +43 -0
  44. data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +35 -0
  45. data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +27 -0
  46. data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +40 -0
  47. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +39 -0
  48. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +57 -0
  49. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +40 -0
  50. data/lib/ruby_smb/dispatcher/socket.rb +4 -3
  51. data/lib/ruby_smb/error.rb +68 -2
  52. data/lib/ruby_smb/generic_packet.rb +33 -4
  53. data/lib/ruby_smb/smb1/commands.rb +1 -1
  54. data/lib/ruby_smb/smb1/file.rb +66 -15
  55. data/lib/ruby_smb/smb1/packet/close_request.rb +2 -5
  56. data/lib/ruby_smb/smb1/packet/close_response.rb +2 -1
  57. data/lib/ruby_smb/smb1/packet/echo_request.rb +2 -4
  58. data/lib/ruby_smb/smb1/packet/echo_response.rb +2 -1
  59. data/lib/ruby_smb/smb1/packet/empty_packet.rb +10 -1
  60. data/lib/ruby_smb/smb1/packet/logoff_request.rb +2 -4
  61. data/lib/ruby_smb/smb1/packet/logoff_response.rb +2 -1
  62. data/lib/ruby_smb/smb1/packet/negotiate_request.rb +2 -5
  63. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +3 -7
  64. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +4 -4
  65. data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +2 -4
  66. data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +2 -1
  67. data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +2 -1
  68. data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +2 -1
  69. data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +2 -4
  70. data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +2 -1
  71. data/lib/ruby_smb/smb1/packet/read_andx_request.rb +2 -5
  72. data/lib/ruby_smb/smb1/packet/read_andx_response.rb +2 -1
  73. data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -1
  74. data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +3 -2
  75. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +2 -5
  76. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +3 -2
  77. data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_request.rb +0 -1
  78. data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_response.rb +3 -2
  79. data/lib/ruby_smb/smb1/packet/trans/request.rb +2 -5
  80. data/lib/ruby_smb/smb1/packet/trans/response.rb +2 -1
  81. data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_request.rb +1 -1
  82. data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_response.rb +1 -1
  83. data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +2 -1
  84. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +8 -2
  85. data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +2 -1
  86. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +8 -2
  87. data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +2 -1
  88. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +2 -1
  89. data/lib/ruby_smb/smb1/packet/trans2/request.rb +2 -4
  90. data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +2 -4
  91. data/lib/ruby_smb/smb1/packet/trans2/response.rb +2 -1
  92. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +2 -1
  93. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +2 -1
  94. data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +2 -4
  95. data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +13 -3
  96. data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
  97. data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -1
  98. data/lib/ruby_smb/smb1/packet/write_andx_request.rb +3 -6
  99. data/lib/ruby_smb/smb1/packet/write_andx_response.rb +2 -1
  100. data/lib/ruby_smb/smb1/pipe.rb +87 -6
  101. data/lib/ruby_smb/smb1/tree.rb +50 -3
  102. data/lib/ruby_smb/smb2/bit_field/session_flags.rb +2 -1
  103. data/lib/ruby_smb/smb2/bit_field/share_flags.rb +6 -4
  104. data/lib/ruby_smb/smb2/file.rb +103 -25
  105. data/lib/ruby_smb/smb2/negotiate_context.rb +108 -0
  106. data/lib/ruby_smb/smb2/packet.rb +2 -0
  107. data/lib/ruby_smb/smb2/packet/close_request.rb +2 -4
  108. data/lib/ruby_smb/smb2/packet/close_response.rb +2 -1
  109. data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +41 -0
  110. data/lib/ruby_smb/smb2/packet/create_request.rb +2 -4
  111. data/lib/ruby_smb/smb2/packet/create_response.rb +2 -1
  112. data/lib/ruby_smb/smb2/packet/echo_request.rb +2 -4
  113. data/lib/ruby_smb/smb2/packet/echo_response.rb +2 -1
  114. data/lib/ruby_smb/smb2/packet/error_packet.rb +15 -3
  115. data/lib/ruby_smb/smb2/packet/ioctl_request.rb +2 -5
  116. data/lib/ruby_smb/smb2/packet/ioctl_response.rb +2 -1
  117. data/lib/ruby_smb/smb2/packet/logoff_request.rb +2 -4
  118. data/lib/ruby_smb/smb2/packet/logoff_response.rb +2 -1
  119. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +51 -17
  120. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +52 -5
  121. data/lib/ruby_smb/smb2/packet/query_directory_request.rb +2 -4
  122. data/lib/ruby_smb/smb2/packet/query_directory_response.rb +8 -2
  123. data/lib/ruby_smb/smb2/packet/read_request.rb +2 -4
  124. data/lib/ruby_smb/smb2/packet/read_response.rb +2 -1
  125. data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
  126. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -1
  127. data/lib/ruby_smb/smb2/packet/set_info_request.rb +2 -4
  128. data/lib/ruby_smb/smb2/packet/set_info_response.rb +2 -1
  129. data/lib/ruby_smb/smb2/packet/transform_header.rb +84 -0
  130. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +93 -10
  131. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +10 -22
  132. data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +2 -4
  133. data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +2 -1
  134. data/lib/ruby_smb/smb2/packet/write_request.rb +2 -4
  135. data/lib/ruby_smb/smb2/packet/write_response.rb +2 -1
  136. data/lib/ruby_smb/smb2/pipe.rb +86 -12
  137. data/lib/ruby_smb/smb2/smb2_header.rb +1 -1
  138. data/lib/ruby_smb/smb2/tree.rb +65 -21
  139. data/lib/ruby_smb/version.rb +1 -1
  140. data/ruby_smb.gemspec +5 -3
  141. data/spec/lib/ruby_smb/client_spec.rb +1612 -108
  142. data/spec/lib/ruby_smb/crypto_spec.rb +25 -0
  143. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +2 -2
  144. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +2 -2
  145. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +410 -0
  146. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +50 -7
  147. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +98 -0
  148. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +13 -0
  149. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +60 -0
  150. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_request_spec.rb +28 -0
  151. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +36 -0
  152. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +108 -0
  153. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +97 -0
  154. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +94 -0
  155. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +82 -0
  156. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +74 -0
  157. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +35 -0
  158. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +90 -0
  159. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +38 -0
  160. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +39 -0
  161. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +113 -0
  162. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +88 -0
  163. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +150 -0
  164. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +32 -0
  165. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +710 -0
  166. data/spec/lib/ruby_smb/dcerpc_spec.rb +81 -0
  167. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +2 -2
  168. data/spec/lib/ruby_smb/error_spec.rb +59 -0
  169. data/spec/lib/ruby_smb/generic_packet_spec.rb +52 -4
  170. data/spec/lib/ruby_smb/smb1/file_spec.rb +191 -2
  171. data/spec/lib/ruby_smb/smb1/packet/empty_packet_spec.rb +68 -0
  172. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +2 -2
  173. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +2 -2
  174. data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +2 -2
  175. data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +1 -1
  176. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +11 -2
  177. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +11 -2
  178. data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +40 -0
  179. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +272 -149
  180. data/spec/lib/ruby_smb/smb1/tree_spec.rb +44 -7
  181. data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +9 -0
  182. data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +27 -0
  183. data/spec/lib/ruby_smb/smb2/file_spec.rb +323 -6
  184. data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +332 -0
  185. data/spec/lib/ruby_smb/smb2/packet/compression_transform_header_spec.rb +108 -0
  186. data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +78 -0
  187. data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +138 -3
  188. data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +120 -2
  189. data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +8 -0
  190. data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +220 -0
  191. data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +339 -9
  192. data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +3 -22
  193. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +286 -149
  194. data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +2 -2
  195. data/spec/lib/ruby_smb/smb2/tree_spec.rb +261 -2
  196. metadata +191 -83
  197. metadata.gz.sig +0 -0
  198. data/lib/ruby_smb/smb1/dcerpc.rb +0 -67
  199. data/lib/ruby_smb/smb2/dcerpc.rb +0 -70
  200. data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +0 -37
@@ -40,27 +40,28 @@ module RubySMB
40
40
  end
41
41
 
42
42
  #Writes data to an open file handle
43
- def write(file_id, offset = 0, data = '', do_recv = true)
43
+ def write(file_id = last_file_id, offset = 0, data = '', do_recv = true)
44
44
  @open_files[file_id].send_recv_write(data: data, offset: offset)
45
45
  end
46
46
 
47
- def read(file_id, offset = 0, length = last_file.size)
47
+ def read(file_id = last_file_id, offset = 0, length = last_file.size, do_recv = true)
48
48
  data = @open_files[file_id].send_recv_read(read_length: length, offset: offset)
49
49
  data.bytes
50
50
  end
51
51
 
52
- def delete(path)
53
- file = last_tree.open_file(filename: path.sub(/^\\/, ''), delete: true)
52
+ def delete(path, tree_id = last_tree_id, do_recv = true)
53
+ tree = @tree_connects.detect{ |tree| tree.id == tree_id }
54
+ file = tree.open_file(filename: path.sub(/^\\/, ''), delete: true)
54
55
  file.delete
55
56
  file.close
56
57
  end
57
58
 
58
- def close(file_id, tree_id)
59
+ def close(file_id = last_file_id, tree_id = last_tree_id, do_recv = true)
59
60
  @open_files[file_id].close
60
61
  end
61
62
 
62
- def tree_disconnect(share)
63
- @tree_connects.detect{|tree| tree.id == share }.disconnect!
63
+ def tree_disconnect(tree_id = last_tree_id, do_recv = true)
64
+ @tree_connects.detect{|tree| tree.id == tree_id }.disconnect!
64
65
  end
65
66
 
66
67
  def native_os
@@ -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
+
@@ -0,0 +1,30 @@
1
+ module RubySMB
2
+ module Crypto
3
+ module KDF
4
+ def self.counter_mode(ki, label, context, length: 128)
5
+ digest = OpenSSL::Digest.new('SHA256')
6
+ r = 32
7
+
8
+ n = length / 256
9
+ n = 1 if n == 0
10
+
11
+ raise ArgumentError if n > 2**r - 1
12
+ result = ""
13
+
14
+ n.times do |i|
15
+ input = [i + 1].pack('L>')
16
+ input << label
17
+ input << "\x00"
18
+ input << context
19
+ input << [length].pack('L>')
20
+ k = OpenSSL::HMAC.digest(digest, ki, input)
21
+ result << k
22
+ end
23
+
24
+ return result[0...(length / 8)]
25
+ rescue OpenSSL::OpenSSLError => e
26
+ raise RubySMB::Error::EncryptionError, "Crypto::KDF.counter_mode OpenSSL error: #{e.message}"
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,15 +1,53 @@
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'
8
13
  require 'ruby_smb/dcerpc/pdu_header'
9
14
  require 'ruby_smb/dcerpc/srvsvc'
15
+ require 'ruby_smb/dcerpc/winreg'
10
16
  require 'ruby_smb/dcerpc/request'
11
17
  require 'ruby_smb/dcerpc/response'
12
18
  require 'ruby_smb/dcerpc/bind'
13
19
  require 'ruby_smb/dcerpc/bind_ack'
20
+
21
+
22
+ # Bind to the remote server interface endpoint.
23
+ #
24
+ # @param options [Hash] the options to pass to the Bind request packet. At least, :endpoint must but provided with an existing Dcerpc class
25
+ # @return [RubySMB::Dcerpc::BindAck] the BindAck response packet
26
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if an invalid packet is received
27
+ # @raise [RubySMB::Dcerpc::Error::BindError] if the response is not a BindAck packet or if the Bind result code is not ACCEPTANCE
28
+ def bind(options={})
29
+ bind_req = RubySMB::Dcerpc::Bind.new(options)
30
+ write(data: bind_req.to_binary_s)
31
+ @size = 1024
32
+ dcerpc_raw_response = read()
33
+ begin
34
+ dcerpc_response = RubySMB::Dcerpc::BindAck.read(dcerpc_raw_response)
35
+ rescue IOError
36
+ raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the DCERPC response"
37
+ end
38
+ unless dcerpc_response.pdu_header.ptype == RubySMB::Dcerpc::PTypes::BIND_ACK
39
+ raise RubySMB::Dcerpc::Error::BindError, "Not a BindAck packet"
40
+ end
41
+
42
+ res_list = dcerpc_response.p_result_list
43
+ if res_list.n_results == 0 ||
44
+ res_list.p_results[0].result != RubySMB::Dcerpc::BindAck::ACCEPTANCE
45
+ raise RubySMB::Dcerpc::Error::BindError,
46
+ "Bind Failed (Result: #{res_list.p_results[0].result}, Reason: #{res_list.p_results[0].reason})"
47
+ end
48
+ @tree.client.max_buffer_size = dcerpc_response.max_xmit_frag
49
+ dcerpc_response
50
+ end
51
+
14
52
  end
15
53
  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,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
+
@@ -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