ruby_smb 1.0.5 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.travis.yml +4 -1
  5. data/README.md +35 -47
  6. data/examples/enum_registry_key.rb +28 -0
  7. data/examples/enum_registry_values.rb +30 -0
  8. data/examples/pipes.rb +2 -1
  9. data/examples/read_registry_key_value.rb +32 -0
  10. data/lib/ruby_smb.rb +0 -1
  11. data/lib/ruby_smb/client.rb +2 -0
  12. data/lib/ruby_smb/client/winreg.rb +46 -0
  13. data/lib/ruby_smb/dcerpc.rb +38 -0
  14. data/lib/ruby_smb/dcerpc/bind.rb +2 -2
  15. data/lib/ruby_smb/dcerpc/bind_ack.rb +2 -2
  16. data/lib/ruby_smb/dcerpc/error.rb +3 -0
  17. data/lib/ruby_smb/dcerpc/ndr.rb +95 -16
  18. data/lib/ruby_smb/dcerpc/pdu_header.rb +1 -1
  19. data/lib/ruby_smb/dcerpc/request.rb +28 -9
  20. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +35 -0
  21. data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -0
  22. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +9 -0
  23. data/lib/ruby_smb/dcerpc/winreg.rb +340 -0
  24. data/lib/ruby_smb/dcerpc/winreg/close_key_request.rb +24 -0
  25. data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +27 -0
  26. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +45 -0
  27. data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +42 -0
  28. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +39 -0
  29. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +36 -0
  30. data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +34 -0
  31. data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +25 -0
  32. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +43 -0
  33. data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +35 -0
  34. data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +27 -0
  35. data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +40 -0
  36. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +39 -0
  37. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +57 -0
  38. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +40 -0
  39. data/lib/ruby_smb/smb1/file.rb +2 -0
  40. data/lib/ruby_smb/smb1/pipe.rb +78 -2
  41. data/lib/ruby_smb/smb2/packet/error_packet.rb +2 -4
  42. data/lib/ruby_smb/smb2/pipe.rb +89 -2
  43. data/lib/ruby_smb/version.rb +1 -1
  44. data/ruby_smb.gemspec +3 -3
  45. data/spec/lib/ruby_smb/client_spec.rb +148 -0
  46. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +2 -2
  47. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +2 -2
  48. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +410 -0
  49. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +50 -7
  50. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +98 -0
  51. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +13 -0
  52. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +60 -0
  53. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_request_spec.rb +28 -0
  54. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +36 -0
  55. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +108 -0
  56. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +97 -0
  57. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +94 -0
  58. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +82 -0
  59. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +74 -0
  60. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +35 -0
  61. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +90 -0
  62. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +38 -0
  63. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +39 -0
  64. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +113 -0
  65. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +88 -0
  66. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +150 -0
  67. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +32 -0
  68. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +710 -0
  69. data/spec/lib/ruby_smb/dcerpc_spec.rb +81 -0
  70. data/spec/lib/ruby_smb/smb1/file_spec.rb +9 -1
  71. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +210 -148
  72. data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +3 -24
  73. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +256 -145
  74. metadata +66 -9
  75. metadata.gz.sig +0 -0
  76. data/lib/ruby_smb/smb1/dcerpc.rb +0 -72
  77. data/lib/ruby_smb/smb2/dcerpc.rb +0 -75
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 104c5f0cf4f597bf65427cf15ab08461943a38aa
4
- data.tar.gz: e2f05f2857a898cd253afd829babecb715011c12
3
+ metadata.gz: 3fe1b1b7bdd2516bd388f86c020a9fa99b70faa0
4
+ data.tar.gz: aa11ed030f543c0d83b61929d10c35eea20a8455
5
5
  SHA512:
6
- metadata.gz: 5070ad2e2008739b1b47407c618e0014bc98e7031d72d2cb94daf61c7d21754a8480ef37f8099f90fe31ef0ac95563943951d00ad4bcea110d465c80c6fcf0f8
7
- data.tar.gz: eb91ae8bff05249dc9ec88c3fa9e18df4b8db979d9e7e9ac702c6f7af237b36c39d9d420dd0e95680e4004480dede90493fc6d58f942f45d08d3a812977a4066
6
+ metadata.gz: 92cc9708588a610104f8bacc8430fedd537f2ba283bb323b791ff45005a43417cf9570ce63f658b7a38c566570c2b651adb17b6750b3b117279552efaf138cab
7
+ data.tar.gz: 071db1651283d080b2adc728cd1f2225e051d52f86608f9f54dd6d79d39330127c3b5179d143ec9e5e155d132af1e128c4c9ca42744264caec8b249e0b0c86ec
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,5 +1,8 @@
1
1
  language: ruby
2
2
  sudo: false
3
3
  rvm:
4
- - '2.2'
4
+ - '2.3.8'
5
+ - '2.4.5'
6
+ - '2.5.3'
7
+ - '2.6.1'
5
8
  - 'jruby-9000'
data/README.md CHANGED
@@ -4,11 +4,12 @@
4
4
  [![Code Climate](https://codeclimate.com/github/rapid7/ruby_smb.png)](https://codeclimate.com/github/rapid7/ruby_smb)
5
5
  [![Coverage Status](https://coveralls.io/repos/github/rapid7/ruby_smb/badge.svg?branch=master)](https://coveralls.io/github/rapid7/ruby_smb?branch=master)
6
6
 
7
- A native Ruby implementation of the SMB Protocol Family. It currently supports
7
+ This is a native Ruby implementation of the SMB Protocol Family. It currently supports:
8
+
8
9
  1. [[MS-SMB]](https://msdn.microsoft.com/en-us/library/cc246231.aspx)
9
10
  1. [[MS-SMB2]](http://msdn.microsoft.com/en-us/library/cc246482.aspx)
10
11
 
11
- This library currently include both a client level, and packet level support. A user can parse and manipulate raw SMB packets, or use the simple client to perform SMB operations.
12
+ The RubySMB library provides client-level and packet-level support for the protocol. A user can parse and manipulate raw SMB packets, or use the client to perform higher-level SMB operations.
12
13
 
13
14
  See the Wiki for more information on this project's long-term goals, style guide, and developer tips.
14
15
 
@@ -32,22 +33,17 @@ Or install it yourself as:
32
33
 
33
34
  ### Defining a packet
34
35
 
35
- All packets are implemented in a declarative style with BinData. Nested data
36
- structures are used where appropriate to give users an easy method of adjusting
37
- data.
36
+ All packets are implemented in a declarative style with BinData. Nested data structures are used where appropriate to give users an easy method of manipulating individual fields inside of a packet.
38
37
 
39
38
  #### SMB1
39
+
40
40
  SMB1 Packets are made up of three basic components:
41
+
41
42
  1. **The SMB Header** - This is a standard SMB Header. All SMB1 packets use the same SMB header.
42
- 1. **The Parameter Block** - This is where function parameters are passed across the wire in the packet. Parameter Blocks will always
43
- have a 'Word Count' field that gives the size of the Parameter Block in words(2-bytes)
44
- 1. **The Data Block** - This is the data section of the packet. the Data Block will always have a 'byte count' field that gives the size of
45
- the Data block in bytes.
43
+ 1. **The Parameter Block** - This is where function parameters are passed across the wire in the packet. Parameter blocks will always have a 'Word Count' field that gives the size of the parameter block in words (2-bytes)
44
+ 1. **The Data Block** - This is the data section of the packet. The data block will always have a 'byte count' field that gives the size of the Data block in bytes.
46
45
 
47
- The SMB Header can always just be declared as a field in the BinData DSL for the packet class, because its structure never changes.
48
- For the ParameterBlock and DataBlocks, we always define subclasses for this particular packet. They inherit the 'Word Count' and
49
- 'Byte Count' fields, along with the auto-calculation routines for those fields, from their ancestors. Any other fields are then
50
- defined in our subclass before we start the DSL declarations for the packet.
46
+ The SMB Header can always just be declared as a field in the BinData DSL for the packet class, because its structure never changes. For the Parameter block and data blocks, we always define subclasses for this particular packet. They inherit the 'Word Count' and 'Byte Count' fields, along with the auto-calculation routines for those fields, from their ancestors. Any other fields are then defined in our subclass before we start the DSL declarations for the packet.
51
47
 
52
48
  Example:
53
49
 
@@ -90,8 +86,7 @@ end
90
86
 
91
87
  #### SMB2
92
88
 
93
- SMB2 Packets are far simpler than their older SMB1 counterparts. We still abstract out the SMB2 header since it is the same
94
- structure used for every packet. Beyond that, the SMB2 packet is relatively flat in comparison to SMB1.
89
+ SMB2 Packets are far simpler than their older SMB1 counterparts. We still abstract out the SMB2 header since it is the same structure used for every packet. Beyond that, the SMB2 packet is relatively flat in comparison to SMB1.
95
90
 
96
91
  Example:
97
92
  ```ruby
@@ -127,8 +122,7 @@ end
127
122
  ### Using a Packet class
128
123
 
129
124
  #### Manually
130
- You can instantiate an instance of a particular packet class, and then reach into the data structure to set or read explicit
131
- values in a fairly straightforward manner.
125
+ You can create an instance of any particular packet class, and then reach into the data structure to set or read explicit values in a fairly straightforward manner.
132
126
 
133
127
  Example:
134
128
  ```ruby
@@ -152,8 +146,7 @@ Example:
152
146
  2.3.3 :009 >
153
147
  ```
154
148
 
155
- You can also pass field/value pairs into the packet constructor as arguments, prefilling out certain fields
156
- if you wish.
149
+ You can also pass field/value pairs into the packet constructor as arguments, defaulting individual fields as desired.
157
150
 
158
151
  Example:
159
152
  ```ruby
@@ -165,9 +158,7 @@ Example:
165
158
 
166
159
  #### Reading from a Binary Blob
167
160
 
168
- Sometimes you need to read a binary blob and apply one of the packet structures to it.
169
- For example, when you are reading a response packet off of the wire, you will need to read the raw response
170
- string into an actual packet class. This is done using the #read class method.
161
+ Sometimes you need to read a binary data and apply one of the packet structures to it. For example, when you are reading a response packet, you will need to read the raw response string into an actual packet class. This is done using the #read class method.
171
162
 
172
163
  ```ruby
173
164
  2.3.3 :014 > blob = "\xFFSMB+\x00\x00\x00\x00\x98\x01`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00"
@@ -178,8 +169,7 @@ string into an actual packet class. This is done using the #read class method.
178
169
  ```
179
170
 
180
171
  #### Outputting to a Binary Blob
181
- Any structure or packet in rubySMB can also be output back into a binary blob using
182
- BinData's #to_binary_s method.
172
+ Any structure or packet in RubySMB can also be converted back into a binary blob using BinData's #to_binary_s method.
183
173
 
184
174
  Example:
185
175
  ```ruby
@@ -190,38 +180,35 @@ Example:
190
180
  ```
191
181
  ### Using the Client
192
182
 
193
- Sitting on top of the packet layer in RubySMB is the RubySMB::Client. This is the level msot users will interact with.
194
- It provides fairly simple conveience methods for performing SMB actions. It handles the creation, sending and receiving of packets
195
- for the user, relying on reasonable defaults in many cases.
183
+ Sitting on top of the packet layer in RubySMB is the RubySMB::Client class. This is the abstraction that most users of RubySMB will interact with. It provides simple conveience methods for performing SMB actions. It handles the creation, sending and receiving of packets for the user, providing reasonable defaults in many cases.
196
184
 
197
185
  #### Negotiation
198
186
 
199
- The RubySMB Client is capabale of multi-protocol negotiation. The user simply specifies whether SMB1 and/or SMB2 should be supported, and
200
- the client will negotiate the propper protocol and dialect behind the scenes.
187
+ The RubySMB client is capable of multi-protocol negotiation. The user simply specifies whether SMB1 and/or SMB2 should be supported, and the client negotiates the protocol and dialect behind the scenes.
201
188
 
202
- In the below example, we tell the client that both SMb1 and SMB2 should be supported. The Client will then Negotiate with the
203
- server on which version should be used. The user does not have to ever worry about which version was negotiated.
204
- Example:
189
+ In the following example, we tell the client that both SMB1 and SMB2 should be supported. The client will then negotiate with the server which version should be used.
190
+
191
+ Negotiation Example:
205
192
  ```ruby
206
193
  sock = TCPSocket.new address, 445
207
194
  dispatcher = RubySMB::Dispatcher::Socket.new(sock)
208
195
 
209
- client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: 'msfadmin', password: 'msfadmin')
196
+ client = RubySMB::Client.new(dispatcher, username: 'msfadmin', password: 'msfadmin')
210
197
  client.negotiate
211
198
  ```
212
199
 
213
200
  #### Authentication
214
201
 
215
- Authentication is achieved via the [ruby ntlm gem](https://rubygems.org/gems/rubyntlm). While the client
216
- will not currently attempt older basic authentication on its own, it will attempt an anonymous login, if no
217
- user credentials are supplied:
202
+ RubySMB uses the [Ruby NTLM gem](https://rubygems.org/gems/rubyntlm) for authentication. While the client
203
+ will not currently attempt older basic authentication on its own, it will attempt an anonymous login if no
204
+ user credentials are supplied.
218
205
 
219
206
  Authenticated Example:
220
207
  ```ruby
221
208
  sock = TCPSocket.new address, 445
222
209
  dispatcher = RubySMB::Dispatcher::Socket.new(sock)
223
210
 
224
- client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: 'msfadmin', password: 'msfadmin')
211
+ client = RubySMB::Client.new(dispatcher, username: 'msfadmin', password: 'msfadmin')
225
212
  client.negotiate
226
213
  client.authenticate
227
214
  ```
@@ -231,24 +218,23 @@ Anonymous Example:
231
218
  sock = TCPSocket.new address, 445
232
219
  dispatcher = RubySMB::Dispatcher::Socket.new(sock)
233
220
 
234
- client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: '', password: '')
221
+ client = RubySMB::Client.new(dispatcher, username: '', password: '')
235
222
  client.negotiate
236
223
  client.authenticate
237
224
  ```
238
225
 
239
226
  #### Connecting to a Tree
240
227
 
241
- While there is one Client, that has branching code-paths for SMB1 and SMB2, once you connect to a
242
- Tree you will be given a protocol specific Tree object. This Tree object will be responsible for all file operations
243
- that are to be conducted on that Tree.
228
+ While there is one RubySMB::Client object that supports both SMB1 and SMB2, once the library connects to an SMB tree, it returns a protocol-specific RubySMB::Tree object. This Tree object executes all subsequent file operations on the tree.
229
+
230
+ In the below example we see a simple script to connect to a remote tree, and list all files in a given sub-directory.
244
231
 
245
- In the below example we see a simple script to connect to a remote Tree, and list all files in a given sub-directory.
246
232
  Example:
247
233
  ```ruby
248
234
  sock = TCPSocket.new address, 445
249
235
  dispatcher = RubySMB::Dispatcher::Socket.new(sock)
250
236
 
251
- client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: 'msfadmin', password: 'msfadmin')
237
+ client = RubySMB::Client.new(dispatcher, username: 'msfadmin', password: 'msfadmin')
252
238
  client.negotiate
253
239
  client.authenticate
254
240
 
@@ -273,28 +259,30 @@ Example:
273
259
 
274
260
 
275
261
  ## Developer tips
276
- You'll want to have Wireshark and perhaps a tool like Impacket (which provides a small SMB client in one of its examples) installed to help with your work:
262
+
263
+ It is useful to have Wireshark and a reference SMB client, such as Impacket's installed to help debug and compare output:
277
264
 
278
265
  ### Wireshark
266
+
267
+ Configure Wireshark in Debian-based systems to be able to capture traffic without root user privileges:
268
+
279
269
  - `sudo apt-get install wireshark`
280
270
  - `sudo dpkg-reconfigure wireshark-common`
281
271
  - `sudo addgroup wireshark`
282
272
  - `sudo usermod -a -G wireshark <USERNAME>`
283
273
 
284
274
  ### Impacket
275
+
285
276
  - `sudo apt-get install python-setuptools`
286
277
  - `sudo easy_install pyasn1 pycrypto`
287
278
  - Download from GitHub (https://github.com/coresecurity/impacket)
288
279
  - `sudo python setup.py install`
289
280
  - `cd examples && python smbclient.py <USER>:<PASS>@<WINDOWS HOST IP>`
290
281
 
291
-
292
-
293
282
  ## License
294
283
 
295
284
  `ruby_smb` is released under a 3-clause BSD license. See [LICENSE.txt](LICENSE.txt) for full text.
296
285
 
297
-
298
286
  ## Contributing
299
287
 
300
288
  1. Fork it ( https://github.com/rapid7/ruby_smb/fork )
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This example script is used for testing Winreg registry key enumeration functionality
4
+ # It will attempt to connect to a host and enumerate registry subkeys of a specified registry key.
5
+ # Example usage: ruby enum_registry_key.rb 192.168.172.138 msfadmin msfadmin HKLM\\My\\Key
6
+ # This will try to connect to \\192.168.172.138 with the msfadmin:msfadmin credentialas and enumerate HKLM\\My\\Key subkeys.
7
+
8
+ require 'bundler/setup'
9
+ require 'ruby_smb'
10
+
11
+ address = ARGV[0]
12
+ username = ARGV[1]
13
+ password = ARGV[2]
14
+ registry_key = ARGV[3]
15
+
16
+ sock = TCPSocket.new address, 445
17
+ dispatcher = RubySMB::Dispatcher::Socket.new(sock, read_timeout: 60)
18
+
19
+ client = RubySMB::Client.new(dispatcher, smb1: true, smb2: true, username: username, password: password)
20
+ protocol = client.negotiate
21
+ status = client.authenticate
22
+
23
+ puts "#{protocol} : #{status}"
24
+
25
+ enum_result = client.enum_registry_key(address, registry_key)
26
+ puts enum_result
27
+
28
+ client.disconnect!
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This example script is used for testing values enumeration of a specific Winreg registry.
4
+ # It will attempt to connect to a host and enumerate values of a specified registry key.
5
+ # Example usage: ruby enum_registry_values.rb 192.168.172.138 msfadmin msfadmin HKLM\\My\\Key
6
+ # This will try to connect to \\192.168.172.138 with the msfadmin:msfadmin credentialas and enumerate HKLM\\My\\Key values.
7
+
8
+ require 'bundler/setup'
9
+ require 'ruby_smb'
10
+
11
+ address = ARGV[0]
12
+ username = ARGV[1]
13
+ password = ARGV[2]
14
+ registry_key = ARGV[3]
15
+
16
+ sock = TCPSocket.new address, 445
17
+ dispatcher = RubySMB::Dispatcher::Socket.new(sock, read_timeout: 60)
18
+
19
+ client = RubySMB::Client.new(dispatcher, smb1: true, smb2: true, username: username, password: password)
20
+ protocol = client.negotiate
21
+ status = client.authenticate
22
+
23
+ puts "#{protocol} : #{status}"
24
+
25
+ enum_result = client.enum_registry_values(address, registry_key)
26
+ puts enum_result
27
+
28
+ client.disconnect!
29
+
30
+
@@ -33,7 +33,8 @@ end
33
33
 
34
34
  client.authenticate
35
35
  client.tree_connect("\\\\#{address}\\IPC$")
36
- pipe = client.create_pipe(pipename, nil)
36
+ client.create_pipe(pipename)
37
+ pipe = client.last_file
37
38
 
38
39
  puts "Available: #{pipe.peek_available}"
39
40
  puts "PipeState: #{pipe.peek_state}" # 3 == OK
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This example script is used for testing the Winreg registry key value read functionality.
4
+ # It will attempt to connect to a host and reads the value of a specified registry key.
5
+ # Example usage: ruby enum_registry_key.rb 192.168.172.138 msfadmin msfadmin HKLM\\My\\Key ValueName
6
+ # This will try to connect to \\192.168.172.138 with the msfadmin:msfadmin credentialas and reads the ValueName data corresponding to the HKLM\\My\\Key registry key.
7
+
8
+ require 'bundler/setup'
9
+ require 'ruby_smb'
10
+
11
+ address = ARGV[0]
12
+ username = ARGV[1]
13
+ password = ARGV[2]
14
+ registry_key = ARGV[3]
15
+ value_name = ARGV[4]
16
+
17
+ sock = TCPSocket.new address, 445
18
+ dispatcher = RubySMB::Dispatcher::Socket.new(sock, read_timeout: 60)
19
+
20
+ client = RubySMB::Client.new(dispatcher, smb1: true, smb2: true, username: username, password: password)
21
+ protocol = client.negotiate
22
+ status = client.authenticate
23
+
24
+ puts "#{protocol}: #{status}"
25
+ puts "Key: #{registry_key}"
26
+ puts "Value: #{value_name}"
27
+
28
+ key_value = client.read_registry_key_value(address, registry_key, value_name)
29
+ puts key_value
30
+
31
+ client.disconnect!
32
+
@@ -15,7 +15,6 @@ module RubySMB
15
15
  require 'ruby_smb/field'
16
16
  require 'ruby_smb/nbss'
17
17
  require 'ruby_smb/fscc'
18
- require 'ruby_smb/dcerpc'
19
18
  require 'ruby_smb/generic_packet'
20
19
  require 'ruby_smb/dispatcher'
21
20
  require 'ruby_smb/version'
@@ -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
@@ -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
+
@@ -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