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,13 @@
1
+ # -*- coding: binary -*-
2
+
3
+ module Rex
4
+
5
+ module Poly
6
+
7
+ require 'metasm'
8
+ require 'rex/poly/machine/machine'
9
+ require 'rex/poly/machine/x86'
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,830 @@
1
+ # -*- coding: binary -*-
2
+
3
+ module Rex
4
+
5
+ module Poly
6
+
7
+ #
8
+ # A machine capable of creating a small blob of code in a metamorphic kind of way.
9
+ # Note: this is designed to perform an exhaustive search for a solution and can be
10
+ # slow. If you need a speedier option, the origional Rex::Polly::Block stuff is a
11
+ # better choice.
12
+ #
13
+ class Machine
14
+
15
+ QWORD = 8
16
+ DWORD = 4
17
+ WORD = 2
18
+ BYTE = 1
19
+
20
+ #
21
+ # A Permutation!
22
+ #
23
+ class Permutation
24
+
25
+ attr_accessor :active, :offset
26
+
27
+ attr_reader :name, :primitive, :length, :args
28
+
29
+ #
30
+ # Create a new permutation object.
31
+ #
32
+ def initialize( name, primitive, machine, source, args=nil )
33
+ @name = name
34
+ @primitive = primitive
35
+ @machine = machine
36
+ @source = source
37
+ @args = args
38
+ @active = false
39
+ @valid = true
40
+ @length = 0
41
+ @offset = 0
42
+ @children = ::Array.new
43
+ end
44
+
45
+ #
46
+ # Add in a child permutation to this one. Used to build the permutation tree.
47
+ #
48
+ def add_child( child )
49
+ @children << child
50
+ end
51
+
52
+ #
53
+ # Does this permutation have children?
54
+ #
55
+ def has_children?
56
+ not @children.empty?
57
+ end
58
+
59
+ #
60
+ # Remove any existing children. Called by the machines generate function
61
+ # to build a fresh tree in case generate was previously called.
62
+ #
63
+ def remove_children
64
+ @children.clear
65
+ end
66
+
67
+ #
68
+ # Actully render this permutation into a raw buffer.
69
+ #
70
+ def render
71
+ raw = ''
72
+ # Zero the length as we will be rendering the raw buffer and the length may change.
73
+ @length = 0
74
+ # If this permutation source is a Primitive/Procedure we can call it, otherwise we have a string
75
+ if( @source.kind_of?( Primitive ) or @source.kind_of?( ::Proc ) )
76
+ if( @source.kind_of?( Primitive ) )
77
+ raw = @source.call( @name, @machine, *@args )
78
+ elsif( @source.kind_of?( ::Proc ) )
79
+ raw = @source.call
80
+ end
81
+ # If the primitive/procedure returned an array, it is an array of assembly strings which we can assemble.
82
+ if( raw.kind_of?( ::Array ) )
83
+ lines = raw
84
+ raw = ''
85
+ # itterate over each line of assembly
86
+ lines.each do | asm |
87
+ # parse the asm and substitute in any offset values specified...
88
+ offsets = asm.scan( /:([\S]+)_offset/ )
89
+ offsets.each do | name, |
90
+ asm = asm.gsub( ":#{name}_offset", @machine.block_offset( name ).to_s )
91
+ end
92
+ # and substitute in and register values for any variables specified...
93
+ regs = asm.scan( /:([\S]+)_reg([\d]+)/ )
94
+ regs.each do | name, size |
95
+ asm = asm.gsub( ":#{name}_reg#{size}", @machine.variable_value( name, size.to_i ) )
96
+ end
97
+ # assemble it into a raw blob
98
+ blob = @machine.assemble( asm )
99
+ #if( not @machine.is_valid?( blob ) )
100
+ # p "#{name}(#{primitive}):#{asm} is invalid"
101
+ #end
102
+ raw << blob
103
+ end
104
+ end
105
+ else
106
+ # the source must just be a static string
107
+ raw = @source
108
+ end
109
+ # Update the length to reflect the new raw buffer
110
+ @length = raw.to_s.length
111
+ # As the temp variable is only assigned for the duration of a single permutation we
112
+ # can now release it if it was used in this permutation.
113
+ @machine.release_temp_variable
114
+ return raw.to_s
115
+ end
116
+
117
+ #
118
+ # Test if this permutation raw buffer is valid in this machine (e.g. against the badchar list).
119
+ #
120
+ def is_valid?
121
+ result = false
122
+ if( @valid )
123
+ begin
124
+ result = @machine.is_valid?( self.render )
125
+ rescue UnallowedPermutation
126
+ # This permutation is unallowed and can never be rendered so just mark it as
127
+ # not valid to skip it during future attempts.
128
+ @valid = false
129
+ rescue UndefinedPermutation
130
+ # allow an undefined permutation to fail validation but keep it marked
131
+ # as valid as it may be defined and passed validation later.
132
+ ensure
133
+ # Should a temporary variable have been assigned we can release it here.
134
+ @machine.release_temp_variable
135
+ end
136
+ end
137
+ return result
138
+ end
139
+
140
+ #
141
+ # Try to find a solution within the solution space by performing a depth first search
142
+ # into the permutation tree and backtracking when needed.
143
+ #
144
+ def solve
145
+ # Check to see if this permutation can make part of a valid solution
146
+ if( self.is_valid? )
147
+ # record this permutation as part of the final solution (the current machines register state is also saved here)
148
+ @machine.solution_push( self )
149
+ # If we have no children we are at the end of the tree and have a potential full solution.
150
+ if( not self.has_children? )
151
+ # We have a solution but doing a final pass to update offsets may introduce bad chars
152
+ # so we test for this and keep searching if this isnt a real solution after all.
153
+ if( not @machine.solution_is_valid? )
154
+ # remove this permutation and keep searching
155
+ @machine.solution_pop
156
+ return false
157
+ end
158
+ # Return true to unwind the recursive call as we have got a final solution.
159
+ return true
160
+ end
161
+ # Itterate over the children of this permutation (the perutations of the proceeding block).
162
+ @children.each do | child |
163
+ # Traverse into this child to keep trying to generate a solution...
164
+ if( child.solve )
165
+ # Keep returning true to unwind as we are done.
166
+ return true
167
+ end
168
+ end
169
+ # If we get here this permutation, origionally thought to be good for a solution, is not after all,
170
+ # so remove it from the machines final solution, restoring the register state aswell.
171
+ @machine.solution_pop
172
+ end
173
+ # No children can be made form part of the solution, return failure for this path in the tree.
174
+ return false
175
+ end
176
+
177
+ end
178
+
179
+ #
180
+ # A symbolic permutation to mark locations like the begining and end of a group of blocks.
181
+ # Used to calculate usefull offsets.
182
+ #
183
+ class SymbolicPermutation < Permutation
184
+ def initialize( name, machine, initial_offset=0 )
185
+ super( name, '', machine, '' )
186
+ # fudge the initial symbolic offset with a default (it gets patched correctly later),
187
+ # helps with the end symbolic block to not be 0 (as its a forward reference it really
188
+ # slows things down if we leave it 0)
189
+ @offset = initial_offset
190
+ # A symbolic block is allways active!
191
+ @active = true
192
+ end
193
+
194
+ #
195
+ # We block all attempts to set the active state of this permutation so as
196
+ # it is always true. This lets us always address the offset.
197
+ #
198
+ def active=( value )
199
+ end
200
+ end
201
+
202
+ #
203
+ # A primitive is a machine defined permutation which accepts some arguments when it is called.
204
+ #
205
+ class Primitive
206
+
207
+ #
208
+ # Initialize this primitive with its target source procedure and the machine it belongs to.
209
+ #
210
+ def initialize( source )
211
+ @source = source
212
+ end
213
+
214
+ #
215
+ # Call the primitives source procedure, passing in the arguments.
216
+ #
217
+ def call( name, machine, *args )
218
+ return @source.call( name, machine, *args )
219
+ end
220
+
221
+ end
222
+
223
+ #
224
+ #
225
+ #
226
+ class Block
227
+
228
+ #attr_accessor :next, :previous
229
+ attr_reader :name
230
+
231
+ def initialize( name )
232
+ @name = name
233
+ @next = nil
234
+ @previous = nil
235
+ @permutations = ::Array.new
236
+ end
237
+
238
+ def shuffle
239
+ @permutations = @permutations.shuffle
240
+ end
241
+
242
+ def solve
243
+ @permutations.first.solve
244
+ end
245
+
246
+ def << ( permutation )
247
+ @permutations << permutation
248
+ end
249
+
250
+ def each
251
+ @permutations.each do | permutation |
252
+ yield permutation
253
+ end
254
+ end
255
+
256
+ end
257
+
258
+ #
259
+ # A class to hold a solution for a Rex::Poly::Machine problem.
260
+ #
261
+ class Solution
262
+
263
+ attr_reader :offset
264
+
265
+ def initialize
266
+ @permutations = ::Array.new
267
+ @reg_state = ::Array.new
268
+ @offset = 0
269
+ end
270
+
271
+ #
272
+ # Reset this solution to an empty state.
273
+ #
274
+ def reset
275
+ @offset = 0
276
+ @permutations.each do | permutation |
277
+ permutation.active = false
278
+ permutation.offset = 0
279
+ end
280
+ @permutations.clear
281
+ @reg_state.clear
282
+ end
283
+
284
+ #
285
+ # Push a new permutation onto this solutions permutations list and save the associated register/variables state
286
+ #
287
+ def push( permutation, reg_available, reg_consumed, variables )
288
+ permutation.active = true
289
+ permutation.offset = @offset
290
+ @offset += permutation.length
291
+ @permutations.push( permutation )
292
+ @reg_state.push( [ [].concat(reg_available), [].concat(reg_consumed), {}.merge(variables) ] )
293
+ end
294
+
295
+ #
296
+ # Pop off the last permutaion and register/variables state from this solution.
297
+ #
298
+ def pop
299
+ reg_available, reg_consumed, variables = @reg_state.pop
300
+ permutation = @permutations.pop
301
+ permutation.active = false
302
+ permutation.offset = 0
303
+ @offset -= permutation.length
304
+ return permutation, reg_available, reg_consumed, variables
305
+ end
306
+
307
+ #
308
+ # Render the final buffer.
309
+ #
310
+ def buffer
311
+ previous_offset = nil
312
+ count = 0
313
+ # perform an N-pass fixup for offsets...
314
+ while( true ) do
315
+ # If we cant get the offsets fixed within a fixed ammount of tries we return
316
+ # nil to indicate failure and keep searching for a solution that will work.
317
+ if( count > 64 )
318
+ return nil
319
+ end
320
+ # Reset the solution offset so as to update it for this pass
321
+ @offset = 0
322
+ # perform a single pass to ensure we are using the correct offset values
323
+ @permutations.each do | permutation |
324
+ permutation.offset = @offset
325
+ # Note: calling render() can throw both UndefinedPermutation and UnallowedPermutation exceptions,
326
+ # however as we assume we only ever return the buffer once a final solution has been generated
327
+ # we should never have either of those exceptions thrown.
328
+ permutation.render
329
+ @offset += permutation.length
330
+ end
331
+ # If we have generated two consecutive passes which are the same length we can stop fixing up the offsets.
332
+ if( not previous_offset.nil? and @offset == previous_offset )
333
+ break
334
+ end
335
+ count +=1
336
+ previous_offset = @offset
337
+ end
338
+ # now a final pass to render the solution into the raw buffer
339
+ raw = ''
340
+ @permutations.each do | permutation |
341
+ #$stderr.puts "#{permutation.name} - #{ "0x%08X (%d)" % [ permutation.offset, permutation.length] } "
342
+ raw << permutation.render
343
+ end
344
+ return raw
345
+ end
346
+
347
+ end
348
+
349
+ #
350
+ # Create a new machine instance.
351
+ #
352
+ def initialize( badchars, cpu )
353
+ @badchars = badchars
354
+ @cpu = cpu
355
+
356
+ @reg_available = ::Array.new
357
+ @reg_consumed = ::Array.new
358
+ @variables = ::Hash.new
359
+ @blocks = ::Hash.new
360
+ @primitives = ::Hash.new
361
+ @solution = Solution.new
362
+
363
+ _create_primitives
364
+
365
+ @blocks['begin'] = Block.new( 'begin' )
366
+ @blocks['begin'] << SymbolicPermutation.new( 'begin', self )
367
+
368
+ _create_variable( 'temp' )
369
+ end
370
+
371
+ #
372
+ # Overloaded by a subclass to return the maximum native general register size supported.
373
+ #
374
+ def native_size
375
+ nil
376
+ end
377
+
378
+ #
379
+ # Use METASM to assemble a line of asm using this machines current cpu.
380
+ #
381
+ def assemble( asm )
382
+ return Metasm::Shellcode.assemble( @cpu, asm ).encode_string
383
+ end
384
+
385
+ #
386
+ # Check if a data blob is valid against the badchar list (or perform any other validation here)
387
+ #
388
+ def is_valid?( data )
389
+ if( data.nil? )
390
+ return false
391
+ end
392
+ return Rex::Text.badchar_index( data, @badchars ).nil?
393
+ end
394
+
395
+ #
396
+ # Generate a 64 bit number whoes bytes are valid in this machine.
397
+ #
398
+ def make_safe_qword( number=nil )
399
+ return _make_safe_number( QWORD, number ) & 0xFFFFFFFFFFFFFFFF
400
+ end
401
+
402
+ #
403
+ # Generate a 32 bit number whoes bytes are valid in this machine.
404
+ #
405
+ def make_safe_dword( number=nil )
406
+ return _make_safe_number( DWORD, number ) & 0xFFFFFFFF
407
+ end
408
+
409
+ #
410
+ # Generate a 16 bit number whoes bytes are valid in this machine.
411
+ #
412
+ def make_safe_word( number=nil )
413
+ return _make_safe_number( WORD, number ) & 0xFFFF
414
+ end
415
+
416
+ #
417
+ # Generate a 8 bit number whoes bytes are valid in this machine.
418
+ #
419
+ def make_safe_byte( number=nil )
420
+ return _make_safe_number( BYTE, number ) & 0xFF
421
+ end
422
+
423
+ #
424
+ # Create a variable by name which will be assigned a register during generation. We can
425
+ # optionally assign a static register value to a variable if needed.
426
+ #
427
+ def create_variable( name, reg=nil )
428
+ # Sanity check we aren't trying to create one of the reserved variables.
429
+ if( name == 'temp' )
430
+ raise RuntimeError, "Unable to create variable, '#{name}' is a reserved variable name."
431
+ end
432
+ return _create_variable( name, reg )
433
+ end
434
+
435
+ #
436
+ # If the temp variable was assigned we release it.
437
+ #
438
+ def release_temp_variable
439
+ if( @variables['temp'] )
440
+ regnum = @variables['temp']
441
+ # Sanity check the temp variable was actually assigned (it may not have been if the last permutation didnot use it)
442
+ if( regnum )
443
+ # place the assigned register back in the available list for consumption later.
444
+ @reg_available.push( @reg_consumed.delete( regnum ) )
445
+ # unasign the temp vars register
446
+ @variables['temp'] = nil
447
+ return true
448
+ end
449
+ end
450
+ return false
451
+ end
452
+
453
+ #
454
+ # Resolve a variable name into its currently assigned register value.
455
+ #
456
+ def variable_value( name, size=nil )
457
+ # Sanity check we this variable has been created
458
+ if( not @variables.has_key?( name ) )
459
+ raise RuntimeError, "Unknown register '#{name}'."
460
+ end
461
+ # Pull out its current register value if it has been assigned one
462
+ regnum = @variables[ name ]
463
+ if( not regnum )
464
+ regnum = @reg_available.pop
465
+ if( not regnum )
466
+ raise RuntimeError, "Unable to assign variable '#{name}' a register value, none available."
467
+ end
468
+ # and add it to the consumed list so we can track it later
469
+ @reg_consumed << regnum
470
+ # and now assign the variable the register
471
+ @variables[ name ] = regnum
472
+ end
473
+ # resolve the register number int a string representation (e.g. 0 in x86 is EAX if size is 32)
474
+ return _register_value( regnum, size )
475
+ end
476
+
477
+ #
478
+ # Check this solution is still currently valid (as offsets change it may not be).
479
+ #
480
+ def solution_is_valid?
481
+ return self.is_valid?( @solution.buffer )
482
+ end
483
+
484
+ #
485
+ # As the solution advances we save state for each permutation step in the solution. This lets
486
+ # use rewind at a later stage if the solving algorithm wishes to perform some backtracking.
487
+ #
488
+ def solution_push( permutation )
489
+ @solution.push( permutation, @reg_available, @reg_consumed, @variables )
490
+ end
491
+
492
+ #
493
+ # Backtrack one step in the solution and restore the register/variable state.
494
+ #
495
+ def solution_pop
496
+ permutation, @reg_available, @reg_consumed, @variables = @solution.pop
497
+
498
+ @reg_available.push( @reg_available.shift )
499
+ end
500
+
501
+ #
502
+ # Create a block by name and add in its list of permutations.
503
+ #
504
+ # XXX: this doesnt support the fuzzy order of block dependencies ala the origional rex::poly
505
+ def create_block( name, *permutation_sources )
506
+ # Sanity check we aren't trying to create one of the reserved symbolic blocks.
507
+ if( name == 'begin' or name == 'end' )
508
+ raise RuntimeError, "Unable to add block, '#{name}' is a reserved block name."
509
+ end
510
+ # If this is the first time this block is being created, create the block object to hold the permutation list
511
+ if( not @blocks[name] )
512
+ @blocks[name] = Block.new( name )
513
+ end
514
+ # Now create a new permutation object for every one supplied.
515
+ permutation_sources.each do | source |
516
+ @blocks[name] << Permutation.new( name, '', self, source )
517
+ end
518
+ return name
519
+ end
520
+
521
+ #
522
+ # Create a block which is based on a primitive defined by this machine.
523
+ #
524
+ def create_block_primitive( block_name, primitive_name, *args )
525
+ # Santiy check this primitive is actually available and is not an internal primitive (begins with an _).
526
+ if( not @primitives[primitive_name] or primitive_name[0] == "_" )
527
+ raise RuntimeError, "Unable to add block, Primitive '#{primitive_name}' is not available."
528
+ end
529
+ # Sanity check we aren't trying to create one of the reserved symbolic blocks.
530
+ if( block_name == 'begin' or block_name == 'end' )
531
+ raise RuntimeError, "Unable to add block, '#{block_name}' is a reserved block name."
532
+ end
533
+ return _create_block_primitive( block_name, primitive_name, *args )
534
+ end
535
+
536
+ #
537
+ # Get the offset for a blocks active permutation. This is easy for backward references as
538
+ # they will already have been rendered and their sizes known. For forward references we
539
+ # can't know in advance but the correct value can be known later once the final solution is
540
+ # available and a final pass to generate the raw buffer is made.
541
+ #
542
+ def block_offset( name )
543
+ if( name == 'end' )
544
+ return @solution.offset
545
+ elsif( @blocks[name] )
546
+ @blocks[name].each do | permutation |
547
+ if( permutation.active )
548
+ return permutation.offset
549
+ end
550
+ end
551
+ end
552
+ # If we are forward referencing a block it will be at least the current solutions offset +1
553
+ return @solution.offset + 1
554
+ end
555
+
556
+ #
557
+ # Does a given block exist?
558
+ #
559
+ def block_exist?( name )
560
+ return @blocks.include?( name )
561
+ end
562
+
563
+ #
564
+ # Does a given block exist?
565
+ #
566
+ def variable_exist?( name )
567
+ return @variables.include?( name )
568
+ end
569
+
570
+ # XXX: ambiguity between variable names and block name may introduce confusion!!! make them be unique.
571
+
572
+ #
573
+ # Resolve a given value into either a number literal, a block offset or
574
+ # a variables assigned register.
575
+ #
576
+ def resolve_value( value, size=nil )
577
+ if( block_exist?( value ) )
578
+ return block_offset( value )
579
+ elsif( variable_exist?( value ) )
580
+ return variable_value( value, size )
581
+ end
582
+ return value.to_i
583
+ end
584
+
585
+ #
586
+ # Get the block previous to the target block.
587
+ #
588
+ def block_previous( target_block )
589
+ previous_block = nil
590
+ @blocks.each_key do | current_block |
591
+ if( current_block == target_block )
592
+ return previous_block
593
+ end
594
+ previous_block = current_block
595
+ end
596
+ return nil
597
+ end
598
+
599
+ #
600
+ # Get the block next to the target block.
601
+ #
602
+ def block_next( target_block )
603
+ @blocks.each_key do | current_block |
604
+ if( block_previous( current_block ) == target_block )
605
+ return current_block
606
+ end
607
+ end
608
+ return nil
609
+ end
610
+
611
+ #
612
+ # Try to generate a solution.
613
+ #
614
+ def generate
615
+
616
+ if( @blocks.has_key?( 'end' ) )
617
+ @blocks.delete( 'end' )
618
+ end
619
+
620
+ @blocks['end'] = Block.new( 'end' )
621
+ @blocks['end'] << SymbolicPermutation.new( 'end', self, 1 )
622
+
623
+ # Mix up the permutation orders for each block and create the tree structure.
624
+ previous = ::Array.new
625
+ @blocks.each_value do | block |
626
+ # Shuffle the order of the blocks permutations.
627
+ block.shuffle
628
+ # create the tree by adding the current blocks permutations as children of the previous block.
629
+ current = ::Array.new
630
+ block.each do | permutation |
631
+ permutation.remove_children
632
+ previous.each do | prev |
633
+ prev.add_child( permutation )
634
+ end
635
+ current << permutation
636
+ end
637
+ previous = current
638
+ end
639
+
640
+ # Shuffle the order of the available registers
641
+ @reg_available = @reg_available.shuffle
642
+
643
+ # We must try every permutation of the register orders, so if we fail to
644
+ # generate a solution we rotate the available registers to try again with
645
+ # a different order. This ensures we perform and exhaustive search.
646
+ 0.upto( @reg_available.length - 1 ) do
647
+
648
+ @solution.reset
649
+
650
+ # Start from the root node in the solution space and generate a
651
+ # solution by traversing the solution space's tree structure.
652
+ if( @blocks['begin'].solve )
653
+ # Return the solutions buffer (perform a last pass to fixup all offsets)...
654
+ return @solution.buffer
655
+ end
656
+
657
+ @reg_available.push( @reg_available.shift )
658
+ end
659
+
660
+ # :(
661
+ nil
662
+ end
663
+
664
+ #
665
+ # An UndefinedPermutation exception is raised when a permutation can't render yet
666
+ # as the conditions required are not yet satisfied.
667
+ #
668
+ class UndefinedPermutation < RuntimeError
669
+ def initialize( msg=nil )
670
+ super
671
+ end
672
+ end
673
+
674
+ #
675
+ # An UnallowedPermutation exception is raised when a permutation can't ever render
676
+ # as the conditions supplied are impossible to satisfy.
677
+ #
678
+ class UnallowedPermutation < RuntimeError
679
+ def initialize( msg=nil )
680
+ super
681
+ end
682
+ end
683
+
684
+ #
685
+ # An InvalidPermutation exception is raised when a permutation receives a invalid
686
+ # argument and cannot continue to render. This is a fatal exception.
687
+ #
688
+ class InvalidPermutation < RuntimeError
689
+ def initialize( msg=nil )
690
+ super
691
+ end
692
+ end
693
+
694
+ protected
695
+
696
+ #
697
+ # Overloaded by a subclass to resolve a register number into a suitable register
698
+ # name for the target architecture. E.g on x64 the register number 0 with size 64
699
+ # would resolve to RCX. Size is nil by default to indicate we want the default
700
+ # machine size, e.g. 32bit DWORD on x86 or 64bit QWORD on x64.
701
+ #
702
+ def _register_value( regnum, size=nil )
703
+ nil
704
+ end
705
+
706
+ #
707
+ # Perform the actual variable creation.
708
+ #
709
+ def _create_variable( name, reg=nil )
710
+ regnum = nil
711
+ # Sanity check this variable has not already been created.
712
+ if( @variables[name] )
713
+ raise RuntimeError, "Variable '#{name}' is already created."
714
+ end
715
+ # If a fixed register is being assigned to this variable then resolve it
716
+ if( reg )
717
+ # Resolve the register name into a register number
718
+ @reg_available.each do | num |
719
+ if( _register_value( num ) == reg.downcase )
720
+ regnum = num
721
+ break
722
+ end
723
+ end
724
+ # If an invalid register name was given or the chosen register is not available we must fail.
725
+ if( not regnum )
726
+ raise RuntimeError, "Register '#{reg}' is unknown or unavailable."
727
+ end
728
+ # Sanity check another variable isnt assigned this register
729
+ if( @variables.has_value?( regnum ) )
730
+ raise RuntimeError, "Register number '#{regnum}' is already consumed by variable '#{@variables[name]}'."
731
+ end
732
+ # Finally we consume the register chosen so we dont select it again later.
733
+ @reg_consumed << @reg_available.delete( regnum )
734
+ end
735
+ # Create the variable and assign it a register number (or nil if not yet assigned)
736
+ @variables[name] = regnum
737
+ return name
738
+ end
739
+
740
+ #
741
+ # Create a block which is based on a primitive defined by this machine.
742
+ #
743
+ def _create_block_primitive( block_name, primitive_name, *args )
744
+ # If this is the first time this block is being created, create the array to hold the permutation list
745
+ if( not @blocks[block_name] )
746
+ @blocks[block_name] = Block.new( block_name )
747
+ end
748
+ # Now create a new permutation object for every one supplied.
749
+ @primitives[primitive_name].each do | source |
750
+ @blocks[block_name] << Permutation.new( block_name, primitive_name, self, source, args )
751
+ end
752
+ return block_name
753
+ end
754
+
755
+ #
756
+ # Overloaded by a subclass to create any primitives available in this machine.
757
+ #
758
+ def _create_primitives
759
+ nil
760
+ end
761
+
762
+ #
763
+ # Rex::Poly::Machine::Primitive
764
+ #
765
+ def _create_primitive( name, *permutations )
766
+ # If this is the first time this primitive is being created, create the array to hold the permutation list
767
+ if( not @primitives[name] )
768
+ @primitives[name] = ::Array.new
769
+ end
770
+ # Add in the permutation object (Rex::Poly::Machine::Primitive) for every one supplied.
771
+ permutations.each do | permutation |
772
+ @primitives[name] << Primitive.new( permutation )
773
+ end
774
+ end
775
+
776
+ #
777
+ # Helper function to generate a number whoes byte representation is valid in this
778
+ # machine (does not contain any badchars for example). Optionally we can supply a
779
+ # number and the resulting addition/subtraction of this number against the newly
780
+ # generated value is also tested for validity. This helps in the assembly primitives
781
+ # which can use these values.
782
+ #
783
+ def _make_safe_number( bytes, number=nil )
784
+ format = ''
785
+ if( bytes == BYTE )
786
+ format = 'C'
787
+ elsif( bytes == WORD )
788
+ format = 'v'
789
+ elsif( bytes == DWORD )
790
+ format = 'V'
791
+ elsif( bytes == QWORD )
792
+ format = 'Q'
793
+ else
794
+ raise RuntimeError, "Invalid size '#{bytes}' used in _make_safe_number."
795
+ end
796
+
797
+ goodchars = (0..255).to_a
798
+
799
+ @badchars.unpack( 'C*' ).each do | b |
800
+ goodchars.delete( b.chr )
801
+ end
802
+
803
+ while( true ) do
804
+ value = 0
805
+
806
+ 0.upto( bytes-1 ) do | i |
807
+ value |= ( (goodchars[ rand(goodchars.length) ] << i*8) & (0xFF << i*8) )
808
+ end
809
+
810
+ if( not is_valid?( [ value ].pack(format) ) or not is_valid?( [ ~value ].pack(format) ) )
811
+ redo
812
+ end
813
+
814
+ if( not number.nil? )
815
+ if( not is_valid?( [ value + number ].pack(format) ) or not is_valid?( [ value - number ].pack(format) ) )
816
+ redo
817
+ end
818
+ end
819
+
820
+ break
821
+ end
822
+
823
+ return value
824
+ end
825
+
826
+ end
827
+
828
+ end
829
+
830
+ end