Reverse1_final

Reverse1_final

四月 13, 2019 (Updated: )

DDCTF2019届最简单的逆向题

直接拉进od,发现进去之后不像是在正常的程序领空,PEiD查一下,发现是一个UPX类型的壳。
百度下载脱壳机,脱壳。
然后拉入od分析,发现我们输入的字符串被程序加密后与“DDCTF{reverseME}”作比较;
也就是flag输入进去之后会被程序加密为“DDCTF{reverseME}”;
将其拉入ida分析

很明显,该函数便是加密函数;进入内部查看

这个‘*v1 = byte_402FF8[(char)v1[v4]];’把我看蒙了;(语言基础太菜的后果QAQ)
于是到od中寻找该循环所在地,查看一下相应汇编代码:

搜索字符串找到关键输入处,跟踪进去,下断点,调试

在输入提示语附近就是输入命令(2)和关键函数(3)的所在地
进入3所指的call内部,进一步观察

发现两处汇编循环,观察寄存器和堆栈数据得知上面的是“strlen”函数对应的操作
下面的便是do...While循环

由此得知加密算法为:将所输入的字符串的每个字符分别与0x402FF8相加,在此处所对应的字符即为加密后的新字符
可以在在ida中找到该地址

发现该地址下面是程序内容,没有单一字符,但是在该地址不远处有一串可以输入的字符集,发现字符集的地址与0x402FF8做差为32,刚好是最小的字符所对应的ascii码数值。
接下来便是找到每一个输入的字符的ascii码减去31后对应的字符,然后将其按“DDCTF{reverseME}”的形式连起来便拿到flag。
写一个小脚本,如下:

#include<iostream>
using namespace std;
int main()
{
    char a[]="1~}|{zyxwvutsrqponmlkjihgfedcba`_^]1[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)(";
    char b[16];
    int i;
    char c[]="DDCTF{reverseME}";
    for(i=0;i<16;i++)
    {
        for(char n='!';n<126;n++)
        {
            b[i]=a[(int)n-31];
            if(b[i]==c[i])
             {
                 cout<<n;
                 break;
             }
        }
    }
    cout<<endl;
    return 0;
}
隐藏