2022-鹏城杯-rota

二木 王者

我们拿到题,我们可以直接发现我们最后的对比数据

image-20231009151020000

跟踪我们输入的数据,我们可以很容易的识别这个是一个base64换表的加密

这里,我们会发现许多很花的伪代码,也不好分析是干什么的,这里,我们使用我们的动态调试

image-20231009151323193

经分析这里的a2就是我们的前面加密后的数据,我们在这之前下一个断点。

image-20231009151643476

我们输入24个A,动态调试之后,我们可以发现,我们的输入被加密成了如下样子,我们拿脚本解来看看。

image-20231009151605430

1
2
3
4
5
6
7
8
9
10
11
import base64
import string

str1 = "M9uiM9uiM9uiM9uiM9uiM9uiM9uiM9uiXXXXXXXXXXX="
str2 = 'ksPhS/34MXifj+Ibtjud2Tikj5HkA7iTpbaNELBebOaIm'
str3 = "W6slMFL/TSPXeZuWqGxMjcKTV2OemQUq+AhjbYIV4fpIm"

string1 = "XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb="
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="

print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))

image-20231009152019580

可以发现,就是通过换表的base64,进行加密的,我们可以再输入32个A,进行测试,通过两次调试结果我们可以发现,那一部分很花的代码,实现的效果就是将我们的输入补齐,补齐到32位,,由此,我们可以大致推测出,我们的flag的长度就是32位。

下面我们分析下面这两个函数,这两个函数需要联合分析。

image-20231009152343563

点开上面的data函数,我们也会发现很花的代码,作者开的优化有点高,这里我们动态调试与分析,我们可以知道,a1生成的其实就是一个类似S盒的一个表,会在待会儿的加密中进行使用。

image-20231009152434187

对于下面的加密函数,我们从整体来看,我们可以发现,用一个循环,一次循环有四个着相同的加密块,也就是说一次循环加密四个数据,因为加密块相同,我们就只需要分析一个加密块即可。

image-20231009152718771

image-20231009152815407

对于每个加密块的前面的一个循环,其逻辑就是实现一个查表,然后返回数据的索引功能

image-20231009153020747

下面的这部分,对于a1中的128是不是很熟悉?就是上面生成a1时候,就使用了128,这里实现的逻辑就是将索引与循环相加,作为索引,取出a1前半部分的值,然后由此作为索引,有去找a1后半部分的值,将其作为索引,去找table里面的值。就是作者自定义的一个查表加密,开的优化有点高,造成分析相对变难了。

image-20231009153207159

复原的逻辑就是这样

1
2
3
4
5
6
7
8
9
10
11
12
13
for j in range(9):
for i in range(5):
idx = Maps.find(inp[j*5+i])
if idx == -1:
idx = 0
v12 = (idx_2 + box1[(idx_1 + idx) & 0x3f]) & 0x3f
v14 = box3[(idx_3 + box2[v12]) & 0x3f]
out[j*5+i] = Maps[v14]

idx_1 = (idx_1 + 1) & 0x3F



由此,我们逆向,我们可以写出脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import base64
arr =[ 51, 52, 44, 54, 29, 18, 30, 12, 26, 60, 41, 16, 32, 20, 61, 59, 25, 8, 14, 31, 48, 5, 56, 3, 17, 27, 23, 33, 46, 4, 24, 35, 43, 2, 39, 55, 28, 36, 57, 63, 53, 45, 38, 19, 42, 10, 0, 7, 62, 1, 40, 47, 50, 34, 13, 6, 37, 58, 9, 15, 22, 11, 21, 49, 12, 44, 13, 33, 34, 9, 2, 57, 49, 23, 26, 51, 6, 36, 16, 4, 27, 11, 52, 18, 56, 39, 14, 32, 43, 46, 0, 19, 62, 58, 5, 30, 54, 8, 50, 41, 25, 35, 61, 59, 60, 63, 55, 48, 24, 22, 53, 37, 10, 45, 40, 38, 21, 17, 7, 29, 42, 15, 31, 20, 1, 28, 3, 47, 19, 13, 53, 49, 7, 17, 27, 35, 11, 12, 16, 37, 43, 33, 51, 24, 39, 41, 2, 47, 40, 48, 14, 25, 60, 8, 52, 32, 61, 46, 5, 21, 44, 28, 54, 34, 30, 36, 56, 10, 63, 26, 4, 38, 22, 42, 58, 31, 45, 50, 6, 55, 3, 59, 0, 23, 29, 18, 9, 1, 62, 57, 15, 20, 1, 0, 0, 77, 252, 127, 0, 0, 4, 1, 0, 0, 252, 127, 0, 0, 107, 115, 80, 104, 83, 47, 51, 52, 77, 88, 105, 102, 106, 43, 73, 98, 116, 106, 117, 100, 50, 84, 105, 107, 106, 53, 72, 107, 65, 55, 105, 84, 112, 98, 97, 78, 69, 76, 66, 101, 98, 79, 97, 73, 109, 0, 0, 0]

base_tab = "XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb="
enc = "ksPhS/34MXifj+Ibtjud2Tikj5HkA7iTpbaNELBebOaIm"
o_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
my_table = "XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb"

out = ""

for t in range(0, len(enc) - 1):
c = enc[t]
for k in range(0, 64):
cnt = k
cnt = arr[(t + cnt)&0x3f] & 0x3f
cnt = arr[cnt + 64] & 0x3f
cnt = arr[cnt + 128]
if c == base_tab[cnt]:
out += base_tab[k]
break

print(base64.b64decode(out.translate(str.maketrans(my_table, o_table))))

解出flag PCL{8cdd01062b7e90dd372c3ea9977be53e}

 评论
目录