ruby_smb 2.0.7 → 2.0.8

Sign up to get free protection for your applications and to get access to all the features.
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'