国家太空安全是国家安全在空间领域的表现。随着太空技术在政治、经济、军事、文化等各个领域的应用不断增加,太空已经成为国家赖以生存与发展的命脉之一,凝聚着巨大的国家利益,太空安全的重要性日益凸显[1]。而在信息化时代,太空安全与信息安全紧密地结合在一起。
2020年9月4日,美国白宫发布了首份针对太空网络空间安全的指令——《航天政策第5号令》,其为美国首个关于卫星和相关系统网络安全的综合性政策,标志着美国对太空网络安全的重视程度达到新的高度。在此背景下,美国自2020年起,连续两年举办太空信息安全大赛“黑掉卫星(Hack-A-Sat)”,在《Hack-A-Sat太空信息安全挑战赛深度解析》一书中有详细介绍,本文介绍了Hack-A-Sat黑掉卫星挑战赛的控制卫星载荷任务调度(monroe)这道赛题的解题过程。
题目介绍
Time for a really gentle introduction to cFS and Cosmos, hopefully you can schedule time to learn it!
Build instructions:
$ ./setup.sh $ source ~/.bashrc $ rm Gemfile.lock $ bundle install
Hint: You will need to enable telemetry locally on the satellite, the udp forwarder will provide it to you as TCP from there:
cosmos.tar.gz calendar_hint1.zip
Connect to the challenge on calendar.satellitesabove.me:5061.
从题目描述中可以获取如下信息:
(1)与cFS、COSMOS有关,在下文会有这两个系统的基本介绍。
(2)本题目需要先使能卫星的遥测功能。
(3)提供了两个压缩包,其中cosmos.tar.gz是定制的COSMOS,并且给出了安装操作的指令;calendar_hint1.zip解压缩后有三个文件,如下所示,都是JSON格式的文件,具体含义还不知道,后文会分析。
cpu1_kit_sch_msg_tbl.json
cpu1_kit_sch_sch_tbl.json
cpu1_kit_to_pkt_tbl.json
以上就是题目的全部信息,可能需要安装COSMOS后可以获得更全面的信息。
编译及测试
为了检验下载的源代码是正确的,可以先编译并测试一下。进入hackasat2020的monroe目录下,直接编译,还是比较顺利的,就是时间可能比较长。
sudo make build
使用如下命令进行测试,测试结果如图6-1所示。从图6-1中可以发现正确地获取到了flag值。
sudo make test
图6-1 monroe测试结果
相关背景知识
1.COSMOS
COSMOS(Command and Control of Embedded Systems)是一套应用程序,可用于控制一组嵌入式系统,包括测试设备(电源、示波器、开关电源板、UPS设备等)、开发板(Arduinos、Raspberry Pi、Beaglebone等)、卫星等。本书编写时COSMOS最新的是V5版本,这是一个Web页面版本,但是本挑战题提供了一个定制的COSMOS,采用的是V4版本,所以本书以COSMOS V4进行介绍。
COSMOS V4是一个客户端/服务器(Client/Server,C/S)架构,不是Web页面方式。其架构在本书第3章有介绍,为便于读者阅读,此处再简单说明一下,COSMOS V4架构如图6-2所示。
(1)最中间的是测控指令服务端(Command & Telemetry Server),可以通过TCP、UDP、串口等方式与各类目标(包括卫星、飞行器等)进行交互。
(2)左上角是实时指令和脚本工具(Realtime Commanding and Scripting Tools)。
(3)右上角是实时遥测可视化工具(Realtime Telemetry Visualization Tools)。
(4)左下角是辅助工具,包括配置编辑器(Config Editor)等。
(5)右下角是离线分析工具,包括遥测查看器(Telemetry Viewer)等。
图6-2 COSMOS V4架构
要安装COSMOS V4可以在其官网下载源代码进行安装,但是本挑战题的COSMOS是主办方修改定制的,为了解答这个挑战题,必须使用主办方提供的COSMOS,因此按照题目的提示,安装主办方提供的COSMOS。经过测试,需要在Ubuntu14.04 64bit上安装,为此需要安装Ubuntu14.04 64bit的虚拟机。在虚拟机中,首先更新Ruby的版本,使用如下命令:
sudo add-apt-repository ppa:brightbox/ruby-ngsudo apt-get update
sudo apt-get purge --auto-remove ruby
sudo apt update
sudo apt-get install ruby2.6 ruby2.6-dev
sudo gem install bundle
source ~/.bashrc
rm Gemfile.lock
sudo bundle install
然后执行如下安装命令:
./setup.sh $ source ~/.bashrc $ rm Gemfile.lock $ bundle install
安装成功后会有如图6-3所示的提示。
图6-3 COSMOS安装成功的提示
此时输入如下命令,就会运行COSMOS,其界面如图6-4所示。从中可以发现其各个小程序的归类基本上是按照图6-2中的架构进行的。
sudo ruby ~/cosmos/tools/Launcher
图6-4 COSMOS主界面
为了模拟主办方设置的本挑战题的环境,首先在宿主机上执行如下命令,其中的IP地址需要依据实际情况修改,这段命令的目的就是运行一个容器,并在其中运行monroe挑战题的服务端。
sudo docker run --rm -i -e SERVICE_HOST=192.168.31.43 -e SERVICE_PORT=19021 -e SEED=1 -e FLAG=flag{zulu49225delta\:G1EnNVMK3-hPvlNKAdEJxcujvp9WK4rEchuEdlDp3yv_Wh_uvB5ehGq-fyRowvwkWpdAMTKbidqhK4JhFsaz1k} -p 19021:54321 monroe:challenge
在虚拟机中首先运行如下命令,使用socat做一个端口转发。
socat -d -d TCP-L:54321,fork,reuseaddr TCP:192.168.31.43:19021
然后在虚拟机中打开COSMOS,单击Config Editor按钮,在弹出的如图6-5所示的界面中,设置遥测服务器地址为127.0.0.1,端口为54321。
图6-5 设置COSMOS中遥测服务器地址、端口信息
再次运行COSMOS,单击HAS Quals按钮,弹出如图6-6所示的界面,显示COSMOS连接遥测服务器成功。
切换到Tlm Packets选项卡,可以发现此时的遥测包的数量是0,表示没有接收到遥测数据包,如图6-7所示。
题目中提到要先使能遥测功能,因此需要在COSMOS主界面中单击Command Sender按钮,弹出指令发送界面,在Target下拉列表中中选择KIT_TO选项,此时在Command下拉列表中中会出现ENABLE_TELEMETRY选项,选中该选项,如图6-8所示。然后单击Send按钮,发送该指令,可以发现很快就收到了遥测包,如图6-9所示,说明使能了卫星的遥测功能。下一步如何操作才能得到flag的值,需要继续分析
图6-6 COSMOS连接遥测服务器成功
图6-7 遥测数据包接收界面
图6-8 使能遥测功能
图6-9 接收到了遥测数据包
2.cFS
在前文已经通过COSMOS成功使能了遥测信息发送功能,并且已经接收到了遥测信息。但是要最终得到flag,还有一些基本知识需要了解。通过COSMOS的操作界面,如指令发送界面的Target下拉列表,如图6-10所示,可以发现有很多以CFE开始的Target,经过资料查找,这些与cFS有关,cFS的具体内容可参见3.2.3节的“cFS”。
3.OpenSatKit
OpenSatKit简称OSK,它集成了COSMOS、cFS,并做了一些扩展,可以使用图6-11简化描述。
图6-10 指令发送界面的Target下拉列表
图6-11 OSK的简化组成
从图6-11中可以知道,OSK添加了几个应用程序,如图6-11中的深色框所示,其作用如下:
- KIT_CI(Kit Command Ingest):用来接收COSMOS发送过来的CCSDS格式(参考本书前面章节的介绍)的指令,并将其发布到软总线上。
- KIT_TO(Kit Telemetry Output):从软总线上读取CCSDS格式的遥测数据报(也称为消息),并将其发送给COSMOS。可使用过滤(Filter)表,以便选择哪个消息发给COSMOS。
- KIT_SCH(Kit Scheduler):调度器,包含了一些表,其中定义了如何将消息发布到软总线上。使用到了两个表,一个是消息(Message)表,一个是调度(Scheduler)表。调度器每秒执行一次,按照调度表中的调度要求,发送消息表中的消息。
使能遥测功能时,选择的Target是KIT_TO,选择的Command是ENABLE_TELEMETRY,即是设置OSK的KIT_TO,使其能够输出遥测信息,发送给COSMOS。
从题目提供的3个文件的名称中可知,这3个文件应该对应的是KIT_TO、KIT_SCH这两个程序的3张表,如下:
cpu1_kit_sch_msg_tbl.json:KIT_SCH的消息表。
cpu1_kit_sch_sch_tbl.json:KIT_SCH的调度表。
cpu1_kit_to_pkt_tbl.json:KIT_TO的过滤表。
至于如何使用这3张表,在下文将会进一步分析。
题目解析
1.KIT_SCH的消息表
打开cpu1_kit_sch_msg_tbl.json,其中有如下描述,这里定义了消息的格式,可以发现是CCSDS消息,关于CCSDS在前文已经有了介绍,就不再介绍了,而且解答本挑战题是不需要知道详细细节的。
"name": "Scheduler Table Message Table",
"description": [
"Maximum of 32 words per CCSDS message. The first three words are",
"the primary header that must be big endian: ",
"uint16 StreamId; /* packet identifier word (stream ID) */ ",
" /* bits shift description */",
" /* 0x07FF 0 : application ID */",
" /* 0x0800 11 : secondary header: 0 = absent, 1 = present */",
" /* 0x1000 12 : packet type: 0 = TLM, 1 = CMD */",
" /* 0xE000 13 : CCSDS version, always set to 0 */",
"uint16 Sequence; /* packet sequence word */ ",
" /* bits shift description */",
" /* 0x3FFF 0 : sequence count */",
" /* 0xC000 14 : segmentation flags: 3 = complete packet */",
"uint16 Length; /* packet length word */ ",
" /* bits shift description */",
" /* 0xFFFF 0 : (total packet length) - 7 */"
],
在定义之后是一些具体的消息,值得注意的是,有一个消息如下,它与flag有关,从名称分析,这应该是让KIT_TO发送flag的消息。
{"message": {
"name": "KIT_TO_SEND_FLAG_MID",
"descr": "Super Secret Flag Sending Telemetry Message",
"id": 42,
"stream-id": 33304,
"seq-seg": 192,
"length": 256
}},
2.KIT_SCH的调度表
打开cpu1_kit_sch_sch_tbl.json,其中有如下描述,这里描述了这张表的作用,大意是每秒调度执行5个slot,每个slot最多有10个activity(活动),可以理解为KIT_SCH依据这张表的信息,周期执行相应的activity。
"name": "Scheduler Activity Table",
"description": ["Activities are defined in time slots. There are 5 slots per second",
"and 10 entries per slot. This kit table is organized based on app",
"role. A flight table would be based on real-time needs.",
"The boolean property uses a string for simplicty.",
"The FSW parser uses named objects for callbacks, but named objects",
"can't be array elements which is why they are in brackets."
],
例如,第1个slot的内容如下,注意每个activity的属性中有一个msg-id,应该是与KIT_SCH的消息表中每个消息的id是对应的。
{"slot": {
"index": 0,
"activity-array" : [
{"activity": {
"name": "cFE ES Housekeeping",
"descr": "",
"index": 0,
"enable": "true",
"frequency": 4,
"offset": 0,
"msg-id": 0
}},
......
{"activity": {
"name": "Time Housekeeping",
"descr": "",
"index": 4,
"enable": "true",
"frequency": 4,
"offset": 0,
"msg-id": 4
}}
]
}},
3.KIT_TO的过滤表
打开cpu1_kit_to_pkt_tbl.json,在最开始有如下描述,定义了会被KIT_TO发送的遥测数据包,在此处使用的KIT_TO不具有过滤功能。在文件中定义了flag消息对应的遥测数据包。后来发现,这个文件在本挑战题的解答过程中,并没有用到。
{
"name": "Telemetry Output Table",
"description": "Define default telemetry packets that are forwarded by KIT_TO.
KIT_TO does not have any filtering capabilities.
Each packet entry contains:
CFE_SB_MsgId_t, CFE_SB_Qos_t (Priority,Reliability), Buffer Limit",
......
"packet": {
"name": "KIT_TO_TLM_FLAG_MID",
"stream-id": "\u0886",
"dec-id": 2182,
"priority": 0,
"reliability": 0,
"buf-limit": 4
},
4.KIT_SCH工作过程分析
OSK的文档中关于KIT_SCH的描述非常少,其内部具体是如何工作的,需要通过代码分析得到。下载OSK的代码,打开kit_sch_app.c,找到KIT_SCH_AppMain函数,其中调用了InitApp函数,在InitApp函数中加载了两张表,两张表就是上文分析的KIT_SCH的消息表、KIT_SCH的调度表。代码如下:
#define KIT_SCH_DEF_MSG_TBL_FILE_NAME "/cf/kit_sch_msg_tbl.json"
#define KIT_SCH_DEF_SCH_TBL_FILE_NAME "/cf/kit_sch_sch_tbl.json"
......
TBLMGR_RegisterTblWithDef(TBLMGR_OBJ, MSGTBL_LoadCmd, MSGTBL_DumpCmd, KIT_SCH_DEF_MSG_TBL_FILE_NAME);
TBLMGR_RegisterTblWithDef(TBLMGR_OBJ, SCHTBL_LoadCmd, SCHTBL_DumpCmd, KIT_SCH_DEF_SCH_TBL_FILE_NAME);
......
再回到KIT_SCH_AppMain函数中,这个函数接着进入一个loop,这个函数会不断调用函数SCHEDULER_Execute,而后者会依次执行KIT_SCH的调度表中定义的slot中的activity,主要操作就是发送activity对应的消息到软总线上,其他对应的应用程序收到该消息后,会执行对应的操作。所以解答本挑战题需要做的就是将KIT_SCH的消息表中的消息KIT_TO_SEND_FLAG_MID想办法插入KIT_SCH的调度表中,成为其中一个activity。
5.修改KIT_SCH的调度表的activity
上文已将解题思路分析清楚了,通过使用COSMOS发现,在指令发送窗口,当Target选择为KIT_SCH时,有一个指令是LOAD_SCH_ENTRY,如图6-12所示。将其中的MSG_TBL_IDX修改为在KIT_SCH的消息表cpu1_kit_sch_msg_tbl.json中找到的KIT_TO_SEND_FLAG_MID,即42,单击Send按钮。
图6-12 当Target选择为KIT_SCH,指令可以选择LOAD_SCH_ENTRY
查询Tlm Packets选项卡中的FLAG_TLM_PKT,如图6-13所示,单击对应的View in Packet Viewer按钮,会显示flag值,如图6-14所示。
图6-13 选择Tlm Packets选项卡中的FLAG_TLM_PKT
图6-14 显示收到的flag