标 题: 【原创】ChinaZip10.8软件破解(附代码)
作 者: piratelzs
时 间: 2008-06-18
【文章标题】:【原创】ChinaZip10.8软件破解(附代码)
【文章作者】: piratelzs
【作者邮箱】: piratelzs@163.com
【作者QQ号】: 15269083
【软件名称】: ChinaZip10.8
【使用工具】: ollydbg
【操作平台】: Windows XP SP2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
在看雪潜水学习有半年时间了,受益于其中博大精深的破解和安全技术,饮水思源,也把我的破解路程向大家共享一下,也给想了解破技术和刚接触破解技术的雏鸟实例和材料;回想自己的破解之路,也是在看雪的学院了一点一滴的积累和成长,这是我破解的第一个软件,菜菜的,看了《加密解密》中破解ChinaZip5.4中的实例,自己也想练手,结果一找,只找到ChinaZip10.8的版本。由于是几个月前的东东乐,软件已经删除,还好逆向的C++加密代码还在简单的介绍一下他的验证算法,没有加壳,也很适合于学习工具使用的新手。
一、得到输入的用户名和注册码
用户名name和注册码key比较的原理一般是f(name) == f1(key)验证的关系,但是本软件运用的办法比较简单,它省略了f1()的函数,直接采用了:f(name) == key的模式,所有在逆向过程中可以直接看到验证码的结果,但是作为最终破解,当然要以写注册机位目标,所以将f(name)这个函数的过程跟踪翻译成C++程序。
void main()
{
szName[0] = '\0';
printf("Input name:\n");
scanf("%s", szName);
unsigned nLen = (unsigned)strlen(szName);
if (nLen > 25 || nLen < 3)
{
printf("user name should with 3 ~ 19 words.\n");
return;
}
makekey();
}
int makekey() // 00405A30
{
unsigned nLength = (unsigned)strlen(szName);
unsigned i;
char number[128];
char szCode[128];
char* p = number;
for (i = 0; i < 7 && i < nLength; i ++)
{
unsigned a = (unsigned)szName[nLength - 1 - i];
unsigned rt = step1(a, 0);
unsigned b = sprintf_s(p, (size_t)nLength, "%u", rt);
p += b;
}
unsigned code = step2(number, 0);
sprintf(szCode, "%x", code);
ZeroFill(szKey, szCode, 12);
printf("%s\n", szKey);
return 0;
}
二、使用用户名生成key值
f(name)主要有两个步骤:我把它写成两个函数step1(unsigned& a, unsigned b)和step2(unsigned& a, unsigned b)我们先来看看step1,连续7次将用户名调用step1使用户名name变成一段数字的特征码,都是做相关轮转和异或的操作。
unsigned step1(unsigned& a, unsigned b)
{
int edx = 3; //
int j, nSeedTemp = nSeed;
unsigned edi = 0;
unsigned esi = 0;
unsigned nSeedTemp = nSeed; // eax
unsigned nEdx_T = edx;
unsigned ebp = 0;
unsigned nFlag;
for (j = 0; j < (unsigned)0x40; j ++)
{
nFlag = _SHL(nSeedTemp);
nFlag = _RCL(nEdx_T, nFlag); // edx
nFlag = _RCL(esi, nFlag);
nFlag = _RCL(edi, nFlag);
if (edi < ebp)
continue;
else if (edi == ebp)
{
if (esi < a)
continue;
}
esi -= a;
edi -= ebp;
if (esi < 0)
edi --;
nSeedTemp += 1;
}
return esi;
}
然后用step1产生的特征码生成最终的验证码key。加密的方法如step2()
unsigned step2( char* str, unsigned b ) // 产生中间代码,最后要进行对齐。
{
int i;
int t_C = 0;
int t_8 = 0x12F;
int t_14 = 0;
unsigned code = 0;
if (str == NULL)
return 0;
char* p1 = str;
while (*p1 < 0x20)
{
p1 ++;
}
if (*p1 == 0x2D)
{
p1 ++;
}
else if (*p1 == 0x2B)
p1 ++;
// 前面有一些检测,但是我们暂时不管。
str = p1;
int nLength = (int)strlen(str);
for (i = 0; i < nLength; i ++) // 进行字符串比较。
{
unsigned char a = (unsigned char)str[i];
unsigned char c = a;
a += 0xD0;
if (a < 0x0A)
int adfidna = 1; // 异常事情;暂时不考虑
a -= 0x0A;
c -= 0x30;
// 这一块尽量不要发生
if (t_C != 0)
{
if (t_8 < 0)
return 0;
}
else if (t_C < 0)
return 0;
code = code * (t_14 + 0xA);
code += (unsigned)c;
}
return code;
}
三个辅助函数介绍:
unsigned _RCL( unsigned& val, unsigned nFlag )
{
int a = (int)(0x80000000 & val);
int b = (a == 0x80000000)? 1: 0;
val *= 2;
val += nFlag;
return b;
}
unsigned _SHL( unsigned& val )
{
int a = (int)(0x80000000 & val);
int b = (a == 0x80000000)? 1: 0;
val *= 2;
return b;
}
void ZeroFill( char* base, char* source, unsigned int nSize )
{
if (!base || !source)
return;
*base = '\0';
int a = (int)strlen(base);
int b = (int)strlen(source);
int c = nSize - b;
while (c > 0)
{
strcat(base, "0");
c --;
}
strcat(base, source);
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)