[BUUCTF]看我回旋踢

题目就是一段密文

1
synt{5pq1004q-86n5-46q8-o720-oro5on0417r1}
img-202111021552174

看这格式, 大胆的猜测, 这就是经过某种变换后的flag

synt自然就是就是flag变换来的了, 那是怎么变换来的呢? 我们可以先自己对比一下ASCII码, 看看能不能找到规律, 就拿"synt"和"flag"对比, 写个脚本:

1
2
3
4
5
6
7
8
9
10
11
12
def show_ascii(*args):
for e in args:
ascii_list = []
for i in e:
ascii_list.append(ord(i))
print(ascii_list)

show_ascii("synt", "flag")


#[115, 121, 110, 116]
#[102, 108, 97, 103]

显而易见, 密文就是把明文的字符的ASCII码逐个加+13得来的, 那么写出解密脚本

1
2
3
4
5
6
res = ''
for i in "synt{5pq1004q-86n5-46q8-o720-oro5on0417r1}":
res += chr(ord(i)-13)
print(res)

#flagn(cd$##'d +)a( ')d+ b*%# beb(ba#'$*e$p

? ? ?

什么鬼?! 这显然是错的, 看样子不能单纯在ASCII码上+13就完事了

经过一番查找, 得知此题的变换方式方式称为ROT13(Rotate by 13 places; 回转13位)

ROT13和它的兄弟们:

ROT5: 只对数字进行编码, 用当前数字往前数的第5个数字替换当前数字, 例如当前为0, 编码后变成5, 当前为1, 编码后变成6, 以此类推顺序循环.

ROT13: 只对字母进行编码, 用当前字母往前数的第13个字母替换当前字母, 例如当前为A, 编码后变成N, 当前为B, 编码后变成O, 以此类推顺序循环.

ROT18: 这是一个异类, 本来没有, 它是将ROT5和ROT13组合在一起, 为了好称呼, 将其命名为ROT18.

ROT47: 对数字、字母、常用符号进行编码, 按照它们的ASCII码进行位置替换,用当前字符ASCII码往前数的第47位对应字符替换当前字符, 例如当前为小写字母z, 编码后变成大写字母K, 当前为数字0, 编码后变成符号_, 用于ROT47编码的字符其ASCII码范围是33-126, 具体可参考ASCII码一览表.

所以这题正确的解密方式就是把字母(除字母外的字符保持不变)移+13位, 到了末尾又从头循环, 那么我们只要仿照这个原理写出解密脚本应该就没问题了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def shift(myChar, offset):
if ord('a') <= ord(myChar) <= ord('z'):
myChar = chr(ord(myChar)+(offset%26))
if ord(myChar) > ord('z'):
myChar = chr(ord(myChar)-26)
if ord(myChar) < ord('a'):
myChar = chr(ord(myChar)+26)
elif ord('A') <= ord(myChar) <= ord('Z'):
myChar = chr(ord(myChar)+(offset%26))
if ord(myChar) > ord('Z'):
myChar = chr(ord(myChar)-26)
if ord(myChar) < ord('A'):
myChar = chr(ord(myChar)+26)
return myChar


ciphertext = "synt{5pq1004q-86n5-46q8-o720-oro5on0417r1}"
res = ''
for i in range(0,len(ciphertext)):
res += shift(ciphertext[i], 13)
print(res)

#flag{5cd1004d-86a5-46d8-b720-beb5ba0417e1}