Merge branch 'RfidResearchGroup:master' into spi_flash_v2
[RRG-proxmark3.git] / tools / pm3_online_check.py
blob925e63de8adceee59e8f8d41cef5d1f1a62ccfad
1 #!/usr/bin/env python3
3 '''
5 # pm3_online_check.py
6 # Christian Herrmann, Iceman, <iceman@icesql.se> 2020
7 # version = 'v1.0.5'
9 # This code is copyright (c) Christian Herrmann, 2020, All rights reserved.
10 # For non-commercial use only, the following terms apply - for all other
11 # uses, please contact the author:
13 # This code is free software; you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation; either version 3 of the License, or
16 # (at your option) any later version.
18 # This code is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
24 # Dependencies:
26 # pip3 install pexpect ansicolors
28 '''
29 import pexpect
30 from colors import color
31 import requests
32 import string
33 import re
34 import time
35 import argparse
37 def pm3_flashbootrom():
38 flbootrom = pexpect.spawnu('./pm3-flash-bootrom')
39 flbootrom.expect(pexpect.EOF)
40 msg = escape_ansi(str(flbootrom.before))
41 if 'Have a nice day!'.lower() in msg:
42 print("Flashing bootrom ", color('[OK]', fg='green'))
43 else:
44 print("Flashing bootrom ", color('[FAIL]', fg='red'))
46 time.sleep(20)
48 def pm3_flashfullimage():
49 flimage = pexpect.spawnu('./pm3-flash-fullimage')
50 flimage.expect(pexpect.EOF)
51 msg = escape_ansi(str(flimage.before))
52 if 'Have a nice day!'.lower() in msg:
53 print("Flashing fullimage ", color('[OK]', fg='green'))
54 else:
55 print("Flashing fullimage ", color('[FAIL]', fg='red'))
57 time.sleep(20)
59 def escape_ansi(line):
60 ansi_escape = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]')
61 return ansi_escape.sub('', str(line)).lower()
63 def pm3_initrdv4(child):
64 child.sendline('script run init_rdv4')
65 i = child.expect('pm3 --> ')
67 msg = escape_ansi(str(child.before))
68 if 'finished init_rdv4'.lower() in msg:
69 print("Init RDV4 ", color('[OK]', fg='green'))
70 else:
71 print("Init RDV4 ", color('[FAIL]', fg='red'))
73 # LF T55x7 wipe/clone/read/wipe test
74 def pm3_lf_t55xx(child):
76 try:
77 print("[=] starting lf t55xx tests...")
79 # wipe t55xx
80 child.sendline('lf t55xx wipe')
81 i = child.expect('pm3 --> ')
83 msg = escape_ansi(str(child.before))
84 if 'Writing page 0 block: 07 data: 0x00000000'.lower() in msg:
85 print("[+] LF T55XX WIPE ", color('[OK]', fg='green'))
86 else:
87 print("[-] LF T55XX WIPE ", color('[FAIL]', fg='red'))
89 # clone HID
90 child.sendline('lf hid clone -r 2006ec0c86')
91 i = child.expect('pm3 --> ')
93 msg = escape_ansi(str(child.before))
94 if 'Done'.lower() in msg:
95 print("[+] LF HID CLONE ", color('[OK]', fg='green'))
96 else:
97 print("[-] LF HID CLONE ", color('[FAIL]', fg='red'))
99 # read HID
100 child.sendline('lf hid read')
101 i = child.expect('pm3 --> ')
103 msg = escape_ansi(str(child.before))
104 if "HID H10301 26-bit; FC: 118 CN: 1603 parity: valid".lower() in msg:
105 print("[+] LF HID READ ", color('[OK]', fg='green'))
106 else:
107 print("[-] LF HID READ ", color('[FAIL]', fg='red'))
109 # wipe t55xx
110 child.sendline('lf t55xx wipe')
111 i = child.expect('pm3 --> ')
112 return True
114 except:
115 print(color("[!] exception for LF T55XX", fg='red'))
116 msg = escape_ansi(str(child.before))
117 print(msg)
118 child.sendline('quit')
119 child.expect(pexpect.EOF)
120 return False
122 def pm3_flash_sm(child):
123 try:
124 print("[+] Updating smart card fw")
125 child.sendline('smart upgrade -f sim014.bin')
126 i = child.expect('pm3 --> ')
127 msg = escape_ansi(str(child.before))
128 print("================")
129 print(" smart card upgrade")
130 print("==== msg ========")
131 print(msg)
132 if "successful" in msg:
133 print("[+] Smart card firmware upgrade ", color('[OK]', fg='green'))
134 return True
135 else:
136 print("[-] Smart card firmware upgrade ", color('[FAIL]', fg='red'))
137 return False
138 except:
139 print(color("[!] exception for SMART UPGRADE", fg='red'))
140 msg = escape_ansi(str(child.before))
141 print(msg)
142 child.sendline('quit')
143 child.expect(pexpect.EOF)
144 return False
146 def main():
148 parser = argparse.ArgumentParser()
149 parser.add_argument("--flash", help="flash bootrom & fullimage", action="store_true")
150 parser.add_argument("--init", help="run init rdv4 script", action="store_true")
151 parser.add_argument("-y", help="automatic yes to prompts", action="store_true")
152 args = parser.parse_args()
154 print("-----------", color('Proxmark3 online test script v1.0.3', fg='cyan'), "------------")
155 print("This script will run some series of test against a connected Proxmark3 device")
156 print("Steps:");
157 print(" 1. flash bootrom, fullimage");
158 print(" 2. init_rdv4 / flash smartcard");
159 print(" 3. check device mismatch message");
160 print(" 4. check smart card fw, flash memory");
161 print(" if needed, flash flash smartcard reader firmware");
162 print(" 5. check antenna tuning");
163 print(" 6. check LF T55x7 functionality");
164 print(" 7. check HF search");
165 print(" 8. check SPIFFS");
166 print(" 9. check HF iCLASS functionality");
167 print("\n");
169 # result
170 res = 0
171 total_tests = 12
172 must_update_fw = 0
173 msg = ''
175 if args.flash:
176 print("-----------------------", color('Flashing phase', fg='cyan'), "---------------------")
177 print("flashing bootrom - don't touch the device or cables")
178 pm3_flashbootrom()
180 print("flashing fullimage - don't touch the device or cables")
181 pm3_flashfullimage()
182 print("\n")
184 # start pm3
185 child = pexpect.spawnu('./pm3')
186 i = child.expect('pm3 --> ')
187 print("[+] Proxmark3 client open")
189 if args.init:
190 print("------------------------", color('Init phase', fg='cyan'), "------------------------")
191 print("Running init rdv4 script - don't touch the device or cables")
192 pm3_initrdv4(child)
193 print("flashing smartcard - don't touch the device or cables")
194 pm3_flash_sm(child)
195 print("\n")
197 print("------------------------", color('Test phase', fg='cyan'), "------------------------")
200 # check device mismatch
201 signature_msg = "device.................... RDV4".lower()
203 # check flashmemory
204 flash_mem = "baudrate................24 mhz".lower()
206 # check smartcard fw version
207 sm_version = "version................. v4.42".lower()
209 # check LF
210 lf_search = "valid hid prox id found!".lower()
212 # check HF
213 hf_search = "Valid iCLASS tag / PicoPass tag found".lower()
215 # mem spiffs info
216 mem_spiffs = "max path length............32 chars".lower()
218 # lf antenna tuning
219 lf_tune = "LF antenna is OK".lower()
221 # hf antenna tuning
222 hf_tune = "HF antenna is OK".lower()
224 try:
225 # HW VERSION checks
226 child.sendline('hw version')
227 i = child.expect('pm3 --> ')
228 msg = escape_ansi(str(child.before))
230 if signature_msg in msg:
231 print("[+] RDV4 signature ", color('[OK]', fg='green'))
232 res += 1
233 else:
234 print("[-] RDV4 signature ", color('[FAIL]', fg='red'))
237 # HW STATUS checks
238 child.sendline('hw status')
239 i = child.expect('pm3 --> ')
240 msg = escape_ansi(str(child.before))
242 if sm_version in msg:
243 print("[+] Smart card firmware version ", color('[OK]', fg='green'))
244 res += 1
245 else:
246 print("[-] Smart card firmware version ", color('[FAIL]', fg='red'), " will upgrade fw in the next step")
247 must_update_fw = 1
249 if flash_mem in msg:
250 print("[+] Flash memory accessible ", color('[OK]', fg='green'))
251 res += 1
252 else:
253 print("[-] Flash memory accessible ", color('[FAIL]', fg='red'))
255 # extract slow clock and verify its OK...
256 # slow clock check:
257 # Slow clock..............30057 Hz
258 for line in msg.splitlines():
259 match_slow = line.find('slow clock..............')
261 if match_slow > -1:
262 match = re.search(r'\d+', line)
263 if match:
264 clock = int(match[0])
265 if clock < 29000:
266 print("[-] Warning, Slow clock too slow (%d Hz)" % (clock), color('[FAIL]', fg='red'))
267 elif clock > 33000:
268 print("[-] Warning, Slow clock too fast (%d Hz)" % (clock), color('[FAIL]', fg='red'))
269 else:
270 print("[+] Slow clock within acceptable range (%d Hz)" % (clock), color('[OK]', fg='green'))
271 res += 1
272 except:
273 print(color("[!] exception for HW STATUS", fg='red'))
274 msg = escape_ansi(str(child.before))
275 print(msg)
276 child.sendline('quit')
277 child.expect(pexpect.EOF)
278 return
280 if must_update_fw == 1:
281 if pm3_flash_sm(child):
282 res += 1
284 try:
285 print("[=] starting antenna tune tests, this takes some time and plot window will flash up...")
286 # HW TUNE checks
287 child.sendline('hw tune')
288 i = child.expect('pm3 --> ')
290 msg = escape_ansi(str(child.before))
291 if lf_tune in msg:
292 print("[+] LF antenna tuning ", color('[OK]', fg='green'))
293 res += 1
294 else:
295 print("[-] LF antenna tuning ", color('[FAIL]', fg='red'))
297 if hf_tune in msg:
298 print("[+] HF antenna tuning ", color('[OK]', fg='green'))
299 res += 1
300 else:
301 print("[-] HF antenna tuning ", color('[FAIL]', fg='red'))
303 except:
304 print(color("[!] exception for hw tune", fg='red'))
305 msg = escape_ansi(str(child.before))
306 print(msg)
307 child.sendline('quit')
308 child.expect(pexpect.EOF)
309 return
311 # hide plot window again
312 child.sendline('data hide')
313 i = child.expect('pm3 --> ')
315 ans = ''
317 while ans != 'y' and args.y == False:
319 ans = (input(color('>>> Put LF card and HF card on Proxmark3 antenna', fg='yellow') + ' [Y/n/q] ') or "y")
321 if ans == 'q':
322 child.sendline('quit')
323 child.expect(pexpect.EOF)
324 print('[!] Aborted all tests ', color('[USER ABORTED]', fg='red'))
325 return
327 # LF T55X7 WIPE/CLONE/READ TESTS
328 if pm3_lf_t55xx(child):
329 res += 1
331 # HF SEARCH TESTS
332 try:
333 print("[=] starting HF SEARCH tests...")
335 # HF SEARCH Test
336 child.sendline('hf search')
337 i = child.expect('pm3 --> ')
339 msg = escape_ansi(str(child.before))
340 if hf_search in msg:
341 print("[+] HF SEARCH ", color('[OK]', fg='green'))
342 res += 1
343 else:
344 print("[-] HF SEARCH ", color('[FAIL]', fg='red'))
346 except:
347 print(color("[!] exception for HF SEARCH", fg='red'))
348 msg = escape_ansi(str(child.before))
349 print(msg)
350 child.sendline('quit')
351 child.expect(pexpect.EOF)
352 return
354 # MEM Tree test
355 child.sendline('mem spiffs info')
356 i = child.expect('/', timeout=10)
358 msg = escape_ansi(str(child.before))
359 if mem_spiffs in msg:
360 print("[+] MEM SPIFFS INFO ", color('[OK]', fg='green'))
361 res += 1
362 else:
363 print("[-] MEM SPIFFS INFO ", color('[FAIL]', fg='red'))
366 ans = ''
367 while ans != 'y' and args.y == False:
369 ans = (input(color('>>> Put iCLASS legacy card on Proxmark3 antenna', fg='yellow') + ' [Y/n/q] ') or "y")
371 if ans == 'q':
372 child.sendline('quit')
373 child.expect(pexpect.EOF)
374 print('[!] Aborted all tests ', color('[USER ABORTED]', fg='red'))
375 return
377 # iCLASS read/write test
378 try:
379 print("[=] starting iCLASS info/read/write tests...")
380 child.sendline('hf iclass info')
381 i = child.expect('pm3 --> ')
383 # iclass info / read / write checks
384 iclass_info = 'Credential... iCLASS legacy'.lower()
386 iclass_ok = False
387 msg = escape_ansi(str(child.before))
388 if iclass_info in msg:
389 print("[+] HF ICLASS INFO ", color('[OK]', fg='green'))
390 res += 1
391 iclass_ok = True
392 else:
393 print("[-] HF ICLASS INFO ", color('[FAIL]', fg='red'))
395 if iclass_ok:
397 child.sendline('hf iclass rdbl -b 10 --ki 0')
398 i = child.expect('pm3 --> ')
399 msg = escape_ansi(str(child.before))
400 for line in msg.splitlines():
401 iclass_read = 'block 10'.lower()
402 if iclass_read in line:
403 res += 1
404 print("[+] HF ICLASS RDBL ", color('[OK]', fg='green'))
405 old_b10 = line[16:].replace(" ","")
407 child.sendline('hf iclass wrbl -b 10 --ki 0 -d 0102030405060708')
408 i = child.expect('pm3 --> ')
409 msg = escape_ansi(str(child.before))
410 iclass_write = 'wrote block 10 successful'.lower()
411 if iclass_write in msg:
412 res += 1
413 print("[+] HF ICLASS WRBL ", color('[OK]', fg='green'))
414 child.sendline('hf iclass wrbl -b 10 --ki 0 -d %s' % (old_b10))
415 i = child.expect('pm3 --> ')
416 else:
417 print("[-] HF ICLASS WRBL ", color('[FAIL]', fg='red'))
419 break;
421 else:
422 print("[-] skipping iclass read/write")
424 except:
425 print(color("[!] exception iCLASS read/write", fg='red'))
426 msg = escape_ansi(str(child.before))
427 print(msg)
428 child.sendline('quit')
429 child.expect(pexpect.EOF)
430 return
433 # exit Proxmark3 client
434 child.sendline('quit')
435 i = child.expect(pexpect.EOF)
437 print("[+] PM3 client closed\n")
439 # validate test results
441 print("-------------------------", color('Results', fg='cyan'), "-------------------------")
442 if res == total_tests:
443 print('[+] Passed ', color('[OK]', fg='green'))
444 else:
445 print('[-] failed test ', color('[FAIL]', fg='red'), '(%d / %d tests)' % (res, total_tests))
446 print("")
448 if __name__ == "__main__":
449 main()