1.查壳,无壳,64位。
2.IDA反编译。
分析一手,非常简单的结构
先输入v5,走一手判断,不小于1就行
然后输入v6,将seed与v6异或
设置随机函数的种子
随机数%1000后放入v9
走MD5加密
将加密后的值与明文比较
由于有MD5反复加密,所以直接走爆破
Seed前面的赋值都可以不用管,因为seed^=v6
而16<v6<0xFFFF,无论如何seed的取值都在0-0xFFFF之间
所以我们只需要编写一个循环增加的seed就可以了
此处有两个要点
1.由于源文件是elf格式,也就是Linux下的文件,写完代码编译的时候需要在Linux下编译,因为windows下的rand()函数得结果与linux不同
2.openssl库在3.0以后的版本中废除了旧的MD5函数,需要使用新的写法
#include<openssl/evp.h>
#include<iostream>
#include<stdlib.h>
#include<cstring>
using namespace std;
int main(){
size_t v3;
int v9 = 0;
int s;
char l[32];
char v10[96];
unsigned char v11[32];
char s1[40];
unsigned int *md_len;
// srand(1023);
// for(i;i<30;i++){
// cout<<rand() %1000<<endl;
// }
// 在Windows下的结果与Linux的不同
for(int seed=0;seed<0xFFFF;seed++){
srand(seed);
EVP_MD_CTX *mdctx;
mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
for(int j = 0;j < 30;j++){
v9 = rand() % 1000;
sprintf(l, "%d", v9);
v3 = strlen(l);
EVP_DigestUpdate(mdctx, l, v3);
}
EVP_DigestFinal_ex(mdctx,v11,md_len);
for (int j = 0; j <= 15; ++j ){
sprintf(&s1[2 * j], "%02x", v11[j]);
}
if ( !strcmp(s1, "5eba99aff105c9ff6a1a913e343fec67") )
{
cout<<"seed:"<<seed<<endl;
}
}
return 0;
}
可以得到seed的结果为59306
由于前面定义了seed=0
所以seed^=v6等于v6的值
也就是说在前面的v5输入1,v6输入59306就可以得到flag
nullcon{nu11c0n_s4yz_x0r1n6_1s_4m4z1ng}