mirror of
https://gitea.osmocom.org/sim-card/simtrace2.git
synced 2026-03-16 21:28:33 +03:00
Moved the replace function from mitm.py to replace.py. This implementation is context insensitive for now. It would be better, to have a mitm class or to pass state information to the function. Because how else can the MITM code know, whether it gets passed data to or from the sim card, to or from the phone?
99 lines
3.3 KiB
Python
Executable File
99 lines
3.3 KiB
Python
Executable File
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
|
|
|
|
from replace import replace
|
|
|
|
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 do_mitm(dev, sim_emul=True):
|
|
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)
|
|
if 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)
|