-
Notifications
You must be signed in to change notification settings - Fork 5
/
test.config.decode.py
executable file
·219 lines (171 loc) · 5.62 KB
/
test.config.decode.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#!/usr/bin/env python3
#
# Look at a packet capture of the app sending the WIFI configuration and try
# to decode what is actually going on
#
# Create these captures by running tcpdump on the phone before using the
# "add device" option in the app
import sys
import pcap
def hexdump(buf):
"""Takes bytes and does a standard hexdump"""
r = ""
addr = 0
hexdigits = ""
strdigits = ""
for b in buf:
hexdigits += "{:02x} ".format(b)
if b >= 0x20 and b <= 0x7e:
strdigits += chr(b)
else:
strdigits += '.'
if addr % 16 == 15:
r += "H: {:03x}: {:48}|{}|\n".format(addr-15, hexdigits, strdigits)
hexdigits = ""
strdigits = ""
addr += 1
if len(strdigits):
r += "H: {:03x}: {:48}|{}|\n".format(
addr-len(strdigits),
hexdigits,
strdigits
)
return r
pc = pcap.pcap(sys.argv[1])
pc.setfilter('udp port 7001')
verbose = False
sync_prev = None # track the most recent sync value
data_set = None # track the ip_dest for the current group
data1_curr = None # track the first in each group of three
data2_index = None # track the second in each group of three
data_index_prev = None # track the counter
data = {}
time_first = None
for timestamp, packet in pc:
if time_first is None:
time_first = timestamp
time_delta = timestamp - time_first
ip_dest = packet[0x21] # essentially the triplet identifier
data_len = len(packet) - 42 # this ends up being the signal data
if data_len > 0x1ff:
# This looks like part of a sync
if sync_prev is None:
if data_len != 0x203:
print("{:.3f} {:02x} {:03x} SYNC bad start".format(
time_delta, ip_dest, data_len,
))
# Populate the data and continue
sync_prev = data_len
continue
if data_len != sync_prev-1:
print("{:.3f} {:02x} {:03x} SYNC detected missing".format(
time_delta, ip_dest, data_len,
))
if data_len == 0x200:
# the final in a sync set
if verbose:
print("{:.3f} {:02x} {:03x} SYNC end".format(
time_delta, ip_dest, data_len,
))
sync_prev = None
continue
sync_prev = data_len
continue
if sync_prev is not None:
# The sync sequence didnt end properly
print("{:.3f} -1 -1 SYNC bad end".format(
time_delta,
))
sync_prev = None
if data_set is None:
# a fresh set of three values is arriving
data_set = ip_dest
data1_curr = data_len
continue
if data_set is not None:
# we expect this to be a continuation of a previous triplet
if data_set != ip_dest:
print("{:.3f} {:02x} {:03x} TRIPLE bad".format(
time_delta, ip_dest, data_len,
))
data_set = None
continue
if data2_index is None:
data2_index = data_len
continue
if data_index_prev is not None and data2_index != data_index_prev+1:
data_index_prev = None
if data2_index != 0x128:
# only show error if it is not a restart
print("{:.3f} {:02x} {:03x} TRIPLE bad counter".format(
time_delta, data_set,
data2_index,
))
if verbose:
print("{:.3f} {:02x} -1 TRIPLE {:03x} {:03x} {:03x} {:010b} {:010b}".format( # noqa
time_delta, data_set,
data2_index,
data1_curr,
data_len,
data1_curr,
data_len,
))
if data2_index in data:
# confirm that the data has not changed
if (data1_curr != data[data2_index][0] or
data_len != data[data2_index][1]):
print("{:.3f} {:02x} -1 DATA mismatch".format(
time_delta, data_set,
))
else:
data[data2_index] = list([data1_curr, data_len])
# save the counter
data_index_prev = data2_index
data_set = None
data1_curr = None
data2_index = None
continue
print("{:.3f} {:02x} {:03x} UNK {:010b}".format(
time_delta, ip_dest,
data_len, data_len,
))
print("\n")
print("DATA")
packet = bytes()
for i in sorted(data.keys()):
d0 = data[i][0]
d2 = data[i][1]
# TODO
# - This guess does not work for a PSK with spaces in it
# - some of the packet contents appear to be changing in unexpected ways
guess = (
(d2 & 0x7) |
(~d2 & 8) |
(d0 & 7) << 4 |
(~d0 & 8) << 4
)
print("{:03x} {:03x} {:03x} : {:010b} {:010b} {:010b} : {:03x}".format(
d0, i, d2,
d0, i, d2,
guess
))
packet += bytes([guess])
if len(packet) == 0:
print("WARN: No data found")
exit(1)
print("")
print(hexdump(packet))
packet_len_total = packet[0]
packet_len_psk = packet[1]
packet_total_xor = packet[4]
packet_psk = packet[9:9 + packet_len_psk]
packet_ssid = packet[9 + packet_len_psk:packet_len_total]
# TODO - this may not be true if the BSSID has been appended (which is
# done in the published ESP TOUCH android app source)
assert len(packet) == packet_len_total, "Received packet length mismatch"
xor = 0
for byte in packet:
xor ^= byte
assert xor == 0, "Received packet failed xor test"
print("PSK = {}".format(packet_psk))
print("SSID = {}".format(packet_ssid))