010破解(四)之注册机
概述
算法总算分析完成了,接下来准备就编写注册机了,根据我们输入的用户名,计算出序列号
思路分析
方法一:暴力枚举,这种方式太费时间,能用技术解决的事不可能用这种方法的
方法二:
- 根据输入用户名计算加密值
- 加密值与密码对应关系可以得到 k4 k5 k6 k7,假设Ret是函数返回的加密值
K[4]=Ret&0xFF
k[5]=(Ret>>8)&0xFF
k[6]=(Ret>>0x10)%0xFF
k[7]=(Ret>>0x18)&0xFF - 根据分析得到的序列号相关计算函数,结合已知条件,枚举剩余的值
注册机
关键代码,两种算法计算方式,有几个关键的序列号计算CALL是直接从IDA拷贝出来的
VOID CalPassword::CrackKey1(CHAR* pUserName,CString& Password,DWORD arg)
{
srand(time(NULL));
BYTE Key[10] = { 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA };
BYTE k0 = 0;
BYTE k1 = 0;
BYTE k2 = 0;
BYTE k3 = 0;
BYTE k4 = 0;
BYTE k5 = 0;
BYTE k6 = 0;
BYTE k7 = 0;
BYTE k8 = 0;
BYTE k9 = 0;
//Key[3] = 0x9C 0xAC 0xFC
//0x9C是8位序列号
Key[3] = 0x9C;
//计算用户名加密值与k4 k5 k6 k7有对应关系
//k4 k5 k6 k7 逆用户名加密值
//说明K[4]=Ret&0xFF
//说明k[5]=(Ret>>8)&0xFF
//说明k[6]=(Ret>>0x10)%0xFF
//说明k[7]=(Ret>>0x18)&0xFF
DWORD dwRetValue = rand() % 0x3e8 + 1; //指定商的范围 0-0x3e8
DWORD dwValue = sub_EncodeName(pUserName, 1, 0, dwRetValue);
Key[4] = dwValue & 0xFF;
Key[5] = (dwValue >> 8) & 0xFF;
Key[6] = (dwValue >> 16) & 0xFF;
Key[7] = (dwValue >> 24) & 0xFF;
//计算k0和k6
while (TRUE)
{
k0 = rand() % 0xFF;
BYTE AL = ((k0 ^ Key[6] ^ 0x18) + 0x3D) ^ 0xA7;
if (AL >= arg)
{
Key[0] = k0;
//Key[6] = k6;
break;
}
}
while (TRUE)
{
k1 = rand() % 0xFF;
k2 = rand() % 0xFF;
//esi=((K[2]^k[5]&0xFF)+(K[1]^k[7]&0xFF)*0x100)&0xFFFF
//EAX=((esi^0x7892+0x4D30)^0x3421&0xFFFF)/0xB
//判断余数是否为0,为0返回商,不为0返回0
//商<=0x3e8
DWORD dwTemp1 = (k2 ^ Key[5]) & 0xFF;
DWORD dwTemp2 = ((k1 ^ Key[7]) & 0xFF) * 0x100;
DWORD dwESI = (dwTemp1 + dwTemp2) & 0xFFFF;
DWORD dwEAX = ((((dwESI ^ 0x7892) + 0x4D30) ^ 0x3421) & 0xFFFF);
if (dwEAX % 0xB == 0 && dwEAX/0xB == dwRetValue)
{
Key[1] = k1;
Key[2] = k2;
break;
}
}
Password.Format(L"%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X", Key[0], Key[1],
Key[2], Key[3], Key[4], Key[5], Key[6], Key[7], Key[8], Key[9]);
}
VOID CalPassword::CrackKey2(CHAR* pUserName, CString& Password, DWORD arg)
{
srand(time(NULL));
BYTE Key[10] = { 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA };
BYTE k0 = 0;
BYTE k1 = 0;
BYTE k2 = 0;
BYTE k3 = 0;
BYTE k4 = 0;
BYTE k5 = 0;
BYTE k6 = 0;
BYTE k7 = 0;
BYTE k8 = 0;
BYTE k9 = 0;
//Key[3] = 0x9C 0xAC 0xFC
//0xAC是10位序列号
Key[3] = 0xAC;
//计算用户名加密值与k4 k5 k6 k7有对应关系
//k4 k5 k6 k7 逆用户名加密值
//说明K[4]=Ret&0xFF
//说明k[5]=(Ret>>8)&0xFF
//说明k[6]=(Ret>>0x10)%0xFF
//说明k[7]=(Ret>>0x18)&0xFF
DWORD dwRetValue = rand() % 0x3e8 + 1; //指定商的范围 0-0x3e8
DWORD dwValue = sub_EncodeName(pUserName, 0xFF, 0, 1);
Key[4] = dwValue & 0xFF;
Key[5] = (dwValue >> 8) & 0xFF;
Key[6] = (dwValue >> 16) & 0xFF;
Key[7] = (dwValue >> 24) & 0xFF;
while (TRUE)
{
k1 = rand() % 0xFF;
k2 = rand() % 0xFF;
//esi=((K[2]^k[5]&0xFF)+(K[1]^k[7]&0xFF)*0x100)&0xFFFF
//EAX=((esi^0x7892+0x4D30)^0x3421&0xFFFF)/0xB
//判断余数是否为0,为0返回商,不为0返回0
//商<=0x3e8
DWORD dwTemp1 = (k2 ^ Key[5]) & 0xFF;
DWORD dwTemp2 = ((k1 ^ Key[7]) & 0xFF) * 0x100;
DWORD dwESI = (dwTemp1 + dwTemp2) & 0xFFFF;
DWORD dwEAX = ((((dwESI ^ 0x7892) + 0x4D30) ^ 0x3421) & 0xFFFF);
if (dwEAX % 0xB == 0 && dwEAX / 0xB == dwRetValue)
{
Key[1] = k1;
Key[2] = k2;
break;
}
}
while (TRUE)
{
k9 = rand() % 0xFF;
k0 = rand() % 0xFF;
DWORD dwTemp1 = k9 ^ Key[5];
DWORD dwTemp2 = Key[4] ^ Key[5];
DWORD dwTemp3 = k0 ^ Key[6];
DWORD dwarg1 = (((dwTemp1 << 8 )+ dwTemp2) << 8) + dwTemp3;
DWORD dwRet = Algorithm2(dwarg1, 0x005B8C27);
if (dwRet != 0 && dwRet <= arg)
{
Key[9] = k9;
Key[0] = k0;
break;
}
}
Password.Format(L"%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X", Key[0], Key[1],
Key[2], Key[3], Key[4], Key[5], Key[6], Key[7], Key[8], Key[9]);
}
成品演示