背景
起因是在为我们学校高三毕业生写毕业贺卡时,给他们写了“迷题”一样的东西上去。反正结果就是我也不知道有没有人猜出来,因为貌似没人看得懂。反正就水篇文章探讨一下,毕竟这些题目还是对于高中生来说有点难度的(指 CTF)。
题目一
MTc2MjJCRjA6MUU2MQ==
出题人:Akira
考察要点
- Base64 编解码的掌握
- IP 地址的进制转换
- 网页 Debug 基础
这份是我自己编的,如果对网络基础知识了解的人可以算是非常简单的了,创意方面我也在 Nazo Game 中获取了不少灵感,不过这里并没有借鉴他们的创意。
Base64 解码
看到这段字符后面的两个等号可能最先想到的就是经过 Base64 转换的字符,那么应该如何区分?
- Base64 是一种基于 64 个可打印字符来表示二进制数据的表示方法,包括大小写字母
A-Z
、a-z
,数字0-9
,两个可打印符号+
,/
(两个可打印符号在不同的系统中而不同)和用作后缀用途的等号=
来表示。 - Base64 编码要求把 3 个 8 位字节(3*8=24)转化为 4 个 6 位的字节(4*6=24),之后在 6 位的前面补两个 0,形成 8 位一个字节的形式。 如果剩下的字符不足 3 个字节,则用 0 填充,输出字符使用
=
,因此编码后输出的文本末尾可能会出现 1 或 2 个=
。 - 为了保证所输出的编码位可读字符,Base64 制定了一个编码表,以便进行统一转换。编码表的大小为 2^6=64,这也是 Base64名称的由来。
索引 | 对应字符 | 索引 | 对应字符 | 索引 | 对应字符 | 索引 | 对应字符 |
---|---|---|---|---|---|---|---|
0 | A | 17 | R | 34 | i | 51 | z |
1 | B | 18 | S | 35 | j | 52 | 0 |
2 | C | 19 | T | 36 | k | 53 | 1 |
3 | D | 20 | U | 37 | l | 54 | 2 |
4 | E | 21 | V | 38 | m | 55 | 3 |
5 | F | 22 | W | 39 | n | 56 | 4 |
6 | G | 23 | X | 40 | o | 57 | 5 |
7 | H | 24 | Y | 41 | p | 58 | 6 |
8 | I | 25 | Z | 42 | q | 59 | 7 |
9 | J | 26 | a | 43 | r | 60 | 8 |
10 | K | 27 | b | 44 | s | 61 | 9 |
11 | L | 28 | c | 45 | t | 62 | + |
12 | M | 29 | d | 46 | u | 63 | / |
13 | N | 30 | e | 47 | v | ||
14 | O | 31 | f | 48 | w | ||
15 | P | 32 | g | 49 | x | ||
16 | Q | 33 | h | 50 | y |
依据这些对 Base64 的介绍,我们可以写一个正则表达式来匹配 Base64 编码 ^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$
那么我们要把这段经过 Base64 编码后的可打印字符解码就可以这样反向推导:
Base64 解码 | |||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Base64 编码 | M | T | c | 2 | 以此类推 | ||||||||||||||||||||
索引 | 12 | 19 | 28 | 54 | |||||||||||||||||||||
二进制位 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | |
ASCII 编码 | 49 | 55 | 54 | ||||||||||||||||||||||
文本 | 1 | 7 | 6 |
因为最后会多出 2 个字节用 =
代替,所以编码前的字节数不能被 3 整除,余数为 2,即最后剩余两个八位(待补足)字节(2 个 byte),而最后一个 6 位的 Base64 字节块有四位是 0 值。
Base64 解码 | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Base64 编码 | M | Q | = | = | ||||||||||||||||||||
索引 | 12 | 16 | ||||||||||||||||||||||
二进制位(补0) | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
ASCII 编码 | 49 | |||||||||||||||||||||||
文本 | 1 |
或者你可以通过在线的 Base64 编解码程序直接转换出来。
最后得到的结果为 17622BF0:1E61
十六进制转 IP 地址
先看这种格式,其实是一个十六进制数的 IP 地址+ 端口,用正则表达式来 Match 可以这么写:^[0-9a-fA-F]{1,3}$
为了防止有人爆破此 IP 我还是选择不明说答案(迫真保命)
那么我们只需要把它转换成十进制就可以得到答案,接着你能通过答案去进入一个网页。
在网页中找到彩蛋
在浏览器中打开上面解出来的 IP:Port
后我们发现这是貌似是一个空白页面,只有标题写着 "What are you looking for?"。遇到这种情况,以多年网上冲浪经验的你应该会想到查看 Elements 或是用 Console 查看或使用调试内容等,算是我们前端 Debug 的通用手段。
这里也是如此,打开 Console 就能看到输出的调试信息,Elements 也能查到。这样你就成功找到了 EGG 了!
题目二
这道题是基于 LCTF2018 的一道比赛题目出的,此题大部分难点在于数据包分析,我们来看看。
OSU
h77p5://1ch1n053.h0n4m1.c1u8/f1135/05u.pc4p
CTF!
出题人:Akira & LCTF2018
考察要点
Leet Speak- 数据包的分析掌握
- exp 脚本运用
1337 Speak
1337 (Leet) Speak,又称黑客语。简单来说就是把原本的字符写成形状相似的其它字符,通常将拉丁字母转变成数字或是特殊符号等。例如标题中字母 l
写成数字 1
,字母 e 写成 数字 3
(相似于大写的 E
),字母 t
写成数字 7
。将单字写成同音的字母或数字也属于 Leet,但这道题目中不会涉及。
转换后 | 转换前 |
7 | t |
5 | s |
1 | i & l |
0 | o |
3 | e |
8 | b |
4 | a |
那么通过对原先单词的猜测可以翻译为网址:https://ichinose.honami.club/files/osu.pcap
对数据包分析
进入上面解出来的 URL 会下载一个 .pcap
的文件,这是由 Wireshark 创建的数据文件。
玩过 CTF 的人会知道,CTF 旨在夺旗(Capture the Flag)。我们需要从这个数据包中找出 FLAG,以下是其中一种解题思路。这里要感谢 @TundraWork 在 Github 上贡献的题目源代码,让我们看看他们团队写的这篇 Writeup 原文地址
你会玩osu!么?
题目描述: 你从未玩过的船新音游, osu.ppy.sh 了解一下
题目给了一个 USB 流量包,首先我们用 Wireshark 打开看一下:
我们发现有多个设备的流量,而且整个捕获持续了很长时间,看来需要详细分析一下。
其中我们发现一个汇报为 G102 Prodigy Gaming Mouse
的罗技鼠标,但过滤后发现此设备的回报数据很少,没有什么价值。另外还发现一个汇报为 CTL-472
的设备,搜索一下发现是 Wacom 的数位板设备,是一个绝对坐标指针设备,而且它的汇报是等时间间隔(固定回报率)的。猜测可能是通过这个设备的移动轨迹提供信息。
二话不说上 tshark
过滤一下数据格式。
分析一下这个设备的数据,发现类似于如下格式:
02:e1:76:2b:e5:13:54:02:1a:00
其中第 3 和第 5 个 byte 变化幅度较小,第 2 和第 4 个 byte 变化幅度较大,可以猜测出是数位板的 x
y
坐标,分别 2 个 byte ,小端。
02:e1:x(76:2b):y(e5:13):54:02:1a:00
同时我们还知道数位板设备是可以汇报笔接触板子的压力大小的,分析数据我们可以发现倒数第 3 个 byte 是压力:
02:e1:x(76:2b):y(e5:13):54:pressure(02):1a:00
同时我们可以查到,这个设备是可以在笔一定距离悬空时仍然检测到笔位置的,那么我们可以大胆猜测笔触板后的移动轨迹里藏着信息。经过分析后找到一个合适的 pressure 阈值,给 CTL-472
设备移动轨迹画图。
The "Easier" Way
如果你有足够的耐心,还是可以找到数位板画 flag 的那一段时间的,只需要过滤出这段时间的数据,按照上面所说根据 pressure 画图,就可以得到比较清楚的结果,直接交题走人。
下面给出 whitzard
的脚本:
import turtle as t
t.screensize(2400, 2400)
t.setup(1.0, 1.0, 0, 0)
keys = open('usbdata.txt')
i=0
for line in keys:
i+=1
if len(line) == 30 and i>3000:
a0 = int(line[6:8], 16)
a1 = int(line[9:11], 16)
x = a0+a1*256
b0 = int(line[12:14], 16)
b1 = int(line[15:17], 16)
y = b0+b1*256
press = int(line[21:23], 16)
if x!=0 and y!=0:
t.setpos(x/20-500,-y/20)
if press > 2:
t.pendown()
else:
t.penup()
The "Harder" Way
但画出来发现无用的线条太多了,我们是不是漏掉了什么过滤条件?
既然题目让我们了解一下这个船新音游,那我们就了解一下,打开 osu.ppy.sh ,点击导航栏 help 进入 wiki ,首先看一下默认游戏模式玩法: https://osu.ppy.sh/help/wiki/Game_Modes/osu!
粗略翻了一下,大意就是用一个指针设备控制移动,z
x
两个按键控制点击。不过在稍下面我们发现了一个有趣的东西:
意思是我们可以在游戏中按下 c
键的同时移动光标画画?
因垂丝汀,我们回头看一下完整的 pcap 包,发现这样一个设备:
这个设备在 1.8.0
汇报状态, 1.8.1
进行数据通信,分析通信数据我们可以很容易看出这是一个典型的 USB HID Keyboard 。我们拿出所有 1.8.1
的数据,它们都是 8 byte 的,根据 USB UID spec :
同时我们查表(链接)得到游戏默认三个按键的对应 keycode :
Z: 1D
X: 1B
C: 06
那么我们只需要扫描第 2-7 byte 的值,找到任何一个 byte 值为 06
的数据包表示此时按下 C
,同时后续第一个没有任何 byte 值为 06
的数据包表示此时松开 C
。过滤出所有按下 C
的时间段内的来自 1.7.1
的数据,再画出数据所表示的点,即可得到清晰的 flag 图像。
至于 exp 脚本?这道题没有一个队伍使用此思路解题,所以留个课后练习,请大家自己动手尝试一下吧~
总结
第一题是是个人出的一个小彩蛋,并没有绕太多弯,只是做个小解密游戏给大家当热身了。第二题要求掌握的要点还是比较苛刻的,如果你曾玩过 OSU! 这款游戏就会相对好理解。本人还是水平有限,毕竟顾及到非专业人士,出的水平还很逊,与 CTF 比赛的题目相比还是自愧不如。
如果您对这这次的文章还算满意或是有其它意见,欢迎在评论区探讨。
Views: 48
Comments 1 条评论
博主 AkiraKotori
这是一条私密评论