image-20230524130631406

本身想说用KALi运行一下的。但是有个啥错误..

image-20230524131542762

管他的。我们已经知道了这个程序是64位的无壳的。放入IDA看看

image-20230524131817274

看到这个Decry函数,很明显这个函数是解这个题的关键

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
67
68
69
70
unsigned __int64 Decry()
{
char v1; // [rsp+Fh] [rbp-51h]
int v2; // [rsp+10h] [rbp-50h]
int v3; // [rsp+14h] [rbp-4Ch]
int i; // [rsp+18h] [rbp-48h]
int v5; // [rsp+1Ch] [rbp-44h]
char src[8]; // [rsp+20h] [rbp-40h] BYREF
__int64 v7; // [rsp+28h] [rbp-38h]
int v8; // [rsp+30h] [rbp-30h]
__int64 v9[2]; // [rsp+40h] [rbp-20h] BYREF
int v10; // [rsp+50h] [rbp-10h]
unsigned __int64 v11; // [rsp+58h] [rbp-8h]

v11 = __readfsqword(0x28u);
*(_QWORD *)src = 0x534C43444ELL;
v7 = 0LL;
v8 = 0;
v9[0] = 0x776F646168LL;
v9[1] = 0LL;
v10 = 0;
text = (char *)join(key3, v9);
strcpy(key, key1);
strcat(key, src);
v2 = 0;
v3 = 0;
getchar();
v5 = strlen(key);
for ( i = 0; i < v5; ++i )
{
if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
key[i] = key[v3 % v5] + 32;
++v3;
}
printf("Please input your flag:");
while ( 1 )
{
v1 = getchar();
if ( v1 == 10 )
break;
if ( v1 == 32 )
{
++v2;
}
else
{
if ( v1 <= 96 || v1 > 122 )
{
if ( v1 > 64 && v1 <= 90 )
{
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
++v3;
}
}
else
{
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
++v3;
}
if ( !(v3 % v5) )
putchar(32);
++v2;
}
}
if ( !strcmp(text, str2) )
puts("Congratulation!\n");
else
puts("Try again!\n");
return __readfsqword(0x28u) ^ v11;
}

image-20230524174005822

为什么这里的src 是 NDCLS呢?

通过点击src

image-20230524174155287

发现是高地址在上面,这种就是大端存放。高地址放高位

https://blog.csdn.net/xiao__1bai/article/details/122845061

image-20230524174808590

所以现在主要的目的就是逆向

1
str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;

这句话

image-20230524175013422

image-20230524175024160

所以text = killshadow

str2是输入的。

key = adsfkndcls

就是说:你输入的字符串经过str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;变化后所组成的新的字符串str2和原本的text=”killshadow”相等就能得到flag。

现在就是知道了密文就是text = killshadow,然后加密中间用到的key = adsfkndcls 求出明文就可了。

下面就是写脚本

爆破思想

C代码

这个是我的作法【下面的是网上找到的Wp】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

int main()
{
char a[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char key[] = "adsfkndcls";
char text[] = "killshadow";
char b[15];
for (int i = 0; i < 10; ++i)
{
for (int j = 0; j < 26; ++j)
{
b[i] = (a[j] - 39 - key[i] + 97) % 26 + 97;
if (b[i] == text[i])
{
printf("%c", a[j]);
}
}
}
return 0;

这个是没改进前

image-20230525133323613

改进后

image-20230525130639975

逆向写代码。

1.python

1
2
3
4
5
6
7
8
9
10
11
12
13
str2 = 'killshadow'
key = 'adsfkndcls'
v3=0
v5=len(key)
flag=[0,0,0,0,0,0,0,0,0,0]
for i in range(0,4):
for j in range(0,10):
v1=(ord(str2[j])-97)+26*i+ord(key[v3%v5])-58
if(v1>65 and v1<=90):
flag[j]=chr(v1)
v3=v3+1
for i in flag:
print(i,end="")

image-20230524182653938

2.c

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
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
int main() {
char key[] = "adsfkndcls";
char text[] = "killshadow";
char flag[15] = { 0 };
char v1;
int text_ = strlen(text);
for (int i = 0; i < text_; i++) {
for (int j = 0;; j++) {
v1 = text[i] - 97 + 26 * j - 58 + key[i];
if ('A' <= v1 && v1 <= 'Z') {
break;

}

}
flag[i] = v1;

}
printf("%s", flag);
return 0;

}

image-20230524182739500

因为不知道%26后得到的答案是几,所以用(int j;;j++)来无限例举

flag{KLDQCUDFZO}

KLDQCUDFZO