-
Notifications
You must be signed in to change notification settings - Fork 5
/
util.py
74 lines (55 loc) · 2.01 KB
/
util.py
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
import struct
class SignatureException(Exception):
pass
def PatchImm(data, ofs, size, imm, signature):
assert size % 2 == 0, 'size must be power of 2!'
assert len(signature) == size * 8, 'signature must be exactly size * 8 long!'
imm = int.from_bytes(imm, 'little')
sfmt = '<' + 'H' * (size // 2)
sigs = [signature[i:i + 16][::-1] for i in range(0, len(signature), 16)]
orig = data[ofs:ofs+size]
words = struct.unpack(sfmt, orig)
patched = []
for i, word in enumerate(words):
for j in range(16):
imm_bitofs = sigs[i][j]
if imm_bitofs is None:
continue
imm_mask = 1 << imm_bitofs
word_mask = 1 << j
if imm & imm_mask:
word |= word_mask
else:
word &= ~word_mask
patched.append(word)
packed = struct.pack(sfmt, *patched)
data[ofs:ofs+size] = packed
return (orig, packed)
def FindPattern(data, signature, mask=None, start=None, maxit=None):
sig_len = len(signature)
if start is None:
start = 0
stop = len(data) - len(signature)
if maxit is not None:
stop = start + maxit
if mask:
assert sig_len == len(mask), 'mask must be as long as the signature!'
for i in range(sig_len):
signature[i] &= mask[i]
for i in range(start, stop):
matches = 0
while signature[matches] is None or signature[matches] == (data[i + matches] & (mask[matches] if mask else 0xFF)):
matches += 1
if matches == sig_len:
return i
raise SignatureException('Pattern not found!')
def NearestConst(x):
n_dist, n_sign = 0xffff, 1
for s in range(32-8):
for i in range(0xff):
y = i << s
assert y <= 0xffffffff, "error while rounding"
dist, sign = abs(y - x), 1 if y - x >= 0 else -1
n_dist, n_sign = (dist, sign)\
if dist < n_dist else (n_dist, n_sign)
return x + n_sign * n_dist