签名:水泊梁山.zZhouQing
算法验证共有四组。
CheckSerial
CheckSerial,这个是之前在论坛看到的一个 tencent 样本,做了点分析。今天拿过来魔改了一下。这个面试题似乎有好几个版本,这份是较难的,主要考察的是 Windows 系统原理,和算法无关。
__forceinline std::string DeCheckSerial1(std::string serial_1) {
unsigned char buffer[32];
hexString2Bytes(serial_1, buffer);
unsigned char _tmp[16] = {};
unsigned char _tmp2[16] = {};
RC6_DE((uint32_t*)_tmp, (uint32_t*)&buffer);
RC6_DE((uint32_t*)_tmp2, (uint32_t*)&buffer[16]);
char fpw[32] = {};
for (size_t i = 0; i < 16; i++)
{
fpw[i] = _tmp[i];
}
for (size_t i = 0; i < 16; i++)
{
fpw[i + 16] = _tmp2[i];
}
return fpw;
}
__forceinline int CheckSerial()
{
auto un = user.GetData<std::string>(userName);
auto pw = user.GetData<std::string>(userSerial);
if (pw.size() < ObfInt2(24))
{
return user.GetData<int>(SerialFailFlag2);
}
user.SetData<int>(gloablConstV, ObfInt2(0x506) ^ user.GetData<int>(KeyGenFlag));
unsigned char uN2 [9];
getUn2((unsigned char*)un.c_str(), uN2);
int constV = user.GetData<int>(gloablConstV);
*(int*)((int*)uN2) ^= constV;
*(int*)((int*)uN2 + 1) ^= constV;
char flag1, flag2, flag3;
unsigned char* serial = new unsigned char[ObfInt2(33)];
serial[ObfInt2(32)] = {};
setMemSig(serial,0,32);
for (size_t i = 0; i != 8; i++)
{
flag1 = ((uN2[i] & ObfInt2(0X30)) + (((uN2[i] & ObfInt2(0X50)) >> ObfInt2(0X8)) & ObfInt2(0X4))) >> ObfInt2(0X5);
flag2 = (uN2[i] & ObfInt2(0X10)) + (((uN2[i] & ObfInt2(0X6)) >> ObfInt2(0X7)) & ObfInt2(0X3)) >> ObfInt2(0X2);
flag3 = uN2[i] & ObfInt2(0X4);
int flag4 = i % 3;
if (flag4 == 2)
{
serial[i * 3] = t5_864[flag3];
serial[i * 3 + 1] = t6_83c[flag1];
serial[i * 3 + 2] = t7_874[flag2];
}
if (flag4 == 1)
{
serial[i * 3] = t3_834[flag1];
serial[i * 3 + 1] = t4_87c[flag2];
serial[i * 3 + 2] = t5_864[flag3];
}
if (flag4 == 0)
{
serial[i * 3] = t3_834[flag2];
serial[i * 3 + 1] = t4_87c[flag3];
serial[i * 3 + 2] = t5_864[flag1];
}
}
for (int i = 0; i != 24; i++)
{
auto npw = DeCheckSerial1(pw);
if (serial[i] != npw[i])
{
user.SetData<int>(gloablSerialFlag, ObfInt2(0x1314));
user.SetData<int>(KeyGenFlag, ObfInt2(0x21));
return user.GetData<int>(SerialFailFlag);
}
}
user.SetData<int>(gloablSerialFlag, ObfInt2(0));
user.SetData<int>(SerialSuccessFlag, ObfInt2(0x999));
return user.GetData<int>(SerialSuccessFlag);
}
CheckSerial2
这部分主要用来反调试,同时 serial_2 参加后续的算法验证。
__forceinline int CheckSerial2(std::string un,std::string serial)
{
SBLS_ANTI_TIME_RDTSC();
auto serial_1 = serial.substr(0, 32 * 2);
SBLS_ANTI_TIME_RDTSC();
auto serial_2 = EnCheckSerial_2(un,serial_1);
SBLS_ANTI_TIME_RDTSC();
auto cur_serial_2 = serial.substr(32 * 2, 8);
SBLS_ANTI_TIME_RDTSC();
SBLS_ANTI_TIME_RDTSC();
if (DeCheckSerial_2(cur_serial_2,serial_1) == DeCheckSerial_2(serial_2, serial_1))
{
return 0;
}
SBLS_ANTI_TIME_RDTSC();
return -1;
}
CheckSerial3
算法流程与 CheckSerial1 类似,修改了表的位置以及讲表的部分数据在特定时候还原。
__forceinline int CheckSerial3(std::string _un,std::string _serial)
{
unsigned char t[0x0010] =
{
0xf7, 0xff, 0xff, 0x89, 0x8d, 0x4c, 0xf7, 0xff, 0xff, 0xc7, 0x85, 0x48, 0xf7, 0xff, 0xff, 0x14
};
unsigned char t2[0x0010] =
{
0x07, 0x82, 0x19, 0xe8, 0x1f, 0xfe, 0xff, 0xff, 0x0f, 0xb6, 0xd0, 0x85, 0xd2, 0x74, 0x05, 0xe9
};
unsigned char t3_834[0x0040] =
{
0x52 ^ 3, 0x51 ^ 3, 0x53 ^ 3, 0x54 ^3, 0x55 ^ 3, 0x57, 0x56, 0x5a, 0x59, 0x58, 0x00, 0x00, 0x40, 0xed, 0x9f, 0xf5,
0x26, 0x3a, 0x6f, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
unsigned char t4_87c[0x00B0] =
{
0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7a, 0x6e, 0x69, 0xc9, 0x1b, 0x40, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x18, 0x00, 0xa0, 0xf0, 0x18, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5a, 0x00, 0x00, 0x40, 0xed, 0x9f, 0xf5, 0x26, 0x3a, 0x6f, 0x8f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
unsigned char t5_864[0x0090] =
{
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x18, 0x00, 0xa0, 0xf0, 0x18, 0x00,
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x40, 0xed, 0x9f, 0xf5,
0x26, 0x3a, 0x6f, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
unsigned char t6_83c[0x001E] =
{
0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5A, 0x7F, 0x00, 0xF6, 0x9A, 0xE2, 0xF7, 0x9B, 0x50, 0x09, 0x80, 0x00, 0x00
};
unsigned char t7_874[0x003C] =
{
0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x19, 0x00, 0xC9, 0x1B, 0x40, 0x00,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00,
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C
};
unsigned char uN2[9];
getUn3((unsigned char*)_un.c_str(), uN2);
int constV = 0x520 ^ (user.GetData<int>(KeyGenFlag) - ObfInt2(2));
*(int*)((int*)uN2) ^= constV;
*(int*)((int*)uN2 + 1) ^= constV;
char flag1, flag2, flag3;
unsigned char* serial = new unsigned char[ObfInt2(33)];
serial[ObfInt2(32)] = {};
setMemSig(serial, 0, 32);
if (user.GetData<int>(KeyGenFlag) != 2)
{
for (size_t i = 0; i != 8; i++)
{
flag1 = ((uN2[i] & ObfInt2(0x20)) + (((uN2[i] & ObfInt2(0x30)) >> ObfInt2(0x40)) & ObfInt2(0X4))) >> ObfInt2(0X5);
flag2 = (uN2[i] & ObfInt2(0x6)) + (((uN2[i] & ObfInt2(0x5)) >> ObfInt2(0X7)) & ObfInt2(0X3)) >> ObfInt2(0X2);
flag3 = uN2[i] & ObfInt2(0X4);
int flag4 = i % 3;
if (flag4 == 2)
{
serial[i * 3] = t5_864[flag2];
serial[i * 3 + 1] = t6_83c[flag1];
serial[i * 3 + 2] = t7_874[flag3];
}
if (flag4 == 1)
{
serial[i * 3] = t3_834[flag2];
serial[i * 3 + 1] = t4_87c[flag3];
serial[i * 3 + 2] = t5_864[flag1];
}
if (flag4 == 0)
{
if (flag3 == 0x4 || flag3 == 0x3 || flag3 == 0x2 || flag3 == 0x1 || flag3 == 0x0)
{
serial[i * 3] = t3_834[flag3] ^ 3;
}
else
{
serial[i * 3] = t3_834[flag3];
}
serial[i * 3 + 1] = t4_87c[flag2];
serial[i * 3 + 2] = t5_864[flag1];
}
}
for (int i = 0; i != 24; i++)
{
auto serial_3 = _serial.substr(32 * 2 + 8, 32 * 2);
auto npw = DeCheckSerial3(serial_3);
if (serial[i] != npw[i])
{
return user.GetData<int>(SerialFailFlag);
}
}
return user.GetData<int>(SerialFailFlag2);
}
else
{
for (size_t i = 0; i != 8; i++)
{
flag1 = ((uN2[i] & ObfInt2(0x20)) + (((uN2[i] & ObfInt2(0x30)) >> ObfInt2(0x40)) & ObfInt2(0X4))) >> ObfInt2(0X5);
flag2 = (uN2[i] & ObfInt2(0x6)) + (((uN2[i] & ObfInt2(0x5)) >> ObfInt2(0X7)) & ObfInt2(0X3)) >> ObfInt2(0X2);
flag3 = uN2[i] & ObfInt2(0X4);
int flag4 = i % 3;
if (flag4 == 2)
{
serial[i * 3] = t5_864[flag2];
serial[i * 3 + 1] = t6_83c[flag1];
serial[i * 3 + 2] = t7_874[flag3];
}
if (flag4 == 1)
{
serial[i * 3] = t3_834[flag2];
serial[i * 3 + 1] = t4_87c[flag3];
serial[i * 3 + 2] = t5_864[flag1];
}
if (flag4 == 0)
{
if (flag3 == 0x4 || flag3 == 0x3 || flag3 == 0x2 || flag3 == 0x1 || flag3 == 0x0)
{
serial[i * 3] = t3_834[flag3] ^ 3;
}
else
{
serial[i * 3] = t3_834[flag3];
}
serial[i * 3 + 1] = t4_87c[flag2];
serial[i * 3 + 2] = t5_864[flag1];
}
}
for (int i = 0; i != 24; i++)
{
auto serial_3 = _serial.substr(32 * 2 + 8, 32 * 2);
auto npw = DeCheckSerial3(serial_3);
if (serial[i] != npw[i])
{
user.SetData<int>(KeyGenFlag, user.GetData<int>(KeyGenFlag) + ObfInt2(0X7));
return user.GetData<int>(SerialFailFlag);
}
}
return user.GetData<int>(SerialSuccessFlag);
}
}
CheckSerial4
将用户名进行 hash 得到 un_md5,crc32(un_md5) 的值为公式 f(x) = e(y) 中的 e(y)。
__forceinline int CheckSerial4(std::string un,std::string serial)
{
auto cur_serial_2 = serial.substr(32 * 2, 8);
auto cur_serial_4 = serial.substr(32 * 2 + 8 + 32 * 2,8);
auto cur_serial_5 = serial.substr(32 * 2 + 8 + 32 * 2 + 8,serial.size());
auto un_md5 = md5sum6(un.c_str());
auto un_crc32 = CRC32((unsigned char*)un_md5.c_str(), un.size());
int cur_serial_2_crc = CRC32((unsigned char*)cur_serial_2.c_str(), cur_serial_2.size());
if (CheckSerial2(un, serial)!=0)
{
return user.GetData<int>(SerialFailFlag);
}
string serial_4 = bytes2HexString((unsigned char*)&cur_serial_2_crc, 4);
if (getMemCmp((unsigned char*)cur_serial_4.c_str(), (unsigned char*)serial_4.c_str(), 8) == 0)
{
unsigned char cur_serial_5_char[8];
hexString2Bytes(cur_serial_5, cur_serial_5_char);
bitset<64> cipher = DES_charTobitset((const char*)cur_serial_5_char);
des_key = DES_charTobitset(cur_serial_4.c_str());
bitset<64> temp_plain = DES_decrypt(cipher);
unsigned char de_cipher[8];
DES_bitsetToChar(temp_plain,(char*)de_cipher);
auto un_crc32_bit = DES_charTobitset(bytes2HexString((unsigned char*)&un_crc32, 4).c_str());
if (un_crc32_bit == temp_plain)
{
return user.GetData<int>(SerialSuccessFlag);
}
}
return user.GetData<int>(SerialFailFlag);
}
注册机
这部分内容,各位大侠看 KeyGen 就好了,不在此赘述。
最后于 2024-8-20 12:21
被zZhouQing编辑
,原因: