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;
}
查看评论