Christina Quast | 69d1f90 | 2015-04-03 11:41:23 +0200 | [diff] [blame] | 1 | import usb.core |
| 2 | import usb.util |
Christina Quast | fb91bb7 | 2015-04-18 13:31:42 +0200 | [diff] [blame] | 3 | import array |
Christina Quast | 69d1f90 | 2015-04-03 11:41:23 +0200 | [diff] [blame] | 4 | |
Christina Quast | 88c7fa1 | 2015-04-06 00:35:03 +0200 | [diff] [blame] | 5 | from ccid_raw import SmartcardConnection |
Christina Quast | 158c1dd | 2015-04-17 20:19:29 +0200 | [diff] [blame] | 6 | from smartcard_emulator import SmartCardEmulator |
Christina Quast | 95270b1 | 2015-04-04 19:59:03 +0200 | [diff] [blame] | 7 | |
Christina Quast | 88c7fa1 | 2015-04-06 00:35:03 +0200 | [diff] [blame] | 8 | from contextlib import closing |
| 9 | |
Christina Quast | f2e53f0 | 2015-04-11 08:42:38 +0200 | [diff] [blame] | 10 | from util import HEX |
Christina Quast | 9547e9f | 2015-04-14 22:18:30 +0200 | [diff] [blame] | 11 | from constants import * |
Christina Quast | 5384061 | 2015-04-16 11:10:59 +0200 | [diff] [blame] | 12 | from apdu_split import Apdu_splitter, apdu_states |
Christina Quast | 88c7fa1 | 2015-04-06 00:35:03 +0200 | [diff] [blame] | 13 | |
Christina Quast | 69d1f90 | 2015-04-03 11:41:23 +0200 | [diff] [blame] | 14 | def find_dev(): |
| 15 | dev = usb.core.find(idVendor=0x03eb, idProduct=0x6004) |
| 16 | if dev is None: |
| 17 | raise ValueError("Device not found") |
| 18 | else: |
| 19 | print("Found device") |
| 20 | return dev |
| 21 | |
Christina Quast | 88c7fa1 | 2015-04-06 00:35:03 +0200 | [diff] [blame] | 22 | def pattern_match(inpt): |
| 23 | print("Matching inpt", inpt) |
Christina Quast | 94ddb91 | 2015-04-11 12:29:41 +0200 | [diff] [blame] | 24 | if (inpt == ATR_SYSMOCOM1) or (inpt == ATR_STRANGE_SIM): |
| 25 | print("ATR: ", inpt) |
Christina Quast | 88c7fa1 | 2015-04-06 00:35:03 +0200 | [diff] [blame] | 26 | return NEW_ATR |
| 27 | elif (inpt == CMD_SEL_FILE): |
Christina Quast | 94ddb91 | 2015-04-11 12:29:41 +0200 | [diff] [blame] | 28 | print("CMD_SEL_FILE:", inpt) |
| 29 | return CMD_SEL_ROOT |
| 30 | elif (inpt == CMD_GET_DATA): |
| 31 | print("CMD_DATA:", inpt) |
Christina Quast | 88c7fa1 | 2015-04-06 00:35:03 +0200 | [diff] [blame] | 32 | return CMD_SEL_ROOT |
| 33 | else: |
| 34 | return inpt |
Christina Quast | 69d1f90 | 2015-04-03 11:41:23 +0200 | [diff] [blame] | 35 | |
Christina Quast | 88c7fa1 | 2015-04-06 00:35:03 +0200 | [diff] [blame] | 36 | def poll_ep(dev, ep): |
| 37 | try: |
Christina Quast | 3a47a4f | 2015-04-11 18:16:14 +0200 | [diff] [blame] | 38 | return dev.read(ep, 64, 10) |
Christina Quast | 88c7fa1 | 2015-04-06 00:35:03 +0200 | [diff] [blame] | 39 | except usb.core.USBError as e: |
| 40 | if e.errno != ERR_TIMEOUT: |
| 41 | raise |
| 42 | return None |
Christina Quast | 69d1f90 | 2015-04-03 11:41:23 +0200 | [diff] [blame] | 43 | |
Christina Quast | 88c7fa1 | 2015-04-06 00:35:03 +0200 | [diff] [blame] | 44 | def write_phone(dev, resp): |
Christina Quast | f2e53f0 | 2015-04-11 08:42:38 +0200 | [diff] [blame] | 45 | print("WR: ", HEX(resp)) |
Christina Quast | 3a47a4f | 2015-04-11 18:16:14 +0200 | [diff] [blame] | 46 | dev.write(PHONE_WR, resp, 10) |
Christina Quast | 88c7fa1 | 2015-04-06 00:35:03 +0200 | [diff] [blame] | 47 | |
Christina Quast | 46a9367 | 2015-04-21 23:00:52 +0200 | [diff] [blame] | 48 | def replace(data): |
| 49 | if data is None: |
| 50 | raise MITMReplaceError |
| 51 | else: |
| 52 | try: |
| 53 | if data[0] == 0x3B: |
| 54 | print("*** Replace ATR") |
Christina Quast | b6e005c | 2015-05-04 15:28:03 +0200 | [diff] [blame] | 55 | return array('B', NEW_ATR) |
Christina Quast | 46a9367 | 2015-04-21 23:00:52 +0200 | [diff] [blame] | 56 | elif data[0] == 0x9F: |
| 57 | print("*** Replace return val") |
| 58 | # return array('B', [0x60, 0x00]) |
Christina Quast | 34d4eb3 | 2015-05-04 17:50:32 +0200 | [diff] [blame] | 59 | elif data == PHONE_BOOK_RESP: |
| 60 | print("*** Replace phone book") |
| 61 | return PHONE_BOOK_RESP_MITM |
Christina Quast | 46a9367 | 2015-04-21 23:00:52 +0200 | [diff] [blame] | 62 | except ValueError: |
| 63 | print("*** Value error! ") |
| 64 | return data |
| 65 | |
Christina Quast | 158c1dd | 2015-04-17 20:19:29 +0200 | [diff] [blame] | 66 | def do_mitm(sim_emul=True): |
Christina Quast | 69d1f90 | 2015-04-03 11:41:23 +0200 | [diff] [blame] | 67 | dev = find_dev() |
Christina Quast | 158c1dd | 2015-04-17 20:19:29 +0200 | [diff] [blame] | 68 | if sim_emul == True: |
| 69 | my_class = SmartCardEmulator |
| 70 | else: |
| 71 | my_class = SmartcardConnection |
| 72 | with closing(my_class()) as sm_con: |
Christina Quast | 6f664a3 | 2015-04-06 19:08:04 +0200 | [diff] [blame] | 73 | atr = sm_con.getATR() |
Christina Quast | 5384061 | 2015-04-16 11:10:59 +0200 | [diff] [blame] | 74 | |
| 75 | apdus = [] |
| 76 | apdu = Apdu_splitter() |
| 77 | |
Christina Quast | 88c7fa1 | 2015-04-06 00:35:03 +0200 | [diff] [blame] | 78 | while True: |
| 79 | cmd = poll_ep(dev, PHONE_INT) |
| 80 | if cmd is not None: |
Christina Quast | f2e53f0 | 2015-04-11 08:42:38 +0200 | [diff] [blame] | 81 | print("Int line ", HEX(cmd)) |
Christina Quast | 88c7fa1 | 2015-04-06 00:35:03 +0200 | [diff] [blame] | 82 | assert cmd[0] == ord('R') |
Christina Quast | 6f664a3 | 2015-04-06 19:08:04 +0200 | [diff] [blame] | 83 | # FIXME: restart card anyways? |
| 84 | # sm_con.reset_card() |
Christina Quast | f2e53f0 | 2015-04-11 08:42:38 +0200 | [diff] [blame] | 85 | print("Write atr: ", HEX(atr)) |
Christina Quast | 46a9367 | 2015-04-21 23:00:52 +0200 | [diff] [blame] | 86 | write_phone(dev, replace(atr)) |
Christina Quast | fb91bb7 | 2015-04-18 13:31:42 +0200 | [diff] [blame] | 87 | apdus = [] |
| 88 | apdu = Apdu_splitter() |
Christina Quast | 69d1f90 | 2015-04-03 11:41:23 +0200 | [diff] [blame] | 89 | |
Christina Quast | 88c7fa1 | 2015-04-06 00:35:03 +0200 | [diff] [blame] | 90 | cmd = poll_ep(dev, PHONE_RD) |
| 91 | if cmd is not None: |
Christina Quast | f2e53f0 | 2015-04-11 08:42:38 +0200 | [diff] [blame] | 92 | print("RD: ", HEX(cmd)) |
Christina Quast | 5384061 | 2015-04-16 11:10:59 +0200 | [diff] [blame] | 93 | for c in cmd: |
Christina Quast | fb91bb7 | 2015-04-18 13:31:42 +0200 | [diff] [blame] | 94 | if apdu.state == apdu_states.APDU_S_FIN: |
| 95 | apdus.append(apdu) |
| 96 | apdu = Apdu_splitter() |
| 97 | |
Christina Quast | 5384061 | 2015-04-16 11:10:59 +0200 | [diff] [blame] | 98 | apdu.split(c) |
Christina Quast | 08ea861 | 2015-05-03 16:34:32 +0200 | [diff] [blame] | 99 | if apdu.state == apdu_states.APDU_S_FIN and apdu.pts_buf == [0xff, 0x00, 0xff]: |
Christina Quast | b6e005c | 2015-05-04 15:28:03 +0200 | [diff] [blame] | 100 | #sim_data = sm_con.send_receive_cmd(apdu.pts_buf) |
| 101 | #write_phone(dev, replace(array('B', sim_data))) |
| 102 | write_phone(dev, replace(array('B', apdu.pts_buf))) |
Christina Quast | 08ea861 | 2015-05-03 16:34:32 +0200 | [diff] [blame] | 103 | continue; |
Christina Quast | fb91bb7 | 2015-04-18 13:31:42 +0200 | [diff] [blame] | 104 | |
Christina Quast | 5384061 | 2015-04-16 11:10:59 +0200 | [diff] [blame] | 105 | if apdu.state == apdu_states.APDU_S_SW1: |
Christina Quast | fb91bb7 | 2015-04-18 13:31:42 +0200 | [diff] [blame] | 106 | if apdu.data is not None and len(apdu.data) == 0: |
Christina Quast | 5384061 | 2015-04-16 11:10:59 +0200 | [diff] [blame] | 107 | # FIXME: implement other ACK types |
Christina Quast | 46a9367 | 2015-04-21 23:00:52 +0200 | [diff] [blame] | 108 | write_phone(dev, replace(array('B', [apdu.ins]))) |
Christina Quast | 5384061 | 2015-04-16 11:10:59 +0200 | [diff] [blame] | 109 | apdu.split(apdu.ins) |
| 110 | else: |
| 111 | sim_data = sm_con.send_receive_cmd(apdu.buf) |
Christina Quast | 46a9367 | 2015-04-21 23:00:52 +0200 | [diff] [blame] | 112 | write_phone(dev, replace(sim_data)) |
Christina Quast | 5384061 | 2015-04-16 11:10:59 +0200 | [diff] [blame] | 113 | for c in sim_data: |
| 114 | apdu.split(c) |
Christina Quast | fb91bb7 | 2015-04-18 13:31:42 +0200 | [diff] [blame] | 115 | elif apdu.state == apdu_states.APDU_S_SEND_DATA: |
Christina Quast | 46a9367 | 2015-04-21 23:00:52 +0200 | [diff] [blame] | 116 | sim_data = sm_con.send_receive_cmd(replace(apdu.buf)) |
Christina Quast | fb91bb7 | 2015-04-18 13:31:42 +0200 | [diff] [blame] | 117 | sim_data.insert(0, apdu.ins) |
Christina Quast | 46a9367 | 2015-04-21 23:00:52 +0200 | [diff] [blame] | 118 | write_phone(dev, replace(sim_data)) |
Christina Quast | fb91bb7 | 2015-04-18 13:31:42 +0200 | [diff] [blame] | 119 | apdu.state = apdu_states.APDU_S_SW1 |
| 120 | for c in sim_data: |
| 121 | apdu.split(c) |