2023-柏鹭杯-re1-imm

二木 王者

我们拿到这道题,判断输入,可以知道验证我们的输入为64个字节,存储在buffer中,下面有一个判断,我们可以知道我们输入的字符范围为0 ~ 9,A ~ F.

image-20231012103158670

其实我们通过整体来看,我们可以发现,在这个大的while循环中就只对这个encode返回的值进行判断,然后break,然后通过后面的flag输出,我们可以推断出主要的逻辑就是,将我们的输入的64进行一系列的操作,与对比,之后再做一系列的操作运算出我们的flag.也就是说我们的加密与对比逻辑就在这个encode函数之中。

image-20231012103510111

我们进入encode函数,我们会发现以下三段的汇编代码,如果学过一点点汇编,对1与3的汇编代码还是好理解,第一个mov,与xor,就是将我们的数据与上面的字符进行异或。

image-20231012103953758

第三段汇编,cmp,mov,zero,很能看出,这里实现的操作就是将加密后的结果,与其上面的数据进行对比

image-20231012104011950

对于第二段汇编,视乎X86体系并不常见,经过搜索,我们可以得知这个汇编实现的操作就是这样。

image-20231012104002124

1
2
3
4
for (int i = 0; i < 32; ++i)
{
a[i] = flag[index[i]];
}

就是将上面的数据作为索引,然后去我们flag里面去寻找对于字符。实现就是将我们原来的数据进行打乱。

由此我们就将加密逻辑分析完了,开始写脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
#include <string.h>
void main()
{
unsigned char data[32] = {
0xCD, 0xEB, 0x5E, 0x76, 0x0F, 0x22, 0xAF, 0x31, 0x82, 0x92, 0x3C, 0xEF, 0xB8, 0xC1, 0x76, 0x06,
0x18, 0x2F, 0xB5, 0x7D, 0x7F, 0x0A, 0xEA, 0x85, 0x92, 0x00, 0x89, 0xA3, 0x2C, 0xE2, 0xE7, 0x32};
unsigned char index[32] = {
0x0A, 0x07, 0x06, 0x0E, 0x02, 0x0B, 0x03, 0x0D, 0x01, 0x09, 0x00, 0x05, 0x04, 0x0F, 0x08, 0x0C,
0x1B, 0x18, 0x17, 0x1F, 0x14, 0x1E, 0x12, 0x13, 0x15, 0x1D, 0x16, 0x1C, 0x11, 0x10, 0x19, 0x1A};

unsigned char flag[32] = {
0x5F, 0x91, 0x99, 0xE8, 0x4E, 0xD0, 0xB0, 0x92, 0xB1, 0x3C, 0x4F, 0xF4, 0x17, 0x76, 0xDA, 0x12,
0x2A, 0x35, 0x01, 0x15, 0xF9, 0x97, 0x5E, 0x19, 0x9D, 0xC2, 0x15, 0x99, 0x70, 0x7D, 0x9F, 0xCC};
unsigned char a[32];

int c[32];
for (int i = 0; i < 32; ++i)
c[i] = i;
unsigned char b[32];
for (int i = 0; i < 32; ++i)
{
b[c[index[i]]] = flag[i];
}
for (int i = 0; i < 32; ++i)
{
b[i] ^= data[i];
}
for (int k = 0; k < 32; ++k)
printf("%X", b[k]);

}

可以得到:825A10C618D636A058AE633FAA539E70655FEB648697FF84A79F4589B5207027

image-20231012104914540

放入程序输入,即可得到我们的flag

flag{ISEC-a49d6b847bdba62c5bfa0a43b69c8575}

 评论
目录