新手破解epubtopdf--算法跟踪
本帖最后由 lknight 于 2013-3-23 15:28 编辑【软件名称】: epubtopdf v2.0.4
【软件大小】: 4.79m
【下载地址】: http://www.epub-to-pdf.com/?soft
【加壳方式】: 无壳
【保护方式】: 序列号
【编写语言】: Microsoft Visual C++ 6.0
【使用工具】: PEiD,ollydbg
【操作平台】: win8
【详细过程】
这个软件是本身没啥太大用处,只是为了提高技术找的练习软件,是比较简单的那种,适合新手。废话不多说,下面开始正题了。
这个软件也可以直接用Universal Extractor解包,作为绿色软件使用的,这个软件给用户15次的试用次数,过了15次就变成下图的启动窗口
下面是破解完成后的破解效果图
下面我们就开始了,软件装好后,直接把15次试用全部试用玩,我们运行软件,随便输入用户名和注册码点击注册,会看到下面图中所示内容,再点击确定程序就推出了
上面图片中的expired就是关键的内容,我们OD载入程序搜索字符串,如下图
双击上图的字符串位置,来到下图的位置
在上图位置可以往上找可以跳过这一提示的跳转,发现上面有这样的跳转,那么我们就拉倒段首下F2断点,F9运行程序,程序断下来了,下图
我们一路F8看程序有什么变化,知道走到下图的call位置,程序状态变为run了,下图
我们在程序中随意输入的用户名和注册码,点击注册按钮,程序暂停了,下图
我们继续往下走F8,看看程序在下面的call中都做了什么,走到下面两个临近的一样的调用call我们看到他们是把用户名和注册码压栈了,下图
用户名和注册码入栈就说明这些信息可能要进行检测了,后面的call我们全都进去看看,进第一个call,下图
上图中我们看到,有两个CALL 0048285A,再次将用户名和注册码入栈了,那么,我们就直接看之后的那个call干了什么吧,跟进CALL 0040EAD0,下图
上图中,我们还是F8一步一步分析,CALL 0040ED30什么都没做,我就不截图了,接着的那个call,CALL 0047C6E8,是检测输入的注册码中是否有链接符“-”的,我们可以跟进看一下
上图中的CALL 0047C6F6,跟进
上图中的CALL 0042CB56,跟进
上图中对连接符的检测分析完了之后的代码没有什么重要的,我们一直返回到CALL 0047C6E8下一行,继续分析,不重要的call我就不跟进了
我这里只分析了跳转实现后的内容,长度不等于16的情况我就不分析了,有兴趣的朋友自己分析吧,下图,是跳转实现后的位置
上面这段代码就是把输入的注册码分成8组,每组两个字符,并计算每组字符在“N3NANBN4NCNDNHNJNKNMP3PAPBP4PCPDPHPJPKPMA3ANABA4ACADAHAJAKAMH3HAHBH4HCHDHNHJHKHMJ3JAJBJ4JCJDJHJNJKJMK3KAKBK4KCKDKHKJKNKMB3BABNB4”
这个表中的位置,然后把每组字符的位置数值右移1位,存放在0018A06C地址,程序运行到上图中最后一行0040EBBF位置是,我们可以在命令框中输入db 0018A06C看到下图中读取输入字符在上表中的位置
输入的注册码中的所有字符位置都得到后,程序就到了下面的位置,就是最终检验注册码是否正确的位置
上图中的CALL 0040ED70,里面计算过程不复杂,我就不详细说了,其实,可以在程序执行到0040EBFE的位置的时候修改0018A06C出保存的1-4组字符(也就是前八个)位置,让位置的数值等于
上面两个call算出来的数值,然后运行就可以了,当然你也可以修改后面的跳转,当然这是爆破,下面我详细说下这个软件的注册机制,并给出c语言编写的注册机。
上面的分析基本分析完了,下面我总结一下这个软件的注册机制:
首先,由上面的分析可以知道,注册码的内容必须有“N3NANBN4NCNDNHNJNKNMP3PAPBP4PCPDPHPJPKPMA3ANABA4ACADAHAJAKAMH3HAHBH4HCHDHNHJHKHMJ3JAJBJ4JCJDJHJNJKJMK3KAKBK4KCKDKHKJKNKMB3BABNB4”中的内容组成, 当然了,这是注册码长度为16的情况(长度不为16的情况各位看官自己玩玩吧),从分析中我们也可以看出,用户名没有参与注册码运算,同样连接符“-”也是可有可无的,同样,连接符“-”的位置也是可以随意调整的, 最终计算过程没有用到连接符。
下面就是算法的具体过程了,首先我们假设输入的注册码是:N3NANBN4-NCNDNHNJ(连接符随意加的方便看,不加也行),这样我们会在内存0018A06C的位置看到这样的16进制数据0001020304050607(注意这是07是高位), 接着把5、6组字符的位置信息取出,组成一个16位的数据及0x0504,这个数据为输入调用CALL 0040ED70(本人水平有限,这个函数只能用汇编了,用c没有搞定。。。汗一个。。。),计算得到一个16位数据,假设这个数据为 0xXXYY,那么XX就对应于01,YY就对应于00,如果都像等的话,就说明这部分注册码是正确的;同样取出7、8组字符位置数值组成16位数据0x0706,这个数据为输入,调用CALL 0040ED70,同样得到一个16位数据结果,假设这个 结果是0xZZWW,那么,ZZ对应于07,WW对应于06,如果都像等的话就说明这部分注册码是正确的。这个软件的注册码计算过程就是这样,但是需要注意的是,输入的注册码中有可能某一组字符可能在表中出现了两次,那么就得 注意了,这样可能造成计算得到的位置和读取的位置错位的现象,我的做法是只用没有重复的字符串。。。
注册机源码(VC 6.0编译通过)keygen.cpp:
#include "windows.h"
#include "stdio.h"
#include "wchar.h"
#include <time.h>
int GenResult(int input);
int main()
{
WCHAR table[] = L"N3NANBN4NCNDNHNJNKNMP3PAPBP4PCPDPHPJPKPMA3ANABA4ACADAHAJAKAMH3HAHBH4HCHDHNHJHKHMJ3JAJBJ4JCJDJHJNJKJM";
int result_tmp = 1,tmp1,tmp2;
int pos={0};
int tablelen = wcslen(table);
WCHAR wstr1=L"";
WCHAR wstr2=L"";
WCHAR wstr3=L"";
WCHAR wstr4=L"";
WCHAR wstr5=L"";
WCHAR wstr6=L"";
WCHAR wstr7=L"";
WCHAR wstr8=L"";
srand((unsigned)time(NULL));
for(int i=4; i<8; i+=2)
{
for(;;)
{
pos = rand()%(tablelen-1);
pos = rand()%(tablelen-1);
tmp1 = pos>>1;
tmp2 = pos>>1;
result_tmp = GenResult(tmp1 | (tmp2<<8));
if(i==4)
{
if (tmp1>0x31 || tmp2>0x31)
{
continue;
}
else
{
pos = (result_tmp & 0x0FF)<<1;
pos = ((result_tmp>>8) & 0x0FF)<<1;
wstr1=table];
wstr1=table+1];
wstr2=table];
wstr2=table+1];
wstr5=table];
wstr5=table+1];
wstr6=table];
wstr6=table+1];
if ((wcsstr(table,wstr1)-&table] <0)|| (wcsstr(table,wstr2) - &table]<0) ||
(wcsstr(table,wstr5)-&table] <0)|| (wcsstr(table,wstr6) - &table]<0))
{
continue;
}
else
{
break;
}
}
}
else
{
if (tmp1>0x31 || tmp2>0x31)
{
continue;
}
else
{
pos = (result_tmp & 0x0FF)<<1;
pos = ((result_tmp>>8) & 0x0FF)<<1;
wstr3=table];
wstr3=table+1];
wstr4=table];
wstr4=table+1];
wstr7=table];
wstr7=table+1];
wstr8=table];
wstr8=table+1];
if ((wcsstr(table,wstr3)-&table] <0)|| (wcsstr(table,wstr4) - &table]<0) ||
(wcsstr(table,wstr7)-&table] <0)|| (wcsstr(table,wstr8) - &table]<0))
{
continue;
}
else
{
break;
}
}
}
}
}
wprintf(L"%s%s%s%s%s%s%s%s\n",wstr1,wstr2,wstr3,wstr4,wstr5,wstr6,wstr7,wstr8);
return 0;
}
int GenResult(int input)
{
int re;
_asm
{
pushad
mov ecx,input
mov ebx,0x351D
mov esi,0x5A39
mov edi,0x1
label1: test bl,0x1
jnz label3
label2: mov eax,ecx
xor edx,edx
imul eax,ecx
div esi
shr ebx,1
test bl,0x1
mov ecx,edx
je label2
label3: mov eax,edi
xor edx,edx
imul eax,ecx
div esi
dec ebx
mov edi,edx
jnz label1
mov eax,edi
mov re,eax
popad
}
return re;
}
第一次写算法跟踪,写的比较乱,高手勿笑。。。
by lknight
--------------------------------------------------------------------------------
【版权声明】: 转载请注明作者并保持文章的完整, 谢谢!
2013年03月23日 14:55:23
写的不错,希望继续发布好破文,
吾爱破解论坛有你更精彩。 不错,支持下 挖槽,那个算法。。无语了 看看 学习一下 高手,学习一下哈 不错 很详细值得学习一下~~谢谢分享~ 膜拜,学习下 看不懂啊,不会编程
顶下帖子了。新手来照着一部一部的做,会得到 成就感的。