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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +1 -0
  3. data.tar.gz.sig +0 -0
  4. data/.gitignore +9 -0
  5. data/.rspec +2 -0
  6. data/.travis.yml +5 -0
  7. data/CODE_OF_CONDUCT.md +49 -0
  8. data/Gemfile +4 -0
  9. data/README.md +32 -0
  10. data/Rakefile +6 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/lib/rex/encoder.rb +15 -0
  14. data/lib/rex/encoder/alpha2.rb +31 -0
  15. data/lib/rex/encoder/alpha2/alpha_mixed.rb +129 -0
  16. data/lib/rex/encoder/alpha2/alpha_upper.rb +138 -0
  17. data/lib/rex/encoder/alpha2/generic.rb +90 -0
  18. data/lib/rex/encoder/alpha2/unicode_mixed.rb +116 -0
  19. data/lib/rex/encoder/alpha2/unicode_upper.rb +123 -0
  20. data/lib/rex/encoder/bloxor/bloxor.rb +327 -0
  21. data/lib/rex/encoder/ndr.rb +90 -0
  22. data/lib/rex/encoder/nonalpha.rb +61 -0
  23. data/lib/rex/encoder/nonupper.rb +64 -0
  24. data/lib/rex/encoder/version.rb +5 -0
  25. data/lib/rex/encoder/xdr.rb +108 -0
  26. data/lib/rex/encoder/xor.rb +69 -0
  27. data/lib/rex/encoder/xor/dword.rb +13 -0
  28. data/lib/rex/encoder/xor/dword_additive.rb +13 -0
  29. data/lib/rex/encoding/xor.rb +20 -0
  30. data/lib/rex/encoding/xor/byte.rb +15 -0
  31. data/lib/rex/encoding/xor/dword.rb +21 -0
  32. data/lib/rex/encoding/xor/dword_additive.rb +92 -0
  33. data/lib/rex/encoding/xor/exceptions.rb +17 -0
  34. data/lib/rex/encoding/xor/generic.rb +146 -0
  35. data/lib/rex/encoding/xor/qword.rb +15 -0
  36. data/lib/rex/encoding/xor/word.rb +21 -0
  37. data/lib/rex/poly.rb +134 -0
  38. data/lib/rex/poly/block.rb +480 -0
  39. data/lib/rex/poly/machine.rb +13 -0
  40. data/lib/rex/poly/machine/machine.rb +830 -0
  41. data/lib/rex/poly/machine/x86.rb +509 -0
  42. data/lib/rex/poly/register.rb +101 -0
  43. data/lib/rex/poly/register/x86.rb +41 -0
  44. data/rex-encoder.gemspec +31 -0
  45. metadata +248 -0
  46. 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