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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 104c5f0cf4f597bf65427cf15ab08461943a38aa
4
- data.tar.gz: e2f05f2857a898cd253afd829babecb715011c12
2
+ SHA256:
3
+ metadata.gz: 6cce717ed3175b8027db1e414fae576e984ff4c88a158568014b4c4eb06406f7
4
+ data.tar.gz: fb9223d4f15a3ed99aca553523dd957ceb3173cef87b4ba3d29a409ae4baffda
5
5
  SHA512:
6
- metadata.gz: 5070ad2e2008739b1b47407c618e0014bc98e7031d72d2cb94daf61c7d21754a8480ef37f8099f90fe31ef0ac95563943951d00ad4bcea110d465c80c6fcf0f8
7
- data.tar.gz: eb91ae8bff05249dc9ec88c3fa9e18df4b8db979d9e7e9ac702c6f7af237b36c39d9d420dd0e95680e4004480dede90493fc6d58f942f45d08d3a812977a4066
6
+ metadata.gz: 94319bee008719b00933ab82140fafd65c13344858f6677ecb26502cf22d087de0200c0feab9304959ac38df17fcac6540707e2b55457d8d92370484fbfbcd06
7
+ data.tar.gz: bf55746b294b17d9a4633e1344d976bfdc13df89e96c1ea5861c55999fdd0e1367d25b0e7e1ec455d4666a9fe0d41bfc7b943c84bc00606e2705f952319f4cb2
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,5 +1,6 @@
1
1
  language: ruby
2
2
  sudo: false
3
3
  rvm:
4
- - '2.2'
5
- - 'jruby-9000'
4
+ - '2.5.8'
5
+ - '2.6.6'
6
+ - '2.7.0'
data/Gemfile CHANGED
@@ -1,11 +1,15 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
- gem 'pry'
4
+ group :development do
5
+ # for development and testing purposes
6
+ gem 'pry-byebug'
7
+ gem 'pry-rescue'
8
+ end
5
9
 
6
10
  group :test do
7
11
  # simplecov test formatter and uploader for Coveralls.io
8
- gem 'coveralls', require: false
12
+ gem "coveralls", '~>0.8.23', :require => false
9
13
  # Testing
10
14
  gem 'rspec'
11
15
  # Coverage reports
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 )
@@ -6,12 +6,12 @@
6
6
  require 'bundler/setup'
7
7
  require 'ruby_smb'
8
8
 
9
- def run_authentication(address, smb1, smb2, username, password)
9
+ def run_authentication(address, smb1, smb2, smb3, username, password)
10
10
  # Create our socket and add it to the dispatcher
11
11
  sock = TCPSocket.new address, 445
12
12
  dispatcher = RubySMB::Dispatcher::Socket.new(sock)
13
13
 
14
- client = RubySMB::Client.new(dispatcher, smb1: smb1, smb2: smb2, username: username, password: password)
14
+ client = RubySMB::Client.new(dispatcher, smb1: smb1, smb2: smb2, smb3: smb3, username: username, password: password)
15
15
  protocol = client.negotiate
16
16
  status = client.authenticate
17
17
  puts "#{protocol} : #{status}"
@@ -27,4 +27,4 @@ username = ''
27
27
  password = ''
28
28
 
29
29
  # Negotiate with only SMB1 enabled
30
- run_authentication(address, true, false, username, password)
30
+ run_authentication(address, true, false, false, username, password)
@@ -9,18 +9,20 @@
9
9
  require 'bundler/setup'
10
10
  require 'ruby_smb'
11
11
 
12
- address = ARGV[0]
13
- username = ARGV[1]
14
- password = ARGV[2]
15
- share = ARGV[3]
16
- file = ARGV[4]
17
- data = ARGV[5]
18
- path = "\\\\#{address}\\#{share}"
12
+ address = ARGV[0]
13
+ username = ARGV[1]
14
+ password = ARGV[2]
15
+ share = ARGV[3]
16
+ file = ARGV[4]
17
+ data = ARGV[5]
18
+ smb_versions = ARGV[6]&.split(',') || ['1','2','3']
19
+
20
+ path = "\\\\#{address}\\#{share}"
19
21
 
20
22
  sock = TCPSocket.new address, 445
21
23
  dispatcher = RubySMB::Dispatcher::Socket.new(sock)
22
24
 
23
- client = RubySMB::Client.new(dispatcher, smb1: true, smb2: true, username: username, password: password)
25
+ client = RubySMB::Client.new(dispatcher, smb1: smb_versions.include?('1'), smb2: smb_versions.include?('2'), smb3: smb_versions.include?('3'), username: username, password: password)
24
26
  protocol = client.negotiate
25
27
  status = client.authenticate
26
28
 
@@ -6,12 +6,12 @@
6
6
  require 'bundler/setup'
7
7
  require 'ruby_smb'
8
8
 
9
- def run_authentication(address, smb1, smb2, username, password)
9
+ def run_authentication(address, smb1, smb2, smb3, username, password)
10
10
  # Create our socket and add it to the dispatcher
11
11
  sock = TCPSocket.new address, 445
12
12
  dispatcher = RubySMB::Dispatcher::Socket.new(sock)
13
13
 
14
- client = RubySMB::Client.new(dispatcher, smb1: smb1, smb2: smb2, username: username, password: password)
14
+ client = RubySMB::Client.new(dispatcher, smb1: smb1, smb2: smb2, smb3: smb3, username: username, password: password)
15
15
  protocol = client.negotiate
16
16
  status = client.authenticate
17
17
  puts "#{protocol} : #{status}"
@@ -32,9 +32,13 @@ address = ARGV[0]
32
32
  username = ARGV[1]
33
33
  password = ARGV[2]
34
34
 
35
+ # Negotiate with SMB1, SMB2 and SMB3 enabled on the client
36
+ run_authentication(address, true, true, true, username, password)
35
37
  # Negotiate with both SMB1 and SMB2 enabled on the client
36
- run_authentication(address, true, true, username, password)
38
+ run_authentication(address, true, true, false, username, password)
37
39
  # Negotiate with only SMB1 enabled
38
- run_authentication(address, true, false, username, password)
40
+ run_authentication(address, true, false, false, username, password)
39
41
  # Negotiate with only SMB2 enabled
40
- run_authentication(address, false, true, username, password)
42
+ run_authentication(address, false, true, false, username, password)
43
+ # Negotiate with only SMB3 enabled
44
+ run_authentication(address, false, false, true, username, password)
@@ -9,17 +9,19 @@
9
9
  require 'bundler/setup'
10
10
  require 'ruby_smb'
11
11
 
12
- address = ARGV[0]
13
- username = ARGV[1]
14
- password = ARGV[2]
15
- share = ARGV[3]
16
- file = ARGV[4]
12
+ address = ARGV[0]
13
+ username = ARGV[1]
14
+ password = ARGV[2]
15
+ share = ARGV[3]
16
+ file = ARGV[4]
17
+ smb_versions = ARGV[5]&.split(',') || ['1','2','3']
18
+
17
19
  path = "\\\\#{address}\\#{share}"
18
20
 
19
21
  sock = TCPSocket.new address, 445
20
22
  dispatcher = RubySMB::Dispatcher::Socket.new(sock)
21
23
 
22
- client = RubySMB::Client.new(dispatcher, smb1: true, smb2: true, username: username, password: password)
24
+ client = RubySMB::Client.new(dispatcher, smb1: smb_versions.include?('1'), smb2: smb_versions.include?('2'), smb3: smb_versions.include?('3'), username: username, password: password)
23
25
 
24
26
  protocol = client.negotiate
25
27
  status = client.authenticate
@@ -0,0 +1,29 @@
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
+ smb_versions = ARGV[4]&.split(',') || ['1','2','3']
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: smb_versions.include?('1'), smb2: smb_versions.include?('2'), smb3: smb_versions.include?('3'), username: username, password: password)
21
+ protocol = client.negotiate
22
+ status = client.authenticate
23
+
24
+ puts "#{protocol} : #{status}"
25
+
26
+ enum_result = client.enum_registry_key(address, registry_key)
27
+ puts enum_result
28
+
29
+ client.disconnect!
@@ -0,0 +1,31 @@
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
+ smb_versions = ARGV[4]&.split(',') || ['1','2','3']
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: smb_versions.include?('1'), smb2: smb_versions.include?('2'), smb3: smb_versions.include?('3'), username: username, password: password)
21
+ protocol = client.negotiate
22
+ status = client.authenticate
23
+
24
+ puts "#{protocol} : #{status}"
25
+
26
+ enum_result = client.enum_registry_values(address, registry_key)
27
+ puts enum_result
28
+
29
+ client.disconnect!
30
+
31
+
@@ -10,17 +10,19 @@
10
10
  require 'bundler/setup'
11
11
  require 'ruby_smb'
12
12
 
13
- address = ARGV[0]
14
- username = ARGV[1]
15
- password = ARGV[2]
16
- share = ARGV[3]
17
- dir = ARGV[4]
13
+ address = ARGV[0]
14
+ username = ARGV[1]
15
+ password = ARGV[2]
16
+ share = ARGV[3]
17
+ dir = ARGV[4]
18
+ smb_versions = ARGV[5]&.split(',') || ['1','2','3']
19
+
18
20
  path = "\\\\#{address}\\#{share}"
19
21
 
20
22
  sock = TCPSocket.new address, 445
21
23
  dispatcher = RubySMB::Dispatcher::Socket.new(sock)
22
24
 
23
- client = RubySMB::Client.new(dispatcher, smb1: true, smb2: true, username: username, password: password)
25
+ client = RubySMB::Client.new(dispatcher, smb1: smb_versions.include?('1'), smb2: smb_versions.include?('2'), smb3: smb_versions.include?('3'), username: username, password: password)
24
26
  protocol = client.negotiate
25
27
  status = client.authenticate
26
28