• 开始

    一般来说,我们拿到一个ctf的题,就是为了得到它的flag,为了它,RE做安全的十分努力,百分艰辛,就为了得到它。

    流程

    试运行

    有了ctf的re的题目,ctfer有一套经典的流程,双击打开xxx.exe开始你的find flag之旅,一般来说就会提示
    Hi,CTFer
    ,它的意思是说,你好,CTFer,输入你的flag,那么你就可以输入,不用说,几乎都是you are wrong
    you are wrong
    所以,为了不错,得到正确的答案flag,就必须选择理解它,信任它。它自然会给你答案。

    反编译

    相信它,自然就是把它扔进ida,进行逆向分析。下面给出简单的几个exe的ctf题。

    T1

    你将会得到
    T1
    看着T1的伪代码,一眼就可以看出这个题的flag,

    1
    flag{YOU_FIND_IT}

    再执行流程,双击打开T1.exe,输入你的flag,就可以得到you are right,就这么简单。

    T2

    拿道题流程完毕,ida,就又可以得到
    T2
    可以看出,用户输入一个str1的字符串,然后利用for循环进行加i操作,最后将新得到的str1和“gmbh|ZPV`GJOE`JU`IBIB~”进行比较,如果相同,就是you are right,不同就是you are wrong。

    • 思路: 对“gmbh|ZPVGJOEJU`IBIB~”进行逐个减去i,即可得到答案。

    • 解题:
      可以用C语言写一个脚本

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      #include <stdio.h> 
      #include <string.h>
      int main(){
      char a[50];
      scanf("%s",a);
      for(int i=0;i<strlen(a);++i){
      --a[i];
      }
      printf("%s-%d",a,strlen(a));
      }

      输入”gmbh|ZPVGJOEJU`IBIB~”得到答案

    T3

    拿题流程完毕,ida可以得到
    T3
    对已知的函数命名,可以看出,T3是对T2的一次升级,加入了异或的算法。

    • 题目: 用scanf输入str1 -> 在 for 中 将str1的每一个字符与其下标异或 -> 将得到的str1与 str2比较

    • 知识点:异或运算是一个二元运算,在C语言中的运算符号为 ^,规则为

      1
      2
      3
      A ^ B = C
      C ^ B = A
      C ^ A = B

      也就是说:

      1
      2
      明文 ^ 密钥 = 密文
      密文 ^ 密钥 = 明文

      所以,解题就是再对str2进行一次异或运算

    • str2

      双击str2会跳转到它的数据定义窗口str2,从’66h’,’6Dh’到’55h’,’68h’,’0’的字符串数据,可以通过LazyIDA插件转换为byte字节。str2的实际数据是

      1
      [0x66, 0x6D, 0x63, 0x64, 0x7F, 0x5C, 0x49, 0x52, 0x57, 0x4F, 0x43, 0x45, 0x48, 0x52, 0x47, 0x5B, 0x4F, 0x59, 0x53, 0x5B, 0x55, 0x68, 0x00]
    • 解题
      C语言的脚本

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      #include <stdio.h>
      #include <string.h>
      int main(){
      char a[]={0x66, 0x6D, 0x63, 0x64, 0x7F, 0x5C, 0x49, 0x52,0x57, 0x4F, 0x43, 0x45, 0x48, 0x52, 0x47, 0x5B, 0x4F, 0x59, 0x53, 0x5B, 0x55, 0x68, 0x00};
      for(int i=0;i<strlen(a);++i){
      a[i]^=i;
      }
      printf("%s",a);
      return 0;
      }

      运行就可以得到flag

    T4

    放进ida之后,可以得到
    T4
    T4.exe在T3.exe基础上加上了一个新的函数处理sub_455A94( )

    • 题目:输入str -> 对str的字符串进行异或 -> 再对整个字符串sub_455A94( )处理 ->与 ”Zm1jZH9cSVJXT0NFSFJHW09ZU1tVaA==”比较

    • sub_455A94

      这是一个啥函数,不知道。但是我们可以了解。双击函数看到sub_455A94 ()再次双击函数sub_45A3F0,这是对sub_45A3F0 的封装,进入底层函数,底层函数该函数多次引用off_529000 ,双击可以跳转到其资源地址,可以把鼠标放在图示位置字符串表可以看到是字符表,推敲为base64,所以sub_455A94()为base64加密处理

    • 解题思路: 对“Zm1jZH9cSVJXT0NFSFJHW09ZU1tVaA==”进行base64解码 -> 再进行异或解密 -> flag

    • 解题代码 (C语言)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      #include <stdio.h>
      #include <string.h>
      int main(){
      char a[]="fmcd\IRWOCEHRG[OYS[Uh";//对“Zm1jZH9cSVJXT0NFSFJHW09ZU1tVaA==”base64解密后的字符串
      for(int i=0;i<strlen(a);++i){
      a[i]^=i;
      }
      printf("%s",a);
      return 0;
      }

    T5

    直接得到如下
    T5
    Amazing,T5和T4竟然差不多,直接按照T4的方法得到flag,你就会得到”you are wrong”wrong这是因为T5和T4还是有不同之处的。

    • 不同之处:在sub_455A94()函数中,依旧是sub_45A3F0(),也使用了off_529000 ,不过内部,并没有使用标准字母表,而是图示改动了的字母表这属于魔改字母表。

    • base64

      base64一般是使用的标准字母表计算出来的字符串

      1
      ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

      但是,标准字母表的字母位置和改动了的字母位置下标应该一样。

    • 替换base64:在表中应该如下替换

      1
      2
      3
      4
      	待替换  Wj1gWE9xPSGUQ0KCPCGET09WR1qSzZ
      魔改表 ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/
      标准表 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
      已替换 Zm1jZH9cSVJXT0NFSFJHW09ZU1tVaA

      也可以写一个Python脚本替换

      1
      2
      3
      4
      5
      6
      7
      8
      import base64;
      v="Wj1gWE9xPSGUQ0KCPCGET09WR1qSzZ";
      a="ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/";
      b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      r="";
      for i in v:
      r+=b[a.find(i)];
      print(r); #结果是Zm1jZH9cSVJXT0NFSFJHW09ZU1tVaA

      替换完成后,就可以使用标准的base64进行解码

    • C语言解题

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      #include <stdio.h>
      #include <string.h>
      int main(){
      char a[]="fmcd\IRWOCEHRG[OYS[Uh" ;//base64解码后的结果
      for(int i=0;i<strlen(a);++i){
      a[i]^=i;
      }
      printf("%s",a);
      return 0;
      }

    T6

    直接IDA,得到
    T6看到伪代码一大堆,不过,也不用怕,可以看到str2为用户输入,将str2和str1作比较,str1是通过一系列代码运算出来的,这么复杂,怎么办?其实很简单,既然是计算出来的,那就可以把计算表达式抄下来,写一个C程序,把str1用printf出来即可。

    不过,IDA这么高级,当然也可以动态调试。

    • 解题:
      在ida的菜单栏里面找到debugger->select debugger
      image
      选择local windows debugger
      image
      在代码行的前面标记小蓝点,就表示在这里需要运行时停下来调试
      image
      在菜单栏->debugger->start progress开始调试运行了
      image
      后面会跳出命令提示框,随便输入点东西,回车继续运行,停止后,将鼠标移动到str1上面,就可以看见程序运行时的结果了。
      image
      你的flag就是它了。

    完整的文件下载

    下载地址:点我下载

    本文如有不对,请指正

    上一篇:
    极客大挑战geek2021-Wp
    下一篇:
    Git for windows
    本文目录
    本文目录