ruby_smb 1.0.3 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2c631886979a7433c911311d4a86e396714d492c
4
- data.tar.gz: 2239c4167668f032308e16d047b40e0f4c1587cb
2
+ SHA256:
3
+ metadata.gz: a683fe9443f70b1f4e7dc98d02d7f4deaf785ae94097752696c516977bc3a36a
4
+ data.tar.gz: 5e74a2b2daaedb9b2f096ef05fcd5465a9caa1b9672af6e42d13f18b70e47110
5
5
  SHA512:
6
- metadata.gz: 1fcc1eacddf7c95375b966772d580357ba321d31c157d277e4c4306e448696f0f1f1aa210f06b127db7f2ffad83b5086f30608e8cbeb0ad370339dd3e1630731
7
- data.tar.gz: 9cb22ee1ce93621365fba1f3bb67f0855a92331e28fc388b42d10e7b32716e587bfb29dda783d8c5bf617b388735f02abdc805a84b438aa1bdad70317f93d4f5
6
+ metadata.gz: efaaf45fb9fb49bd37a3f45681800f26437efdd76bd6b06ee763768c3674292fe3e7bc35946a489300a3d696a7f060cad2802335aabfd766dd6bc8dd9f503fdd
7
+ data.tar.gz: cef65fae806b5b6bce656ef799f5ca4376a0cc71e1ad5746ddaf44898652580ce990d728960b2a4767898d1e7ebcb8e12d997919123b4cbc4a2d113c7db57822
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 )
@@ -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
+
@@ -7,18 +7,61 @@
7
7
  require 'bundler/setup'
8
8
  require 'ruby_smb'
9
9
 
10
- def run_negotiation(address, smb1, smb2)
10
+ def run_negotiation(address, smb1, smb2, smb3, opts = {})
11
11
  # Create our socket and add it to the dispatcher
12
12
  sock = TCPSocket.new address, 445
13
13
  dispatcher = RubySMB::Dispatcher::Socket.new(sock)
14
14
 
15
- client = RubySMB::Client.new(dispatcher, smb1: smb1, smb2: smb2, username: 'msfadmin', password: 'msfadmin')
15
+ client = RubySMB::Client.new(dispatcher, smb1: smb1, smb2: smb2, smb3: smb3, username: 'msfadmin', password: 'msfadmin')
16
16
  client.negotiate
17
17
  end
18
18
 
19
- # Negotiate with both SMB1 and SMB2 enabled on the client
20
- run_negotiation(ARGV[0], true, true)
21
- # Negotiate with only SMB1 enabled
22
- run_negotiation(ARGV[0], true, false)
23
- # Negotiate with only SMB2 enabled
24
- run_negotiation(ARGV[0], false, true)
19
+ begin
20
+ puts "Negotiate with only SMB1 enabled..."
21
+ puts " Negotiated version: #{run_negotiation(ARGV[0], true, false, false)}"
22
+ rescue RubySMB::Error::RubySMBError => e
23
+ puts "Error: #{e.message}"
24
+ end
25
+
26
+ begin
27
+ puts "Negotiate with only SMB2 enabled..."
28
+ puts " Negotiated version: #{run_negotiation(ARGV[0], false, true, false)}"
29
+ rescue RubySMB::Error::RubySMBError => e
30
+ puts "Error: #{e.message}"
31
+ end
32
+
33
+ begin
34
+ puts "Negotiate with only SMB3 enabled..."
35
+ puts " Negotiated version: #{run_negotiation(ARGV[0], false, false, true)}"
36
+ rescue RubySMB::Error::RubySMBError => e
37
+ puts "Error: #{e.message}"
38
+ end
39
+
40
+ begin
41
+ puts "Negotiate with both SMB1 and SMB2 enabled on the client..."
42
+ puts " Negotiated version: #{run_negotiation(ARGV[0], true, true, false)}"
43
+ rescue RubySMB::Error::RubySMBError => e
44
+ puts "Error: #{e.message}"
45
+ end
46
+
47
+ begin
48
+ puts "Negotiate with both SMB2 and SMB3 enabled on the client..."
49
+ puts " Negotiated version: #{run_negotiation(ARGV[0], false, true, true)}"
50
+ rescue RubySMB::Error::RubySMBError => e
51
+ puts "Error: #{e.message}"
52
+ end
53
+
54
+ begin
55
+ puts "Negotiate with both SMB1 and SMB3 enabled on the client..."
56
+ puts " Negotiated version: #{run_negotiation(ARGV[0], true, false, true)}"
57
+ rescue RubySMB::Error::RubySMBError => e
58
+ puts "Error: #{e.message}"
59
+ end
60
+
61
+ begin
62
+ puts "Negotiate with SMB1, SMB2 and SMB3 enabled on the client..."
63
+ puts " Negotiated version: #{run_negotiation(ARGV[0], true, true, true)}"
64
+ rescue RubySMB::Error::RubySMBError => e
65
+ puts "Error: #{e.message}"
66
+ end
67
+
@@ -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,56 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This example script is used for testing the reading of a file.
4
+ # It will attempt to connect to a specific share and then read a specified file.
5
+ # Example usage: ruby read_file.rb 192.168.172.138 msfadmin msfadmin TEST_SHARE short.txt
6
+ # This will try to connect to \\192.168.172.138\TEST_SHARE with the msfadmin:msfadmin credentials
7
+ # and read the file short.txt
8
+
9
+ require 'bundler/setup'
10
+ require 'ruby_smb'
11
+
12
+ address = ARGV[0]
13
+ username = ARGV[1]
14
+ password = ARGV[2]
15
+ share = ARGV[3]
16
+ filename = ARGV[4]
17
+ path = "\\\\#{address}\\#{share}"
18
+
19
+ sock = TCPSocket.new address, 445
20
+ dispatcher = RubySMB::Dispatcher::Socket.new(sock)
21
+
22
+ # To require encryption on the server, run this in an elevated Powershell:
23
+ # C:\> Set-SmbServerConfiguration -EncryptData $true
24
+
25
+ # To enable per-share encryption on the server, run this in an elevated Powershell:
26
+ # C:\ Set-SmbServerConfiguration -EncryptData $false
27
+ # C:\ Set-SmbShare -Name <share name> -EncryptData 1
28
+
29
+ # For this encryption to work, it has to be SMBv3. By only setting smb3 to true,
30
+ # we make sure the server will negotiate this version, if it supports it
31
+ opts = {
32
+ smb1: false,
33
+ smb2: false,
34
+ smb3: true,
35
+ username: username,
36
+ password: password,
37
+ }
38
+
39
+ # By default, the client uses encryption even if it is not required by the server. Disable this by setting always_encrypt to false
40
+ #opts[:always_encrypt] = false
41
+
42
+ client = RubySMB::Client.new(dispatcher, opts)
43
+ protocol = client.negotiate
44
+ status = client.authenticate
45
+
46
+ begin
47
+ tree = client.tree_connect(path)
48
+ rescue StandardError => e
49
+ puts "Failed to connect to #{path}: #{e.message}"
50
+ end
51
+
52
+ file = tree.open_file(filename: filename)
53
+
54
+ data = file.read
55
+ puts data
56
+ file.close