BUUCTF-RE-SimpleRev
一、查壳
64位文件
二、IDA分析
int __cdecl __noreturn main(int argc, const char **argv, const char **envp) { int v3; // eax char v4; // [rsp+Fh] [rbp-1h] while ( 1 ) { while ( 1 ) { printf("Welcome to CTF game!\nPlease input d/D to start or input q/Q to quit this program: ", argv, envp); v4 = getchar(); if ( v4 != 'd' && v4 != 'D' ) break; Decry(); } if ( v4 == 'q' || v4 == 'Q' ) Exit(); puts("Input fault format!"); v3 = getchar(); putchar(v3); } }
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 = '\0'; 19 v8 = 0; 20 v9 = 'wodah'; //是小端序标记的 21 v10 = '\0'; 22 v11 = 0; 23 text = join(key3, (const char *)&v9); //key3=kills v9=wodah text=killshadow 24 strcpy(key, key1); //key1=ADSFK 25 strcat(key, src); //连接两个char类型 key=ADSFKNDCLS 26 v2 = 0; 27 v3 = 0; 28 getchar(); 29 v5 = strlen(key); 30 for ( i = 0; i < v5; ++i ) 31 { 32 if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 ) 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 == '\n' ) //输入为换行符,退出 41 break; 42 if ( v1 == ' ' ) //输入为空格,则v2+1 43 { 44 ++v2; 45 } 46 else 47 { 48 if ( v1 <= 96 || v1 > 122 ) //如果v1不为小写 49 { 50 if ( v1 > 64 && v1 <= 90 ) //如果v1为大写 51 str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97; //对str2[v2]进行处理 52 } 53 else //如果v1为小写字母 54 { 55 str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97; 56 } 57 if ( !(v3 % v5) ) //如果不为大小写字母,则不进行处理 58 putchar(32); 59 ++v2; 60 } 61 } 62 if ( !strcmp(text, str2) ) //如果text和str2储存的相同,则成功 63 puts("Congratulation!\n"); 64 else 65 puts("Try again!\n"); 66 return __readfsqword(0x28u) ^ v12; 67 }
对第30-35行分析后 发现 30-35是把key从大写转到小写 key="adsfkndcls"
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include<stdio.h> #include<string.h> int main() { char key[]= "ADSFKSLCDN"; int v5; v5 = 10; int i,v3 = 0; for (i = 0; i < v5; ++i) { if (key[v3 % v5] > 64 && key[v3 % v5] <= 90) key[i] = key[v3 % v5] + 32; ++v3; } printf_s("%s\n",key); }
解法有二
Ⅰ爆破
key="ADSFKNDCLS" text="killshadow" s="" flag="" loop="ABCDEFGHIJKLMNOPQRSTUVWXYZ" v2 = 0 v3 = 0 v5 = len(key) for i in range(0,v5): if ( ord(key[i]) > 64 and ord(key[i]) <= 90 ): s += chr(ord(key[i]) + 32) else: s +=key[i] print(s) #变小写 for i in range(0,len(text)): for j in loop: if ord(text[i])==(ord(j)-39-ord(s[i])+97)%26+97: flag+=j print(flag)
Ⅱ 逆推
#include <stdio.h> #include <string.h> int main(void) { char text[] = "killshadow"; char key[] = "adsfkndcls"; int key_ = strlen(key), text_ = strlen(text), i, j; char str2[15] = { 0 }; for (i = 0; i < text_; i++) for (j = 0;; j++) { str2[i] = text[i] - 97 + 26 * j + 39 - 97 + key[i]; if (str2[i] > 64 && str2[i] < 91) break; } printf("flag{%s}", str2); return 0; }
三、flag
flag{KLDQCUDFZO}