CNSSrecruit-1

RE签到题

shift+f12查看字符串

2048

一个小游戏,得到100w分得到flag,既然能用CE,为什么不用呢XD

海南鸽子

关键部分:

1
2
3
4
5
6
7
8
9
10
scanf("%19s", &v6);
sub_401005(&v6, (int)&v2);
for ( i = 0; i < strlen(&v2); ++i )
--*(&v2 + i);
if ( !strcmp(&v2, "X14yb2sEVk8BXWMkMiQ8") )
printf("Success!\n\n");
else
printf(aWrongFlagO);
system("pause");
return 0;

sub401005是base64加密,判断方式为如果输入进行base64加密后,再每一位减去1,若与X14yb2sEVk8BXWMkMiQ8相等则success,逆运算得到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
33
34
35
36
37
38
39
40
41
42
43
stream = fopen("./score.data", "rb+");
if ( stream )
{
ptr = 0LL;
v6 = 0LL;
v0 = 16LL;
fread(&ptr, 0x10uLL, 1uLL, stream);
fclose(stream);
puts("-----Score Board-----");
LODWORD(v3) = 0;
while ( (signed int)v3 <= 3 )
{
v0 = (unsigned int)(v3 + 1);
printf("level%d: %d steps\n", v0, *((unsigned int *)&ptr + (signed int)v3), v3);
LODWORD(v3) = v3 + 1;
}
if ( ptr == 0x2500000011LL )
{
v7 = -8977570383032666059LL;
v8 = 4503996766676335161LL;
v9 = 51;
v10 = 105;
v11 = 52;
v12 = -122;
v13 = 78;
v14 = 105;
v15 = 102;
v16 = 67;
v17 = -124;
v18 = 108;
v19 = 58;
v20 = 51;
v21 = 75;
v22 = -106;
v23 = 0;
for ( HIDWORD(v3) = 0; SHIDWORD(v3) <= 29; ++HIDWORD(v3) )
{
*((_BYTE *)&v7 + SHIDWORD(v3)) -= 48;
*((_BYTE *)&v7 + SHIDWORD(v3)) ^= 0x66u;
}
v0 = (unsigned __int64)&v7;
printf("\n%s\n", &v7, v3);
}

这里有两个选择,一是根据ptr==0x2500000011,将score.data中的数据改成1100 0000 2500 0000 0000 0000 0000 0000,然后再打开scoreboard就可以触发条件得到flag,二是直接根据生成flag的函数计算出flag。

源码审计

源码define了很多哲学词汇,例如deep♂dark♂fantasy。用sublime搜索全部然后替换掉就看起来很明白了,不过要注意的是,定义变量时也定义了很多带_的变量,不注意的话可能会替换错误,处理后代码如下:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char input[1024] = { 0 };
int aaa(char* b)
{
int v3 = 0,v2 = 0;
char key[] ={ 0,0,0,0x21, 0x5, 0x32, 0x43, 0x54, 0x21, 0x8, 0x32, 0x43, 0x54, 0x21, 0x15, 0x32, 0x43, 0x54, 0x21, 0x15, 0x32, 0x43, 0x54, 0x21, 0x1d, 0x32, 0x43, 0x54, 0x21, 0x7, 0x32, 0x43, 0x54, 0x21, 0x39, 0x32, 0x43, 0x54, 0x21, 0x55, 0x32, 0x43, 0x54, 0x21, 0x27, 0x32, 0x43, 0x54, 0x21, 0x15, 0x32, 0x43, 0x54, 0x21, 0x1f, 0x32, 0x43, 0x54, 0x21, 0x39, 0x32, 0x43, 0x54, 0x21, 0x30, 0x32, 0x43, 0x54, 0x21, 0xb, 0x32, 0x43, 0x54, 0x21, 0x1b, 0x32, 0x43, 0x54 ,0x65};
int i = 0;
int i_ = 0;
1:
int p__ = key[i ++];
if (p__== 0)
goto 1;
if (p__== 0x21)
goto 2;
if (p__== 0x32)
goto 3;
if (p__== 0x43)
goto 4;
if (p__== 0x54)
goto 5;
if (p__== 0x65)
goto 6;
3:
v2 = input[i_ ++];
goto 7;
4:
v3 = v3^0x66^v2;
goto 1;
2:
v3 = key[i ++];
goto 7;
7:
goto 1;

5:
if (v3== 0)
goto 1;
6:

return v3;
}

int main()
{
printf("Please ");
printf("input ");
printf("flag:");
scanf("%s", input);
if(strlen(input)==15)
goto start;
start:
int p = aaa(input);
if (p==0)
{
printf("\no yes\n");
system("pause");
return 0;
}
end:
printf("\nnonono\n");
system("pause");
return 0;
}

分析可以发现,根据key中的值,对input进行处理之后如果v3=0的话就可以了。key中0x21,****,0x32,0x43,0x54构成一个循环,操作是使得****处的值异或input中的值再异或0x66等于0,所以input=****^0x66,运算脚本如下:

1
2
3
key=[0x5,0x8,0x15,0x15,0x1d,0x7,0x39,0x55,0x27,0x15,0x1f,0x39,0x30,0xb,0x1b]
flag="".join([chr(i^0x66)for i in key])
print flag
文章目录
  1. 1. RE签到题
  2. 2. 2048
  3. 3. 海南鸽子
  4. 4. 推箱子游戏
  5. 5. 源码审计
|