跳转至

Beckley

beckley

这一关叫做模拟卫星视角,给了我们一个卫星拍摄时的 TLE,我们通过谷歌地球去设置卫星视角观察得到 flag

环境搭建

进入 generator-base 之后运行docker build -t generator-base .把基础的镜像生成出来

然后进入 beckley 文件夹把 solver 和 challenge 文件夹中的 Dockerfile 的 get-pip.py 的 url 换一下,换成:

https://bootstrap.pypa.io/pip/2.7/get-pip.py

1670410052916-ccedc3b6-5f37-49a5-9014-ee3f331929e1.png

我会把我用的最终版本放在 https://github.com/yichen115/hackasat-qualifier-2020 用这个就不用改 url 了

使用make build生成镜像,也可以用make challenge只生成题目镜像

使用apt install socat安装 socat

使用以下命令运行环境

socat -v tcp-listen:19020,reuseaddr exec:"docker run --rm -i -e SERVICE_HOST=172.17.0.1 -e SERVICE_PORT=19021 -e SEED=1000 -e FLAG=flag{zulu49225delta\:GG1EnNVMK3-hPvlNKAdEJxcujvp9WK4rEchuEdlDp3yv_Wh_uvB5ehGq-fyRowvwkWpdAMTKbidqhK4JhFsaz1k} -p 19021\:80 beckley\:challenge"

咱也不知道这题是啥意思,按照 wp 先验证一下能不能拿到 flag,新开一个终端运行得到一些提示

nc 172.17.0.1 19020

然后运行下面的命令得到 flag

curl http://172.17.0.1:19021/cgi-bin/HSCKML.py?CAMERA=-77.03,38.89,430000,40.3694166667,63.5358055556 -H 'User-Agent: GoogleEarth/7.3.2.5815(X11;Linux (5.2.0.0);en;kml:2.2;client:Pro;type:default)' -H 'Accept: application/vnd.google-earth.kml+xml, application/vnd.google-earth.kmz, image/*, */*' -H 'Accept-Language: en-US, *' -H 'Connection: keep-alive'

如图所示

1670469285235-8c0f85d4-3764-4168-a26d-fd6ea6e6618a.png

正式做题

按照 https://blog.csdn.net/hackasat/article/details/127814688 的描述,这道题环境搭建起来后你能看的就只有 static 文件夹里面的 remote.kml 和一个 172.17.0.1 19020 的地址

就从这两个提示开始入手,nc 连接之后获得了如下信息

We've captured data from a satellite that shows a flag located at the base of the Washington Monument.
The image was taken on March 26th, 2020, at 21:53:13
The satellite we used was: 

REDACT
1 13337U 98067A   20087.38052801 -.00000452  00000-0  00000+0 0  9995
2 13337  51.6460  33.2488 0005270  61.9928  83.3154 15.48919755219337

Use a Google Earth Pro KML file to 'Link' to http://172.17.0.1:19021/cgi-bin/HSCKML.py
and 'LookAt' that spot from where the satellite when it took the photo and get us that flag!

大意是太空中有颗卫星于 2020 年 3 月 26 日 21:52:55 按照特定的视角拍到了华盛顿纪念碑,让我们通过 Google Earth Pro 的 KML 文件模拟卫星拍摄时的位置看一下华盛顿纪念碑从而获得 flag

Google Earth Pro 可以在这里下载到 https://www.google.com/earth/versions/

KML 文件格式

https://developers.google.com/kml/documentation/kmlreference

可以在谷歌地球上新建一个地标,试试 kml 文件是怎么创建的,点击这个黄色的工字钉

1670499178278-b6451ecd-3ae6-4e02-bf28-beb191cd1286.png

然后随便在地图上找个点,把工字钉拖上去,随便写点名称和说明

1670499284583-ff46a87a-31be-4075-b21e-6842fe685237.png

然后将右键地图上的工字钉,保存的时候选择类型是 kml 格式

1670499313894-03bd72d6-71c3-4547-90c7-ae7bd0cc6faa.png1670499385697-5fe120be-261f-4276-9cbd-a5afdcde8d16.png

可以看到主要的位置信息就是在 LookAt 这个标签里面的,LookAt 就是你从哪个视角来观看这个地标的

1670499734621-329d124f-2cbd-413d-994a-124915214353.png

对应的,在题目给的 remote.kml 文件中也是要我们修改这个位置的信息

1670501179413-052e3085-b18b-4e63-a948-9b289d44f633.png

longitude 是经度,不用解释吧

latitude 是纬度,不用解释吧

altitude 是海拔,不用解释吧

heading 是飞行器前进的方向,看下面的图示,就是按照左边这个图来的

1670509197854-e969d424-a206-4c5b-a042-0d8165777d67.gif

tilt 是卫星与地球表面法线之间的角度

range 是卫星距离目标的距离

altitudeMode 是高度模式,这个不用咱们改

1670509085510-b8456cbd-fbef-49ee-a59e-cd5eb0e0aa8b.gif

还有一个在这里面没有体现出来的 标签,这个是用来通过网络链接获取 KML 文件,那我们先把这个 link 换成 nc 连接上后获得的地址 http://172.17.0.1:19021/cgi-bin/HSCKML.py,选择文件 -> 打开 -> remote.kml 把临时位置的层级全部展开,可以看到一个地标是 Keep Looking... 说明咱还没找到正确的观察视角1670503374181-b3d8119f-9de2-4a9f-8f26-2b1f4792e999.png

双线元素集 (TLE)

接下来我们研究研究 LookAt 要怎么设置,就是卫星拍到华盛顿纪念碑时的位置,相关线索就是 nc 上去输出的两行信息,这个叫做双线元素集 (TLE),好家伙,专业知识来了

https://www.space-track.org/documentation#/tle

卫星双线元素集(TLE)是一种编码格式,用于在两行中存储卫星的轨道参数。这些轨道参数是由观测到的卫星运动数据计算得出的。TLE 可以用来预测卫星的运动,并用于各种应用,例如卫星导航和通信

REDACT
1 13337U 98067A   20087.38052801 -.00000452  00000-0  00000+0 0  9995
2 13337  51.6460  33.2488 0005270  61.9928  83.3154 15.48919755219337

我们做个表说明一下这些数据的含义(感觉给的这些数据对不太起来)

第 0 行
数据 描述
1-24 REDACT 基于卫星目录的信息的对象的通用名称
第 1 行
数据 描述
1 1 行号
3-7 13337 北美防空司令部 的卫星编号
8 U U 非保密的,C 机密的,S 绝密的
10-17 98067A 国际卫星标识符,98表示年,067表示这年第几次发射,A 表示卫星的第一部分
可以参考:https://www.zhihu.com/question/268074570/answer/332683919
19-32 20087.38052801 TLE历时,轨道数据的时间点,20 表示 20 年,087表示第 87 天(我咋算的 86 天),38052801 表示这一天的时刻
34-43 -.00000452 平均运动对时间的一阶导数
45-52 00000-0 平均运动对时间的二阶导数(假设有小数点)
54-61 00000+0 BSTAR拖调制系数
63 0 美国空军空间指挥中心内部使用的为 1,美国空军空间指挥中心以外公开使用标识为 0
65-68 999 星历编号,星历编号是TLE数据按新发现卫星的先后顺序的编号
69 5 校验和,指这一行的所有非数字字符,按照“字母、空格、句点、正号= 0;负号=1”的规则换算成0和1后,将这一行中原来的全部数字加起来,以10为模计算后所得的和
第 2 行
数据 描述
1 2 行号
3-7 13337 北美防空司令部 的卫星编号
9-16 51.6460 轨道的交角度数,指天体的轨道面和地球赤道面之间的夹度
18-25 33.2488 升交点赤经度数,指从地球的球心点望过去,升交点的赤经坐标
27-33 0005270 轨道离心率,指卫星椭圆轨道的中心点到地球的球心点的距离(c)除以卫星轨道半长轴(a)得到的一个0(圆型)到1(抛物线)之间的小数值
35-42 61.9928 近地点角距,指在卫星的轨道平面内,从升交点到近地点按照卫星运行方向所走过的角度
44-51 83.3154 平近点角度数,指平近点角与真近点角和偏近点角之间的关系,即卫星在椭圆轨道上的瞬间位置
53-63 15.48919755 平均运动,指在一个太阳日内(24h),卫星在它的轨道上绕了多少圈
64-68 21933 在轨圈数,指卫星从发射到 TLE 数据记录的 TLE 历时之间卫星在轨道上绕行的总圈数
69 7 校验和

解析TLE得到卫星视角

我们需要通过给出的 TLE 数据填充 LookAt 中的信息,其中 longitude 和 latitude 是经纬度,直接在谷歌地球中找就行了,按照上面添加地标的方式添加保存为 KML 文件,再查看即可,纬度:38.88937190244597,经度:-77.03521514741283

同时因为 altitudeMode 是 clampToGround,表示可以忽略高度,因此 altitude 是 0

1670595166121-8d95f129-d23a-40b1-aa8d-18ca762c78c1.png

这意味着我们只需要解析出来 heading、tilt、range 即可,我们用 Python 来实现,参考这个库:

https://rhodesmill.org/skyfield/earth-satellites.html

首先从字符集加载 TLE 数据,然后根据时间确定卫星在头顶的位置(注意这里的时间要用 nc 上去之后题目给我们的时间而不是 TLE 解析的时间),这里得到的位置是地心天球参考系中卫星的 x、y、z 坐标,也就是说是以地心为观察者视角得到的卫星的位置

from skyfield.api import EarthSatellite, load, Topos

ts = load.timescale()
line1 = '1 13337U 98067A   20087.38052801 -.00000452  00000-0  00000+0 0  9995'
line2 = '2 13337  51.6460  33.2488 0005270  61.9928  83.3154 15.48919755219337'
# 从字符串加载TLE集
satellite = EarthSatellite(line1, line2, 'REDACT', ts)
print("\nsatellite:")
print(satellite)

# 通过卫星在头顶上面的时间确定卫星位置,这里按照题目提示时间 2020 年 3 月 26 日 21:52:55
t = ts.utc(2020, 3, 26, 21, 52, 55)
geocentric = satellite.at(t)
print("\ngeocentric.position.km:")
print(geocentric.position.km)

我们解题需要知道的是以华盛顿纪念碑为观察者视角的卫星位置,需要先创建一个 Topos 对象来表示观察者的位置,然后用卫星相对地心的位置减去华盛顿纪念碑相对于地心的位置,以此确定卫星相对于观察者的位置信息,其中距离就是我们要修改的 range 值

# 计算华盛顿纪念碑看卫星的角度
bluffton = Topos('38.88937190244597 N', '77.03521514741283 W')
huashengdun = bluffton.at(t)
print(huashengdun.position.km)
difference = satellite - bluffton  # 这俩一减得到了华盛顿纪念碑和卫星之间的位置信息
topocentric = difference.at(t)
print(topocentric.position.km)
alt, az, distance = topocentric.altaz() # 通过altaz函数得到高度角、方位角、距离
print('\nAltitude: %f' % alt.degrees)   # 高度角
print('Azimuth: %f' % az.degrees)       # 方位角
print('Distance: %d' % int(distance.m)) # 距离

得到这个之后我们来看一下 heading 和 tilt 与高度角和方位角的关系,其中 tilt 与高度角是互补的,因此直接用 90 减去高度角就是 tilt

1670662912949-be09c18c-9c5a-41ce-9e8d-a347b6e2f5ea.png

heading 是卫星前进的方向,与当前的方位角有个 180 度的差值,所以在 Azimuth 的基础上加上 180 度得到 heading,再模 360 度是为了保证度数在 360 度之内

1670673053704-139ec96b-ab3b-4c5d-968b-5cc3b15ab7f9.png

heading = (180 + az.degrees) % 360
print('\nHeading: %f' % heading)
tilt = 90 - alt.degrees
print('Tilt: %f' % tilt)

根据输出的结果修改 LookAt 中的值,然后用谷歌地球打开就可以看到 flag 了

      <LookAt id="ID">
          <longitude>-77.03</longitude>
          <latitude>38.89</latitude>
          <altitude>0</altitude>
          <heading>63.532442</heading>
          <tilt>40.371925</tilt>
          <range>538562</range>
          <altitudeMode>clampToGround</altitudeMode>
      </LookAt>

1670593047495-8ad92b99-efce-40cd-b120-b1b2b3bb9491.png

参考

https://github.com/solar-wine/writeups/blob/master/2020/Qualifications/Astronomy%2C%20Astrophysics%2C%20Astrometry%2C%20Astrodynamics%2C%20AAAA/I%20Like%20to%20Watch/writeup.md

https://blog.csdn.net/hackasat/article/details/127814688

原文: https://www.yuque.com/hxfqg9/iot/hao7seuuop37u8gk