-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathbinbase_find.py
113 lines (99 loc) · 3.43 KB
/
binbase_find.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
#!/usr/bin/env python3
# https://github.com/mncoppola/ws30/blob/master/basefind.py
import os
import re
import signal
import struct
import sys
from operator import itemgetter
chars = "A-Za-z0-9/\\-:.,_$%'\"()[\]<> "
min_length = 10
scores = []
top_score = 0
regexp = bytes("[{}]{{{:d},}}".format(chars, min_length), "us-ascii")
pattern = re.compile(regexp)
regexpc = bytes("[{}]{{1,}}".format(chars), "us-ascii")
patternc = re.compile(regexpc)
def get_strings(filename, size):
table = set()
offset = 0
with open(filename, "rb") as f:
while True:
if offset >= size:
break
f.seek(offset)
try:
data = f.read(10)
except:
break
match = pattern.match(data)
if match:
f.seek(offset - 1)
try:
char = f.read(1)
except:
continue
if not patternc.match(char):
table.add(offset)
offset += len(match.group(0))
offset += 1
return table
def get_pointers(filename):
table = {}
with open(filename, "rb") as f:
while True:
try:
value = struct.unpack("<L", f.read(4))[0]
try:
table[value] += 1
except KeyError:
table[value] = 1
except:
break
return table
def high_scores(signal, frame):
print("\nTop 20 base address candidates:")
for score in sorted(scores, key=itemgetter(1), reverse=True)[:20]:
print("0x{:x}\t{:d}".format(*score))
sys.exit(0)
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
def auto_int(x):
return int(x, 0)
parser.add_argument("--min_addr", type=auto_int, help="start searching at this address", default=0)
parser.add_argument("--max_addr", type=auto_int, help="stop searching at this address", default=0xfe000000)
parser.add_argument("--page_size", type=auto_int, help="search every this many byte", default=0x1000)
parser.add_argument("infile", help="file to scan")
args = parser.parse_args()
size = os.path.getsize(args.infile)
scores = []
print("Scanning binary for strings...")
str_table = get_strings(args.infile, size)
print("Total strings found: {:d}".format(len(str_table)))
print("Scanning binary for pointers...")
ptr_table = get_pointers(args.infile)
print("Total pointers found: {:d}".format(len(ptr_table)))
signal.signal(signal.SIGINT, high_scores)
for base in range(args.min_addr, args.max_addr, args.page_size):
if base % ( args.page_size * 1000 ) == 0:
print("Trying base address 0x{:x}".format(base))
print("\u001b[F\u001b[K", end="")
score = 0
ptrs = list(ptr_table.keys())
for ptr in ptrs:
if ptr < base:
#print("Removing pointer 0x{:x} from table".format(ptr))
del ptr_table[ptr]
continue
if ptr >= (base + size):
continue
offset = ptr - base
if offset in str_table:
score += ptr_table[ptr]
if score:
scores.append((base, score))
if score > top_score:
top_score = score
print("New highest score, 0x{:x}: {:d}".format(base, score))
high_scores(0, 0)