rex-encoder 0.1.0

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