Fork me on GitHub

BUUCTF--SimpleRev

测试文件:https://buuoj.cn/files/7458c5c0ce999ac491df13cf7a7ed9f1/SimpleRev?token=eyJ0ZWFtX2lkIjpudWxsLCJ1c2VyX2lkIjoxOTAzLCJmaWxlX2lkIjoyNDN9.XXnIgg.L-8ifBkOTka-7o-QXZDkKNm77x4

 

1.准备

获取信息

  1. 64位文件

 

2.IDA打开

将main函数反编译为C代码

 1 int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
 2 {
 3   int v3; // eax
 4   char v4; // [rsp+Fh] [rbp-1h]
 5 
 6   while ( 1 )
 7   {
 8     while ( 1 )
 9     {
10       printf("Welcome to CTF game!\nPlease input d/D to start or input q/Q to quit this program: ", argv, envp);
11       v4 = getchar();
12       if ( v4 != 'd' && v4 != 'D' )
13         break;
14       Decry();
15     }
16     if ( v4 == 'q' || v4 == 'Q' )
17       Exit();
18     puts("Input fault format!");
19     v3 = getchar();
20     putchar(v3);
21   }
22 }

 

3.代码分析

很明显,这道题的关键在于Decry()

 1 unsigned __int64 Decry()
 2 {
 3   char v1; // [rsp+Fh] [rbp-51h]
 4   int v2; // [rsp+10h] [rbp-50h]
 5   int v3; // [rsp+14h] [rbp-4Ch]
 6   int i; // [rsp+18h] [rbp-48h]
 7   int v5; // [rsp+1Ch] [rbp-44h]
 8   char src[8]; // [rsp+20h] [rbp-40h]
 9   __int64 v7; // [rsp+28h] [rbp-38h]
10   int v8; // [rsp+30h] [rbp-30h]
11   __int64 v9; // [rsp+40h] [rbp-20h]
12   __int64 v10; // [rsp+48h] [rbp-18h]
13   int v11; // [rsp+50h] [rbp-10h]
14   unsigned __int64 v12; // [rsp+58h] [rbp-8h]
15 
16   v12 = __readfsqword(0x28u);
17   *(_QWORD *)src = 'SLCDN';
18   v7 = 0LL;
19   v8 = 0;
20   v9 = 'wodah';
21   v10 = 0LL;
22   v11 = 0;
23   text = join(key3, (const char *)&v9);         // text = 'killshadow'
24   strcpy(key, key1);
25   strcat(key, src);                             // key = 'ADSFKNDCLS'
26   v2 = 0;
27   v3 = 0;
28   getchar();
29   v5 = strlen(key);                             // v5 = 10
30   for ( i = 0; i < v5; ++i )
31   {
32     if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )// key = 'adsfkndcls'
33       key[i] = key[v3 % v5] + 32;
34     ++v3;
35   }
36   printf("Please input your flag:", src);
37   while ( 1 )
38   {
39     v1 = getchar();
40     if ( v1 == 10 )
41       break;
42     if ( v1 == 32 )
43     {
44       ++v2;
45     }
46     else
47     {
48       if ( v1 <= 96 || v1 > 122 )
49       {
50         if ( v1 > 64 && v1 <= 90 )              // 大写字母
51           str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
52       }
53       else                                      // 小写字母
54       {
55         str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
56       }
57       if ( !(v3 % v5) )
58         putchar(' ');
59       ++v2;
60     }
61   }
62   if ( !strcmp(text, str2) )
63     puts("Congratulation!\n");
64   else
65     puts("Try again!\n");
66   return __readfsqword(0x28u) ^ v12;
67 }

转换成可以运行的C代码是

 1 #include <bits/stdc++.h>
 2 
 3 #pragma warning(disable:4996)
 4 
 5 int main(void)
 6 {
 7     int i, j, n = 0, v5 = 10, v3 = 0, v2 = 0;
 8     char v1;
 9     char flag[11] = { 0 };
10     char str2[104] = { 0 };
11     char key[] = "ADSFKNDCLS";
12     char text[] = "killshadow";
13 
14 
15     for (i = 0; i < v5; ++i)
16     {
17         if (key[v3 % v5] > 64 && key[v3 % v5] <= 90)
18             key[i] = key[v3 % v5] + 32;
19         ++v3;
20     }
21     printf("Please input your flag:");
22     while (1)
23     {
24         v1 = getchar();
25         printf("v1:%c\nv2:%d\n\n", v1, v2);
26         if (v1 == 10) {
27             printf("进入1\n");
28             break;
29         }
30         if (v1 == 32)
31         {
32             printf("进入2\n");
33             ++v2;
34         }
35         else
36         {
37             if (v1 <= 96 || v1 > 122)
38             {
39                 if (v1 > 64 && v1 <= 90) {
40                     str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
41                     printf("计算1\n");
42                 }
43             }
44             else
45             {
46                 str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
47                 printf("计算1\n");
48             }
49             if (!(v3 % v5))
50                 putchar(' ');
51             ++v2;
52         }
53     }
54     if (!strcmp(text, str2))
55         puts("Congratulation!\n");
56     else {
57         printf("str2:%s\n", str2);
58         puts("Try again!\n");
59     }
60 
61     system("PAUSE");
62     return 0;
63 }
View Code

 

第30~35行代码的实际作用是将大写字母转换为小写。

 

第37~61行代码实际上就是遍历输入的字符(flag),进行str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;运算,最后与text比较。

因此我们只要反向就能求出输入的v1

 

4.程序获取flag

#include <bits/stdc++.h>

#pragma warning(disable:4996)

int main(void)
{
    int i, j, n = 0, v5 = 10, v3 = 0, v2 = 0;
    char v1;
    char flag[11] = { 0 };
    char str2[104] = { 0 };
    char key[] = "ADSFKNDCLS";
    char text[] = "killshadow";


    for (i = 0; i < v5; ++i)
    {
        if (key[v3 % v5] > 64 && key[v3 % v5] <= 90)
            key[i] = key[v3 % v5] + 32;
        ++v3;
    }
    for (j = 0; j < 10; ++j) {
        for (v2 = 0; v2 < 10; ++v2) {
            v1 = text[v2] - 97 + 26 * j - 97 + key[v3++ % v5] + 39;
            if ((v1 >= 65 && v1 <= 90) || (v1 >= 97 && v1 <= 122)) {
                flag[v2] = v1;
                if (++n == 10) {
                    printf("%s\n", flag);
                    system("PAUSE");
                    return 0;
                }
            }
        }
    }

    system("PAUSE");
    return 0;
}

 

5.get flag!

flag{KLDQCUDFZO}

 

posted @ 2019-09-12 12:40 MayflyIT 阅读(...) 评论(...) 编辑 收藏