ruby_smb 2.0.7 → 2.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c1e0d11d506c513f94ddc1efedf51d0e65b5a5f888f8d176cd93ffb960837ba9
4
- data.tar.gz: b971db16ef47093b1d94ff9197b3cf5d222cbd475d9fda693bb0909341605072
3
+ metadata.gz: e3cfb7914736c49c84c366382e133ea0c2e9a5ecb6f0a3badceb498652bbaa76
4
+ data.tar.gz: 6f47a0ad156545a259d0496f9e1c59d50b6327889600b6acda0e93ec5c835963
5
5
  SHA512:
6
- metadata.gz: cb50b51053a49ad9d06109b882eaad4288329f58609626630b4cb3b77cf88acf9fa51243778741d1fac514904bee5cb46ccb97af211aee3983b2ef03a93b47a8
7
- data.tar.gz: c57b3002a49e2a001fd17b1e088ad74dd8b1b465c6d393611817be2ae71217bde1f86fe579025a0af23b8d6e8d894a1ae24f376fda8dc24d5e2a2f274c65ae9f
6
+ metadata.gz: 90c181090093eeb71d4ef508a2b1e7b75ccb31b7e40cdee973397f7554af1085e8b39a518f43e9e4e3eba5fd12d0677d1f059ed614eab8dfb5b0db74a956236a
7
+ data.tar.gz: 443e97e78383d44deb155c0d6e3ca8bc3923c49b2561fa41670e09d7916cdfaa7223143a29b24697699e7470cdcaf6f71a2e0e4167d8c19a7b80b2fc56b2a555
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
@@ -1 +1 @@
1
- l]@@�g���ښ����r2�ƥ�(N:⋚𐻨����t���S���³R+r���(M[y�� =����3�gj83��R�_r@Ѡ@m×ޘ�<��m��`c�@rk��Ȗ�������Ç蚌�YHW��[wQ1Ac�U�}���AW���A=��*�u|�q���J���*��py�o�׬|x0)��*��o���
1
+ �Ss�.�倮�����;�ͦ��c7-ȡ��.�84����R�Q�.]��^�_��w� =r��ܖhu9r(�9 �0D@�˫"c��zN{-��F~U�3����@/��nD~,O���B��^tƯ�F>�Ż��4��tתp@ҫw�,B������j9��
2
2
  ��J�t��&kk��94��*��GTL9p�C
@@ -0,0 +1,56 @@
1
+ name: Verify
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - '*'
7
+ pull_request:
8
+ branches:
9
+ - '*'
10
+
11
+ jobs:
12
+ test:
13
+ runs-on: ubuntu-16.04
14
+ timeout-minutes: 40
15
+
16
+ strategy:
17
+ fail-fast: true
18
+ matrix:
19
+ ruby:
20
+ - 2.5
21
+ - 2.6
22
+ - 2.7
23
+ test_cmd:
24
+ - bundle exec rspec
25
+
26
+ env:
27
+ RAILS_ENV: test
28
+
29
+ name: Ruby ${{ matrix.ruby }} - ${{ matrix.test_cmd }}
30
+ steps:
31
+ - name: Checkout code
32
+ uses: actions/checkout@v2
33
+
34
+ - uses: actions/setup-ruby@v1
35
+ with:
36
+ ruby-version: ${{ matrix.ruby }}
37
+
38
+ - name: Setup bundler
39
+ run: |
40
+ gem install bundler
41
+ - uses: actions/cache@v2
42
+ with:
43
+ path: vendor/bundle
44
+ key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
45
+ restore-keys: |
46
+ ${{ runner.os }}-gems-
47
+ - name: Bundle install
48
+ run: |
49
+ bundle config path vendor/bundle
50
+ bundle install --jobs 4 --retry 3
51
+ - name: ${{ matrix.test_cmd }}
52
+ run: |
53
+ echo "${CMD}"
54
+ bash -c "${CMD}"
55
+ env:
56
+ CMD: ${{ matrix.test_cmd }}
data/README.md CHANGED
@@ -1,6 +1,5 @@
1
1
  # RubySMB
2
2
 
3
- [![Build Status](https://travis-ci.org/rapid7/ruby_smb.svg?branch=master)](https://travis-ci.org/rapid7/ruby_smb)
4
3
  [![Code Climate](https://codeclimate.com/github/rapid7/ruby_smb.png)](https://codeclimate.com/github/rapid7/ruby_smb)
5
4
  [![Coverage Status](https://coveralls.io/repos/github/rapid7/ruby_smb/badge.svg?branch=master)](https://coveralls.io/github/rapid7/ruby_smb?branch=master)
6
5
 
data/lib/ruby_smb.rb CHANGED
@@ -8,8 +8,8 @@ require 'windows_error'
8
8
  require 'windows_error/nt_status'
9
9
  # A packet parsing and manipulation library for the SMB1 and SMB2 protocols
10
10
  #
11
- # [[MS-SMB] Server Mesage Block (SMB) Protocol Version 1](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
12
- # [[MS-SMB2] Server Mesage Block (SMB) Protocol Versions 2 and 3](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
11
+ # [[MS-SMB] Server Message Block (SMB) Protocol Version 1](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
12
+ # [[MS-SMB2] Server Message Block (SMB) Protocol Versions 2 and 3](https://msdn.microsoft.com/en-us/library/cc246482.aspx)
13
13
  module RubySMB
14
14
  require 'ruby_smb/error'
15
15
  require 'ruby_smb/dispositions'
@@ -26,4 +26,5 @@ module RubySMB
26
26
  require 'ruby_smb/smb1'
27
27
  require 'ruby_smb/client'
28
28
  require 'ruby_smb/crypto'
29
+ require 'ruby_smb/compression'
29
30
  end
@@ -296,7 +296,7 @@ module RubySMB
296
296
  @smb3 = smb3
297
297
  @username = username.encode('utf-8') || ''.encode('utf-8')
298
298
  @max_buffer_size = MAX_BUFFER_SIZE
299
- # These sizes will be modifed during negotiation
299
+ # These sizes will be modified during negotiation
300
300
  @server_max_buffer_size = SERVER_MAX_BUFFER_SIZE
301
301
  @server_max_read_size = RubySMB::SMB2::File::MAX_PACKET_SIZE
302
302
  @server_max_write_size = RubySMB::SMB2::File::MAX_PACKET_SIZE
@@ -431,7 +431,7 @@ module RubySMB
431
431
  end
432
432
 
433
433
  # Sends a packet and receives the raw response through the Dispatcher.
434
- # It will also sign the packet if neccessary.
434
+ # It will also sign the packet if necessary.
435
435
  #
436
436
  # @param packet [RubySMB::GenericPacket] the request to be sent
437
437
  # @param encrypt [Boolean] true if encryption has to be enabled for this transaction
@@ -275,8 +275,8 @@ module RubySMB
275
275
  context_type: RubySMB::SMB2::NegotiateContext::SMB2_COMPRESSION_CAPABILITIES
276
276
  )
277
277
  # Adding all possible compression algorithm even if we don't support
278
- # them yet. This will force the server to disclose the support
279
- # algorithms in the repsonse.
278
+ # them yet. This will force the server to disclose the supported
279
+ # algorithms in the response.
280
280
  nc.data.compression_algorithms << RubySMB::SMB2::CompressionCapabilities::LZNT1
281
281
  nc.data.compression_algorithms << RubySMB::SMB2::CompressionCapabilities::LZ77
282
282
  nc.data.compression_algorithms << RubySMB::SMB2::CompressionCapabilities::LZ77_Huffman
@@ -0,0 +1,7 @@
1
+ module RubySMB
2
+ module Compression
3
+
4
+ require 'ruby_smb/compression/lznt1'
5
+
6
+ end
7
+ end
@@ -0,0 +1,164 @@
1
+ module RubySMB
2
+ module Compression
3
+ module LZNT1
4
+ def self.compress(buf, chunk_size: 0x1000)
5
+ out = ''
6
+ until buf.empty?
7
+ chunk = buf[0...chunk_size]
8
+ compressed = compress_chunk(chunk)
9
+ # chunk is compressed
10
+ if compressed.length < chunk.length
11
+ out << [0xb000 | (compressed.length - 1)].pack('v')
12
+ out << compressed
13
+ else
14
+ out << [0x3000 | (chunk.length - 1)].pack('v')
15
+ out << chunk
16
+ end
17
+ buf = buf[chunk_size..-1]
18
+ break if buf.nil?
19
+ end
20
+
21
+ out
22
+ end
23
+
24
+ def self.compress_chunk(chunk)
25
+ blob = chunk
26
+ out = ''
27
+ pow2 = 0x10
28
+ l_mask3 = 0x1002
29
+ o_shift = 12
30
+ until blob.empty?
31
+ bits = 0
32
+ tmp = ''
33
+ i = -1
34
+ loop do
35
+ i += 1
36
+ bits >>= 1
37
+ while pow2 < (chunk.length - blob.length)
38
+ pow2 <<= 1
39
+ l_mask3 = (l_mask3 >> 1) + 1
40
+ o_shift -= 1
41
+ end
42
+
43
+ max_len = [blob.length, l_mask3].min
44
+ offset, length = find(chunk[0...(chunk.length - blob.length)], blob, max_len)
45
+
46
+ # try to find more compressed pattern
47
+ _offset2, length2 = find(chunk[0...chunk.length - blob.length + 1], blob[1..-1], max_len)
48
+
49
+ length = 0 if length < length2
50
+
51
+ if length > 0
52
+ symbol = ((offset - 1) << o_shift) | (length - 3)
53
+ tmp << [symbol].pack('v')
54
+ # set the highest bit
55
+ bits |= 0x80
56
+ blob = blob[length..-1]
57
+ else
58
+ tmp += blob[0]
59
+ blob = blob[1..-1]
60
+ end
61
+
62
+ break if blob.empty? || i == 7
63
+ end
64
+
65
+ out << [bits >> (7 - i)].pack('C')
66
+ out << tmp
67
+ end
68
+
69
+ out
70
+ end
71
+
72
+ def self.decompress(buf, length_check: true)
73
+ out = ''
74
+ until buf.empty?
75
+ header = buf.unpack1('v')
76
+ length = (header & 0xfff) + 1
77
+ raise EncodingError, 'invalid chunk length' if length_check && length > (buf.length - 2)
78
+
79
+ chunk = buf[2...length + 2]
80
+ out << if header & 0x8000 == 0
81
+ chunk
82
+ else
83
+ decompress_chunk(chunk)
84
+ end
85
+ buf = buf[length + 2..-1]
86
+ end
87
+
88
+ out
89
+ end
90
+
91
+ def self.decompress_chunk(chunk)
92
+ out = ''
93
+ until chunk.empty?
94
+ flags = chunk[0].unpack1('C')
95
+ chunk = chunk[1..-1]
96
+ 8.times do |i|
97
+ if (flags >> i & 1) == 0
98
+ out << chunk[0]
99
+ chunk = chunk[1..-1]
100
+ else
101
+ flag = chunk.unpack1('v')
102
+ pos = out.length - 1
103
+ l_mask = 0xfff
104
+ o_shift = 12
105
+ while pos >= 0x10
106
+ l_mask >>= 1
107
+ o_shift -= 1
108
+ pos >>= 1
109
+ end
110
+
111
+ length = (flag & l_mask) + 3
112
+ offset = (flag >> o_shift) + 1
113
+
114
+ if length >= offset
115
+ out_offset = out[-offset..-1]
116
+ tmp = out_offset * (0xfff / out_offset.length + 1)
117
+ out << tmp[0...length]
118
+ else
119
+ out << out[-offset..-offset + length - 1]
120
+ end
121
+ chunk = chunk[2..-1]
122
+ end
123
+ break if chunk.empty?
124
+ end
125
+ end
126
+
127
+ out
128
+ end
129
+
130
+ class << self
131
+ private
132
+
133
+ def find(src, target, max_len)
134
+ result_offset = 0
135
+ result_length = 0
136
+ 1.upto(max_len - 1) do |i|
137
+ offset = src.rindex(target[0...i])
138
+ next if offset.nil?
139
+
140
+ tmp_offset = src.length - offset
141
+ tmp_length = i
142
+ if tmp_offset == tmp_length
143
+ src_offset = src[offset..-1]
144
+ tmp = src_offset * (0xfff / src_offset.length + 1)
145
+ i.upto(max_len) do |j|
146
+ offset = tmp.rindex(target[0...j])
147
+ break if offset.nil?
148
+
149
+ tmp_length = j
150
+ end
151
+ end
152
+
153
+ if tmp_length > result_length
154
+ result_offset = tmp_offset
155
+ result_length = tmp_length
156
+ end
157
+ end
158
+
159
+ result_length < 3 ? [0, 0] : [result_offset, result_length]
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
@@ -55,7 +55,7 @@ module RubySMB
55
55
 
56
56
  # Read a packet off the wire and parse it into a string
57
57
  #
58
- # @param full_response [Boolean] whether to include the NetBios Session Service header in the repsonse
58
+ # @param full_response [Boolean] whether to include the NetBios Session Service header in the response
59
59
  # @return [String] the raw response (including the NetBios Session Service header if full_response is true)
60
60
  # @raise [RubySMB::Error::NetBiosSessionService] if there's an error reading the first 4 bytes,
61
61
  # which are assumed to be the NetBiosSessionService header.
@@ -3,6 +3,9 @@ module RubySMB
3
3
  module Packet
4
4
  # An SMB2 COMPRESSION_TRANSFORM_HEADER Packet as defined in
5
5
  # [2.2.42 SMB2 COMPRESSION_TRANSFORM_HEADER](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/1d435f21-9a21-4f4c-828e-624a176cf2a0)
6
+ # NOTE: On 2021-04-06 the official documentation split the definition of COMPRESSION_TRANSFORM_HEADER into the following two variants:
7
+ # * SMB2_COMPRESSION_TRANSFORM_HEADER_CHAINED
8
+ # * SMB2_COMPRESSION_TRANSFORM_HEADER_UNCHAINED
6
9
  class CompressionTransformHeader < BinData::Record
7
10
  endian :little
8
11
 
@@ -11,6 +14,7 @@ module RubySMB
11
14
  uint16 :compression_algorithm, label: 'Compression Algorithm'
12
15
  uint16 :flags, label: 'Flags'
13
16
  uint32 :offset, label: 'Offset / Length'
17
+ array :compressed_data, label: 'Compressed Data', type: :uint8, read_until: :eof
14
18
  end
15
19
 
16
20
  # An SMB2 SMB2_COMPRESSION_TRANSFORM_HEADER_PAYLOAD Packet as defined in
@@ -1,3 +1,3 @@
1
1
  module RubySMB
2
- VERSION = '2.0.7'.freeze
2
+ VERSION = '2.0.8'.freeze
3
3
  end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RubySMB::Compression::LZNT1 do
4
+ describe '.compress' do
5
+ it 'generates an empty blob when provided an empty blob' do
6
+ expected = "".b
7
+ expect(described_class.compress('')).to eq(expected)
8
+ end
9
+
10
+ it 'generates a compressed blob when provided a string with non-reoccurring characters' do
11
+ expect(described_class.compress('RubySMB')).to eq("\x060RubySMB".b)
12
+ end
13
+
14
+ it 'generates a compressed blob when provided a string of reoccurring characters' do
15
+ expect(described_class.compress("\x01" * 0x200)).to eq("\x03\xB0\x02\x01\xFC\x01".b)
16
+ end
17
+ end
18
+
19
+ describe '.decompress' do
20
+ it 'generates a decompressed blob for a string with non-reoccurring characters' do
21
+ expect(described_class.decompress("\x060RubySMB".b)).to eq('RubySMB')
22
+ end
23
+
24
+ it 'generates a decompressed blob for a string of reoccurring characters' do
25
+ expect(described_class.decompress("\x03\xB0\x02\x01\xFC\x01".b)).to eq("\x01" * 0x200)
26
+ end
27
+
28
+ it 'raises an EncodingError when the length is invalid' do
29
+ expect { described_class.decompress("\x010".b) }.to raise_error(EncodingError)
30
+ end
31
+ end
32
+ end
data/spec/spec_helper.rb CHANGED
@@ -7,7 +7,7 @@ end
7
7
  require 'coveralls'
8
8
  require 'ruby_smb'
9
9
 
10
- if ENV['TRAVIS'] == 'true'
10
+ if ENV['CI'] == 'true'
11
11
  # don't generate local report as it is inaccessible on travis-ci, which is
12
12
  # why coveralls is being used.
13
13
  SimpleCov.formatter = Coveralls::SimpleCov::Formatter
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_smb
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.7
4
+ version: 2.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Metasploit Hackers
@@ -97,7 +97,7 @@ cert_chain:
97
97
  EknWpNgVhohbot1lfVAMmIhdtOVaRVcQQixWPwprDj/ydB8ryDMDosIMcw+fkoXU
98
98
  9GJsSaSRRYQ9UUkVL27b64okU8D48m8=
99
99
  -----END CERTIFICATE-----
100
- date: 2020-11-19 00:00:00.000000000 Z
100
+ date: 2021-04-09 00:00:00.000000000 Z
101
101
  dependencies:
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: redcarpet
@@ -246,10 +246,10 @@ executables: []
246
246
  extensions: []
247
247
  extra_rdoc_files: []
248
248
  files:
249
+ - ".github/workflows/verify.yml"
249
250
  - ".gitignore"
250
251
  - ".rspec"
251
252
  - ".simplecov"
252
- - ".travis.yml"
253
253
  - ".yardopts"
254
254
  - CONTRIBUTING.md
255
255
  - Gemfile
@@ -284,6 +284,8 @@ files:
284
284
  - lib/ruby_smb/client/tree_connect.rb
285
285
  - lib/ruby_smb/client/utils.rb
286
286
  - lib/ruby_smb/client/winreg.rb
287
+ - lib/ruby_smb/compression.rb
288
+ - lib/ruby_smb/compression/lznt1.rb
287
289
  - lib/ruby_smb/crypto.rb
288
290
  - lib/ruby_smb/dcerpc.rb
289
291
  - lib/ruby_smb/dcerpc/bind.rb
@@ -526,6 +528,7 @@ files:
526
528
  - lib/ruby_smb/version.rb
527
529
  - ruby_smb.gemspec
528
530
  - spec/lib/ruby_smb/client_spec.rb
531
+ - spec/lib/ruby_smb/compression/lznt1_spec.rb
529
532
  - spec/lib/ruby_smb/crypto_spec.rb
530
533
  - spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb
531
534
  - spec/lib/ruby_smb/dcerpc/bind_spec.rb
@@ -760,6 +763,7 @@ specification_version: 4
760
763
  summary: A pure Ruby implementation of the SMB Protocol Family
761
764
  test_files:
762
765
  - spec/lib/ruby_smb/client_spec.rb
766
+ - spec/lib/ruby_smb/compression/lznt1_spec.rb
763
767
  - spec/lib/ruby_smb/crypto_spec.rb
764
768
  - spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb
765
769
  - spec/lib/ruby_smb/dcerpc/bind_spec.rb
metadata.gz.sig CHANGED
Binary file
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- language: ruby
2
- sudo: false
3
- rvm:
4
- - '2.5.8'
5
- - '2.6.6'
6
- - '2.7.0'