-
Notifications
You must be signed in to change notification settings - Fork 283
Expand file tree
/
Copy pathencoded_strings.py
More file actions
59 lines (48 loc) · 2.06 KB
/
encoded_strings.py
File metadata and controls
59 lines (48 loc) · 2.06 KB
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
from binaryninja import (StringRecognizer, CustomStringType, DataBuffer, DerivedString, DerivedStringLocation,
DerivedStringLocationType, PointerType, InstructionTextToken, InstructionTextTokenType)
encoded_string_type = CustomStringType.register("Encoded", "", "_enc")
class EncodedStringRecognizer(StringRecognizer):
recognizer_name = "encoded_strings"
decoders = {
"xor_encoded": lambda encoded, key: encoded ^ key,
"sub_encoded": lambda encoded, key: (encoded - key) & 0xff,
"add_encoded": lambda encoded, key: (encoded + key) & 0xff
}
def is_valid_for_type(self, func, type):
if not isinstance(type, PointerType):
return False
for name in self.__class__.decoders.keys():
if name in type.target.attributes:
return True
return False
def recognize_constant_pointer(self, instr, type, val):
if not isinstance(type, PointerType):
return None
values = None
decoder = None
for name in self.__class__.decoders.keys():
if name in type.target.attributes:
try:
values = bytes.fromhex(type.target.attributes[name])
decoder = self.__class__.decoders[name]
except Exception:
return None
if values is None or decoder is None:
return None
encoded_null = "encoded_null" in type.target.attributes
result = b""
i = 0
while True:
byte = instr.function.view.read(val + i, 1)
if len(byte) != 1:
return False
if not encoded_null and byte[0] == 0:
break
byte = decoder(byte[0], values[i % len(values)])
if byte == 0:
break
result += bytes([byte])
i += 1
loc = DerivedStringLocation(DerivedStringLocationType.DataBackedStringLocation, val, i)
return DerivedString(result, loc, encoded_string_type)
EncodedStringRecognizer().register()