最近在外文博客看了相关的系列文章,学习结束后决定翻译整理做一个笔记,整理笔记的过程中曾试图放弃,阅读实践半小时,整理笔记用几天,以后再慢慢培养整理笔记的技能吧。
CAN 是控制器局域网络(Controller Area Network)的简称,是实现汽车所有或部分部件之间通信的中枢神经系统,由以研发和生产汽车电子产品著称的德国 BOSCH 公司开发并最终成为国际标准(ISO 11898),是国际上应用最广泛的现场总线之一。在使用 CAN 作为车内通信系统之前,汽车制造商使用的是点对点布线系统,当汽车内部电子单元越来越多时,这种布线系统会显得特别庞大且维护成本太高,后来通过使用 CAN 代替来解决这个问题。
简单来说,CAN 可以让汽车上的各个电子单元相互通信、共享数据,提出 CAN 的主要原因是它允许多个 ECU(Electronic Control Unit,电子控制单元)共用一根导线进行通信。在一辆现代汽车中存在多达 70 个 ECU,例如:发动机控制单元、安全气囊、变速箱、齿轮单元、防抱死制动系统(ABS)、信息娱乐系统、气候控制系统、车窗、车门等部件,为了让这些单元之间能够相互通信,点对点布线会显得特别庞大。试想一下,每一个组件都连接到其它全部组件,对于后期故障诊断和排除来说是相当糟糕的,但是有了 CAN 就可以用单线代替,每个元件之间的通信就简单了许多。
CAN 总线可以被认为是一个嘈杂、拥挤、慢速版的以太网局域网,只是流量是 UDP 而不是 TCP。值得注意的是,并不是所有的汽车控制系统都使用 CAN,而且 CAN 不仅仅是汽车系统中使用的通信协议,还可能有其它协议,如蓝牙、GSM/LTE 蜂窝网络、卫星无线电、LIN(Local Interconnect Network)等。在实际场景中,CAN 并不是唯一的攻击面,可能还存在很多其它的攻击面。
一辆汽车可以有多个节点,能够发送或接收报文,这个报文基本上由一个 ID 组成,它的优先级,也可以包含 CAN 报文,一次可以是 8 个字节或更少。如果两个或两个以上的节点同时开始发送报文,那么以主导 ID 发送的报文将覆盖依次主导 ID 发送的报文,这就是所谓的基于优先级的总线仲裁。ID 数值越小的报文优先级越高,这就是节点判断报文传输先后的依据。来自制动器的报文比来自音频播放器的报文具有更高的优先级。
CAN 总线由两根不同的导线组成,由于它是总线,因此这些导线可以连接到多个设备。一个 CAN 帧有 3 个主要部分:
1、仲裁标识符
2、数据长度代码
3、数据领域
下面来看看 CAN 数据帧的结构:
为了访问汽车的 CAN 总线,需要先访问车载自诊断端口,也就是 OBD。虽然可能存在数以百计的其它诊断标准或者端口,但基本上现在所有汽车都使用的 OBD-Ⅱ,这也正是修车修理工用来识别汽车故障的途径,OBD 是最直接访问 CAN 的,找到 OBD-Ⅱ 的方法非常简单,它通常位于乘客座椅或者驾驶员座椅附近,且不用使用螺丝刀就能访问。
这就是 OBD 的具体样子:
如果您想知道 OBD 的引脚,下面是 OBD 端口的引脚:
因为电脑不能直接与 CAN 连接,为了与 CAN 总线交互,需要类似 USB 转 CAN 的工具,通过 USB 连接到 OBD-II 端口,这样就可以发送或接收 CAN 数据包。同时在软件上需要一些能够读取或写入 CAN 数据包以及编码或解码 CAN 数据包的工具。只要有一点硬件和软件,绝对可以连接 CAN。
连接 OBD-II 所需的硬件可以很容易地在市场上找到,有昂贵以及廉价的硬件设备。高端设备包括 Kvaser 和 EMS,这些设备价格昂贵且矫枉过正,性价比很高的组合是 USB2CAN 和原生的 Linux 系统。
另外,很多时候会遇到 ELM327,它是一个基于蓝牙的设备,但对于黑客来说是非常糟糕的,原因是它的数据速率比较慢,最后会丢失很多数据包。
Macchina M2 是一个开源的汽车接口,可以通过 OBD-II 与 CAN 总线通信。Macchina M2 最大的优点是它是模块化的,也就是说可以在 Macchina M2 的基础上增加 WiFi、GSM、LTE、BLE 模块。Macchina M2 有 2 个 CAN 通道。Macchina M2 还具有 LIN,可以通过访问链接:
https://www.macchina.cc/catalog/m2-boards/m2-under-dash
获取更多关于 Macchina M2 的信息。
另一个低成本的选择是 CSS 电子公司的 CLX000,它可以记录和流式传输 CAN 数据,数据可以在免费的开源软件 Wireshark 中可视化,一个插件便可以实现逆向功能,CLX000 是可视化和远程信息处理的理想选择。
可以通过访问链接:
https://www.csselectronics.com/screen/page/reverse-engineering-can-bus-messages-with-wireshark/language/en
获取更多关于 CLX000 的信息,在博客中也有一些关于 CAN 的文章。
在软件方面,Linux 内核中内置了 SocketCAN、can-utils、vcan,它们的作用是发送和接收 CAN 数据包,对数据进行编码或解码,也可以通过 Wireshark 分析 CAN 数据包。
如果想了解更多关于 CAN 操作的知识,而又不想破坏自己的汽车,ICSim 将会是首选工具:
https://github.com/zombieCraig/ICSim
SDL 是用于计算机图形和音频的跨平台开发库,由于 ISCim 使用 SDL 绘制虚拟汽车组合仪表板的动画,因此必须安装。这可以通过 apt-get 安装:
sudo apt-get install libsdl2-dev libsdl2-image-dev -y
can-utils 是一套 Linux 特有的实用工具,它可以让 Linux 与车辆上的 CAN 网络进行通信,为了发送、接收和分析 CAN 数据包,需要安装 CAN utils。canutils 主要包括 5 个经常使用的工具:
1、cansniffer 用于嗅探数据包
2、cansend 发送一条数据
3、candump 转储所有接收的数据包
4、canplayer 重播 CAN 数据包
5、cangen 随机生成 CAN 数据包
这可以通过 apt-get 安装:
sudo apt-get install can-utils -y
git clone https://github.com/zombieCraig/ICSim cd ICSim make
进入 ICSim 目录,有一个名为 setup_vcan.sh 的 shell 脚本:
modprobe 命令是用来加载内核模块,比如 can 和 vcan 模块,最后两行将创建一个 vcan0 接口以便模拟汽车网络,可以运行下面的命令来设置一个虚拟的 can 接口:
./setup_vcan.sh
要验证 vcan0 接口,如果配置 vcan0 将显示:
运行 ICSim 至少需要两个组件,一个仪表盘和一个控制器,用来模拟加速、刹车、控制车门、转向灯等,需要至少 3 个终端窗口或标签来运行仪表盘、控制器和 can-utils。
为了运行仪表盘,需要运行一个名为 icsim 的文件,参数为 vcan0,也就是之前创建的接口。
./icsim vcan0
此时,仪表盘仍无法正常工作,包括速度表、转向灯、刹车和车门。这是因为接口 vcn0 上没有流量,为了模拟接口 vcan0 上的流量,这里需要启动控制器。
./controls vcan0
vcan0 是一个虚拟的 CAN 接口,ICSim 将通过它来发送和接收 CAN 帧,当启动控制面板时,可以观察到车速表有一些波动,这是因为控制面板模拟了噪声,启动控制面板后,便可以使用键盘来模拟流量。
行为 | 快捷键 |
---|---|
加速 | ↑ |
左右转向 | ←/→ |
解锁前左右车门 | Right-Shift + A/B |
解锁后左右车门 | Right-Shift + X/Y |
锁定全部车门 | Right-Shift + Left-Shift |
解锁全部车门 | Left-Shift + Right-Shift |
这是 CAN 报文通过 can-utils 采集后的具体样子,如果把这几列细分的话,第一列是接口,第二列是仲裁 ID,第三列是 CAN 报文的大小,这个不能超过 8 个字节,如果看一下 CAN 帧,就更明白为什么这个不能超过 8 个字节,第四列是 CAN 数据本身。
在这个例子中,这是一个 8 字节的帧,该消息是由一个仲裁 ID 0x111 发送的,仪表盘看到这个报文后,首先会确定这个报文是否是为仪表盘准备的,如果是那么它就会读取这个报文,这个报文的数据是 0x0BB8,即十进制的 3000,现在仪表盘会将转速表的指针移到 3000。
了解了 CAN 报文的意义后,就可以进一步通过 ODB-II 在 CAN 总线上注入假的或修改后的数据包来欺骗转速表或其它东西。
在进入 ICSim 的演示之前,需要先看看 can-utils 提供的其它工具是如何工作的,要做到这一点首先需要设置虚拟 can 接口,下面的内容主要是讲解 setup_vcan.sh 文件内的命令具体是什么含义,在实际操作中可以直接运行 setup_vcan.sh 文件。
加载 CAN 的内核模块以及虚拟 CAN 的内核模块:
sudo modprobe can sudo modprobe vcan
验证是否加载了所需的内核模块:
lsmod | grep can
这将显示 can 和 vcan 的内核模块是否被加载:
接下来设置虚拟接口:
sudo ip link add dev vcan0 type vcan sudo ip link set up vcan0
可以通过下面方法来验证虚拟 CAN 接口是否设置成功:
ifconfig vcan0
虚拟 CAN 接口设置成功后就可以在这个接口中发送或接收 CAN 数据包了,接下来使用 can-utils 中的一个叫做 cangen 的工具来生成虚拟的 CAN 数据包。
cangen 可以生成用于测试的 CAN 帧,要使用 cangen 需要指定要生成 CAN 帧的接口,这里 vcan0 是创建的虚拟 CAN 接口:
cangen vcan0
生成 CAN 帧后,有很多工具可以查看 CAN 帧的内容,这里以 Wireshark 举例。
这里可能会看到很多接口可用,但只需要关注 CAN 帧生成的接口 vcan0,点击 vcan0 接口便可以看到 CAN 帧的内容:
还能看到更多 CAN 帧的详细信息:
另外,可以选择使用 can-utils 提供的工具,比如 cansniffer 和 candump,它们的功能和 Wireshark 差不多。
可以使用 candump 转储或记录 CAN 帧:
candump vcan0
candump 会将 CAN 帧输出显示:
下面的终端中正在运行 cangen 生成 CAN 帧,上面的终端正在运行 candump 记录 CAN 帧,记录的 CAN 帧可以分为四列,第一列是 CAN 接口,第二列是仲裁 ID,第三列是 CAN 数据的大小,第四列是数据本身。
candump 还可以转储 CAN 帧,如果想进行重放攻击,需要先转储 CAN 帧,然后使用 canplayer 对转储的 CAN 帧进行重放,CAN 帧的转储可以使用 -l 参数启动:
candump -l vcan0
使用 candump 转储 CAN 帧时,会创建一个以 candump 为前缀和日期命令的文件,如果想查看转储文件的内容,可以在 Linux 中使用 cat 命令查看:
顾名思义,canplayer 是用来重放 CAN 帧的工具。理想情况下,当必须进行重放攻击时,首先需要转储或记录 CAN 帧,然后使用 canplayer 对 CAN 帧进行重放。
想象一个场景,希望对转速表进行欺骗,但是却不知道转速表的读数在哪个仲裁 ID 上工作,这种情况需要先用 candump 的 -l 参数转储 CAN 帧数,然后用 canplayer 重放转储的 CAN 帧,使用 canplayer 重放 CAN 帧时需要通过 -I 参数来接受输入文件:
canplayer -I canfile.log
canplayer 还有一些其它非常好用的参数,可以通过man canplayer
获取。
cansniffer 是用于嗅探 CAN 数据包的工具。cansniffer 的 -c 参数可以通过颜色高亮突出变化的字节,当需要判断执行某些操作是否会导致 CAN 数据变化时使用。
cansniffer -c vcan0
cansniffer 可以通过仲裁 ID 进行过滤,当需要只显示某一个特定仲裁 ID 的帧时,只需在嗅探的过程中,按减号(-)然后输入 000000,再按 Enter 键清除所有的帧,按加号(+)然后输入仲裁 ID,再按 Enter 键便只显示特定仲裁 ID 的帧。
cansend 是用于将 CAN 帧发送到特定 CAN 接口的工具:
cansend interface frame
以上就是在 ICSim 中将会使用到的工具。
前面已经介绍了如何安装和设置 ICSim,这里直接启动仪表盘和控制器:
./icsim vcan0 ./controls vcan0
如果按照前面的流程,这里应该没有什么问题,可以看到速度表指针正在来回移动,这是噪音引起的预期行为。
将使用 can-utils 提供的 cansniffer 工具来嗅探数据包,可以打开一个新的终端并启动 cansniffer,并通过 -c 参数显示 CAN 帧内字节的变化:
cansniffer -c vcan0
可以看到 CAN 帧的变化非常快,很难跟上通信发生的速度,在真实的汽车中,这种通信会发生得更快,为了跟上它的速度,可以使用仲裁 ID 过滤。如果只想查看仲裁 ID 为 40C 的帧,可以按减号(-)然后输入 000000,再按 Enter 键清除所有的帧,按加号(+)然后输入 40C,再按 Enter 键便只显示仲裁 ID 为 40C 的帧。
在进行重放攻击前需要打开 ICSim,这个时候会在 cansnifer 工具中看到 CAN 帧的变化,在使用candump -l vcan0
转储 CAN 帧的同时在控制器对仪表盘进行操作,例如:加速、转向,然后停止转储,将会看到创建了一个 candump-XXXXX.log 命名的文件,接下来使用canplayer -I candump-XXXXX.log
对转储的 CAN 帧进行重放,将会在仪表盘中看到转储时进行的操作。
在真实的汽车中,CAN 总线的噪音可能会大很多,且 CAN 帧出现速度也会快很多,所以如何识别出关键的仲裁 ID 是一个难题,这里列出两种方法:二分法和统计法,推荐使用统计法。
将转储的 CAN 帧文件一分为二,然后分别重放观察哪一个文件包含了关键的仲裁 ID,然后对相应的文件再进行操作,依次循环。
以仲裁 ID 或仲裁 ID 和 CAN 数据为依据,统计出 CAN 帧文件各仲裁 ID 或仲裁 ID 和 CAN 数据出现的次数,根据出现的此处进行判断。
目前有很多软件可以监控和过滤 CAN 通信,其中包含收费的专业工具和免费的开源工具,这篇文章的主要目的是在免费的情况下学习汽车黑客,所以不会对收费的专业工具进行介绍。前面已经介绍了 can-utils、Wireshark 两款免费的工具,下面将介绍另外一款图形界面的工具,SavvyCAN 提供了更多额外的功能,它除了能够轻轻的浏览、过滤数据包和仲裁 ID,还可以在 CAN 帧上执行脚本、Fuzzing,以及内置了几个逆向工具。
"SavvyCAN "是一个基于 QT 的跨平台 C++ 程序。它是一个 CAN 总线逆向和捕获工具。它最初是为了利用 EVTV 硬件,如 EVTVDue 和 CANDue 硬件而编写的。它已经扩展到能够使用任何 socketCAN 兼容设备以及 Macchina M2 和 Teensy 3.x 板。它可以同时采集并发送至多个总线和 CAN 采集设备。"
SavvyCAN 官网是这么介绍这款工具的,可以通过链接:
https://www.savvycan.com/
获取更多关于 SavvyCAN 的内容,个人感觉 SavvyCAN比can-utils 更容易使用,这里只是个人观点,不进行争论,大家可以选择自己习惯的工具完成相应的操作。
SavvyCAN 的安装非常简单,可以直接通过访问链接:
https://www.savvycan.com
下载 windows、Linux、mac os 下的二进制文件。这里只在 Linux 下进行演示:
wget https://github.com/collin80/SavvyCAN/releases/download/V199.1/SavvyCAN-305dafd-x86_64.AppImage
这里下载的直接是二进制文件,不需要安装便可运行:
chmod 744 SavvyCAN-305dafd-x86_64.AppImage ./SavvyCAN-305dafd-x86_64.AppImage
当 SavvyCAN 与 Macchina M2 或任何其它兼容硬件一起使用时,不需要再安装其它额外的东西,但是当与 ICSim 一起使用时,由于需要连接 QT SerialBus Devices,运行直接下载的 SavvyCAN 二进制文件,在 Connection->Open Connection Window->Add New Device Connection 中可以观察到 QT SerialBus Devices 被禁用,需要手动编译 SavvyCAN:
wget http://download.qt.io/official_releases/qt/5.12/5.12.4/qt-opensource-linux-x64-5.12.4.run chmod +x ./qt-opensource-linux-x64-5.12.4.run sudo ./qt-opensource-linux-x64-5.12.4.run
安装的过程中如果提示登陆账号,断网重新安装便可。
外文博客中这里还编译安装了 qtserialbus,在编译 qtserialbus 的过程中出现了报错,可能是由于版本原因造成的,后来发现不安装 qtserialbus 的情况下也可以正常使用 SavvyCAN。
git clone https://github.com/collin80/SavvyCAN cd SavvyCAN /opt/Qt5.12.4/5.12.4/gcc_64/bin/qmake CONFIG+=debug make
编译完成后,就可以启动 ICSim 模拟器,接下来不再使用 can-utils,而是使用 SocketCAN 捕获 CAN 通信。
这里启动的是刚刚编译的 Savvycan 二进制文件,而不是前面下载的 Savvycan 二进制文件,如果在真实的汽车上使用,那么无需手动编译,直接运行下载的 Savvycan 二进制文件即可。
cd SavvyCAN ./SavvyCAN
在 Connection->Open Connection Window->Add New Device Connection 中选择 QT SerialBus Devices,将 SerialBus Devices 选择为 socketcan,将 Port 选择为虚拟端口 vcan0:
创建新连接结束后,在 SavvyCAN 窗口可以看到已经捕获到了 CAN 帧:
为了更好的了解 SavvyCAN 的功能,将使用 SavvyCAN 完成前面用 can-utils 完成的操作,在 SavvyCAN 窗口的右边可能通过选择来过滤仲裁 ID:
由于一些玄学问题,SavvyCAN 的功能并没有完全使用,下面只介绍几个功能,更多功能和用法还是需要以后慢慢摸索。
使用 SavvyCAN 执行重放攻击要容易得多,在 Send Frames 中选择 Playback,可以从文件加载数据或直接从捕获的数据加载数据,还可以从 ID 筛选菜单中选择要重播的 ID。
SavvyCAN 提供了许多逆向工具,其中经常使用的是 Sniffer,它能够弹出非活动字节,通过二分法过滤仲裁 ID 便可以快速识别出关键的仲裁 ID:
在上面勾选的仲裁 ID 中并没有发现任何与操作相对应的字节变化,接下来选择上面未勾选的仲裁 ID 进行观察:
SavvyCAN 还有一个非常实用的功能,在 Send Frames 中选择 Custom,它能够发送自定义的帧并可以实时修改:
SavvyCAN 还有一个非常酷的功能,在 Send Frames 中选择 Fuzzing,它能够非常容易的对 CAN 帧进行 fuzzing。
识别油门、车门和转向信号的仲裁 ID,并通过 CAN 完成加速、打开关闭车门、转向的操作。
模拟器实践结束,总感觉与真车相比会有很大不同,但是又买不起车,又没有窃格瓦拉的技术,还是需要有机会在真车上实践一番。
Car Hacking 101: Practical Guide to Exploiting CAN-Bus using Instrument Cluster Simulator — Part I: Setting Up:
https://yogeshojha.com/me/car-hacking-101-practical-guide-to-exploiting-can-bus-using-instrument-cluster-simulator-part-i-setting-up/
Car Hacking 101: Practical Guide to Exploiting CAN-Bus using Instrument Cluster Simulator — Part II: Exploitation:
https://yogeshojha.com/me/car-hacking-101-practical-guide-to-exploiting-can-bus-using-instrument-cluster-simulator-part-ii-exploitation/
Car Hacking 101: Practical Guide to Exploiting CAN-Bus using Instrument Cluster Simulator - Part III: SavvyCAN, Fuzzing CAN Frame and playing around with CAN frames:
https://yogeshojha.com/me/car-hacking-101-practical-guide-to-exploiting-can-bus-using-instrument-cluster-simulator%e2%80%8a-%e2%80%8apart-iii-savvycan-fuzzing-can-frame-and-playing-around-with-can-frames/