一直没敢踏入写KEYGEN的门槛,原先一直停留在PATCH的层次,前几天突然想练练,于是开始找CM下手.第一个CM是不知名的某虾写的,有点简单,发了也没意思,第二个是去年金山逆向分析挑战赛的第一题,搞了总计6,7个小时吧,总算是折腾出来了,然后深感自己功力之薄弱,哎...
不过正如KANXUE说的,逆向分析,破解这事,有它的乐趣,能满足人的好奇心里...呵呵...
直接贴代码了,代码里包括了CM的验证流程和KEYGEN的计算流程,写的非常烂,从它能正常计算KEY开始我就没改过,呵呵,算号过程应该可以更优化.
#include <stdio.h>
#include <string.h>
#include <memory.h>
char pre_state[10] = {0};
char fin_state[10] = {0};
char key[0x1000] = {0};
char tmp_key[0x1000] = {0};
int key_len = 0;
int tmp_key_len = 0;
int get_name_hash(char* name)
{
size_t name_len = strlen(name);
int name_hash = 0x13572468;
int tmp_1 = 0;
int tmp_2 = 0;
for (size_t i = 0; i < name_len; i++)
{
tmp_1 = (name[i] + name_hash)*0x3721273 + 0x24681357;
tmp_2 = tmp_1;
name_hash = (tmp_2 << 0x19) | (tmp_1 >> 7);
}
return name_hash;
}
void init_state(int name_hash)
{
__asm
{
mov edi, 1
mov ebx, 1
lable1:
mov eax, name_hash
mov ecx, edi
shr eax, cl
and al, bl
mov pre_state[edi], al
inc edi
cmp edi, 9
jl lable1
}
pre_state[9] = 1;
}
int get_edx(int idx, int name_hash)
{
int the_edx = 0;
__asm
{
mov eax, idx
push 0x1F
cdq
pop ecx
idiv ecx
mov eax, name_hash
push 0x0A
mov ecx, edx
xor edx, edx
shr eax, cl
pop ecx
div ecx
mov the_edx, edx
}
return the_edx;
}
int check_key(int name_hash)
{
int the_edx;
for (int i = 0; i < key_len; i++)
{
the_edx = get_edx(i, name_hash);
the_edx = the_edx + key[i] - 0x30;
the_edx = the_edx % 10;
if (the_edx == 1)
{
pre_state[the_edx] ^= 1;
}
else
{
if (pre_state[the_edx - 1] != 1)
{
return 0;
}
if (the_edx < 3)
{
pre_state[the_edx] ^= 1;
}
else
{
for (int j = 1; j <= the_edx - 2; j++)
{
if (pre_state[j] == 1)
{
return 0;
}
}
pre_state[the_edx] ^= 1;
}
}
}
for (int i = 1; i < 10; i++)
{
if (pre_state[i] == 1)
{
return 0;
}
}
return 1;
}
void recursion_compute(char* state, int idx, int flag)
{
if (idx == 1)
{
if (state[1] != flag)
{
state[1] ^= 1;
tmp_key[tmp_key_len] = 1;
tmp_key_len++;
}
}
else if (idx == 2)
{
if (state[2] != flag)
{
recursion_compute(state, 1, 1);
state[2] ^= 1;
tmp_key[tmp_key_len] = 2;
tmp_key_len++;
recursion_compute(state, 1, 0);
}
}
else
{
if (state[idx] != flag)
{
for (int j = idx - 2; j >= 1; j--)
{
recursion_compute(state, j, 0);
}
recursion_compute(state, idx - 1, 1);
state[idx] ^= 1;
tmp_key[tmp_key_len] = idx;
tmp_key_len++;
recursion_compute(state, idx - 1, 0);
}
}
}
void get_key(int name_hash)
{
recursion_compute(fin_state, 9, 0);
int the_edx;
for (int i = 0; i < tmp_key_len; i++)
{
the_edx = get_edx(i, name_hash);
tmp_key[i] += 10;
tmp_key[i] -= the_edx;
tmp_key[i] %= 10;
key[i] = tmp_key[i] + '0';
}
key_len = tmp_key_len;
}
int main()
{
int name_hash = get_name_hash("abcdeabcdeabcd");
init_state(name_hash);
memcpy(fin_state, pre_state, 10);
get_key(name_hash);
printf("%s\n", key);
int check_result = check_key(name_hash);
if (check_result == 1)
{
printf("check ok\n");
}
else
{
printf("check fail\n");
}
return 1;
}
代码冗长不优美,恩,各方面功力还有待大大提高...
过几天再弄一个KEYGEN,再发,希望届时能再有些须提高.
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!