-
Notifications
You must be signed in to change notification settings - Fork 5
/
exploit.py
128 lines (103 loc) · 4.26 KB
/
exploit.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
124
125
126
127
import serial
import time
import signal
import sys
import datetime
import os
# This script is the actual exploit script
# it writes the data read to a file 'data.csv'
# it can restart without losing progress
# only the locations list needs to be updatet
locations = [(33733, 6), (178005, 6)]
if os.path.exists('data.csv'):
with open('data.csv') as f:
for line in f:
pass
last_line = line
begin_address = int(last_line.split(',')[0]) + 1
else:
begin_address = 0
current_address = begin_address
data = {}
class BitArray:
def __init__(self, size):
self.size = size
self.bytearray = bytearray(size)
def get_bit(self, bit_ix):
if not isinstance(bit_ix, int):
raise IndexError("bit array index not an int")
if bit_ix < 0 or bit_ix >= self.size*8:
raise IndexError("bit array index out of range")
byte_ix = bit_ix >> 3
bit_ix = 7 - (bit_ix & 7)
return (self.bytearray[byte_ix] >> bit_ix) & 1
def set_bit(self, bit_ix, val):
if not isinstance(bit_ix, int):
raise IndexError("bit array index not an int")
if bit_ix < 0 or bit_ix >= self.size*8:
raise IndexError("bit array index out of range")
if not isinstance(val, int):
raise ValueError("bit array value not an int")
if val not in (0, 1):
raise ValueError("bit array value must be 0 or 1")
byte_ix = bit_ix >> 3
bit_ix = 7 - (bit_ix & 7)
bit_val = 1 << bit_ix
if val:
self.bytearray[byte_ix] |= bit_val
else:
self.bytearray[byte_ix] &= ~bit_val
def __getitem__(self, key):
return self.get_bit(key)
def __setitem__(self, key, value):
self.set_bit(key, value)
def add_pulse(bitarray: BitArray, offset: int, pulse_width: int):
for idx in range(offset, offset+pulse_width):
bitarray[idx] = 1
return bitarray
def generate_waveform(array_size: int, *args):
bitarray = BitArray(array_size)
for offset, pulse_width in args:
add_pulse(bitarray, offset, pulse_width)
# print("WARNING: 0xff bytearray")
# return bytearray([0xff]*array_size)
return bitarray.bytearray
start = time.time()
start_datetime = datetime.datetime.now()
last_success = datetime.datetime.now()
def signal_handler(sig, frame):
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
with serial.Serial('/dev/ttyACM0', 115200) as ser:
with open('data.csv', 'a') as datafile:
ser.write(b's')
glitch_size_bytes = int(ser.read_until(b'.')[:-1]) * 4
print(f'Glitch buffer size = {glitch_size_bytes}')
ser.write(b'a')
ser.write([0x90, (current_address>>8)&0xff, current_address&0xff, 0xE0]) # set dptr, load dptr to A
assert ser.read(2) == b'a.'
ser.write(b'd')
pulse = generate_waveform(glitch_size_bytes, *locations)
ser.write(pulse)
response = ser.read_until(b'.')
assert response == b'd.', response
while current_address < 0x8000:
ser.write(b'g')
response = ser.read(5)
if response[1] == 0xb2 and response[3] == 0xb2:
print(f'SUCCESS: {response.hex(" ")}')
data[current_address] = response[2]
print(f'{current_address},{response[2]}', file=datafile)
current_address += 1
if current_address & 0xff == 0:
print(data)
datafile.flush()
ser.write(b'a')
ser.write([0x90, (current_address>>8)&0xff, current_address&0xff, 0xE0]) # set dptr, load dptr to A
assert ser.read(2) == b'a.'
last_success = datetime.datetime.now()
total_work = 0x8000 - begin_address
progress = (current_address - begin_address + 0.5) / total_work
time_spent = datetime.datetime.now() - start_datetime
total_time_estimated = time_spent / progress
print(response.hex(' '), f"{current_address} all={current_address/0x8000*100:>5.2f}% now={progress*100:>5.2f}% [{' X'[response[1] == 0xb2]}] [{' X'[response[3] == 0xb2]}] elapsed={time_spent} eta={start_datetime + total_time_estimated} since_success={datetime.datetime.now() - last_success}")