一、软件防调手段:
1:用EnableWindow方法禁止窗口活动。
2:验证代码在取得输入函数很远的地方,用PostMessage方式。
3:对验证代码之间用GetTickCount检测执行时间,小于100ms,失败
二、注册流程:
1:用CreateFile方式取得硬盘序列号,失败用GetColumeInformation;
2:对硬盘序列号前8个字节作运算得一个DWORD数;
3:对上面的DWORD数查表计算得出一个QWORD数;
4:对输入的注册码写入ini文件;
5:对输入前半部分数运算得出个DWORD数;
6:对输入后半部分数运算得出个DWORD数;
7:浮点指令装入3步的QWORD数,浮点比较5、6步产生的两个DWORD数;
8:相等就注册成功(一台机器理论有很多注册码,我只找到两个成功注册)。
三:遗留的问题:
1、还不能逆5、6步的算法,只能穷举,穷兴有点慢,20分钟才找到2个;
2、软件产生的序列号和硬盘序列号的关系没找到;
四:部分伪代码(代码是OD动态分析来的):
1:第二步的:
DWORD CServUPAWDlg::MyCalc1()
{
UpdateData(TRUE);
DWORD myreturn = 0;
BYTE a1,a2,a3,a4;
a1 = m_PdHash.GetAt(0) * m_PdHash.GetAt(1);
a2 = m_PdHash.GetAt(2) * m_PdHash.GetAt(3);
a3 = m_PdHash.GetAt(4) * m_PdHash.GetAt(5);
a4 = m_PdHash.GetAt(6) * m_PdHash.GetAt(7);
myreturn = a4;
myreturn <<= 0x08;
myreturn += a3;
myreturn <<= 0x08;
myreturn += a2;
myreturn <<= 0x08;
myreturn += a1;
return myreturn;
}
2:第三步的:
void CServUPAWDlg::MyEncHash()
{
int i =0;
PwHash2 = 0x19a28;
PwHash1 = DiskHash;
DWORD temp1 = DiskHash;
CString msg;
do
{
temp1 = PwHash1;
temp1 += Table5F2CF8[Table5F2D98[i]];
PwHash2 ^= MyEnc4228F0(temp1);
MyEnc4229A0();
i++;
}while(i<32);
MyEnc4229A0();
return;
}
DWORD CServUPAWDlg::MyEnc4228F0(DWORD a)
{
DWORD temp = a;
DWORD bb;
DWORD myreturn = 0;
BYTE a1;
temp >>= 0x18;
temp &= 0x0f;
a1 = Table5F2D78[temp];
temp = a;
temp >>=0x1c;
temp &= 0x0f;
myreturn = Table5F2D88[temp];
myreturn <<= 4;
myreturn |= a1;
temp = a;
temp >>= 0x14;
temp &= 0x0f;
a1 = Table5F2D68[temp];
myreturn <<= 4;
myreturn |= a1;
temp = a;
temp >>= 0x10;
temp &= 0x0f;
a1 = Table5F2D58[temp];
myreturn <<= 4;
myreturn |= a1;
temp = a;
temp >>= 0x0c;
temp &= 0x0f;
a1 = Table5F2D48[temp];
myreturn <<= 4;
myreturn |= a1;
temp = a;
temp >>= 0x08;
temp &= 0x0f;
a1 = Table5F2D38[temp];
myreturn <<= 4;
myreturn |= a1;
temp = a;
temp >>= 0x04;
temp &= 0x0f;
a1 = Table5F2D28[temp];
myreturn <<= 4;
myreturn |= a1;
temp = a;
temp &= 0x0f;
a1 = Table5F2D18[temp];
myreturn <<= 4;
myreturn |= a1;
bb = myreturn;
myreturn = (bb >> 0x15 | myreturn << 0x0b);
return myreturn;
}
void CServUPAWDlg::MyEnc4229A0()
{
//交换a1和a2的内容
__asm
{
push PwHash1
push PwHash2
pop PwHash1
pop PwHash2
}
return ;
}
3:第5、6步的:
DWORD MyEncA(CString part1)
{
int slen = ::strlen(part1);
DWORD A = 0;
DWORD B = 0;
int i = 0;
for(i=slen;i>0;i--)
{
B *= 8;
B -= A;
B *= 5;
B += ChangeChar(part1.GetAt(i-1));//str[i]要经过转换,如0x39->0x09
A = B;
}
return B;
}
DWORD MyEncB(CString part2)
{
int slen = ::strlen(part2);
DWORD A = 0;
DWORD B = 0;
int i = 0;
for(i=slen;i>0;i--)
{
B <<= 4;
B += A;
B <<= 1;
B += ChangeChar(part2.GetAt(i-1));//str[i]要经过转换,如0x39->0x09
A = B;
}
return B;
}
- 标 题:对CardMaker5.2部分注册算法研究...
- 作 者:lankerr
- 时 间:2010-04-23 01:17:48
- 链 接:http://bbs.pediy.com/showthread.php?t=111543