本环境是蛇矛实验室基于”火天网演攻防演训靶场”进行搭建,通过火天网演中的环境构建模块,可以灵活的对目标网络进行设计和配置,并且可以快速进行场景搭建和复现验证工作。
关于CAN总线协议
CAN 是Controller Area Network 的缩写(以下称为CAN),是ISO国际标准化的串行通信协议。在汽车产业中,出于对安全性、舒适性、方便性、低功耗、低成本的要求,各种各样的电子控制系统被开发了出来。由于这些系统之间通信所用的数据类型及对可靠性的要求不尽相同,由多条总线构成的情况很多,线束的数量也随之增加。为适应“减少线束的数量”、“通过多个LAN,进行大量数据的高速通信”的需要,1986 年德国电气商博世公司开发出面向汽车的CAN 通信协议。此后,CAN 通过ISO11898 及ISO11519 进行了标准化,在欧洲已是汽车网络的标准协议。CAN 的高性能和可靠性已被认同,并被广泛地应用于工业自动化、船舶、医疗设备、工业设备等方面。现场总线是当今自动化领域技术发展的热点之一,被誉为自动化领域的计算机局域网。它的出现为分布式控制系统实现各节点之间实时、可靠的数据通信提供了强有力的技术支持。
ICSim模拟分析
在了解CAN之前,我们先来理解一下什么是ECU(Electronic Control Unit),早期分布式的电子电气架构下,每个 ECU 通常只负责控制一个单一的功能单元,彼此独立,分别控制着发动机、刹车、车 门等部件。虽然现在ECU变得越来越复杂,但其基本部件不会改变,ECU 控制车辆的不同功能,现代汽车中有多达 70 个 ECU。如果这些ECU需要通信,那么就用到了CAN。在CAN总线出现之前,汽车制造商使用点对点布线,因此大多数部件都需要互相连接才能实现通信。如果汽车布线时出现故障,诊断会变得非常困难。CAN的出现使这种状况变得简单,CAN是一种总线协议,它允许微控制器(MCU)和ECU相互通信,并且它是一种基于消息的协议。通过单个 CAN 接口,ECU 可以通过集中式系统与每个之间进行通信,涉及更少的布线,并且数据通过数字信号而不是模拟信号传输,它使信号在传输过程中发生错误的概率减小。要访问汽车的CAN总线进行调试,我们需要连接汽车的OBD接口(现在汽车都使用OBD-II接口),一般情况下,这个接口位于驾驶员座位的前方附近。下图中为汽车的调试接口
我们学习vehicle安全的最便宜简单的方法是使用汽车模拟器。我们可以使用 ICSim工具,很方便的了解和学习 CAN 的内容。由于本小节只是简单介绍CAN和ICSim模拟器的使用,使初学者对CAN有初步了解,对CAN的详细内容并不会进行讲解,如果大家有兴趣可以去看<<智能汽车安全攻防大揭秘>>这本书。ICSim(Instrument Cluster Simulator),是由Open Garages推出的工具。它可以产生多个CAN信号,同时会产生许多背景噪声,让我们可以在没有汽车或不改造汽车的情况下即可练习CAN总线的逆向技术。ICSim 包括一个带有车速表、门锁指示灯、转向信号灯和控制面板的仪表板。模拟控制器允许用户与模拟汽车网络进行交互,应用加速、刹车、控制门锁和转向信号。
安装ICSim环境,需要首先安装ICSim所需依赖库:
sudo apt install libsdl2-dev libsdl2-image-dev
要发送、接收和分析 CAN 包,我们需要 CAN 分析工具。Can-utils 是一组 Linux 实用程序,允许 Linux 与车载 CAN 网络进行通信。Can-utils 包含 4个我们经常使用的主要工具:
sudo apt install can-utils
#candump : 显示、过滤和记录CAN数据到文件。candump并不会解码数据。
#canplayer : 对记录的CAN数据进行重放。
#cansend : 发送CAN数据。
#cansniffer : 显示CAN数据并高亮显示变化的字节。
切换到ICSim目录,执行”make”命令,就可以编译成功。编译成功后,就可以使用”icsim van0″来模拟车辆,我们另起一个终端,使用”controls vcan0″,这时出现仪表盘的窗口是模拟控制器,并且控制器中的速度表一直忽上忽下的跳到在0mph以上的位置,说明ICSim工作正常。
下面,我们可以使用如下键位来操作控制器
上方向键加速
向左方向键左转
向右方向键右转
右shift+A/X开左车门(前/后)
右shift+B/Y开右前车门(前/后)
左shift+A/X关左车门(前/后)
左shift+B/Y关右前车门(前/后)
运行后,我们可以使用ifconfig来查看网络接口,发现会多出来一个vcan0的网络接口。
我们可以使用”candump vcan0″来抓取CAN包裹流量,这时我们对控制器进行操作就会抓取相应命令的流量。如下图,左侧可以看到抓取的流量直接打印到屏幕上,显示流量时还是比较乱的。
这时我们可以使用”candump -l vcan0″,candump会自动将抓取的流量包放入candump-xxx.log文件中。
想要停止抓取可以按”ctrl+c”。查看一下抓取流量包,第一列,括号内的是时间戳,第二列中vcan0为我们的虚拟can接口。后面的是ID和数据,ID和数据以#号分割。
candump可以监听并记录原始数据,会有很多对我们无用的数据。can-utils工具包中还有一款可以根据仲裁ID进行分组显示,并对变化的数据以红色显示,使我们比较容易分辨,它就是cansniffer。我们使用”cansniffer -c vcan0″命令来对vcan0进行监听。
我们可以测试一下,当我按下左方向键时,仪表盘开始出现左转向的灯。同时左侧的流量包开始变动,但是我不太好观察到哪里出现了变化。
这时,我们可以将ID这一列截图固定在左侧,因为cansniffer已经对ID做了分类,当进行左转向的操作,就可以观察出哪里出现了变化。如下图所示,当我按下左转向时,发现左侧多出了一行,这一行为”188#01000000″,那么这一条流量包大概率是对转向进行操作的包裹。
同理,我们继续测试一下右转向,发现左侧多出一行,即为”188#02000000″。发现和左转向仅仅相差1字节,说明id为188很有可能是对转向的控制命令。接下来,我们验证一下。
cansend可以模拟发送包裹,cansend命令的使用为”cansend vcan0 ID#XXXXXXXX”。上面我们已经观察到188为转向控制ID,我们发送一下sniffer的左转包裹,发现确实仪表盘出现了左转,证明了我们188确实是左转控制ID。
同理,我们测试一下右转。
按照前面的思路,我们测试一下开车门的操作,步骤和上面相同。当我按下”右shift+A”时,左前车门开启,同时我们发现开左前车门的ID为19B,并且数据为”00000E000000″。
同时,测试一下关闭左前车门时的命令包裹。发现为”19B#00000F000000″。
使用”cansend vcan0 19B#00000E000000″命令发送开启左前车门的包裹,发送完毕后发现仪表盘左前车门打开。
使用”cansend vcan0 19B#00000F000000″命令发送关闭左前车门指令,发送完毕后,车门关闭。证实了我们分析的车门开启和关闭的指令。
测试加油的指令时,上面的操作也可以比较方便的分析出加油指令ID和数据。这里不在重复讲解,上面的方法固然好用,但是也有不适用的时候,比如情况比较复杂,出现的ID变化或者较多。我们还有一种方法可以分析出对车辆的指令。我们首先使用”candump -l vcan0″进行流量抓取,抓取过程中进行加油门操作,然后松开油门,使其速度将为最低,最后停止抓取流量。
这样一来,整个的过程就可以抓取到log文件中。我们使用重放的发送,发送这个log文件中的所有内容。
命令如下,使用”canplayer -I candump-xxx.log”命令就会将抓取到的流量重新发送一边。发送后可以观察到我们上面加速和减速的整个过程,接下里我们就要使用二分法截取加速的部分。
使用二分法截取加速过程,例如这里我抓取的log文件有200000条数据,我们先截取前1000000条数据进行重放。观察是否只是加速过程,这里我发现有减速过程就继续使用二分法。一直当我截取到20000-40000条时,我发现只为加速过程。然后我们就可以进行下一步了。
我们将log文件的时间戳去掉后,使用”cat xxx.log | sort | uniq -c | sort -n”命令来分类我们的流量包日志文件。这条命令的结果是去重后,按照ID出现的次数进行排序。一般情况下,一直加油时发出的指令都是单次的,并不会重复。按照这一现象,我们分类后,发现出现1次,并且ID相同并且递增的命令就是加速指令。
如下图所示,”244#0000001xxx”即为加速指令。我们重放后,可以观察到加速现象。
同理,我们也可以测试开关车门的指令,比如我这里开了4次左前车门,关了3次左前车门(开门和关门次数不同时容易比较分析)。然后使用”cat xxx.log | sort | uniq -c | sort -n”命令进行分类,分类后可以简单方便的查找车开关车门的指令。
Fuzzing
我们可以使用savvyCAN工具对can协议进行fuzz测试。
savvyCAN安装过程如下,
首先需要安装qt环境,这里我使用5.14.2版本(https://download.qt.io/archive/qt/5.14/5.14.2/)(savvyCAN环境要求>=5.14.0版本),下载”.run”的在线安装程序,然后其赋予执行权限(chmod 755 qt-xxx.run),使用”./qt-xxx.run”进行安装,这里我安装完毕后的目录为”~/Qt5.14.2/5.14.2″。
git clone https://github.com/collin80/SavvyCAN.git
sudo apt install libqt5serialbus5-dev libqt5serialport5-dev qtdeclarative5-dev qttools5-dev
cd SavvyCAN
~/Qt5.14.2/5.14.2/gcc_64/bin/qmake
make
安装完毕后就可以使用”./savvyCAN”启动工具,启动后的页面如下。我们需要先连接vcan0才能进行下一步操作。点击Connection然后点击”open Connection Window”。
点击”Add New Device Connection – QT SerialBus Device-socketcan-vcan0″,然后点击”Create New Connections”,最后”Save Bus Settings”就创建好连接了。
savvyCAN工具部分功能与我们上面使用的can-utils工具相同,下图为RE tools中的sniffer功能,与我们上面操作使用的cansniffer功能相同,但是savvyCAN中变化的数据使用了颜色进行标记,更便于我们辨识数据。
savvyCAN工具的重点即为fuzz功能,点击”Send Frames-fuzzing”就会出现下图中的fuzzing window,这个窗口中的功能适用于我们想要fuzz否个ID范围,并且可以自定义fuzz的数据。
下图中为我测试0x244 ID的fuzz效果,绿框部分为我们想要fuzz数据的位数,这里我设置只fuzz最后俩个bytes的数据,并且数据范围为00-FF。ID Scanning为Random模式,这里可以设置seqential,效果更为明显。
fuzzing功能对我们测试某个范围的ID功能极有帮助,可以帮助我们快速辨别出id的功能。
总结
这一小节,我们学习了使用ICSim模拟器模拟车辆,并且通过can-utils和savvyCAN工具对CAN总线进行抓包和分析,初步了解了CAN的内容。
蛇矛实验室成立于2020年,致力于安全研究、攻防解决方案、靶场对标场景仿真复现及技战法设计与输出等相关方向。团队核心成员均由从事安全行业10余年经验的安全专家组成,团队目前成员涉及红蓝对抗、渗透测试、逆向破解、病毒分析、工控安全以及免杀等相关领域。
原文始发于微信公众号(蛇矛实验室):物联网安全实战从零开始-CAN总线协议初探