aboutsummaryrefslogtreecommitdiffstats
path: root/usb_application/mitm.py
blob: a3951f0640d87556e353b69f11a700289786bb6b (plain)
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
import usb.core
import usb.util
import array

from ccid_raw import SmartcardConnection
from smartcard_emulator import SmartCardEmulator
from gsmtap import gsmtap_send_apdu

from contextlib import closing

from util import HEX
from constants import *
from apdu_split import Apdu_splitter, apdu_states

def find_dev():
    dev = usb.core.find(idVendor=0x03eb, idProduct=0x6004)
    if dev is None:
        raise ValueError("Device not found")
    else:
        print("Found device")
    return dev

def pattern_match(inpt):
    print("Matching inpt", inpt)
    if (inpt == ATR_SYSMOCOM1) or (inpt == ATR_STRANGE_SIM):
        print("ATR: ", inpt)
        return NEW_ATR
    elif (inpt == CMD_SEL_FILE):
        print("CMD_SEL_FILE:", inpt)
        return CMD_SEL_ROOT
    elif (inpt == CMD_GET_DATA):
        print("CMD_DATA:", inpt)
        return CMD_SEL_ROOT
    else:
        return inpt

def poll_ep(dev, ep):
    try:
        return dev.read(ep, 64, 10)
    except usb.core.USBError as e:
        if e.errno != ERR_TIMEOUT:
            raise
        return None

def write_phone(dev, resp):
    print("WR: ", HEX(resp))
    dev.write(PHONE_WR, resp, 10)

def replace(data):
    if data is None:
        raise MITMReplaceError
    else:
        try:
            if data[0] == 0x3B:
                print("*** Replace ATR")
                return array('B', NEW_ATR)
            elif data[0] == 0x9F:
                print("*** Replace return val")
#                return array('B', [0x60, 0x00])
            elif data == PHONE_BOOK_RESP:
                print("*** Replace phone book")
                return PHONE_BOOK_RESP_MITM
        except ValueError:
            print("*** Value error! ")
    return data

def do_mitm(sim_emul=True):
    dev = find_dev()
    if sim_emul == True:
        my_class = SmartCardEmulator
    else:
        my_class = SmartcardConnection
    with closing(my_class()) as sm_con:
        atr = sm_con.getATR()

        apdus = []
        apdu = Apdu_splitter()

        while True:
            cmd = poll_ep(dev, PHONE_INT)
            if cmd is not None:
                print("Int line ", HEX(cmd))
                assert cmd[0] == ord('R')
# FIXME: restart card anyways?
#               sm_con.reset_card()
                print("Write atr: ", HEX(atr))
                write_phone(dev, replace(atr))
                apdus = []
                apdu = Apdu_splitter()

            cmd = poll_ep(dev, PHONE_RD)
            if cmd is not None:
                print("RD: ", HEX(cmd))
                for c in cmd:
                    if apdu.state == apdu_states.APDU_S_FIN:
                        apdus.append(apdu)
                        gsmtap_send_apdu(apdu.buf)
                        apdu = Apdu_splitter()

                    apdu.split(c)
                    if apdu.state == apdu_states.APDU_S_FIN and apdu.pts_buf == [0xff, 0x00, 0xff]:
                        #sim_data = sm_con.send_receive_cmd(apdu.pts_buf)
                        #write_phone(dev,  replace(array('B', sim_data)))
                        write_phone(dev,  replace(array('B', apdu.pts_buf)))
                        continue;

                    if apdu.state == apdu_states.APDU_S_SW1:
                        if apdu.data is not None and len(apdu.data) == 0:
                            # FIXME: implement other ACK types
                            write_phone(dev,  replace(array('B', [apdu.ins])))
                            apdu.split(apdu.ins)
                        else:
                            sim_data = sm_con.send_receive_cmd(apdu.buf)
                            write_phone(dev, replace(sim_data))
                            for c in sim_data:
                                apdu.split(c)
                    elif apdu.state == apdu_states.APDU_S_SEND_DATA:
                            sim_data = sm_con.send_receive_cmd(replace(apdu.buf))
                            sim_data.insert(0, apdu.ins)
                            write_phone(dev, replace(sim_data))
                            apdu.state = apdu_states.APDU_S_SW1
                            for c in sim_data:
                                apdu.split(c)