有趣的Hack-A-Sat黑掉卫星挑战赛——解读卫星遥测数据
国家太空安全作为国家安全的重要组成部分,在空间领域发挥着核心作用。由于太空技术在政治、经济、军事以及文化等多个领域不断取得突破进展,在信息化时代背景下得到了广泛应用和发展。如今太空已发展成为国家的战略资源之一,它承载着重要的战略价值,正处在一个战略高度[1]。而在信息化时代下,不仅有传统的物理层保护,还有先进的人工智能技术协同保护,使得两者实现了深度融合。
于2020年9月4日,《航天政策第5号令》被美国白宫发布为针对太空网络空间安全的第一份指导方针。该政策标志着这一领域的重要性得到美方的高度认可,并成为其第一个专注于卫星及关联系统的网络安全综合方案。在此背景下,在那一年起每年举办两年次‘ Hack-A-Sat’太空信息安全大赛。从那一年起每年举办两年次‘ Hack-A-Sat’太空信息安全大赛从那一年起每年举办两年次‘ Hack-A-Sat’太空信息安全大赛从那一年起每年举办两年次‘ Hack-A-Sat’太空信息安全大赛从那一年起每年举办两年次‘ Hack-A-Sat’太空信息安全大赛从那一年起每年举办两年次‘ Hack-A-Sat’太空信息安全大赛从那一年起每年举办两年次‘ Hack-A-Sat’太空信息安全大赛从那一年起每年举办两年次‘ Hack-A-Sat’太空信息安全大赛
题目介绍
注
本挑战题以LaunchDotCom地面站为例,在Carnac1.0卫星上实现了遥测数据的接收。本挑战题的任务是依据XTCE标准开发解码器电路,并通过该电路完成遥测数据的解码。
本次挑战题提供了某个起始链接地址。通过netcat工具连接至指定链接后随后会提供额外提示信息(如图4-7所示)。该服务位于另一个IP地址位置(如图4-8所示)。接着再用netcat工具访问该IP位置显示遥测服务正在发送了一系列二进制数据流至远程端口。打印输出呈现乱码字符序列目前并未识别出明显的标志符或指示信息依据本题提供的条件和要求请参赛者基于XTCE标准对收集到的数据进行解码处理以提取标志符。

图4-7 verizon题目的提示信息

图4-8 连接到遥测服务后,接收到的数据
所得资料为telemetry.zip文件。经解压缩仅得到一个文件telemetry.xtce。此文件采用XTCE格式。XTCE作为遥测及指令数据规范的标准格式(见下文中的相关知识介绍)。此文件可用来解析遥测服务发送之二进制数据的意义。
题目编译及测试
本题的代码存储于verizon目录中。在challenge和solver目录下的Dockerfile文件中发现其中使用了python:3.7-slim版本。为了提高程序运行效率,在verizon目录中新增sources.list文件。内容如下:
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bullseye-security main contrib non-free
将sources.list复制至verizon、challenge及solver目录中,在verizon目录下优化Dockerfile配置文件,在所有以FROM python:3.7-slim开头的Dockerfile指令后添加:
ADD sources.list /etc/apt/sources.list
打开终端,进入verizon所在目录,执行命令:
sudo make build
使用make test命令进行测试,会顺利通过,其输出信息如图4-9所示。

图4-9 verizon挑战题测试输出
相关背景知识
1.CCSDS
CCSDS(即 Consultative Committee for Space Data Systems...)成立于1982年月,在全球范围内负责协调太空数据系统的相关事务。作为联合国下属的一个国际空间合作机构, 该组织自上世纪九十年代以来就制定了多项太空数据系统的行业规范与技术标准, 其覆盖领域包括卫星通信网络规划与管理、飞行器性能评估指标体系构建等内容
该机构批准发布的一批文件如图4-10所示, 按照用途类型和标准化流程的不同阶段分为八类, 并分别以八种不同的颜色标注
- 蓝皮书(Blue):推荐的标准文件(Recommended Standards)。
- 洋红皮书(Magenta):推荐的实践文件(Recommended Practices)。
- 绿皮书(Green):信息类文件(Informational Files)。
- 红皮书(Red):标准或实践文件的手稿(Draft Versions of Standards/Practices)。
- 橙皮书(Orange):试验性文档(Experimental Documents)。
- 黄皮书(Yellow):管理文档(Administrative Documents)。
- 银皮书(Silver):具有历史性质的档案文件(Archival Files with Historical Significance)。
- 粉皮书(Pink):用于评审的修订稿手稿(Draft Revisions for Review and Examination)。

图4-10 CCSDS发布的文件
2.XTCE
XTCE(XML Telemetric and Command Exchange)是一套由OMG制定的基于XML语言的数据规范体系。
OMG是由一个国际化的、非营利性的计算机行业协会组成的开放成员组织。
该协会旨在提供一种国际化的新体制与标准以支持卫星数据的有效交换。
其中1.0版版本遵循了Green皮书的标准。
该规范体系的内容与版本持续按照标准要求进行完善。
全球知名的航天机构和卫星制造商(涉及如美国洛克希德·马丁公司、欧洲空间局、法国国家空间研究所、波音公司及美国国家航空航天局等多个重要参与者)共同参与了XTCE标准的相关研究项目,并已在多个航天项目中开始应用。目前来看,CCSDS XTCE标准处于持续改进和完善的过程中,并已在包括美国在内的多个研制项目的 satellite 系统中获得了较为广泛的应用。XTCE现已成为一个广泛应用的 satellite 数据信息描述与表达方法。相应地开发出了XTCE相关的应用软件工具,并将其应用于 satellite 载荷数据信息的设计工作之中。
XTCE标准中元素节点采用图4-11进行展示。该布局清晰地展示了基于空间系统的元素组织结构,具体包括头部元素、遥测元数据元素、遥控元数据元素、服务元素以及子空间系统元素等关键组成部分。元数据被定义为用于描述数据属性的数据信息。

图4-11 XTCE 标准中元素节点的结构
头部元素涵盖与 XTCE 文件本身相关的数据信息, 包括文件来源、生成日期、版本号以及作者等基本信息. 服务功能可以通过参数配置实现. 此外, 空间系统的层次划分使得子空间系统的管理更加条理. 其结构模式一致, 即每个子空间系统与其父系统的元素类型相同. XTCE 格式采用层次分明的结构来描述各子系统的属性和关系. 这种设计模式与真实航天器内部的空间布局架构高度一致, 因此能够有效模仿真实的航天器内部状态. 通过这种分层化的表达方式, 不仅能够减少同一级别信息名称之间的冲突可能性, 而且还能使不同级别的属性体系更加独立完整. 这种方式有助于简化管理流程, 避免集成上的复杂性. 下面重点对遥测元数据和遥控元数据的具体内容展开介绍.
(1)遥测元数据是对遥测数据的描述,并包含以下要素:
- 参数类航天器系统参数类型集
- 参数
- 容器
- 消息
- 数据流
- 算法
- ParameterTypeSet:遥测参数的元数据集合。当实例化参数类型后即可描述遥测参数的信息。该数据集包含以下关键信息:数据类型、说明内容、告警阈值、输出数据所在的工程单元、长度以及在天地传输过程中的编码方式等。
- ParameterSet:遥测中一组参数及其引用的集合体。其中的参数均为实例化后的具体参数类型,并包含一个名称属性及指向对应ParameterTypeRef的对象引用。
- SequenceContainer:一组有序排列的参数序列容器集合体。此类容器能够描述包、数据帧、子帧或结构数据项等多种对象,并支持基于基础容器实现功能重用以简化配置管理。
- ContainerSet:一系列无序排列的SequenceContainer容器集合体。
- MessageSet:通过匹配方式唯一标识服务中某个容器的一种消息机制,并基于该容器内的元素与预定值的一致性关系实现过滤操作。
- StreamSet:一组无序排列的数据流Stream集合体,在航天器上行和下行的数据均被纳入该体系进行统一处理。
- AlgorithmSet:针对地面系统预先构建的一组基础算法库集合体,在此之上可构建更为复杂的遥测遥控数据处理算法逻辑。
描述遥测参数的步骤如下:首先以ParameterSet的形式设定遥测参数;随后采用ParameterTypeSet来确定遥测参数的类型;接着设定Container作为容器;随后建立StreamSet作为空间信息流集合;最后以AlgorithmSet的形式构建遥测数据处理算法集合。
(2)遥控元数据。
遥控元数据的形式与遥测数据的形式相近,在于两者均包含ParameterTypeSet、ParameterSet、MessageSet、StreamSet以及AlgorithmSet等元素;此外还包含有ArgumentTypes和Metacommand。
- ArgumentTypes类群(判据类别群):判据类别群在结构和组成上与属性类别群具有显著相似性。
每个判据类别群实例化后通常都会被绑定到特定的遥控命令中。
该集合主要包括数据类型的定义域信息、文本描述说明以及正常的值范围限制等关键要素。 - Metacommand高级命令群:高级命令群专门用于定义遥控操作的逻辑。
通过详细说明每个操作的名称和作用域范围,并规定它们之间的相互依赖关系以及排列顺序来构建完整的遥控操作体系。
3.ASCII码
ASCII码(美国标准信息交换代码)是一种采用7位或8位二进制数字编码的方法,在计算领域中能够为256种不同的字符(包括字母、数字、标点符号等)分配数值。该编码方案于1968年被提出,并被广泛应用于不同计算机硬件和软件系统中以实现数据传输的标准化工作,在当前的小型计算机及所有个人电脑中均得到应用。
ASCII码被划分为两个组别:标准ASCII字符集由128个字符组成(基于7位二进制编码),而扩展ASCII字符集则增加了额外的128个字符(采用8位二进制编码表示)。
由于计算机仅能接收数字信息,ASCII编码方式是以特定方式将字符转化为数字代码。例如,在这种编码体系下,英文字母大写字母N对应的ASCII码值为78。
特别地,在其定义域内包含了两个重要的控制性角色元素:LF(换行)和CR(回车)。特别地,在其定义域内包含了两个重要的控制性角色元素:LF(换行)和CR(回车)。特别地,在其定义域内包含了两个重要的控制性角色元素:LF(换行)和CR(回车)。特别地,在其定义域内包含了两个重要的控制性角色元素:LF(换行)和CR(回车)。
这些位置分别对应于数字'0'至'9'共十个数值以及大写字母'A'至'Z'共计二十六个字母体面
表4-1 标准ASCII码
| ASCII值 | 字符 | ASCII值 | 字符 | ASCII值 | 字符 | ASCII值 | 字符 | |
|---|---|---|---|---|---|---|---|---|
| 0 | NUT | 32 | (space) | 64 | @ | 96 | 、 | |
| 1 | SOH | 33 | ! | 65 | A | 97 | a | |
| 2 | STX | 34 | ” | 66 | B | 98 | b | |
| 3 | ETX | 35 | # | 67 | C | 99 | c | |
| 4 | EOT | 36 | $ | 68 | D | 100 | d | |
| 5 | ENQ | 37 | % | 69 | E | 101 | e | |
| 6 | ACK | 38 | & | 70 | F | 102 | f | |
| 7 | BEL | 39 | , | 71 | G | 103 | g | |
| 8 | BS | 40 | ( | 72 | H | 104 | h | |
| 9 | HT | 41 | ) | 73 | I | 105 | i | |
| 10 | LF | 42 | ********* | 74 | J | 106 | j | |
| 11 | VT | 43 | + | 75 | K | 107 | k | |
| 12 | FF | 44 | , | 76 | L | 108 | l | |
| 13 | CR | 45 | - | 77 | M | 109 | m | |
| 14 | SO | 46 | . | 78 | N | 110 | n | |
| 15 | SI | 47 | / | 79 | O | 111 | o | |
| 16 | DLE | 48 | 0 | 80 | P | 112 | p | |
| 17 | DCI | 49 | 1 | 81 | Q | 113 | q | |
| 18 | DC2 | 50 | 2 | 82 | R | 114 | r | |
| 19 | DC3 | 51 | 3 | 83 | X | 115 | s | |
| 20 | DC4 | 52 | 4 | 84 | T | 116 | t | |
| 21 | NAK | 53 | 5 | 85 | U | 117 | u | |
| 22 | SYN | 54 | 6 | 86 | V | 118 | v | |
| 23 | TB | 55 | 7 | 87 | W | 119 | w | |
| 24 | CAN | 56 | 8 | 88 | X | 120 | x | |
| 25 | EM | 57 | 9 | 89 | Y | 121 | y | |
| 26 | SUB | 58 | : | 90 | Z | 122 | z | |
| 27 | ESC | 59 | ; | 91 | [ | 123 | { | |
| 28 | FS | 60 | < | 92 | / | 124 | **** | **** |
| 29 | GS | 61 | = | 93 | ] | 125 | } | |
| 30 | RS | 62 | ****> **** | 94 | ^ | 126 | ~ | |
| 31 | US | 63 | ? | 95 | — | 127 | DEL |
标准ASCII编码采用7位结构,并由此可得出拥有2^7=128个字符(其中包括一些不可见字符)。然而,在计算机系统中,通常采用1字节等于8位来表示一个单元。早期计算机往往不够稳定,在传输过程中容易出现错误。因此,在这种情况下,默认情况下会将第8位指定为数据检验码的位置,并主要采用奇偶检验法来进行检查。在传统的标准ASCII编码方案下,则直接将这一位置用于奇偶检验码的设计上。随着技术的发展与改进,在这种情况下不再依赖于这一机制的存在而发展出了扩展型ASCII编码方案。
扩展ASCII字符集总共包括了2^{8}=256个字符,并采用的是8位编码方案。其中前128个字符与原有的完全一致(即原有ASCII码在7位编码的基础上统一在第7位添加了一个固定值0),而后半部分128个位置则全部设置了高位统一为1。扩展ASCII码体系赋予每个字符第8位的位置来标识附加的特殊符号、外来语言字母以及图形符号等信息。
4.bitstring模块简介
bitstring是一种用于简化二进制数据创建与分析的Python模块。该模块允许用户直接从基本数据类型如整数型对象(如int)、浮点型对象(如float)、十六进制数值对象(如hex)、十进制数值对象(如int)以及二进制数值对象(如bytes)等构建bitstring的对象。通过该模块提供的简单功能或拼接符操作符可以实现对这些对象的切分段操作以及合并操作,并提供反转功能。类似文件流或其他可迭代的数据结构, 该模块还支持通过其相关函数读取内容, 进行搜索与修改运算。在设计上, bitstring模块包含四个核心类: Bits, ConstBitStream, BitArray 和 BitStream. 其中, BitArray 类继承自Bits类; BitStream 类继承自ConstBitStream与BitArray两类; 而ConstBitStream 类则继承自Bits类

图4-12 bitstring继承关系图
(1)构造bitstring。
通过pack方法进行构建,在输入指定的格式和变量值参数后,根据输入的格式和变量值参数一一对应地构造出相应的对象。需要注意的是,该方法返回的对象类型为BitStream。
通过pack方法进行构建,在输入指定的格式和变量值参数后,则会根据输入的格式和变量值参数一一对应地构造出相应的对象。需要注意的是,该方法返回的对象类型为BitStream。
width, height = 352, 288
s = bitstring.pack('0x000001b3, 2*uint:12', width, height)
其中,
2^{*}\texttt{uint}:12用于构建两个具有12位宽度的变量,
其对应的\texttt{width}和\texttt{height}变量,
而0x000001b3已经是经过格式化的具体数值,
因此无需再次传递该数值。
(2)BitStream解析数据。
BitStream包含一种与readlist相似的功能名为unpack。这种功能遵循特定格式逐步解析数据流。例如,在前构造好的BitStream实例s上执行解析操作时会生成相应的数据序列
s.unpack('bytes:4, 2*uint:12, uint:4')
['\x00\x00\x01\xb3', 352, 288]
题目解析
指导依据XTCE规范进行解码器的实现。通过查看telemetry.xtce文件可以看出其组成部分。
通过快速查看XTCE文件,可以找到flag是如何定义的:
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG11"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG12"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG13"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG14"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG15"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG16"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG17"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG18"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG19"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG10"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG1"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG2"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG3"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG4"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG5"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG6"/>
<xtce:Parameter parameterTypeRef="7BitInteger" name="FLAG7"/>
在查阅上述flag包格式时(除了包含在包头部分的内容),其中内容仅由FLAGXXX字段构成。每个FLAGXXX字段代表单个ASCII字符。这些编码均为7位数表示。然而,在计算机中使用8位ASCII码来表示每个字符时(这表明,在原始二进制文件中将不会看到有意义的flag)。
在SequenceContainer中,我们可以看到包的结构。包头结构如下:
<xtce:SequenceContainer name="AbstractTM Packet Header" shortDescription="CCSDS TM Packet Header" abstract="isAbstract">
<xtce:ParameterReference parameterReference="CCSDS_VERSION ID"/>
<xtce:ParameterReference parameterReference="CCSDS_TYPE ID"/>
<xtce:ParameterReference parameterReference="CCSDS_SEC_HD ID"/>
<xtce:ParameterReference parameterReference="CCSDS_APID ID"/>
<xtce:ParameterReference parameterReference="CCSDS_GP_FLAGS ID"/>
<xtce:ParameterReference parameterReference="CCSDS_SSC ID"/>
<xtce:ParameterReference parameterReference="CCSDS_PLENGTH ID"/>
</xtce:SequenceContainer>
该部分指定了一个名为AbstractTM Packet Header的实体。特别关注parameterRef参数,并将其关联到ParameterSet部分已定义的参数。
<xtce:Parameter parameterTypeRef="3BitInteger" name="CCSDS_VERSION"/>
<xtce:Parameter parameterTypeRef="1BitInteger" name="CCSDS_TYPE"/>
<xtce:Parameter parameterTypeRef="1BitInteger" name="CCSDS_SEC_HD"/>
<xtce:Parameter parameterTypeRef="11BitInteger" name="CCSDS_APID"/>
<xtce:Parameter parameterTypeRef="2BitInteger" name="CCSDS_GP_FLAGS"/>
<xtce:Parameter parameterTypeRef="14BitInteger" name="CCSDS_SSC"/>
<xtce:Parameter parameterTypeRef="2ByteInteger" name="CCSDS_PLENGTH"/>
从这里我们可以得知,包头结构如图4-13所示。

图4-13 包头结构
当我们将所有字段相加时,总能得到一个长度为6个字节的前缀信息块(即包头)。其中我们可以观察到该参数CCSDS_APID,在本题中代表应用过程识别符(API),其作用在于唯一标识特定类型的数据显示包(即数据包)所对应的类型标识符(即类型ID)。
查看flag包的格式:
<xtce:SequenceContainer name="AbstractFlag Packet" shortDescription="Flag TM Packet Header" abstract="true">
<xtce:ParameterRefEntry parameterRef="FLAG1"/>
<xtce:ParameterRefEntry parameterRef="FLAG2"/>
<xtce:ParameterRefEntry parameterRef="FLAG3"/>
<xtce:ParameterRefEntry parameterRef="FLAG4"/>
<xtce:ParameterRefEntry parameterRef="FLAG5"/>
<xtce:ParameterRefEntry parameterRef="FLAG6"/>
<xtce:ParameterRefEntry parameterRef="FLAG7"/>
<xtce:ParameterRefEntry parameterRef="FLAG8"/>
<xtce:ParameterRefEntry parameterRef="FLAG9"/>
<xtce:ParameterRefEntry parameterRef="FLAG10"/>
<xtce:ParameterRefEntry parameterRef="FLAG11"/>
<xtce:ParameterRefEntry parameterRef="FLAG12"/>
<xtce:ParameterRefEntry parameterRef="FLAG13"/>
<xtce:ParameterRefEntry parameterRef="FLAG14"/>
<xtce:ParameterRefEntry parameterRef="FLAG15"/>
<xtce:ParameterRefEntry parameterRef="FLAG16"/>
<xtce:ParameterRefEntry parameterRef="FLAG17"/>
<xtce:ParameterRefEntry parameterRef="FLAG18"/>
……(略)
<xtce:ParameterRefEntry parameterRef="FLAG110"/>
<xtce:ParameterRefEntry parameterRef="FLAG111"/>
<xtce:ParameterRefEntry parameterRef="FLAG112"/>
<xtce:ParameterRefEntry parameterRef="FLAG113"/>
<xtce:ParameterRefEntry parameterRef="FLAG114"/>
<xtce:ParameterRefEntry parameterRef="FLAG115"/>
<xtce:ParameterRefEntry parameterRef="FLAG116"/>
<xtce:ParameterRefEntry parameterRef="FLAG117"/>
<xtce:ParameterRefEntry parameterRef="FLAG118"/>
<xtce:ParameterRefEntry parameterRef="FLAG119"/>
<xtce:ParameterRefEntry parameterRef="FLAG120"/>
</xtce:EntryList>
<xtce:BaseContainer containerRef="AbstractTM Packet Header">
<xtce:RestrictionCriteria >
<xtce:Comparison parameterRef="CCSDS_VERSION" value="0"/>
<xtce:Comparison parameterRef="CCSDS_TYPE" value="0"/>
<xtce:Comparison parameterRef="CCSDS_SEC_HD" value="0"/>
<xtce:Comparison parameterRef="CCSDS_APID " value="102 "/>
</xtce:ComparisonList>
</xtce:RestrictionCriteria >
</xtce:BaseContainer>
</xtce:SequenceContainer>
</xtce:ContainerSet>
</xtce:TelemetryMetaData>
</xtce:SpaceSystem>
我们可以在此观察到一项新的规定——RestrictionCriteria(限制标准)。这一项规定了一种筛选规则。这一项告诉了解析器应遵循哪些参数才能将其识别为flag数据包。具体来说,则表示FlagDataPackageHeader的字段必须符合以下筛选规则:
- CCSDS_VERSION为0。
- CCSDS_TYPE为0。
- CCSDS_SEC_HD为0。
- CCSDS_APID为102。
至此,这道题目的解题思路可以分为4步:
(1)根据如图4-13所示的包头结构,解码出包头APID的值。
(2)取出APID为102的数据包,即flag包。
(3)对于给定的数据包,请逐步提取对应的7-bit字符,并在其编码中将该字段最高有效位设为0以生成8-bit的ASCII字符
(4)转换后的FLAGXXX字段拼接得到flag值。
关键代码如下:
import bitstring
import os
import sys
import socket
FLAG_APID = 102 # 定义flag包的APID为102
EPS_APID = 103
PAYLOAD_APID = 105
HOST = '172.16.26.1'
if name == 'main':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)#IPv4
sock.connect((HOST, 31333))
line = sock.recv(128)
sock.close()
_, Port = line.split(b" ")[-1].split(b":")
print(Host,Port)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, int(Port)))
while True:
data = b''
while len(data) < 6:
data += sock.recv(6 - len(data))
s = bitstring.BitArray(data)
version, type, sec_header, apid, sequence_flags, sequence_count, data_length = s.unpack('uint:3, uint:1, uint:1, uint:11, uint:2, uint:14, uint:16')
print("APID: {}\nLength: {}\n".format(apid, data_length))# 解析包头
data = b''
while len(data) < data_length+1:
data += sock.recv(data_length+1 - len(data))
if apid != FLAG_APID: # 不是flag包,忽略
print("Ignoring APID we don't care about")
continue
s = bitstring.ConstBitStream(data) # 是flag包
char = ' '
flag = ''
while char != '}':
是flag包,依次读出7bit
将7bit的内容转换成8bit字符类型,最高位补0
char = chr(s.read('uint:7'))
flag += char
print(flag)
break
