接上次的,将序列号的验证算法流程及代码都整理出来了,最后弄成了三个小函数,为了更加方面阅读,理解验证算法的原理,进而为序列号生成算法的设计做铺垫,这里,我们将上次代码中的汇编部分,都逆向成C/C++来表述。
首先是计算部分的Step1:
void CalculateKeyStep1( const char *pStrName, const char *pStrSerialNum,
DWORD &outTempNum1, DWORD &outTempNum2 )
{
assert( NULL != pStrName );
assert( NULL != pStrSerialNum );
if ( NULL == pStrName || NULL == pStrSerialNum )
return;
outTempNum1 = *(DWORD*)pStrName;
outTempNum2 = *(DWORD*)(pStrName+4);
DWORD nSerialTemp1 = *(DWORD*)pStrSerialNum;
DWORD nSerialTemp2 = *(DWORD*)(pStrSerialNum+4);
outTempNum1 ^= nSerialTemp1;
outTempNum2 ^= nSerialTemp2;
outTempNum1 &= 0x7F3F1F0F; //0111 1111-0011 1111-0001 1111-0000 1111
//x31=0,x23=0,x15=0,x7=0
outTempNum2 &= 0x07030100; //0111 0000-0011 0000-0001 0000-0000 0000
//x31=0,x23=0,x15=0,x7=0
for (int idx=0; idx<8; ++idx)
{
std::bitset<32> vBtsEAX( outTempNum1<<idx );
std::bitset<32> vBtsEBX( outTempNum2<<idx );
std::bitset<32> vBtsR(0);
vBtsR[7] = vBtsEAX[31];
vBtsR[6] = vBtsEAX[23];
vBtsR[5] = vBtsEAX[15];
vBtsR[4] = vBtsEAX[7];
vBtsR[3] = vBtsEBX[31];
vBtsR[2] = vBtsEBX[23];
vBtsR[1] = vBtsEBX[15];
vBtsR[0] = vBtsEBX[7];
int nValue = vBtsR.to_ulong();
if (idx <= 3)
{
nValue <<= 8*(3-idx);
outTempNum1 ^= nValue;
}
else
{
nValue <<= 8*(7-idx);
outTempNum2 ^=nValue;
}
}
}
接着就是最后一个验证步骤Step2,由于验证步骤里面有一个递归调用,故此,Step2拆分成两个函数,如下:
void Func( DWORD nTempNum1, DWORD nTempNum2,
UINT &uCount, DWORD &nMagicNum )
{
if ( uCount <= 0x80 ) return;
UINT uTMCount = uCount;
DWORD nValue = nTempNum1;
uCount &= 0xff; //取最低一个字节,根据下面程序的执行
if ( uCount > 8 ) //其实为取CL的低四位.
{
nValue = nTempNum2;
uCount >>= 4; //取CL高4位.
}
//nValue为DWORD,占4个字节,如下图示:
//|---|---|---|---|
//| 1 | 2 | 3 | 4 |
//|___|___|___|___|
//
UINT uRotateCount = (UINT)(log((float)uCount)/log(2.0f));
switch( uRotateCount%4 )
{
case 1:
nValue >>= 16; //|---|
break; //| 2 |
//|___|
case 2:
nValue >>= 8; //|---|
break; //| 3 |
//|___|
case 3:
break; //|---|
//| 4 |
//|___|
default:
nValue >>= 24; //|---|
break; //| 1 |
//|___|
}
uCount = (uTMCount&0xff00)>>8;
nValue &=uCount;
uCount = 0x80;
while ( uCount&nValue ? 1:uCount>>=1 )
{
if ( !(uCount&nValue) ) continue;
nValue ^= uCount;
uCount ^= ((uCount&0xff)<<8);
uTMCount &= 0xff00;
uTMCount ^= uCount;
++nMagicNum;
Func( nTempNum1, nTempNum2, uTMCount, nMagicNum );
uCount = 0x80;
}
uCount = uTMCount; //In order to retrieve the return value
}
bool CalculateKeyStep2( const DWORD nTempNum1, const DWORD nTempNum2,
const char *pStrName, const char *pStrSerialNum )
{
DWORD nMagicNum = 0xfedcba98;
UINT uCount = 0xff01;
Func( nTempNum1, nTempNum2, uCount,nMagicNum );
if ( 1 == uCount )
{
nTempNum1 = *(DWORD*)(pStrName+8);
nTempNum2 = *(DWORD*)(pStrName+ 0xc);
nTempNum1 ^= nTempNum2;
nTempNum1 ^= nMagicNum;
nTempNum1 |= 0x40404040;
nTempNum1 &= 0x77777777;
nTempNum1 ^= *(DWORD*)(pStrSerialNum+8);
nTempNum1 ^= *(DWORD*)(pStrSerialNum+0xc);
if ( 0 == nTempNum1 )
return true;
}
return false;
}
至此,将汇编代表都转成了C/C++语言的形式,但是依然不是很好阅读,需要进一步做调整。To be continued......