Skip to content

Commit a902480

Browse files
committed
Break out subclasses into their own files
1 parent 0938190 commit a902480

File tree

3 files changed

+168
-149
lines changed

3 files changed

+168
-149
lines changed

lib/rex/proto/smb/simpleclient.rb

Lines changed: 5 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ class SimpleClient
1212
require 'rex/proto/smb/crypt'
1313
require 'rex/proto/smb/utils'
1414
require 'rex/proto/smb/client'
15+
require 'rex/proto/smb/simpleclient/open_file'
16+
require 'rex/proto/smb/simpleclient/open_pipe'
1517

1618
# Some short-hand class aliases
1719
CONST = Rex::Proto::SMB::Constants
@@ -20,157 +22,11 @@ class SimpleClient
2022
XCEPT = Rex::Proto::SMB::Exceptions
2123
EVADE = Rex::Proto::SMB::Evasions
2224

23-
24-
class OpenFile
25-
attr_accessor :name, :tree_id, :file_id, :mode, :client, :chunk_size
26-
27-
def initialize(client, name, tree_id, file_id)
28-
self.client = client
29-
self.name = name
30-
self.tree_id = tree_id
31-
self.file_id = file_id
32-
self.chunk_size = 48000
33-
end
34-
35-
def delete
36-
begin
37-
self.close
38-
rescue
39-
end
40-
self.client.delete(self.name, self.tree_id)
41-
end
42-
43-
# Close this open file
44-
def close
45-
self.client.close(self.file_id, self.tree_id)
46-
end
47-
48-
# Read data from the file
49-
def read(length = nil, offset = 0)
50-
if (length == nil)
51-
data = ''
52-
fptr = offset
53-
ok = self.client.read(self.file_id, fptr, self.chunk_size)
54-
while (ok and ok['Payload'].v['DataLenLow'] > 0)
55-
buff = ok.to_s.slice(
56-
ok['Payload'].v['DataOffset'] + 4,
57-
ok['Payload'].v['DataLenLow']
58-
)
59-
data << buff
60-
if ok['Payload'].v['Remaining'] == 0
61-
break
62-
end
63-
fptr += ok['Payload'].v['DataLenLow']
64-
65-
begin
66-
ok = self.client.read(self.file_id, fptr, self.chunk_size)
67-
rescue XCEPT::ErrorCode => e
68-
case e.error_code
69-
when 0x00050001
70-
# Novell fires off an access denied error on EOF
71-
ok = nil
72-
else
73-
raise e
74-
end
75-
end
76-
end
77-
78-
return data
79-
else
80-
ok = self.client.read(self.file_id, offset, length)
81-
data = ok.to_s.slice(
82-
ok['Payload'].v['DataOffset'] + 4,
83-
ok['Payload'].v['DataLenLow']
84-
)
85-
return data
86-
end
87-
end
88-
89-
def << (data)
90-
self.write(data)
91-
end
92-
93-
# Write data to the file
94-
def write(data, offset = 0)
95-
# Track our offset into the remote file
96-
fptr = offset
97-
98-
# Duplicate the data so we can use slice!
99-
data = data.dup
100-
101-
# Take our first chunk of bytes
102-
chunk = data.slice!(0, self.chunk_size)
103-
104-
# Keep writing data until we run out
105-
while (chunk.length > 0)
106-
ok = self.client.write(self.file_id, fptr, chunk)
107-
cl = ok['Payload'].v['CountLow']
108-
109-
# Partial write, push the failed data back into the queue
110-
if (cl != chunk.length)
111-
data = chunk.slice(cl - 1, chunk.length - cl) + data
112-
end
113-
114-
# Increment our painter and grab the next chunk
115-
fptr += cl
116-
chunk = data.slice!(0, self.chunk_size)
117-
end
118-
end
119-
end
120-
121-
class OpenPipe < OpenFile
122-
123-
# Valid modes are: 'trans' and 'rw'
124-
attr_accessor :mode
125-
126-
def initialize(*args)
127-
super(*args)
128-
self.mode = 'rw'
129-
@buff = ''
130-
end
131-
132-
def read_buffer(length, offset=0)
133-
length ||= @buff.length
134-
@buff.slice!(0, length)
135-
end
136-
137-
def read(length = nil, offset = 0)
138-
case self.mode
139-
when 'trans'
140-
read_buffer(length, offset)
141-
when 'rw'
142-
super(length, offset)
143-
else
144-
raise ArgumentError
145-
end
146-
end
147-
148-
def write(data, offset = 0)
149-
case self.mode
150-
151-
when 'trans'
152-
write_trans(data, offset)
153-
when 'rw'
154-
super(data, offset)
155-
else
156-
raise ArgumentError
157-
end
158-
end
159-
160-
def write_trans(data, offset=0)
161-
ack = self.client.trans_named_pipe(self.file_id, data)
162-
doff = ack['Payload'].v['DataOffset']
163-
dlen = ack['Payload'].v['DataCount']
164-
@buff << ack.to_s[4+doff, dlen]
165-
end
166-
end
167-
168-
16925
# Public accessors
170-
attr_accessor :last_error
26+
attr_accessor :last_error
17127

17228
# Private accessors
173-
attr_accessor :socket, :client, :direct, :shares, :last_share
29+
attr_accessor :socket, :client, :direct, :shares, :last_share
17430

17531
# Pass the socket object and a boolean indicating whether the socket is netbios or cifs
17632
def initialize(socket, direct = false)
@@ -180,7 +36,7 @@ def initialize(socket, direct = false)
18036
self.shares = { }
18137
end
18238

183-
def login( name = '', user = '', pass = '', domain = '',
39+
def login(name = '', user = '', pass = '', domain = '',
18440
verify_signature = false, usentlmv2 = false, usentlm2_session = true,
18541
send_lm = true, use_lanman_key = false, send_ntlm = true,
18642
native_os = 'Windows 2000 2195', native_lm = 'Windows 2000 5.0', spnopt = {})
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# -*- coding: binary -*-
2+
module Rex
3+
module Proto
4+
module SMB
5+
class SimpleClient
6+
7+
class OpenFile
8+
attr_accessor :name, :tree_id, :file_id, :mode, :client, :chunk_size
9+
10+
def initialize(client, name, tree_id, file_id)
11+
self.client = client
12+
self.name = name
13+
self.tree_id = tree_id
14+
self.file_id = file_id
15+
self.chunk_size = 48000
16+
end
17+
18+
def delete
19+
begin
20+
self.close
21+
rescue
22+
end
23+
self.client.delete(self.name, self.tree_id)
24+
end
25+
26+
# Close this open file
27+
def close
28+
self.client.close(self.file_id, self.tree_id)
29+
end
30+
31+
# Read data from the file
32+
def read(length = nil, offset = 0)
33+
if (length == nil)
34+
data = ''
35+
fptr = offset
36+
ok = self.client.read(self.file_id, fptr, self.chunk_size)
37+
while (ok and ok['Payload'].v['DataLenLow'] > 0)
38+
buff = ok.to_s.slice(
39+
ok['Payload'].v['DataOffset'] + 4,
40+
ok['Payload'].v['DataLenLow']
41+
)
42+
data << buff
43+
if ok['Payload'].v['Remaining'] == 0
44+
break
45+
end
46+
fptr += ok['Payload'].v['DataLenLow']
47+
48+
begin
49+
ok = self.client.read(self.file_id, fptr, self.chunk_size)
50+
rescue XCEPT::ErrorCode => e
51+
case e.error_code
52+
when 0x00050001
53+
# Novell fires off an access denied error on EOF
54+
ok = nil
55+
else
56+
raise e
57+
end
58+
end
59+
end
60+
61+
return data
62+
else
63+
ok = self.client.read(self.file_id, offset, length)
64+
data = ok.to_s.slice(
65+
ok['Payload'].v['DataOffset'] + 4,
66+
ok['Payload'].v['DataLenLow']
67+
)
68+
return data
69+
end
70+
end
71+
72+
def << (data)
73+
self.write(data)
74+
end
75+
76+
# Write data to the file
77+
def write(data, offset = 0)
78+
# Track our offset into the remote file
79+
fptr = offset
80+
81+
# Duplicate the data so we can use slice!
82+
data = data.dup
83+
84+
# Take our first chunk of bytes
85+
chunk = data.slice!(0, self.chunk_size)
86+
87+
# Keep writing data until we run out
88+
while (chunk.length > 0)
89+
ok = self.client.write(self.file_id, fptr, chunk)
90+
cl = ok['Payload'].v['CountLow']
91+
92+
# Partial write, push the failed data back into the queue
93+
if (cl != chunk.length)
94+
data = chunk.slice(cl - 1, chunk.length - cl) + data
95+
end
96+
97+
# Increment our painter and grab the next chunk
98+
fptr += cl
99+
chunk = data.slice!(0, self.chunk_size)
100+
end
101+
end
102+
end
103+
end
104+
end
105+
end
106+
end
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# -*- coding: binary -*-
2+
3+
module Rex
4+
module Proto
5+
module SMB
6+
class SimpleClient
7+
8+
class OpenPipe < OpenFile
9+
10+
# Valid modes are: 'trans' and 'rw'
11+
attr_accessor :mode
12+
13+
def initialize(*args)
14+
super(*args)
15+
self.mode = 'rw'
16+
@buff = ''
17+
end
18+
19+
def read_buffer(length, offset=0)
20+
length ||= @buff.length
21+
@buff.slice!(0, length)
22+
end
23+
24+
def read(length = nil, offset = 0)
25+
case self.mode
26+
when 'trans'
27+
read_buffer(length, offset)
28+
when 'rw'
29+
super(length, offset)
30+
else
31+
raise ArgumentError
32+
end
33+
end
34+
35+
def write(data, offset = 0)
36+
case self.mode
37+
38+
when 'trans'
39+
write_trans(data, offset)
40+
when 'rw'
41+
super(data, offset)
42+
else
43+
raise ArgumentError
44+
end
45+
end
46+
47+
def write_trans(data, offset=0)
48+
ack = self.client.trans_named_pipe(self.file_id, data)
49+
doff = ack['Payload'].v['DataOffset']
50+
dlen = ack['Payload'].v['DataCount']
51+
@buff << ack.to_s[4+doff, dlen]
52+
end
53+
end
54+
end
55+
end
56+
end
57+
end

0 commit comments

Comments
 (0)