6 # Christian Herrmann, Iceman, <iceman@icesql.se> 2020
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.
26 # pip3 install pexpect ansicolors
30 from colors
import color
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'))
44 print("Flashing bootrom ", color('[FAIL]', fg
='red'))
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'))
55 print("Flashing fullimage ", color('[FAIL]', fg
='red'))
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'))
71 print("Init RDV4 ", color('[FAIL]', fg
='red'))
73 # LF T55x7 wipe/clone/read/wipe test
74 def pm3_lf_t55xx(child
):
77 print("[=] starting lf t55xx tests...")
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'))
87 print("[-] LF T55XX WIPE ", color('[FAIL]', fg
='red'))
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'))
97 print("[-] LF HID CLONE ", color('[FAIL]', fg
='red'))
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'))
107 print("[-] LF HID READ ", color('[FAIL]', fg
='red'))
110 child
.sendline('lf t55xx wipe')
111 i
= child
.expect('pm3 --> ')
115 print(color("[!] exception for LF T55XX", fg
='red'))
116 msg
= escape_ansi(str(child
.before
))
118 child
.sendline('quit')
119 child
.expect(pexpect
.EOF
)
122 def pm3_flash_sm(child
):
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 ========")
132 if "successful" in msg
:
133 print("[+] Smart card firmware upgrade ", color('[OK]', fg
='green'))
136 print("[-] Smart card firmware upgrade ", color('[FAIL]', fg
='red'))
139 print(color("[!] exception for SMART UPGRADE", fg
='red'))
140 msg
= escape_ansi(str(child
.before
))
142 child
.sendline('quit')
143 child
.expect(pexpect
.EOF
)
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")
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");
176 print("-----------------------", color('Flashing phase', fg
='cyan'), "---------------------")
177 print("flashing bootrom - don't touch the device or cables")
180 print("flashing fullimage - don't touch the device or cables")
185 child
= pexpect
.spawnu('./pm3')
186 i
= child
.expect('pm3 --> ')
187 print("[+] Proxmark3 client open")
190 print("------------------------", color('Init phase', fg
='cyan'), "------------------------")
191 print("Running init rdv4 script - don't touch the device or cables")
193 print("flashing smartcard - don't touch the device or cables")
197 print("------------------------", color('Test phase', fg
='cyan'), "------------------------")
200 # check device mismatch
201 signature_msg
= "device.................... RDV4".lower()
204 flash_mem
= "baudrate................24 mhz".lower()
206 # check smartcard fw version
207 sm_version
= "version................. v4.42".lower()
210 lf_search
= "valid hid prox id found!".lower()
213 hf_search
= "Valid iCLASS tag / PicoPass tag found".lower()
216 mem_spiffs
= "max path length............32 chars".lower()
219 lf_tune
= "LF antenna is OK".lower()
222 hf_tune
= "HF antenna is OK".lower()
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'))
234 print("[-] RDV4 signature ", color('[FAIL]', fg
='red'))
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'))
246 print("[-] Smart card firmware version ", color('[FAIL]', fg
='red'), " will upgrade fw in the next step")
250 print("[+] Flash memory accessible ", color('[OK]', fg
='green'))
253 print("[-] Flash memory accessible ", color('[FAIL]', fg
='red'))
255 # extract slow clock and verify its OK...
257 # Slow clock..............30057 Hz
258 for line
in msg
.splitlines():
259 match_slow
= line
.find('slow clock..............')
262 match
= re
.search(r
'\d+', line
)
264 clock
= int(match
[0])
266 print("[-] Warning, Slow clock too slow (%d Hz)" % (clock
), color('[FAIL]', fg
='red'))
268 print("[-] Warning, Slow clock too fast (%d Hz)" % (clock
), color('[FAIL]', fg
='red'))
270 print("[+] Slow clock within acceptable range (%d Hz)" % (clock
), color('[OK]', fg
='green'))
273 print(color("[!] exception for HW STATUS", fg
='red'))
274 msg
= escape_ansi(str(child
.before
))
276 child
.sendline('quit')
277 child
.expect(pexpect
.EOF
)
280 if must_update_fw
== 1:
281 if pm3_flash_sm(child
):
285 print("[=] starting antenna tune tests, this takes some time and plot window will flash up...")
287 child
.sendline('hw tune')
288 i
= child
.expect('pm3 --> ')
290 msg
= escape_ansi(str(child
.before
))
292 print("[+] LF antenna tuning ", color('[OK]', fg
='green'))
295 print("[-] LF antenna tuning ", color('[FAIL]', fg
='red'))
298 print("[+] HF antenna tuning ", color('[OK]', fg
='green'))
301 print("[-] HF antenna tuning ", color('[FAIL]', fg
='red'))
304 print(color("[!] exception for hw tune", fg
='red'))
305 msg
= escape_ansi(str(child
.before
))
307 child
.sendline('quit')
308 child
.expect(pexpect
.EOF
)
311 # hide plot window again
312 child
.sendline('data hide')
313 i
= child
.expect('pm3 --> ')
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")
322 child
.sendline('quit')
323 child
.expect(pexpect
.EOF
)
324 print('[!] Aborted all tests ', color('[USER ABORTED]', fg
='red'))
327 # LF T55X7 WIPE/CLONE/READ TESTS
328 if pm3_lf_t55xx(child
):
333 print("[=] starting HF SEARCH tests...")
336 child
.sendline('hf search')
337 i
= child
.expect('pm3 --> ')
339 msg
= escape_ansi(str(child
.before
))
341 print("[+] HF SEARCH ", color('[OK]', fg
='green'))
344 print("[-] HF SEARCH ", color('[FAIL]', fg
='red'))
347 print(color("[!] exception for HF SEARCH", fg
='red'))
348 msg
= escape_ansi(str(child
.before
))
350 child
.sendline('quit')
351 child
.expect(pexpect
.EOF
)
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'))
363 print("[-] MEM SPIFFS INFO ", color('[FAIL]', fg
='red'))
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")
372 child
.sendline('quit')
373 child
.expect(pexpect
.EOF
)
374 print('[!] Aborted all tests ', color('[USER ABORTED]', fg
='red'))
377 # iCLASS read/write test
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()
387 msg
= escape_ansi(str(child
.before
))
388 if iclass_info
in msg
:
389 print("[+] HF ICLASS INFO ", color('[OK]', fg
='green'))
393 print("[-] HF ICLASS INFO ", color('[FAIL]', fg
='red'))
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
:
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
:
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 --> ')
417 print("[-] HF ICLASS WRBL ", color('[FAIL]', fg
='red'))
422 print("[-] skipping iclass read/write")
425 print(color("[!] exception iCLASS read/write", fg
='red'))
426 msg
= escape_ansi(str(child
.before
))
428 child
.sendline('quit')
429 child
.expect(pexpect
.EOF
)
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'))
445 print('[-] failed test ', color('[FAIL]', fg
='red'), '(%d / %d tests)' % (res
, total_tests
))
448 if __name__
== "__main__":