其实此CM本来还是比较简单的,不过由于64位程序很少看,程序中还有不少垃圾代码,看得眼花:(
下面从IDA F5的代码中列出主要验证部分,就能看清验证流程,从而得到找到SN的方法.
设输入的SN为snInput, snLen 为SN长度:
//串的HASH值计算函数
signed __int64 __fastcall getHash(char *a1)
{
char v1; // dl
signed __int64 result; // rax
signed __int64 v3; // rax
v1 = *a1;
for ( result = 0xCBF29CE484222325i64; *a1; result = 0x100000001B3i64 * v3 )
{
++a1;
v3 = result ^ v1;
v1 = *a1;
}
return result;
}
//关键代码调用
if ( a1 == 2 )
{
strncpy_s(snInput, 260i64, *(const char **)(a2 + 8), 260i64); //复制输入的SN
sub_140002E00(&retaddr); //调用验证函数
result = 0i64;
}
//以下是sub_140002E00验证函数的主要验证片段.
snLen = -1i64;
do
++snLen;
while ( snInput[snLen] ); //计算输入SN的长度,设为snLen
//垃圾代码略
if ( (snLen & 0xFFF) + (v533 << 12) == 30 )
{ //要到这儿才能通过,也就是SN的长度要为30个字符
v8 = 0;
v9 = 0;
if ( snLen )
{
v10 = snInput;
do
{
v188 = 0;
v11 = *v10;
LOBYTE(v188) = v11;
v12 = (char *)&v188;
v13 = 0xCBF29CE484222325i64;
if ( v11 )
{
do
{
v13 = 0x100000001B3i64 * (v13 ^ v11);
v11 = *++v12;
}
while ( *v12 );
}
v14 = v8 + 1;
if ( v13 != 0xAF63B44C8601A894i64 )
v14 = v8;
v8 = v14;
++v9;
++v10;
}
while ( v9 < snLen );
v1 = 32i64;
if ( v14 >= 3 )
{ //这儿要大于3才行,不过只要别的条件满足,这儿也就满足了
.......
}
//垃圾代码略
//这儿开始验证SN前9位,由于是一个字符一个字符的验证,所以由getHash函数很易暴出为:KXCTF2018
*(_WORD *)sTmp = 0;
sTmp[0] = snInput[0];
if ( getHash(sTmp) == 0xAF64064C860233EAi64 )
{
sTmp[0] = snInput[1];
if ( getHash(sTmp) == 0xAF64154C86024D67i64 )
{
sTmp[0] = snInput[2];
if ( getHash(sTmp) == 0xAF63FE4C86022652i64 )
{
sTmp[0] = snInput[3];
if ( getHash(sTmp) == 0xAF64094C86023903i64 )
{
sTmp[0] = snInput[4];
if ( getHash(sTmp) == 0xAF63FB4C86022139i64 )
{
sTmp[0] = snInput[5];
if ( getHash(sTmp) == 0xAF63AF4C8601A015i64 )
{
sTmp[0] = snInput[6];
if ( getHash(sTmp) == 0xAF63AD4C86019CAFi64 )
{
sTmp[0] = snInput[7];
if ( getHash(sTmp) == 0xAF63AC4C86019AFCi64 )
{
sTmp[0] = snInput[8];
if ( getHash(sTmp) == 0xAF63B54C8601AA47i64 )
{
v42 = 0i64; //要到这儿才能通过,也就是snInput前9个字符计算出来的HASH值要依次等于以上的9个值
v37 = 0;
v43 = 0x50700i64;
}
else
{
v42 = 0x100000000i64;
v43 = 0x393B00i64;
}
}
else
{
v42 = 0x100000000i64;
v43 = 0x393B00i64;
}
}
else
{
v42 = 0x100000000i64;
v43 = 3750656i64;
}
}
else
{
v42 = 0x100000000i64;
v43 = 3750656i64;
}
}
else
{
v42 = 0x100000000i64;
v43 = 3750656i64;
}
}
else
{
v42 = 0x100000000i64;
v43 = 3750656i64;
}
}
else
{
v42 = 0x100000000i64;
v43 = 0x393B00i64;
}
}
else
{
v42 = 0x100000000i64;
v43 = 0x393B00i64;
}
}
else
{
v42 = 0x100000000i64;
v43 = 0x393B00i64;
}
//垃圾代码略
//对整个SN的HASH值校验,
if ( getHash(snInput) == 0x4F8075587499C0FFi64 )
{ //SN的HASH值必须等于以上值
LODWORD(v46) = 31;
LODWORD(v47) = 0;
}
//垃圾代码略
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)