这篇笔记是我对自己初步学习CTF的一个小总结,主要涉及了Crypto板块的编码,这部分内容比较简单,利用一些工具就可以轻松解决,但是有些需要很强的观察分析能力,所以此篇笔记主要起到一个分析总结的作用。
单纯BASE编码相对来说比较简单,使用在线解码工具或者使用Python编写代码就能轻易解决,但是BASE题往往是嵌套类型的,比如BASE16嵌套BASE32,或者是多重编码嵌套,所以有时候一时半会无法解决,这就需要我们耐心观察和分析了(一把梭除外)。
接下来我们来介绍一下BASE编码:
BASE16编码就是将二进制文本转换为以下16个字符组成的文本:
0123456789ABCDEF
所以BASE16有他的显著特征,就是所有的数字以及A~F的大写字母,这和其他几种BASE编码有些许不同。
BASE32对应的文本如下所示,其中=号是填充字符:
ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=
BASE32主要的特点就是全大写字母加2~7的数字。
BASE64对应的文本如下所示:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
BASE64主要的特点就是小写字母加+/这些特殊符号,所以算是比较号区分的。
BASE85与前面有些不同,他是将四个字节的二进制数组成一个32位的数,然后转换为85进制,最后每一位加上32转为字符,所以并无显著特征。
接下来我们来看一道BASE编码的题目来强化一下:
题目:[AFCTF 2018]BASE | NSSCTF
我们下载附件,得到一个文本文件,部分如下所示:
78546C526A643035555454464E56453134546C56464D5535715654464F61306B7A546B5253525535555458704E52474E33546B526A4D5535715654424F56555578546B52564D5531365158705056464A43546C524E4D6C4671556B5A4F56466B77556C52615245355652544252656C5636545870424D3035455658704F56456B78546D7057516B35455754464F56467045546B56564D55353656586C4E656B5577555652535245355557544A52616C6B77546C526A4D5535555458644F656C4577555652564D3035725354464F616C557A546C524E4D553571556B4A4F52553078546D704E6430357254544253616C5635546C52564D55357156544A
我们观察一下,发现这是BASE16编码,于是我们使用在线解码工具或者编程,看一下解码结果是什么,结果如下所示:
xTlRjd05UTTFNVE14TlVFMU5qVTFOa0kzTkRSRU5UTXpNRGN3TkRjMU5qVTBOVUUxTkRVMU16QXpPVFJCTlRNMlFqUkZOVFkwUlRaRE5VRTBRelV6TXpBM05EVXpOVEkxTmpWQk5EWTFOVFpETkVVMU56VXlNekUwUVRSRE5UWTJRalkwTlRjMU5UTXdOelEwUVRVM05rSTFOalUzTlRNMU5qUkJORU0xTmpNd05rTTBSalV5TlRVMU5qVTJ
发现这是BASE64格式的,所以我们猜测这应该是BASE嵌套解码,所以我们写一个脚本来运行一下,代码如下所示:
import re, base64
s = open("flag_encode.txt", "rb").read()
# 正则表达式,用来尽可能多的匹配字符串
base16_dic = r'^[A-F0-9]*$'
base32_dic = r'^[A-Z2-7=]*$'
base64_dic = r'^[A-Za-z0-9/+=]*$'
# 循环解码
while True:
t = s.decode()
if '{' in t:
print(t)
break
elif re.match(base16_dic, t):
s = base64.b16decode(s)
print(16)
elif re.match(base32_dic, t):
s = base64.b32decode(s)
print(32)
elif re.match(base64_dic, t):
s = base64.b64decode(s)
print(64)
运行结果如下所示:
16
64
64
16
64
32
32
32
16
32
32
32
32
32
16
32
32
64
32
64
64
32
32
16
32
64
64
16
64
64
afctf{U_5h0u1d_Us3_T00l5}
最终我们得到了flag,同时也说明我们是正确的,他就是包含了很多的BASE编码。
Uuencode编码其实和BASE64的原理类似,只不过他是处理完之后对每个数加32,这样使结果正好在ASCII的可打印字符中,所以编码结果就是一堆字符,无明显规律,这种情况就可以使用Uuencode编码试试了。
题目:[SWPUCTF 2021 新生赛]crypto8
打开附件得到一串字符,考虑使用Uuencode解码(有很多在线工具都可以)
73E-30U1&>V-H965S95]I
解码结果如下所示:
NSSCTF{cheese_is_power}
Rabbit编码Rabbit 是一种高速流密码,于 2003 年在 FSE 研讨会上首次提出。 Rabbit 使用一个 128 位密钥和一个 64 位初始化向量。 该算法的核心组件是一个位流生成器,该流生成器每次迭代都会加密 128 个消息位。主要有以下三个特征:
接下来我们看一道题目,来加强一下认知:
题目:BUUCTF在线评测 (buuoj.cn)
我们可以看到附件只有一行以U2FsdGVkX1开头的字母:
U2FsdGVkX1/+ydnDPowGbjjJXhZxm2MP2AgI
所以我们采用在线解码工具,得到:
Cute_Rabbit
这便是我们需要的flag。
URL编码就比较简单,有着很明显的特征,就是许多的%号,所以一眼看到就能大概能猜到是URL编码。
题目:BUUCTF在线评测 (buuoj.cn)
打开附件,得到如下信息:
%66%6c%61%67%7b%61%6e%64%20%31%3d%31%7d
使用在线解码工具,结果如下所示:
flag{and 1=1}
Quoted-Printable编码方法,适合所传输数据中,只有少量的非ASCII编码,用一个等号(=)后面加两个数字字符来表示一个非ASCII码字符。所以特征也很明显,那就是有许多的=号。
题目:BUUCTF在线评测 (buuoj.cn)
打开附件,得到如下信息:
=E9=82=A3=E4=BD=A0=E4=B9=9F=E5=BE=88=E6=A3=92=E5=93=A6
使用在线解码工具,结果如下所示:
那你也很棒哦
CTF中的编码远远不止这些,比如XXencode、jjencode、bubbleBabble、Ook、佛曰、社会主义核心价值观等等,我会在接下来的学习中不断补充,同时也希望我能一直坚持下去。