-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
xor.asm
83 lines (69 loc) · 2.27 KB
/
xor.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<%
import six
from pwnlib.shellcraft import pretty, common, i386, registers
from pwnlib.util.packing import pack, unpack
from pwnlib.context import context as ctx
from pwnlib.log import getLogger
%>
<%page args="key, address, count"/>
<%docstring>
XORs data a constant value.
Args:
key (int,str): XOR key either as a 4-byte integer,
If a string, length must be a power of two,
and not longer than 4 bytes.
Alternately, may be a register.
address (int): Address of the data (e.g. 0xdead0000, 'esp')
count (int): Number of bytes to XOR, or a register containing
the number of bytes to XOR.
Example:
>>> sc = shellcraft.read(0, 'esp', 32)
>>> sc += shellcraft.xor(0xdeadbeef, 'esp', 32)
>>> sc += shellcraft.write(1, 'esp', 32)
>>> io = run_assembly(sc)
>>> io.send(cyclic(32))
>>> result = io.recvn(32)
>>> expected = xor(cyclic(32), p32(0xdeadbeef))
>>> result == expected
True
</%docstring>
<%
log = getLogger('pwnlib.shellcraft.templates.i386.xor')
# By default, assume the key is a register
key_size = ctx.bytes
key_pretty = key
key_register = registers.get_register(key)
if key_register:
assert key_register.bytes == ctx.bytes
else:
key_str = key
key_int = key
if isinstance(key, six.integer_types):
key_str = pack(key, bytes=4)
else:
key_int = unpack(key, 'all')
if len(key_str) > ctx.bytes:
log.error("Key %s is too large (max %i bytes)" % (pretty(key), ctx.bytes))
if len(key_str) not in (1,2,4):
log.error("Key length must be a power of two (got %s)" % pretty(key))
key_size = len(key_str)
key_pretty = pretty(key_int)
if count == 0 or key_size == 0:
return '/* noop xor */'
start = common.label('start')
## Determine the move size
word_name = {1:'BYTE', 2:'WORD', 4:'DWORD', 8:'QWORD'}[key_size]
## Set up the register context
regctx = {'eax': count, 'ecx': address}
if key_register and key_register.name in regctx:
regctx['ebx'] = key
key_pretty = 'ebx'
%>
/* xor(${pretty(key)}, ${pretty(address)}, ${pretty(count)}) */
${i386.setregs(regctx)}
add eax, ecx
${start}:
xor ${word_name} PTR [ecx], ${key_pretty}
add ecx, ${key_size}
cmp ecx, eax
jb ${start}