-
Notifications
You must be signed in to change notification settings - Fork 29
/
symbolyzer.py
123 lines (107 loc) · 4.57 KB
/
symbolyzer.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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
######################################################################################
# #
# Author: Stephanie Archibald <sarchibald@cylance.com> #
# Copyright (c) 2017 Cylance Inc. All rights reserved. #
# #
# Redistribution and use in source and binary forms, with or without modification, #
# are permitted provided that the following conditions are met: #
# #
# 1. Redistributions of source code must retain the above copyright notice, this #
# list of conditions and the following disclaimer. #
# #
# 2. Redistributions in binary form must reproduce the above copyright notice, #
# this list of conditions and the following disclaimer in the documentation and/or #
# other materials provided with the distribution. #
# #
# 3. Neither the name of the copyright holder nor the names of its contributors #
# may be used to endorse or promote products derived from this software without #
# specific prior written permission. #
# #
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND #
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED #
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE #
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR #
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES #
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; #
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON #
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT #
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS #
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #
# #
######################################################################################
import sys
def calc_int(string, offset):
"""
Return a hex string representation of the integer found by referencing offset bytes into string.
"""
try:
return "".join(reversed(["%02x" % ord(string[offset + i]) for i in range(4)]))
except:
print offset, string
raise
class results:
"""
Class to generate the offset / int pairs for a list of symbols.
"""
def __init__(self, symbols):
self.symbols = symbols
self.results = []
self.cant_match = []
self.generate()
def generate(self):
"""
Create the offset / int pairs for all the symbols.
"""
for i in range(len(self.symbols)):
symbol = self.symbols[i]
j = 0
for n in self.symbols:
if n == symbol: continue
k = self.find_unique_offset(symbol, n)
if k == -1:
self.cant_match.append(symbol)
break
if k > j:
j = k
if symbol not in self.cant_match:
self.results.append(result(symbol, j))
def find_unique_offset(self, symbol1, symbol2):
"""
Finds a unique offset between two symbols.
"""
symbol1 += "\0"
symbol2 += "\0"
looplen = min(len(symbol1), len(symbol2)) - 3
if looplen < 0: return -1
i = 0
for i in range(looplen):
if calc_int(symbol1, i) != calc_int(symbol2, i):
break
if i == looplen:
if len(symbol1) > len(symbol2):
return i
return -1
return i
class result:
"""
Helper class to store and print the offset / int pairs for a given symbol.
"""
def __init__(self, name, offset):
self.name = name
self.set_offset(offset)
def set_offset(self, offset):
self.offset = offset
self.int = calc_int(self.name + "\0", offset)
def __str__(self):
return "%s[%i] = 0x%s" % (self.name, self.offset, self.int)
if __name__ == "__main__":
try:
r = results([line.strip() for line in sys.stdin.readlines() if line != "\n"])
for p in r.results:
print p
if r.cant_match:
print "\nDIDN'T WORK (%i):" % len(r.cant_match)
for n in r.cant_match:
print n
except KeyboardInterrupt:
pass