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,509 @@
1
+ # -*- coding: binary -*-
2
+
3
+ module Rex
4
+
5
+ module Poly
6
+
7
+ #
8
+ # A subclass to represent a Rex poly machine on the x86 architecture.
9
+ #
10
+ class MachineX86 < Rex::Poly::Machine
11
+
12
+ def initialize( badchars='', consume_base_pointer=nil, consume_stack_pointer=true )
13
+ super( badchars, Metasm::Ia32.new )
14
+
15
+ @reg_available << Rex::Arch::X86::EAX
16
+ @reg_available << Rex::Arch::X86::EBX
17
+ @reg_available << Rex::Arch::X86::ECX
18
+ @reg_available << Rex::Arch::X86::EDX
19
+ @reg_available << Rex::Arch::X86::ESI
20
+ @reg_available << Rex::Arch::X86::EDI
21
+ @reg_available << Rex::Arch::X86::EBP
22
+ @reg_available << Rex::Arch::X86::ESP
23
+
24
+ # By default we consume the EBP register if badchars contains \x00. This helps speed
25
+ # things up greatly as many instructions opperating on EBP introduce a NULL byte. For
26
+ # example, a MOV instruction with EAX as the source operand is as follows:
27
+ # 8B08 mov ecx, [eax]
28
+ # but the same instruction with EBP as the source operand is as follows:
29
+ # 8B4D00 mov ecx, [ebp] ; This is assembled as 'mov ecx, [ebp+0]'
30
+ # we can see that EBP is encoded differently with an offset included. We can still
31
+ # try to generate a solution with EBP included and \x00 in the badchars list but
32
+ # it can take considerably longer.
33
+ if( ( consume_base_pointer.nil? and not Rex::Text.badchar_index( "\x00", @badchars ).nil? ) or consume_base_pointer == true )
34
+ create_variable( 'base_pointer', 'ebp' )
35
+ end
36
+
37
+ # By default we consume the ESP register to avoid munging the stack.
38
+ if( consume_stack_pointer )
39
+ create_variable( 'stack_pointer', 'esp' )
40
+ end
41
+
42
+ # discover all the safe FPU instruction we can use.
43
+ @safe_fpu_instructions = ::Array.new
44
+ Rex::Arch::X86.fpu_instructions.each do | fpu |
45
+ if( is_valid?( fpu ) )
46
+ @safe_fpu_instructions << fpu
47
+ end
48
+ end
49
+ end
50
+
51
+ #
52
+ # The general purpose registers are 32bit
53
+ #
54
+ def native_size
55
+ Rex::Poly::Machine::DWORD
56
+ end
57
+
58
+ #
59
+ # Overload this method to intercept the 'set' primitive with the 'location' keyword
60
+ # and create the block with the '_set_variable_location'. We do this to keep a
61
+ # consistent style.
62
+ #
63
+ def create_block_primitive( block_name, primitive_name, *args )
64
+ if( primitive_name == 'set' and args.length == 2 and args[1] == 'location' )
65
+ _create_block_primitive( block_name, '_set_variable_location', args[0] )
66
+ else
67
+ super
68
+ end
69
+ end
70
+
71
+ #
72
+ # XXX: If we have a loop primitive, it is a decent speed bump to force the associated variable
73
+ # of the first loop primitive to be assigned as ECX (for the x86 LOOP instruction), this is not
74
+ # neccasary but can speed generation up significantly.
75
+ #
76
+ #def generate
77
+ # @blocks.each_value do | block |
78
+ # if( block.first.primitive == 'loop' )
79
+ # @variables.delete( block.first.args.first )
80
+ # create_variable( block.first.args.first, 'ecx' )
81
+ # break
82
+ # end
83
+ # end
84
+ # # ...go go go
85
+ # super
86
+ #end
87
+
88
+ protected
89
+
90
+ #
91
+ # Resolve a register number into a suitable register name.
92
+ #
93
+ def _register_value( regnum, size=nil )
94
+ value = nil
95
+ # we default to a native 32 bits if no size is specified.
96
+ if( size.nil? )
97
+ size = native_size()
98
+ end
99
+
100
+ if( size == Rex::Poly::Machine::DWORD )
101
+ value = Rex::Arch::X86::REG_NAMES32[ regnum ]
102
+ elsif( size == Rex::Poly::Machine::WORD )
103
+ value = Rex::Arch::X86::REG_NAMES16[ regnum ]
104
+ elsif( size == Rex::Poly::Machine::BYTE )
105
+ # (will return nil for ESI,EDI,EBP,ESP)
106
+ value = Rex::Arch::X86::REG_NAMES8L[ regnum ]
107
+ else
108
+ raise RuntimeError, "Register number '#{regnum}' (size #{size.to_i}) is unavailable."
109
+ end
110
+ return value
111
+ end
112
+
113
+ #
114
+ # Create the x86 primitives.
115
+ #
116
+ def _create_primitives
117
+
118
+ #
119
+ # Create the '_set_variable_location' primitive. The first param it the variable to place the current
120
+ # blocks location value in.
121
+ #
122
+ _create_primitive( '_set_variable_location',
123
+ ::Proc.new do | block, machine, variable |
124
+ if( @safe_fpu_instructions.empty? )
125
+ raise UnallowedPermutation
126
+ end
127
+ [
128
+ "dw #{ "0x%04X" % [ @safe_fpu_instructions[ rand(@safe_fpu_instructions.length) ].unpack( 'v' ).first ] }",
129
+ "mov #{machine.variable_value( 'temp' )}, esp",
130
+ "fnstenv [ #{machine.variable_value( 'temp' )} - 12 ]",
131
+ "pop #{machine.variable_value( variable )}"
132
+ ]
133
+ end,
134
+ ::Proc.new do | block, machine, variable |
135
+ if( @safe_fpu_instructions.empty? )
136
+ raise UnallowedPermutation
137
+ end
138
+ [
139
+ "dw #{ "0x%04X" % [ @safe_fpu_instructions[ rand(@safe_fpu_instructions.length) ].unpack( 'v' ).first ] }",
140
+ "mov #{machine.variable_value( 'temp' )}, esp",
141
+ "fnstenv [ #{machine.variable_value( 'temp' )} - 12 ]",
142
+ "pop #{machine.variable_value( variable )}"
143
+ ]
144
+ end,
145
+ ::Proc.new do | block, machine, variable |
146
+ if( @safe_fpu_instructions.empty? )
147
+ raise UnallowedPermutation
148
+ end
149
+ [
150
+ "dw #{ "0x%04X" % [ @safe_fpu_instructions[ rand(@safe_fpu_instructions.length) ].unpack( 'v' ).first ] }",
151
+ "push esp",
152
+ "pop #{machine.variable_value( 'temp' )}",
153
+ "fnstenv [ #{machine.variable_value( 'temp' )} - 12 ]",
154
+ "pop #{machine.variable_value( variable )}"
155
+ ]
156
+ end,
157
+ ::Proc.new do | block, machine, variable |
158
+ if( @safe_fpu_instructions.empty? )
159
+ raise UnallowedPermutation
160
+ end
161
+ [
162
+ "dw #{ "0x%04X" % [ @safe_fpu_instructions[ rand(@safe_fpu_instructions.length) ].unpack( 'v' ).first ] }",
163
+ "fnstenv [ esp - 12 ]",
164
+ "pop #{machine.variable_value( variable )}"
165
+ ]
166
+ end,
167
+ ::Proc.new do | block, machine, variable |
168
+ [
169
+ "call $+5",
170
+ "pop #{machine.variable_value( variable )}",
171
+ "push #{machine.block_offset( block ) + 5}",
172
+ "pop #{machine.variable_value( 'temp' )}",
173
+ "sub #{machine.variable_value( variable )}, #{machine.variable_value( 'temp' )}"
174
+ ]
175
+ end,
176
+ ::Proc.new do | block, machine, variable |
177
+ [
178
+ "db 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0",
179
+ "pop #{machine.variable_value( variable )}",
180
+ "push #{machine.block_offset( block ) + 5}",
181
+ "pop #{machine.variable_value( 'temp' )}",
182
+ "sub #{machine.variable_value( variable )}, #{machine.variable_value( 'temp' )}"
183
+ ]
184
+ end
185
+ )
186
+
187
+ #
188
+ # Create the 'loop' primitive. The first param it the counter variable which holds the number of
189
+ # times to perform the loop. The second param it the destination block to loop to.
190
+ #
191
+ _create_primitive( 'loop',
192
+ ::Proc.new do | block, machine, counter, destination |
193
+ if( machine.variable_value( counter ) != Rex::Arch::X86::REG_NAMES32[ Rex::Arch::X86::ECX ] )
194
+ # we raise and UndefinedPermutation exception to indicate that untill a valid register (ECX) is
195
+ # chosen we simply can't render this. This lets the machine know we can still try to use this
196
+ # permutation and at a later stage the requirements (counter==ecx) may be satisfied.
197
+ raise UndefinedPermutation
198
+ end
199
+ offset = -( machine.block_offset( machine.block_next( block ) ) - machine.block_offset( destination ) )
200
+ Rex::Arch::X86.loop( offset )
201
+ end,
202
+ ::Proc.new do | block, machine, counter, destination |
203
+ offset = -( machine.block_offset( machine.block_next( block ) ) - machine.block_offset( destination ) )
204
+ [
205
+ "dec #{machine.variable_value( counter )}",
206
+ "test #{machine.variable_value( counter )}, #{machine.variable_value( counter )}",
207
+ # JNZ destination
208
+ "db 0x0F, 0x85 dd #{ "0x%08X" % [ offset & 0xFFFFFFFF ] }"
209
+ ]
210
+ end
211
+ )
212
+
213
+ #
214
+ # Create the 'xor' primitive. The first param it the variable to xor with the second param value which
215
+ # can be either a variable, literal or block offset.
216
+ #
217
+ _create_primitive( 'xor',
218
+ ::Proc.new do | block, machine, variable, value |
219
+ [
220
+ "xor #{machine.variable_value( variable )}, #{machine.resolve_value( value )}"
221
+ ]
222
+ end,
223
+ ::Proc.new do | block, machine, variable, value |
224
+ # a ^ b == (a | b) & ~(a & b)
225
+ [
226
+ "mov #{machine.variable_value( 'temp' )}, #{machine.variable_value( variable )}",
227
+ "or #{machine.variable_value( 'temp' )}, #{machine.resolve_value( value )}",
228
+ "and #{machine.variable_value( variable )}, #{machine.resolve_value( value )}",
229
+ "not #{machine.variable_value( variable )}",
230
+ "and #{machine.variable_value( variable )}, #{machine.variable_value( 'temp' )}"
231
+ ]
232
+ end
233
+ )
234
+
235
+ #
236
+ # Create the 'goto' primitive. The first param is a destination block to jump to.
237
+ #
238
+ _create_primitive( 'goto',
239
+ ::Proc.new do | block, machine, destination |
240
+ offset = -( machine.block_offset( machine.block_next( block ) ) - machine.block_offset( destination ) )
241
+ if( ( offset > 0 and offset > 127 ) or ( offset < 0 and offset < -127 ) )
242
+ raise UnallowedPermutation
243
+ end
244
+ [
245
+ # short relative jump
246
+ "db 0xEB db #{ "0x%02X" % [ offset & 0xFF ] }"
247
+ ]
248
+ end,
249
+ ::Proc.new do | block, machine, destination |
250
+ offset = -( machine.block_offset( machine.block_next( block ) ) - machine.block_offset( destination ) )
251
+ [
252
+ # near relative jump
253
+ "db 0xE9 dd #{ "0x%08X" % [ offset & 0xFFFFFFFF ] }"
254
+ ]
255
+ end
256
+ )
257
+
258
+ #
259
+ # Create the 'add' primitive. The first param it the variable which will be added to the second
260
+ # param, which may either be a literal number value, a variables assigned register or a block
261
+ # name, in which case the block offset will be used.
262
+ #
263
+ _create_primitive( 'add',
264
+ ::Proc.new do | block, machine, variable, value |
265
+ if( machine.variable_exist?( value ) )
266
+ raise UnallowedPermutation
267
+ end
268
+ [
269
+ "lea #{machine.variable_value( variable )}, [ #{machine.variable_value( variable )} + #{machine.resolve_value( value )} ]"
270
+ ]
271
+ end,
272
+ ::Proc.new do | block, machine, variable, value |
273
+ [
274
+ "push #{machine.resolve_value( value )}",
275
+ "add #{machine.variable_value( variable )}, [esp]",
276
+ "pop #{machine.variable_value( 'temp' )}"
277
+ ]
278
+ end,
279
+ ::Proc.new do | block, machine, variable, value |
280
+ [
281
+ "add #{machine.variable_value( variable )}, #{machine.resolve_value( value )}"
282
+ ]
283
+ end,
284
+ ::Proc.new do | block, machine, variable, value |
285
+ if( machine.variable_exist?( value ) )
286
+ raise UnallowedPermutation
287
+ end
288
+ [
289
+ "sub #{machine.variable_value( variable )}, #{ "0x%08X" % [ ~(machine.resolve_value( value ) - 1) & 0xFFFFFFFF ] }"
290
+ ]
291
+ end
292
+ # ::Proc.new do | block, machine, variable, value |
293
+ # if( machine.variable_exist?( value ) )
294
+ # raise UnallowedPermutation
295
+ # end
296
+ # [
297
+ # "push #{ "0x%08X" % [ ~(machine.resolve_value( value ) - 1) & 0xFFFFFFFF ] }",
298
+ # "pop #{machine.variable_value( 'temp' )}",
299
+ # "not #{machine.variable_value( 'temp' )}",
300
+ # "add #{machine.variable_value( variable )}, #{machine.variable_value( 'temp' )}"
301
+ # ]
302
+ # end,
303
+ # ::Proc.new do | block, machine, variable, value |
304
+ # if( machine.variable_exist?( value ) )
305
+ # raise UnallowedPermutation
306
+ # end
307
+ # [
308
+ # "xor #{machine.variable_value( 'temp' )}, #{machine.variable_value( 'temp' )}",
309
+ # "mov #{machine.variable_value( 'temp', 16 )}, #{ "0x%04X" % [ ~(machine.resolve_value( value ) - 1) & 0xFFFF ] }",
310
+ # "not #{machine.variable_value( 'temp', 16 )}",
311
+ # "add #{machine.variable_value( variable )}, #{machine.variable_value( 'temp' )}"
312
+ # ]
313
+ # end,
314
+ )
315
+
316
+ #
317
+ # Create the 'set' primitive. The first param it the variable which will be set. the second
318
+ # param is the value to set the variable to (a variable, block or literal).
319
+ #
320
+ _create_primitive( 'set',
321
+ ::Proc.new do | block, machine, variable, value |
322
+ if( machine.variable_exist?( value ) )
323
+ raise UnallowedPermutation
324
+ end
325
+ [
326
+ "push #{ "0x%08X" % [ ~machine.resolve_value( value ) & 0xFFFFFFFF ] }",
327
+ "pop #{machine.variable_value( variable )}",
328
+ "not #{machine.variable_value( variable )}"
329
+ ]
330
+ end,
331
+ ::Proc.new do | block, machine, variable, value |
332
+ if( machine.variable_exist?( value ) )
333
+ raise UnallowedPermutation
334
+ end
335
+ if( machine.resolve_value( value, WORD ) > 0xFFFF )
336
+ raise UndefinedPermutation
337
+ end
338
+ [
339
+ "xor #{machine.variable_value( variable )}, #{machine.variable_value( variable )}",
340
+ "mov #{machine.variable_value( variable, WORD )}, #{ "0x%04X" % [ ~machine.resolve_value( value, WORD ) & 0xFFFF ] }",
341
+ "not #{machine.variable_value( variable, WORD )}"
342
+ ]
343
+ end,
344
+ ::Proc.new do | block, machine, variable, value |
345
+ [
346
+ "push #{machine.resolve_value( value )}",
347
+ "pop #{machine.variable_value( variable )}"
348
+ ]
349
+ end,
350
+ ::Proc.new do | block, machine, variable, value |
351
+ [
352
+ "mov #{machine.variable_value( variable )}, #{machine.resolve_value( value )}"
353
+ ]
354
+ end,
355
+ ::Proc.new do | block, machine, variable, value |
356
+ if( machine.variable_exist?( value ) )
357
+ raise UnallowedPermutation
358
+ end
359
+ if( machine.resolve_value( value, WORD ) > 0xFFFF )
360
+ raise UndefinedPermutation
361
+ end
362
+ [
363
+ "xor #{machine.variable_value( variable )}, #{machine.variable_value( variable )}",
364
+ "mov #{machine.variable_value( variable, WORD )}, #{ "0x%04X" % [ machine.resolve_value( value, WORD ) & 0xFFFF ] }"
365
+ ]
366
+ end,
367
+ ::Proc.new do | block, machine, variable, value |
368
+ if( machine.variable_exist?( value ) )
369
+ raise UnallowedPermutation
370
+ end
371
+ dword = machine.make_safe_dword( machine.resolve_value( value ) )
372
+ [
373
+ "mov #{machine.variable_value( variable )}, #{ "0x%08X" % [ dword ] }",
374
+ "sub #{machine.variable_value( variable )}, #{ "0x%08X" % [ dword - machine.resolve_value( value ) ] }"
375
+ ]
376
+ end,
377
+ ::Proc.new do | block, machine, variable, value |
378
+ if( machine.variable_exist?( value ) )
379
+ raise UnallowedPermutation
380
+ end
381
+ dword = machine.make_safe_dword( machine.resolve_value( value ) )
382
+ [
383
+ "mov #{machine.variable_value( variable )}, #{ "0x%08X" % [ dword - machine.resolve_value( value ) ] }",
384
+ "add #{machine.variable_value( variable )}, #{ "0x%08X" % [ ~dword & 0xFFFFFFFF ] }",
385
+ "not #{machine.variable_value( variable )}"
386
+ ]
387
+ end
388
+ )
389
+
390
+ #
391
+ # Create the 'load' primitive. The first param it the variable which will be set. The second
392
+ # param is the value (either a variable or literal) to load from. the third param is the size
393
+ # of the load operation, either DWORD, WORD or BYTE.
394
+ #
395
+ _create_primitive( 'load',
396
+ ::Proc.new do | block, machine, variable, value, size |
397
+ result = nil
398
+ if( size == Rex::Poly::Machine::DWORD )
399
+ result = [ "mov #{machine.variable_value( variable )}, [#{machine.resolve_value( value )}]" ]
400
+ elsif( size == Rex::Poly::Machine::WORD )
401
+ result = [ "movzx #{machine.variable_value( variable )}, word [#{machine.resolve_value( value )}]" ]
402
+ elsif( size == Rex::Poly::Machine::BYTE )
403
+ result = [ "movzx #{machine.variable_value( variable )}, byte [#{machine.resolve_value( value )}]" ]
404
+ else
405
+ raise InvalidPermutation
406
+ end
407
+ result
408
+ end,
409
+ ::Proc.new do | block, machine, variable, value, size |
410
+ result = nil
411
+ if( size == Rex::Poly::Machine::DWORD )
412
+ # we raise and UnallowedPermutation here as this permutation should only satisfy requests for
413
+ # sizes of WORD or BYTE, any DWORD requests will be satisfied by the above permutation (otherwise
414
+ # we would just be duplicating a 'mov dest, [src]' sequence which is the same as above.
415
+ raise UnallowedPermutation
416
+ elsif( size == Rex::Poly::Machine::WORD )
417
+ result = [
418
+ "mov #{machine.variable_value( variable )}, [#{machine.resolve_value( value )}]",
419
+ "shl #{machine.variable_value( variable )}, 16",
420
+ "shr #{machine.variable_value( variable )}, 16"
421
+ ]
422
+ elsif( size == Rex::Poly::Machine::BYTE )
423
+ result = [
424
+ "mov #{machine.variable_value( variable )}, [#{machine.resolve_value( value )}]",
425
+ "shl #{machine.variable_value( variable )}, 24",
426
+ "shr #{machine.variable_value( variable )}, 24"
427
+ ]
428
+ else
429
+ raise InvalidPermutation
430
+ end
431
+ result
432
+ end,
433
+ ::Proc.new do | block, machine, variable, value, size |
434
+ result = nil
435
+ if( size == Rex::Poly::Machine::DWORD )
436
+ result = [
437
+ "push [#{machine.resolve_value( value )}]",
438
+ "pop #{machine.variable_value( variable )}"
439
+ ]
440
+ elsif( size == Rex::Poly::Machine::WORD )
441
+ result = [
442
+ "push [#{machine.resolve_value( value )}]",
443
+ "pop #{machine.variable_value( variable )}",
444
+ "shl #{machine.variable_value( variable )}, 16",
445
+ "shr #{machine.variable_value( variable )}, 16"
446
+ ]
447
+ elsif( size == Rex::Poly::Machine::BYTE )
448
+ result = [
449
+ "push [#{machine.resolve_value( value )}]",
450
+ "pop #{machine.variable_value( variable )}",
451
+ "shl #{machine.variable_value( variable )}, 24",
452
+ "shr #{machine.variable_value( variable )}, 24"
453
+ ]
454
+ else
455
+ raise InvalidPermutation
456
+ end
457
+ result
458
+ end
459
+ )
460
+
461
+ #
462
+ # Create the 'store' primitive.
463
+ #
464
+ _create_primitive( 'store',
465
+ ::Proc.new do | block, machine, variable, value, size |
466
+ result = nil
467
+ if( size == Rex::Poly::Machine::DWORD )
468
+ result = [ "mov [#{machine.variable_value( variable )}], #{machine.resolve_value( value )}" ]
469
+ elsif( size == Rex::Poly::Machine::WORD )
470
+ result = [ "mov word [#{machine.variable_value( variable )}], #{machine.resolve_value( value, WORD )}" ]
471
+ elsif( size == Rex::Poly::Machine::BYTE )
472
+ if( machine.resolve_value( value, BYTE ).nil? )
473
+ # so long as we cant resolve the variable to an 8bit register value (AL,BL,CL,DL) we must raise
474
+ # an UndefinedPermutation exception (this will happen when the variable has been assigned to ESI,
475
+ # EDI, EBP or ESP which dont have a low byte representation)
476
+ raise UndefinedPermutation
477
+ end
478
+ result = [ "mov byte [#{machine.variable_value( variable )}], #{machine.resolve_value( value, BYTE )}" ]
479
+ else
480
+ raise InvalidPermutation
481
+ end
482
+ result
483
+ end,
484
+ ::Proc.new do | block, machine, variable, value, size |
485
+ result = nil
486
+ if( size == Rex::Poly::Machine::DWORD )
487
+ result = [
488
+ "push #{machine.resolve_value( value )}",
489
+ "pop [#{machine.variable_value( variable )}]"
490
+ ]
491
+ elsif( size == Rex::Poly::Machine::WORD )
492
+ result = [
493
+ "push #{machine.resolve_value( value, WORD )}",
494
+ "pop word [#{machine.variable_value( variable )}]"
495
+ ]
496
+ else
497
+ # we can never do this permutation for BYTE size (or any other size)
498
+ raise UnallowedPermutation
499
+ end
500
+ result
501
+ end
502
+ )
503
+ end
504
+
505
+ end
506
+
507
+ end
508
+
509
+ end