很郁闷。。。
这是我处女KEYGEN,原本想的挺简单,谁知道弄了我一个晚上,伤心吖。。。 评委组有同情分没?
代码如下:
哈希算法,注册算法,都没什么问题,就是逆回去的时候发现 根本对应不到用户名与注册码。这个程序是把ABCDEFGHJKMNPQRSTVWXYZ1234567890 32个字符的位置对应到一章表(256个字节)上 然后取注册码的字符然后用这个字符做索引在这个表里查询,由于有效就有34个,(算上了0xFF + '='号), 后面有个计算的路径,不过最多的组合就是34 * 34 种算子的组合。 里面各有两个运算, 单个字节是256 ,这样有很大的几率对应不上。
也不多说了。。我把代码贴这里,希望KEYGEN高手可以帮我解答一下。。。 向你们学习。
#include <stdio.h>
#include <windows.h>
#define __MAX_USERNAME_SIZE__ 35
#define __MAX_SERIAL_NUMBER__ 35
#define __USERNAME_SERIAL_NUMBER_SIZE__ 0x5C//92
BYTE g_UserNameKeyTable[__USERNAME_SERIAL_NUMBER_SIZE__] = {0};
DWORD g_UserNameSerialNumber[5] = {0};
BYTE g_SerialNumber[32] = {0};
BYTE g_KeyTable[256] = {0};
CONST PCHAR g_ValidCharTable = "ABCDEFGHJKMNPQRSTVWXYZ1234567890";
CONST PCHAR g_AnsiTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
DWORD Bswap(DWORD dwDword) {
DWORD r = 0;
__asm {
mov eax, dwDword
bswap eax
mov r, eax
}
return r;
}
BYTE Shl(BYTE b, BYTE n) {
BYTE r = 0;
__asm {
mov al, b
mov cl, n
shl al, cl
mov r, al
}
return r;
}
BYTE Shr(BYTE b, BYTE n) {
BYTE r = 0;
__asm {
mov al, b
mov cl, n
shr al, cl
mov r, al
}
return r;
}
#define __TABLE_1__ 0
#define __TABLE_2__ 64
DWORD dwSwitch = 0;
VOID HashIt(PUCHAR pKeyArray, PUCHAR pUserNameKeyString) {
DWORD dwKeyX = 0;
DWORD dwKeyY = 0;
DWORD dwEbp = 0;//模仿的EBP
BYTE Table[64 + 256] = {0};//第一张表64字节,第二张表256字节
// 生成第一章表
// 第一次循环将pUserNameKeyString指向的内存中的64个字节每
// 4个字节做反转存入表1
__asm {
cld
xor ecx, ecx
mov esi, pUserNameKeyString
lea edi, Table
_make_table_1:
lodsd
bswap eax
stosd
add ecx, 1
cmp ecx, 0x10
jl _make_table_1
}
// 生成第二章表
__asm {
mov edx, 0x40
lea eax, [Table + 0x08]
_make_table_2:
mov ecx, dword ptr [eax + 0x2C]
xor ecx, dword ptr [eax + 0x18]
add eax, 4
xor ecx, dword ptr [eax - 0x0C]
xor ecx, dword ptr [eax - 0x04]
rol ecx, 1
sub edx, 1
mov dword ptr [eax + 0x34], ecx
jnz _make_table_2
}
// 这里开始计算两个重要的KEY
__asm {
mov eax, pKeyArray
mov edx, dword ptr [eax + 0x04]
//push ebx
mov ebx, dword ptr [eax + 0x0C]
//push ebp
//push esi
mov esi, dword ptr [eax + 0x08]
//push edi
mov edi, dword ptr [eax]
mov eax, dword ptr [eax + 0x10]
mov dwKeyX, eax
mov dwKeyY, edi
xor eax, eax
mov edi, edi
_fuck_loop:
rol edi, 5
mov dwEbp, esi
and dwEbp, edx
mov ecx, edx
not ecx
and ecx, ebx
xor ecx, dwEbp
add edi, ecx
add edi, dword ptr [Table + eax * 4]
mov ecx, dwKeyX
lea ecx, dword ptr [edi + ecx + 0x5A827999]
mov edi, dwKeyY
mov dwKeyX, ebx
ror edx, 2
mov dwKeyY, ecx
rol ecx, 5
mov ebx, edi
not ebx
and ebx, esi
mov dwEbp, edx
and dwEbp, edi
xor ebx, dwEbp
add ecx, ebx
{
// add ecx, dword ptr [esp + eax * 4 + 0x1C]
mov dwSwitch, edi
lea edi, [Table + eax * 4]
add edi, 0x04
add ecx, dword ptr [edi]
mov edi, dwSwitch
}
mov ebx, dwKeyX
lea ecx, dword ptr [ecx + ebx + 0x5A827999]
ror edi, 2
mov dwKeyX, esi
mov ebx, edx
mov edx, dwKeyY
mov dwKeyY, ecx
rol ecx, 5
mov dwEbp, edi
and dwEbp, edx
mov esi, edx
not esi
and esi, ebx
xor esi, dwEbp
add ecx, esi
{
// add ecx, dword ptr [esp + eax * 4 + 0x20]
mov dwSwitch, edi
lea edi, [Table + eax * 4]
add edi, 0x08
add ecx, dword ptr [edi]
mov edi, dwSwitch
}
mov esi, dwKeyX
lea ecx, dword ptr [ecx + esi + 0x5A827999]
mov esi, dwKeyY
ror edx, 2
mov dwKeyX, ebx
mov dwKeyY, ecx
rol ecx, 5
mov ebx, esi
not ebx
and ebx, edi
mov dwEbp, edx
and dwEbp, esi
xor ebx, dwEbp
add ecx, ebx
{
// add ecx, dword ptr [esp + eax * 4 + 0x24]
mov dwSwitch, edi
lea edi, [Table + eax * 4]
add edi, 0x0C
add ecx, dword ptr [edi]
mov edi, dwSwitch
}
mov ebx, dwKeyX
lea ecx, dword ptr [ecx + ebx + 0x5A827999]
ror esi, 2
mov dwKeyX, edi
mov ebx, esi
mov esi, dwKeyY
mov edi, esi
not edi
and edi, edx
mov dwKeyY, ecx
rol ecx, 5
mov dwEbp, ebx
and dwEbp, esi
xor edi, dwEbp
add ecx, edi
{
// add ecx, dword ptr [esp + eax * 4 + 0x28]
mov dwSwitch, edi
lea edi, [Table + eax * 4]
add edi, 0x10
add ecx, dword ptr [edi]
mov edi, dwSwitch
}
mov edi, dwKeyX
lea ecx, dword ptr [ecx + edi + 0x5A827999]
mov dwEbp, edx
mov edx, dwKeyY
mov edi, ecx
add eax, 5 //指针计数增加
ror esi, 2
{
// mov dword ptr [esp + 0x10], ebp
mov dwSwitch, eax
mov eax, dwEbp
mov dwKeyX, eax
mov eax, dwSwitch
}
mov dwKeyY, edi
cmp eax, 0x14
jl _fuck_loop
}
// 继续计算KEY
__asm {
_fuck_loop2:
mov dwEbp, ebx
xor dwEbp, esi
xor dwEbp, edx
rol ecx, 5
add ecx, dwEbp
add ecx, dword ptr [Table + eax * 4]
{
// mov ebp, dwKeyX
mov dwSwitch, eax
mov eax, dwKeyX
mov dwEbp, eax
mov eax, dwSwitch
}
{
// lea ecx, dword ptr [ecx + ebp + 0x6ED9EBA1]
mov dwSwitch, eax
mov eax, dwEbp
lea ecx, dword ptr [ecx + eax + 0x6ED9EBA1]
mov eax, dwSwitch
}
ror edx, 2
mov dwEbp, ebx
mov ebx, esi
add eax, 1 // 移动指针
cmp eax, 0x28
mov esi, edx
mov edx, edi
{
// mov dwKeyX, ebp
mov dwSwitch, eax
mov eax, dwEbp
mov dwKeyX, eax
mov eax, dwSwitch
}
mov edi, ecx
jl _fuck_loop2
}
// 单独设置一下KeyY
__asm {
mov dwKeyY, ecx
}
// 继续
__asm {
_fuck_loop3:
mov edi, esi
xor edi, edx
and edi, ebx
mov dwEbp, esi
and dwEbp, edx
rol ecx, 5
add ecx, dwKeyX
xor edi, dwEbp
add edi, dword ptr [Table + eax * 4]
ror edx, 2
mov dwEbp, ebx
mov ebx, esi
add eax, 1
cmp eax, 0x3C
lea ecx, dword ptr [edi + ecx + 0x8F1BBCDC]
mov esi, edx
mov edx, dwKeyY
{
// mov dwKeyX, ebp
mov dwSwitch, eax
mov eax, dwEbp
mov dwKeyX, eax
mov eax, dwSwitch
}
mov dwKeyY, ecx
jl _fuck_loop3
}
// 还有
__asm {
_fuck_loop4:
mov edi, ebx
xor edi, esi
rol ecx, 5
xor edi, edx
add edi, dword ptr [Table + eax * 4]
add ecx, dwEbp
ror edx, 2
mov dwEbp, ebx
mov ebx, esi
add eax, 1
cmp eax, 0x50
lea ecx, [edi + ecx + 0xCA62C1D6]
mov esi, edx
mov edx, dwKeyY
mov dwKeyY, ecx
jl _fuck_loop4
}
// 输出结果
__asm {
mov eax, pKeyArray
mov edi, dword ptr [eax]
add edi, ecx
mov ecx, dword ptr [eax + 0x04]
add ecx, edx
mov dword ptr [eax + 0x04], ecx
mov ecx, dword ptr [eax + 0x08]
add ecx, esi
mov dword ptr [eax + 0x08], ecx
mov ecx, dword ptr [eax + 0x0C]
add ecx, ebx
mov dword ptr [eax], edi
mov dword ptr [eax + 0x0C], ecx
mov ecx, dword ptr [eax + 0x10]
add ecx, dwEbp
mov dword ptr [eax + 0x10], ecx
}
return;
}
VOID ShowSign() {
DWORD dwSign = 0;
int i = 0;
do {
dwSign += 0xFFFFFFFD;
dwSign &= 7;
printf("%d ", dwSign);
if ((i != 0) && (i % 0x10 == 0))
printf("\r\n");
i++;
} while (i < 0x20);
}
// 注册算法
VOID SerialNumberGen(PCHAR pSerialNumberString) {
DWORD dwSign = 0;
int i = 0, j = 0;
DWORD n = 0;
BYTE ch = 0, ch2 = 0;
do {
// 读取一个字符
ch = pSerialNumberString[i];
ch = g_KeyTable[ch];
if (dwSign <= 3) {
dwSign += 0xFFFFFFFD;
dwSign &= 7;
if (dwSign == 0) {
g_SerialNumber[j] |= ch;
j++;
} else {
n = 8 - dwSign;
ch = Shl(ch, (BYTE)n);
g_SerialNumber[j] |= ch;
}
} else {
dwSign += 0xFFFFFFFD;
dwSign &= 7;
ch2 = ch;
n = (BYTE)dwSign;
ch2 = Shr(ch2, (BYTE)n);
g_SerialNumber[j] |= ch2;
j++;
// 设置下一个字节
n = 8 - dwSign;
ch = Shl(ch, (BYTE)n);
g_SerialNumber[j] |= ch;
}
i++;
} while (i < 0x20);
}
/*
* 最多 34 * 34 种组合的值,不能满足所有用户名的需求
*/
// 逆向注册算法
// 流程处理到5, 2 ,7, 4, 1, 6, 3, 0其余做同样的循环
CONST BYTE g_ReverseSign[33] = {//由ShowSign得出
"\x05\x02\x07\x04\x01\x06\x03\x00\x05\x02\x07\x04\x01\x06\x03\x00"
"\x05\x02\x07\x04\x01\x06\x03\x00\x05\x02\x07\x04\x01\x06\x03\x00"
};
VOID ReverseSerialNumberGen(PUCHAR pSerialNumber, PCHAR pSerialNumberString) {
CHAR ch = 0, ch2 = 0, x = 0, y = 0, z = 0, result = 0;
BYTE _ch = 0, _ch2 = 0, _c = 0;
int i = 0, j = 0;
int n = 0, m = 0;
for (n = 0; n < 20; n+=5) {
// 0, 5, 2-
result = pSerialNumber[n];
for (i = 0; i < 36; i++) {
ch = g_AnsiTable[i];
_ch = g_KeyTable[ch];
_ch = Shl(_ch, 8 - 5);
x |= _ch;
y = x;
for (j = 0; j < 36; j++) {
ch2 = g_AnsiTable[j];
_ch2 = g_KeyTable[ch2];
_c = _ch2;
_ch2 = Shr(_ch2, 2);
x |= _ch2;
if (x == result) {
pSerialNumberString[m++] = ch;
pSerialNumberString[m++] = ch2;
goto _byte_2;
}
x = y;
}/* end for */
x = 0;
}
_byte_2:
// -2, 7, 4-
x = 0;
result = pSerialNumber[n+1];
_c = Shl(_c, 8 - 2);
x |= _c;
z = x;
for (i = 0; i < 36; i++) {
ch = g_AnsiTable[i];
_ch = g_KeyTable[ch];
_ch = Shl(_ch, 8 - 7);
x |= _ch;
y = x;
for (j = 0; j < 36; j++) {
ch2 = g_AnsiTable[j];
_ch2 = g_KeyTable[ch2];
_c = _ch2;
_ch2 = Shr(_ch2, 4);
x |= _ch2;
if (x == result) {
pSerialNumberString[m++] = ch;
pSerialNumberString[m++] = ch2;
goto _byte_3;
}
x = y;
}/* end for */
x = z;
}
_byte_3:
// -4, 1-
x = 0;
result = pSerialNumber[n+2];
_c = Shl(_c, 8 - 4);
x |= _c;
z = x;
for (i = 0; i < 36; i++) {
ch = g_AnsiTable[i];
_ch = g_KeyTable[ch];
_c = _ch;
_ch = Shr(_ch, 1);
x |= _ch;
if (x == result) {
pSerialNumberString[m++] = ch;
goto _byte_4;
}
x = z;
}
_byte_4:
// -1, 6, 3-
x = 0;
result = pSerialNumber[n+3];
_c = Shl(_c, 8 - 1);
x |= _c;
z = x;
for (i = 0; i < 36; i++) {
ch = g_AnsiTable[i];
_ch = g_KeyTable[ch];
_ch = Shl(_ch, 8 - 6);
x |= _ch;
y = x;
for (j = 0; j < 36; j++) {
ch2 = g_AnsiTable[j];
_ch2 = g_KeyTable[ch2];
_c = _ch2;
_ch2 = Shr(_ch2, 3);
x |= _ch2;
if (x == result) {
pSerialNumberString[m++] = ch;
pSerialNumberString[m++] = ch2;
goto _byte_5;
}
x = y;
}
x = z;
}
_byte_5:
// -3, 0
x = 0;
result = pSerialNumber[n+4];
_c = Shl(_c, 8 - 3);
x |= _c;
z = x;
for (i = 0; i < 36; i++) {
ch = g_AnsiTable[ch];
_ch = g_KeyTable[i];
x |= _ch;
if (x == result) {
pSerialNumberString[m++] = ch;
goto _next_turn;
}
x = z;
}
_next_turn:
;
}/* end for */
}
// 生成注册字符表
VOID MakeValidCharTable() {
int i = 0;
CHAR ch = '=';
memset(g_KeyTable, 0xFF, 256);
do {
ch = g_ValidCharTable[i];
g_KeyTable[ch] = i;
i++;
} while (i < 0x20);
g_KeyTable[0x3D] = 0x20;//i
}
/*
* 感觉最后逆注册算法上算子组合的有很大可能碰不到用户名生成的HASH值
* 最后只有34种可能32个有效字符 + 0xFF + 0x20,但是可能有些路径上
* 只有34种单一的选择,至少我的KEYGEN能力到这里了。
* 哈希算法正确,注册算法正确,生表算法正确,最后的逆运算应该也没错,
* 不知道神人们是怎么弄出来的,多多向你们学习。
*/
int main() {
DWORD VolumeSerialNumber = 0;
DWORD dwMagicLen = 0;
DWORD dwTmp = 0;
CHAR UserName[__MAX_USERNAME_SIZE__ + 1] = {0};
CHAR SerialNumber[__MAX_SERIAL_NUMBER__ + 1] = {0};
CHAR Command[64] = {0};
int Len = 0;
PUCHAR pKeyArray = NULL;
PUCHAR pUserNameKeyString = NULL;
int i = 0;
//ShowSign();
printf("输入用户名(最长35个字节):");
fgets(Command, 64, stdin);
Len = strlen(Command);
Len--;
Command[Len] = '\0';
strcpy(UserName, Command);
// 获取C盘序列号
GetVolumeInformationA("C:\\", \
0, \
0, \
&VolumeSerialNumber, \
0, \
0, \
0, \
0);
// 通过长度获取值
dwMagicLen = (Len + 11) * 8;
dwMagicLen = Bswap(dwMagicLen);
// 开始设置表
memset(g_UserNameKeyTable, 0, __USERNAME_SERIAL_NUMBER_SIZE__);
memcpy(g_UserNameKeyTable + 0x00, "\x00\x20\x00\x00\x00\x00\x00\x00", 8);
memcpy(g_UserNameKeyTable + 0x08, "\xCA\xB1\xCA\xB1", 4);
memcpy(g_UserNameKeyTable + 0x0C, "\xBF\xCC\xBF\xCC", 4);
memcpy(g_UserNameKeyTable + 0x10, "\xBE\xD6\xB2\xBF", 4);
memcpy(g_UserNameKeyTable + 0x14, "\xB5\xD8\xC7\xF8", 4);
memcpy(g_UserNameKeyTable + 0x18, "\xCD\xBC\xC7\xEE", 4);
memcpy(g_UserNameKeyTable + 0x1C, UserName, Len);
memcpy(g_UserNameKeyTable + 0x1C + Len, &VolumeSerialNumber, 4);
memcpy(g_UserNameKeyTable + 0x1C + Len + 4, "Tencent", 7);
memcpy(g_UserNameKeyTable + 0x1C + Len + 4 + 7, "\x80\x00\x00\x00", 4);
memcpy(g_UserNameKeyTable + 0x58, &dwMagicLen, 4);
// 将这个数据传人哈希算法
pKeyArray = (g_UserNameKeyTable + 0x08);
pUserNameKeyString = (g_UserNameKeyTable + 0x1C);
HashIt(pKeyArray, pUserNameKeyString);
// 将得到的哈希值每个都经过一次翻转, 总共20个字节
for (i = 0; i < 5; i++) {
dwTmp = *((PDWORD)pKeyArray + i);
g_UserNameSerialNumber[i] = Bswap(dwTmp);
}
// 通过用户名的哈希值算出注册码
MakeValidCharTable();//生成有效字符表
ReverseSerialNumberGen((PUCHAR)g_UserNameSerialNumber, SerialNumber);
printf("Serial Number = %C%C%C%C%C%C%C%C-%C%C%C%C%C%C%C%C-%C%C%C%C%C%C%C%C-%C%C%C%C%C%C%C%C\r\n", \
SerialNumber[0], SerialNumber[1], SerialNumber[2], SerialNumber[3], \
SerialNumber[4], SerialNumber[5], SerialNumber[6], SerialNumber[7], \
SerialNumber[8], SerialNumber[9], SerialNumber[10], SerialNumber[11], \
SerialNumber[12], SerialNumber[13], SerialNumber[14], SerialNumber[15], \
SerialNumber[16], SerialNumber[17], SerialNumber[18], SerialNumber[19], \
SerialNumber[20], SerialNumber[21], SerialNumber[22], SerialNumber[23], \
SerialNumber[24], SerialNumber[25], SerialNumber[26], SerialNumber[27], \
SerialNumber[28], SerialNumber[29], SerialNumber[30], SerialNumber[31]);
//SerialNumberGen("FFFFFFFF-FFFFFFFF-FFFFFFFF-FFFFFFFF");
fgetc(stdin);
// 打印最终结果
return 0;
}