rex-encoder 0.1.0
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 +7 -0
- checksums.yaml.gz.sig +1 -0
- data.tar.gz.sig +0 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/README.md +32 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/rex/encoder.rb +15 -0
- data/lib/rex/encoder/alpha2.rb +31 -0
- data/lib/rex/encoder/alpha2/alpha_mixed.rb +129 -0
- data/lib/rex/encoder/alpha2/alpha_upper.rb +138 -0
- data/lib/rex/encoder/alpha2/generic.rb +90 -0
- data/lib/rex/encoder/alpha2/unicode_mixed.rb +116 -0
- data/lib/rex/encoder/alpha2/unicode_upper.rb +123 -0
- data/lib/rex/encoder/bloxor/bloxor.rb +327 -0
- data/lib/rex/encoder/ndr.rb +90 -0
- data/lib/rex/encoder/nonalpha.rb +61 -0
- data/lib/rex/encoder/nonupper.rb +64 -0
- data/lib/rex/encoder/version.rb +5 -0
- data/lib/rex/encoder/xdr.rb +108 -0
- data/lib/rex/encoder/xor.rb +69 -0
- data/lib/rex/encoder/xor/dword.rb +13 -0
- data/lib/rex/encoder/xor/dword_additive.rb +13 -0
- data/lib/rex/encoding/xor.rb +20 -0
- data/lib/rex/encoding/xor/byte.rb +15 -0
- data/lib/rex/encoding/xor/dword.rb +21 -0
- data/lib/rex/encoding/xor/dword_additive.rb +92 -0
- data/lib/rex/encoding/xor/exceptions.rb +17 -0
- data/lib/rex/encoding/xor/generic.rb +146 -0
- data/lib/rex/encoding/xor/qword.rb +15 -0
- data/lib/rex/encoding/xor/word.rb +21 -0
- data/lib/rex/poly.rb +134 -0
- data/lib/rex/poly/block.rb +480 -0
- data/lib/rex/poly/machine.rb +13 -0
- data/lib/rex/poly/machine/machine.rb +830 -0
- data/lib/rex/poly/machine/x86.rb +509 -0
- data/lib/rex/poly/register.rb +101 -0
- data/lib/rex/poly/register/x86.rb +41 -0
- data/rex-encoder.gemspec +31 -0
- metadata +248 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,480 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
module Rex
|
3
|
+
module Poly
|
4
|
+
|
5
|
+
###
|
6
|
+
#
|
7
|
+
# This class encapsulates a LogicalBlock permutation. Block permutations can
|
8
|
+
# take the form of a static string or a procedure. This makes it possible to
|
9
|
+
# have simple blocks and more complicated ones that take into account other
|
10
|
+
# variables, such as dynamic registers. The to_s method will return the
|
11
|
+
# string version of the permutation, regardless of whether or not the
|
12
|
+
# underlying permutation is a string or a procedure.
|
13
|
+
#
|
14
|
+
###
|
15
|
+
class Permutation
|
16
|
+
|
17
|
+
#
|
18
|
+
# Initializes the permutation and its associated block.
|
19
|
+
#
|
20
|
+
def initialize(perm, block)
|
21
|
+
@perm = perm
|
22
|
+
@block = block
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Returns the length of the string returned by to_s.
|
27
|
+
#
|
28
|
+
def length
|
29
|
+
to_s.length
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Returns the string representation of the permutation. If the underlying
|
34
|
+
# permutation is a procedure, the procedure is called. Otherwise, the
|
35
|
+
# string representation of the permutation is returned.
|
36
|
+
#
|
37
|
+
def to_s
|
38
|
+
if (@perm.kind_of?(Proc))
|
39
|
+
@perm.call(@block).to_s
|
40
|
+
else
|
41
|
+
@perm.to_s
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_reader :perm
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
###
|
50
|
+
#
|
51
|
+
# This class represents a logical block which is defined as a concise portion
|
52
|
+
# of code that may have one or more functionally equivalent implementations.
|
53
|
+
# A logical block should serve a very specific purpose, and any permutations
|
54
|
+
# beyond the first should result in exactly the same functionality without any
|
55
|
+
# adverse side effects to other blocks.
|
56
|
+
#
|
57
|
+
# Like blocks of code, LogicalBlock's can depend on one another in terms of
|
58
|
+
# ordering and precedence. By marking blocks as dependent on another, a
|
59
|
+
# hierarchy begins to form. This is a block dependency graph.
|
60
|
+
#
|
61
|
+
# To add permutations to a LogicalBlock, they can either be passed in as a
|
62
|
+
# list of arguments to the constructor following the blocks name or can be
|
63
|
+
# added on the fly by calling the add_perm method. To get a random
|
64
|
+
# permutation, the rand_perm method can be called.
|
65
|
+
#
|
66
|
+
# To mark one block as depending on another, the depends_on method can be
|
67
|
+
# called with zero or more LogicalBlock instances as parameters.
|
68
|
+
#
|
69
|
+
###
|
70
|
+
class LogicalBlock
|
71
|
+
|
72
|
+
#
|
73
|
+
# Initializes the logical block's name along with zero or more specific
|
74
|
+
# blocks.
|
75
|
+
#
|
76
|
+
def initialize(name, *perms)
|
77
|
+
@name = name
|
78
|
+
|
79
|
+
reset
|
80
|
+
|
81
|
+
add_perm(*perms)
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# Resets the block back to its starting point.
|
86
|
+
#
|
87
|
+
def reset
|
88
|
+
@perms = []
|
89
|
+
@depends = []
|
90
|
+
@next_blocks = []
|
91
|
+
@clobbers = []
|
92
|
+
@offset = nil
|
93
|
+
@state = nil
|
94
|
+
@once = false
|
95
|
+
@references = 0
|
96
|
+
@used_references = 0
|
97
|
+
@generated = false
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# Returns the block's name.
|
102
|
+
#
|
103
|
+
def name
|
104
|
+
@name
|
105
|
+
end
|
106
|
+
|
107
|
+
#
|
108
|
+
# Flags whether or not the block should only be generated once. This can
|
109
|
+
# be used to mark a blog as being depended upon by multiple blocks, but
|
110
|
+
# making it such that it is only generated once.
|
111
|
+
#
|
112
|
+
def once=(tf)
|
113
|
+
@once = tf
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
# Returns true if this block is a 'once' block. That is, this block is
|
118
|
+
# dependend upon by multiple blocks but should only be generated once.
|
119
|
+
#
|
120
|
+
def once
|
121
|
+
@once
|
122
|
+
end
|
123
|
+
|
124
|
+
#
|
125
|
+
# Increments the number of blocks that depend on this block.
|
126
|
+
#
|
127
|
+
# @see #deref
|
128
|
+
def ref
|
129
|
+
@references += 1
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
# Increments the number of blocks that have completed their dependency
|
134
|
+
# pass on this block. This number should never become higher than the
|
135
|
+
# `@references` attribute.
|
136
|
+
#
|
137
|
+
# @see #ref
|
138
|
+
def deref
|
139
|
+
@used_references += 1
|
140
|
+
end
|
141
|
+
|
142
|
+
#
|
143
|
+
# Returns true if there is only one block reference remaining.
|
144
|
+
#
|
145
|
+
def last_reference?
|
146
|
+
(@references - @used_references <= 0)
|
147
|
+
end
|
148
|
+
|
149
|
+
#
|
150
|
+
# Adds zero or more specific permutations that may be represented either as
|
151
|
+
# strings or as Proc's to be called at evaluation time.
|
152
|
+
#
|
153
|
+
def add_perm(*perms)
|
154
|
+
@perms.concat(perms)
|
155
|
+
end
|
156
|
+
|
157
|
+
#
|
158
|
+
# Returns a random permutation that is encapsulated in a Permutation class
|
159
|
+
# instance.
|
160
|
+
#
|
161
|
+
def rand_perm
|
162
|
+
perm = nil
|
163
|
+
|
164
|
+
if (@state.badchars)
|
165
|
+
perm = rand_perm_badchars
|
166
|
+
else
|
167
|
+
perm = Permutation.new(@perms[rand(@perms.length)], self)
|
168
|
+
end
|
169
|
+
|
170
|
+
if (perm.nil?)
|
171
|
+
raise RuntimeError, "Failed to locate a valid permutation."
|
172
|
+
end
|
173
|
+
|
174
|
+
perm
|
175
|
+
end
|
176
|
+
|
177
|
+
#
|
178
|
+
# Returns a random permutation that passes any necessary bad character
|
179
|
+
# checks.
|
180
|
+
#
|
181
|
+
def rand_perm_badchars
|
182
|
+
idx = rand(@perms.length)
|
183
|
+
off = 0
|
184
|
+
|
185
|
+
while (off < @perms.length)
|
186
|
+
p = @perms[(idx + off) % @perms.length]
|
187
|
+
|
188
|
+
if (p.kind_of?(Proc) or
|
189
|
+
@state.badchars.nil? or
|
190
|
+
Rex::Text.badchar_index(p, @state.badchars).nil?)
|
191
|
+
return Permutation.new(p, self)
|
192
|
+
end
|
193
|
+
|
194
|
+
off += 1
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
#
|
199
|
+
# Sets the blocks that this block instance depends on.
|
200
|
+
#
|
201
|
+
def depends_on(*depends)
|
202
|
+
@depends = depends.dup
|
203
|
+
|
204
|
+
# Increment dependent references
|
205
|
+
@depends.each { |b| b.ref }
|
206
|
+
end
|
207
|
+
|
208
|
+
#
|
209
|
+
# Defines the next blocks, but not in a dependency fashion but rather in a
|
210
|
+
# linking of separate block contexts.
|
211
|
+
#
|
212
|
+
def next_blocks(*blocks)
|
213
|
+
@next_blocks = blocks.dup
|
214
|
+
end
|
215
|
+
|
216
|
+
#
|
217
|
+
# Defines the list of zero or more LogicalRegister's that this block
|
218
|
+
# clobbers.
|
219
|
+
#
|
220
|
+
def clobbers(*registers)
|
221
|
+
@clobbers = registers
|
222
|
+
end
|
223
|
+
|
224
|
+
#
|
225
|
+
# Enumerates each register instance that is clobbered by this block.
|
226
|
+
#
|
227
|
+
def each_clobbers(&block)
|
228
|
+
@clobbers.each(&block)
|
229
|
+
end
|
230
|
+
|
231
|
+
#
|
232
|
+
# Generates the polymorphic buffer that results from this block and any of
|
233
|
+
# the blocks that it either directly or indirectly depends on. A list of
|
234
|
+
# register numbers to be saved can be passed in as an argument.
|
235
|
+
#
|
236
|
+
# This method is not thread safe. To call this method on a single block
|
237
|
+
# instance from within multiple threads, be sure to encapsulate the calls
|
238
|
+
# inside a locked context.
|
239
|
+
#
|
240
|
+
def generate(save_registers = nil, state = nil, badchars = nil)
|
241
|
+
# Create a localized state instance if one was not supplied.
|
242
|
+
state = Rex::Poly::State.new if (state == nil)
|
243
|
+
buf = nil
|
244
|
+
cnt = 0
|
245
|
+
|
246
|
+
# This is a lame way of doing this. We just try to generate at most 128
|
247
|
+
# times until we don't have badchars. The reason we have to do it this
|
248
|
+
# way is because of the fact that badchars can be introduced through
|
249
|
+
# block offsetting and register number selection which can't be readily
|
250
|
+
# predicted or detected during the generation phase. In the future we
|
251
|
+
# can make this better, but for now this will have to do.
|
252
|
+
begin
|
253
|
+
buf = do_generate(save_registers, state, badchars)
|
254
|
+
|
255
|
+
if (buf and
|
256
|
+
(badchars.nil? or Rex::Text.badchar_index(buf, badchars).nil?))
|
257
|
+
break
|
258
|
+
end
|
259
|
+
end while ((cnt += 1) < 128)
|
260
|
+
|
261
|
+
# If we passed 128 tries, then we can't succeed.
|
262
|
+
buf = nil if (cnt >= 128)
|
263
|
+
|
264
|
+
buf
|
265
|
+
end
|
266
|
+
|
267
|
+
#
|
268
|
+
# Returns the offset of a block. If the active state for this instance is
|
269
|
+
# operating in the first phase, then zero is always returned. Otherwise,
|
270
|
+
# the correct offset for the supplied block is returned.
|
271
|
+
#
|
272
|
+
def offset_of(lblock)
|
273
|
+
if (@state.first_phase)
|
274
|
+
0
|
275
|
+
else
|
276
|
+
if (lblock.kind_of?(SymbolicBlock::End))
|
277
|
+
@state.curr_offset
|
278
|
+
else
|
279
|
+
lblock.offset
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
#
|
285
|
+
# Returns the register number associated with the supplied LogicalRegister
|
286
|
+
# instance. If the active state for this instance is operating in the
|
287
|
+
# first phase, then zero is always returned. Otherwise, the correct
|
288
|
+
# register number is returned based on what is currently assigned to the
|
289
|
+
# supplied LogicalRegister instance, if anything.
|
290
|
+
#
|
291
|
+
def regnum_of(reg)
|
292
|
+
(@state.first_phase) ? 0 : reg.regnum
|
293
|
+
end
|
294
|
+
|
295
|
+
def size_of(lblock)
|
296
|
+
@state.block_list.map { |b, p|
|
297
|
+
if b == lblock
|
298
|
+
return p.length
|
299
|
+
end
|
300
|
+
}
|
301
|
+
0
|
302
|
+
end
|
303
|
+
|
304
|
+
#
|
305
|
+
# This attributes contains the currently assigned offset of the permutation
|
306
|
+
# associated with this block into the polymorphic buffer that is being
|
307
|
+
# generated.
|
308
|
+
#
|
309
|
+
attr_accessor :offset
|
310
|
+
|
311
|
+
#
|
312
|
+
# Whether or not this block has currently been generated for a given
|
313
|
+
# iteration.
|
314
|
+
#
|
315
|
+
attr_accessor :generated
|
316
|
+
|
317
|
+
protected
|
318
|
+
|
319
|
+
#
|
320
|
+
# Performs the actual polymorphic buffer generation. Called from generate
|
321
|
+
#
|
322
|
+
def do_generate(save_registers, state, badchars)
|
323
|
+
# Reset the state in case it was passed in.
|
324
|
+
state.reset
|
325
|
+
|
326
|
+
# Set the bad character list
|
327
|
+
state.badchars = badchars if (badchars)
|
328
|
+
|
329
|
+
# Consume any registers that should be saved.
|
330
|
+
save_registers.each { |reg|
|
331
|
+
state.consume_regnum(reg)
|
332
|
+
} if (save_registers)
|
333
|
+
|
334
|
+
# Build the linear list of blocks that will be processed. This
|
335
|
+
# list is built in a dynamic fashion based on block dependencies.
|
336
|
+
# The list that is returned is an Array of which each element is a two
|
337
|
+
# member array, the first element being the LogicalBlock instance that
|
338
|
+
# the permutation came from and the second being an instance of the
|
339
|
+
# Permutation class associated with the selected permutation.
|
340
|
+
block_list = generate_block_list(state)
|
341
|
+
|
342
|
+
# Transition into the second phase which enables offset_of and regnum_of
|
343
|
+
# calls to return real values.
|
344
|
+
state.first_phase = false
|
345
|
+
|
346
|
+
# Now that every block has been assigned an offset, generate the
|
347
|
+
# buffer block by block, assigning registers as necessary.
|
348
|
+
block_list.each { |b|
|
349
|
+
|
350
|
+
# Generate the next permutation and append it to the buffer.
|
351
|
+
begin
|
352
|
+
state.buffer += b[1].to_s
|
353
|
+
# If an invalid register exception is raised, try to consume a random
|
354
|
+
# register from the register's associated architecture register
|
355
|
+
# number set.
|
356
|
+
rescue InvalidRegisterError => e
|
357
|
+
e.reg.regnum = state.consume_regnum_from_set(e.reg.class.regnum_set)
|
358
|
+
retry
|
359
|
+
end
|
360
|
+
|
361
|
+
# Remove any of the registers that have been clobbered by this block
|
362
|
+
# from the list of consumed register numbers so that they can be used
|
363
|
+
# in the future.
|
364
|
+
b[0].each_clobbers { |reg|
|
365
|
+
begin
|
366
|
+
state.defecate_regnum(reg.regnum)
|
367
|
+
|
368
|
+
reg.regnum = nil
|
369
|
+
rescue InvalidRegisterError
|
370
|
+
end
|
371
|
+
}
|
372
|
+
|
373
|
+
}
|
374
|
+
|
375
|
+
# Finally, return the buffer that has been created.
|
376
|
+
state.buffer
|
377
|
+
end
|
378
|
+
|
379
|
+
#
|
380
|
+
# Generates the linear list of block permutations which is stored in the
|
381
|
+
# supplied state instance. This is done prior to assigning blocks offsets
|
382
|
+
#
|
383
|
+
def generate_block_list(state, level=0)
|
384
|
+
if @depends.length > 1
|
385
|
+
@depends.length.times {
|
386
|
+
f = rand(@depends.length)
|
387
|
+
@depends.push(@depends.delete_at(f))
|
388
|
+
}
|
389
|
+
end
|
390
|
+
|
391
|
+
@depends.length.times { |cidx|
|
392
|
+
|
393
|
+
pass = false
|
394
|
+
|
395
|
+
while (not pass)
|
396
|
+
|
397
|
+
if (@depends[cidx].generated)
|
398
|
+
break
|
399
|
+
|
400
|
+
# If this dependent block is a once block and the magic 8 ball turns
|
401
|
+
# up zero, skip it and let a later block pick it up. We only do this
|
402
|
+
# if we are not the last block to have a dependency on this block.
|
403
|
+
elsif ((@depends[cidx].once) and
|
404
|
+
(rand(2).to_i == 0) and
|
405
|
+
(@depends[cidx].last_reference? == false))
|
406
|
+
break
|
407
|
+
end
|
408
|
+
|
409
|
+
# Generate this block
|
410
|
+
@depends[cidx].generate_block_list(state, level+1)
|
411
|
+
|
412
|
+
if level != 0
|
413
|
+
return
|
414
|
+
else
|
415
|
+
@depends.length.times {
|
416
|
+
f = rand(@depends.length)
|
417
|
+
@depends.push(@depends.delete_at(f))
|
418
|
+
}
|
419
|
+
|
420
|
+
next
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
next
|
425
|
+
}
|
426
|
+
|
427
|
+
self.deref
|
428
|
+
|
429
|
+
# Assign the instance local state for the duration of this generation
|
430
|
+
@state = state
|
431
|
+
|
432
|
+
# Select a random permutation
|
433
|
+
perm = rand_perm
|
434
|
+
|
435
|
+
# Set our block offset to the current state offset
|
436
|
+
self.offset = state.curr_offset
|
437
|
+
|
438
|
+
# Flag ourselves as having been generated for this iteration.
|
439
|
+
self.generated = true
|
440
|
+
|
441
|
+
# Adjust the current offset based on the permutations length
|
442
|
+
state.curr_offset += perm.length
|
443
|
+
|
444
|
+
# Add it to the linear list of blocks
|
445
|
+
state.block_list << [ self, perm ]
|
446
|
+
|
447
|
+
# Generate all the blocks that follow this one.
|
448
|
+
@next_blocks.each { |b|
|
449
|
+
b.generate_block_list(state)
|
450
|
+
}
|
451
|
+
|
452
|
+
# Return the state's block list
|
453
|
+
state.block_list
|
454
|
+
end
|
455
|
+
|
456
|
+
end
|
457
|
+
|
458
|
+
###
|
459
|
+
#
|
460
|
+
# Symbolic blocks are used as special-case LogicalBlock's that have meaning
|
461
|
+
# a more general meaning. For instance, SymbolicBlock::End can be used to
|
462
|
+
# symbolize the end of a polymorphic buffer.
|
463
|
+
#
|
464
|
+
###
|
465
|
+
module SymbolicBlock
|
466
|
+
|
467
|
+
###
|
468
|
+
#
|
469
|
+
# The symbolic end of a polymorphic buffer.
|
470
|
+
#
|
471
|
+
###
|
472
|
+
class End < LogicalBlock
|
473
|
+
def initialize
|
474
|
+
super('__SYMBLK_END__')
|
475
|
+
end
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
end
|
480
|
+
end
|