这题学习了好多知识。
首先查壳,无壳。然后扔进IDA按F5。
这些估计是垃圾代码。
这部分就很有意思了,一开始我也以为是垃圾代码,毕竟对输入的v17根本没影响。
但很明显,B60这个函数是接受两个参数的,IDA只识别出来一个参数。
那就是IDA识别出了点问题,那怎么办呢?
那就对着上图这一行的libname_4函数右击,点击这个:
就可以正常显示了:
这样子的话,可以猜测sub_311B60是string的[ ]。
然后这里是秘钥和密文。注意,这的密钥是小端序的,也就是说把字节拼起来的时候要注意是小端序顺序。(涉及到数组都可以考虑小端序)
这里的密文也是小端序,但放进去解密的时候要按照IDA反汇编的顺序放,不然解密会出错,等到最后打印字符的时候再按小端序处理。
解密脚本如下:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
unsigned int cipher[50]=
{
0x2C796E3E,0x3FD7AA48,0x30D01B1D,0x22873528,0xE61567C6,0x207FA2D5
};
unsigned char flag[50];
unsigned char key2[50]="674094872038771148666737";
//这里的是sub_401620生成的v16,把代码拉下来跑一下就可以得到
//至于为什么v16就是随机数生成的这些数字,只能靠猜猜看尝试下了
unsigned int a3[50]=
{
0x12345678, 0x9ABCDEF0, 0xFEDCBA98, 0x76543210
};
signed main()
{
int v8=52/6+6;
unsigned int v9=0;
//unsigned int delta=0x4786C861;
unsigned int delta=0x61C88647;
v9-=delta*v8;
unsigned int z;
unsigned int e;
unsigned int y=cipher[0];
for(int round=0;round<v8;round++)
{
e=(v9>>2)&3;
for(int i=6-1;i>=0;i--)
{
z=cipher[(i-1+6)%6];
cipher[i]-=(((z^a3[1*(e^i&3)])+(cipher[(i+1)%6]^v9))^(((16*z)^(cipher[(i+1)%6]>>3))+((4*cipher[(i+1)%6])^(z>>5))));
}
v9+=delta;
for(int i=0;i<6;i++)
{
printf("%u ",cipher[i]);
}
printf("%u\n",v9);
}
int len=0;
for(int i=0;i<6;i++)
{
flag[len++]=(cipher[i]>>(0*8))&0xFF;
flag[len++]=(cipher[i]>>(1*8))&0xFF;
flag[len++]=(cipher[i]>>(2*8))&0xFF;
flag[len++]=(cipher[i]>>(3*8))&0xFF;
}
for(int i=0;i<len;i++)
{
flag[i]^=(key2[i]-'0');
if(i%2)
{
flag[i]-=2;
}
else
{
flag[i]+=3;
}
}
printf("%s",flag);
}