预赛逆向题有三道
第一道为巴黎解密ctf文件
第二道为画出FLAG
第三道为Stephen
决赛逆向题有四道,只做出了前两题。
第一题为MFC程序跑不起来
第二道为Elf64、STL对素数表加密
第三道使用 VirtualProtect 反调试。
第四道使用了一个linux程序对数据进行封装,没时间做。
前两道相对简单
巴黎解密ctf文件
有个文件加密工具,能将一个文件加密到一个.ctf文件中去。
有一个犯罪分子将存有犯罪记录的一个名为“CTFtest.ctf”
的加密文件被删除了。现经过数据恢复,我们已经恢复了该文件。
但是很不幸,该文件头部的部分数据已经被覆盖掉了。这个.ctf文件已经不能正常打开了。
而且加密该文件的口令,犯罪分子也不愿意交代,我们只知道他惯用的口令是一个8位纯数字口令。
请选手下载http://ctf.ecnu.edu.cn/question/attachment1.zip
通过其中的.ctf文件以及解密程序最大限度地恢复出文件中的内容,flag就在里面。
Flag形式为大写32位md5。
题目给出了一个解密程序以及一个加密后丢失了一部分文件头的文件
如图:
目测丢失了前35bytes的数据
解密程序无壳无花,直接IDA,MFC静态库编译。
结合导入表以及程序运行来看,调用了CreateFile、ReadFile、MessageBox等参数,
顺利跟踪到了程序关键地址 0x402570
分析函数,局部变量比较多,
应该八九不十了。
接着分析:
程序打开文件,判断前4 bytes 内容为 0x33465443 转换为字符CTF3
接着读4bytes转为DWORD型,为接下来要读取的长度并存储。
接着读文件16字节,取密码框内容,
将密码进行两次MD5加密,将结果与取到的16字节进行对比。
接着读4bytes转为DWORD型,做为接下来要读取的长度,再次读取,然后关闭文件。
至此,加密文件全部读取完毕,小结一下文件结构:
4 bytes 为固定字符‘CTF3’
4 bytes 为len of head
{...} 为head
16 bytes 将密码经两次MD5加密的密文
4 bytes 为len of body
{...} 为body
此时回过头来分析.ctf加密文件内容。
发现偏移为0x29位置4bytes的内容为0x0000619C,这一部分正好对应为文件此后的长度,
可以推定为len_of_body
存储位置。向前16bytes为MD5密文区域,并且只有6bytes保留。
根据提示,密码为8位数字,通过这一部分MD5,应该可以还原。
编写程序:
#include <stdio.h>
#include <windows.h>
#include "md5.h"
unsigned char data[6]={0x48, 0xB1, 0xED, 0x05, 0x8D, 0xF7 };
int main()
{
unsigned char a[100] = {0},b[17] = {0},c[17] = {0};
int num = 0, i=0;
for( num = 10000000; num < 99999999; num++){
_itoa(num,(char *)a, 10);
MD5_CTX md5;
MD5Init(&md5);
MD5Update(&md5,a,strlen((char *)a));
MD5Final(&md5,b);
MD5Init(&md5);
MD5Update(&md5,b,16);
MD5Final(&md5,c);
i=0;
while(data[i] == c[i+10])
{
i++;
if(i>=6)
goto l;
}
}
l:
printf("%d", num);
getchar();
getchar();
system("pause");
return 1;
}
程序跑出密码为20160610
。
此时还剩11bytes的head内容不知道。
接着查找程序对head部分的引用,发现程序对head沁使用多字节字符转宽字符库函数。
进行字符串拼接之后,传入CreateFile。
由此可以断定,head部分内容为加密文件的文件名。
至此我们可以对加密文件的分析,基本结束,将文件头丢失部分恢复,Head部分随便指定一个文件名。
解密程序将文件恢复:
得到一个压缩包文件,查看内容为Word文件,打开得到Flag。