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,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
|