BUUCTF--SimpleRev

Posted mayfly-nymph

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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!

flagKLDQCUDFZO

 

以上是关于BUUCTF--SimpleRev的主要内容,如果未能解决你的问题,请参考以下文章