CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/proto/dcerpc/packet.rb
Views: 11704
1
# -*- coding: binary -*-
2
module Rex
3
module Proto
4
module DCERPC
5
class Packet
6
7
require 'rex/text'
8
9
UUID = Rex::Proto::DCERPC::UUID
10
11
# Create a standard DCERPC BIND request packet
12
def self.make_bind(uuid, vers, xfer_syntax_uuid=UUID.xfer_syntax_uuid, xfer_syntax_vers=UUID.xfer_syntax_vers)
13
14
# Process the version strings ("1.0", 1.0, "1", 1)
15
bind_vers_maj, bind_vers_min = UUID.vers_to_nums(vers)
16
xfer_vers_maj, xfer_vers_min = UUID.vers_to_nums(xfer_syntax_vers)
17
18
if UUID.is? xfer_syntax_uuid
19
xfer_syntax_uuid = UUID.uuid_pack(xfer_syntax_uuid)
20
end
21
22
# Create the bind request packet
23
buff =
24
[
25
5, # major version 5
26
0, # minor version 0
27
11, # bind type
28
3, # flags
29
0x10000000, # data representation
30
72, # frag length
31
0, # auth length
32
0, # call id
33
5840, # max xmit frag
34
5840, # max recv frag
35
0, # assoc group
36
1, # num ctx items
37
0, # context id
38
1, # num trans items
39
UUID.uuid_pack(uuid), # interface uuid
40
bind_vers_maj, # interface major version
41
bind_vers_min, # interface minor version
42
xfer_syntax_uuid, # transfer syntax
43
xfer_vers_maj, # syntax major version
44
xfer_vers_min, # syntax minor version
45
].pack('CCCCNvvVvvVVvvA16vvA16vv')
46
47
return buff, 0
48
end
49
50
# Create an obfuscated DCERPC BIND request packet
51
def self.make_bind_fake_multi(uuid, vers, bind_head=0, bind_tail=0)
52
53
bind_head = bind_head.to_i
54
bind_tail = bind_tail.to_i
55
bind_head = rand(6)+10 if bind_head == 0
56
bind_tail = rand(4)+1 if bind_head == 0
57
58
u = Rex::Proto::DCERPC::UUID
59
60
# Process the version strings ("1.0", 1.0, "1", 1)
61
bind_vers_maj, bind_vers_min = UUID.vers_to_nums(vers)
62
xfer_vers_maj, xfer_vers_min = UUID.vers_to_nums(UUID.xfer_syntax_vers)
63
64
bind_total = bind_head + bind_tail + 1
65
bind_size = (bind_total * 44) + 28
66
real_ctx, ctx = 0, 0
67
68
# Create the header of the bind request
69
data =
70
[
71
5, # major version 5
72
0, # minor version 0
73
11, # bind type
74
3, # flags
75
0x10000000, # data representation
76
bind_size, # frag length
77
0, # auth length
78
0, # call id
79
5840, # max xmit frag
80
5840, # max recv frag
81
0, # assoc group
82
bind_total, # num ctx items
83
].pack('CCCCNvvVvvVV')
84
85
# Generate the fake UUIDs prior to the real one
86
1.upto(bind_head) do ||
87
# Generate some random UUID and versions
88
rand_uuid = Rex::Text.rand_text(16)
89
rand_imaj = rand(6)
90
rand_imin = rand(4)
91
92
data +=
93
[
94
ctx, # context id
95
1, # num trans items
96
rand_uuid, # interface uuid
97
rand_imaj, # interface major version
98
rand_imin, # interface minor version
99
UUID.xfer_syntax_uuid, # transfer syntax
100
xfer_vers_maj, # syntax major version
101
xfer_vers_min, # syntax minor version
102
].pack('vvA16vvA16vv')
103
ctx += 1
104
end
105
106
# Stuff the real UUID onto the end of the buffer
107
real_ctx = ctx;
108
data +=
109
[
110
ctx, # context id
111
1, # num trans items
112
UUID.uuid_pack(uuid), # interface uuid
113
bind_vers_maj, # interface major version
114
bind_vers_min, # interface minor version
115
UUID.xfer_syntax_uuid, # transfer syntax
116
xfer_vers_maj, # syntax major version
117
xfer_vers_min, # syntax minor version
118
].pack('vvA16vvA16vv')
119
ctx += 1
120
121
122
# Generate the fake UUIDs after the real one
123
1.upto(bind_tail) do ||
124
# Generate some random UUID and versions
125
rand_uuid = Rex::Text.rand_text(16)
126
rand_imaj = rand(6)
127
rand_imin = rand(4)
128
129
data +=
130
[
131
ctx, # context id
132
1, # num trans items
133
rand_uuid, # interface uuid
134
rand_imaj, # interface major version
135
rand_imin, # interface minor version
136
UUID.xfer_syntax_uuid, # transfer syntax
137
xfer_vers_maj, # syntax major version
138
xfer_vers_min, # syntax minor version
139
].pack('vvA16vvA16vv')
140
ctx += 1
141
end
142
143
# Return both the bind packet and the real context_id
144
return data, real_ctx
145
end
146
147
# Create a standard DCERPC ALTER_CONTEXT request packet
148
def self.make_alter_context(uuid, vers)
149
u = Rex::Proto::DCERPC::UUID
150
151
# Process the version strings ("1.0", 1.0, "1", 1)
152
bind_vers_maj, bind_vers_min = UUID.vers_to_nums(vers)
153
xfer_vers_maj, xfer_vers_min = UUID.vers_to_nums(UUID.xfer_syntax_vers)
154
155
buff =
156
[
157
5, # major version 5
158
0, # minor version 0
159
14, # alter context
160
3, # flags
161
0x10000000, # data representation
162
72, # frag length
163
0, # auth length
164
0, # call id
165
5840, # max xmit frag
166
5840, # max recv frag
167
0, # assoc group
168
1, # num ctx items
169
0, # context id
170
1, # num trans items
171
UUID.uuid_pack(uuid), # interface uuid
172
bind_vers_maj, # interface major version
173
bind_vers_min, # interface minor version
174
UUID.xfer_syntax_uuid, # transfer syntax
175
xfer_vers_maj, # syntax major version
176
xfer_vers_min, # syntax minor version
177
].pack('CCCCNvvVvvVVvvA16vvA16vv')
178
end
179
180
181
# Used to create a piece of a DCERPC REQUEST packet
182
def self.make_request_chunk(flags=3, opnum=0, data="", ctx=0, object_id = '')
183
184
flags = flags.to_i
185
opnum = opnum.to_i
186
ctx = ctx.to_i
187
188
dlen = data.length
189
flen = dlen + 24
190
191
use_object = 0
192
193
object_str = ''
194
195
if object_id.size > 0
196
flags |= 0x80
197
flen = flen + 16
198
object_str = UUID.uuid_pack(object_id)
199
end
200
201
buff =
202
[
203
5, # major version 5
204
0, # minor version 0
205
0, # request type
206
flags, # flags
207
0x10000000, # data representation
208
flen, # frag length
209
0, # auth length
210
0, # call id
211
dlen, # alloc hint
212
ctx, # context id
213
opnum, # operation number
214
].pack('CCCCNvvVVvv') + object_str + data
215
end
216
217
# Used to create standard DCERPC REQUEST packet(s)
218
def self.make_request(opnum=0, data="", size=data.length, ctx=0, object_id = '')
219
220
opnum = opnum.to_i
221
size = [4000, size.to_i].min
222
ctx = ctx.to_i
223
224
chunks, frags = [], []
225
ptr = 0
226
227
# Break the request into fragments of 'size' bytes
228
while ptr < data.length
229
chunks.push( data[ ptr, size ] )
230
ptr += size
231
end
232
233
# Process requests with no stub data
234
if chunks.length == 0
235
frags.push( make_request_chunk(3, opnum, '', ctx, object_id) )
236
return frags
237
end
238
239
# Process requests with only one fragment
240
if chunks.length == 1
241
frags.push( make_request_chunk(3, opnum, chunks[0], ctx, object_id) )
242
return frags
243
end
244
245
# Create the first fragment of the request
246
frags.push( make_request_chunk(1, opnum, chunks.shift, ctx, object_id) )
247
248
# Create all of the middle fragments
249
while chunks.length != 1
250
frags.push( make_request_chunk(0, opnum, chunks.shift, ctx, object_id) )
251
end
252
253
# Create the last fragment of the request
254
frags.push( make_request_chunk(2, opnum, chunks.shift, ctx, object_id) )
255
256
return frags
257
end
258
259
end
260
end
261
end
262
end
263
264