BUUCTF--SimpleRev

匿名 (未验证) 提交于 2019-12-03 00:03:02

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

 

1.准备

获取信息

64位文件

 

1.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 }

 

2.代码分析

很明显,这道题的关键在于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

 

3.程序获取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; }

 

4.get flag!

KLDQCUDFZO

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!