[原创]DcdComposer(1.01版)注册框的拦截与注册算法原理
发表于:
2006-11-28 22:26
7541
[原创]DcdComposer(1.01版)注册框的拦截与注册算法原理
本人也只是一个初学者,为了对初学者有所帮助,文章的语言可能有点?嗦。请高手指教!
DvdComposer是一款制作DVD视频光盘的较好的软件,可以达到专业的DVD标准。它目前没有中文版,但可用eXeScope对其目录下的DvdCompLOC.dll字符串汉化,就完成了软件完全汉化的目的。英文不太好的用户很难完全发挥其功能。半年前在一本发行量很大的电脑杂志上看见有人介绍这个软件,他把“wizard”(向导)中的“Generate Project and Start Building DVD”解释为“制作并刻录”,其实该软件没有刻录功能,其本意是生成DVD方案(保存你的制作设计)并开始制作(制作时间很长),制作其实是生成刻录文件,最后还得要Nero来该录。好了扯远了,回归主题。
声明:以下内容完全是研究和学习软件技术,若被他人利用,责任自负!
半年前我发现了这款软件并喜欢了它,我企图获取它的注册码但没有成功,我只好将其爆破并汉化。爆破其实很简单:将00441BFA的call 0070C03E 改为nop ……nop,并将je改为jmp,再将0044C133的je 0044c1B0改为jnz或jmp就可以了。我在这里只想告诉软件作者花那么多的精力去设计注册算法,不如在防“爆破”上下点功夫。本软件的特点是:爆破容易,注册太难!
1.拦截DcdComposer注册框的困惑
开始我用OllDebug跟进所有出现注册对话框的Call,最后来到一个消息循环过程,无论怎样按住F8不放,都不出现注册框,按下F9,则弹出了注册框但却失去了与OD的联系。无论怎样反复注册和弹出注册码错误的消息,都不会重返OD。后用Spy.exe软件弄清了注册框是#32770类型的DialogBoxParamW对话框,用SoftICE拦截DialogBoxParamW、DialogBoxParamA或MessageBoxW居然毫无反映!用尽了所有工具仍然查不到注册框是在什么位置运行,实在是困惑了半年!甚至动摇了我(业余的)学习软件的信心。
前不久我突然想到用菜单ID跟踪注册框,忙用eXeScope查到注册菜单ID=3A6,在OD中查找所有case分支中的3A6所在地一路跟踪,最后还是进入一个消息循环OD不能自拔,但我却恍然大悟,完全改变了思路就有了后面的结果。
分析:
(1)该软件调用DialogBoxParamW函数不是在程序中直接call(调用),而是发消息,所以OD总是进入消息循环。本软件要进入对话框过程必须拦截windows消息。
(2)在OD监控下运行F8,程序运行很慢,大多的windows消息都会丢失,所以不会弹出对话框。
(3)我发现若OD的所有交叉调用中有DialogBoxParam函数,用SoftICE设断可以拦截,若OD中不出现则SoftICE基本上都不能拦截。我猜想:因程序中没有DialogBoxParam函数名,运行加载时windows不会提交给该应用程序关于DialogBoxParam函数的地址,这时SoftICE不知道该在什么地址设断,故不能成功拦截。同样在给程序的地址设断时,SoftICE也经常失败,其原因是windows的页面交换机制使该地址所在的页面还没有提交给内存,SoftICE不能给一个不存在的内存设断,所以失败。这只是我的猜测,我不知道SoftICE是怎么工作的,请高手指教。
2.在消息驱动机制中过滤有用信息
原来DcdComposer注册框是用消息来驱动的,OD是不能跟踪消息的。急忙打开SoftICE、Spy.exe,并让DvdComposer弹出对话框,用Spy取得对话框句柄,在SoftICE中用命令HWND获取对话框的入口地址(在Spy.exe中也有WinProc,但它指向的是USER32,不能用)。如果你在获取的入口地址设断,程序将无法运行,原因是窗口(即对话框)过程有大量的消息进入,若所有的消息都靠你手动放行,程序还能正常么?
可在该过程的00708456处设计一个消息过滤器,让对我无用的消息安全通过。该地址的代码是:
0070844B FF75 14 __________push dword ptr [ebp+14] ;消息中的lParam
0070844E FF75 10 __________push dword ptr [ebp+10] ;消息中的wParam
00708451 FF75 0C __________push dword ptr [ebp+C] ;消息中的Msg
00708454 56 _______________push esi ;对话框句柄
00708455 50 _______________push eax
00708456 E8 DFFEFFFF ______call 0070833A
0070845B EB 10 ____________jmp short 0070846D
将00708456的call 0070833A改为jmp 0074DC10(跳到程序空白字节处),加入下列代码:
消息过滤器代码:
0074DC10 817D 0C110100000 _____cmp dword ptr [ebp+C], 111 ;不是WM_COMMAND则跳
0074DC17 75 12 ________________jnz short 0074DC2B
0074DC19 50 ___________________push eax
0074DC1A 8B45 14 ______________mov eax, [ebp+14] ;不是子窗口来的命令则跳
0074DC1D 83F8 00 ______________cmp eax, 0
0074DC20 74 08 ________________je short 0074DC2A
0074DC22 25 FFFF0000 __________and eax, 0FFFF ;大量高位非0的lParam则跳
0074DC27 74 01 ________________je short 0074DC2A ;是子窗口来的命令则断下
0074DC29 90 ___________________nop ;在此处设断
0074DC2A 58 ___________________pop eax
0074DC2B E8 0AA7FBFF __________call 0070833A
0074DC30 E9 26A8FBFF __________jmp 0070845B
OD中,先让程序弹出注册对话框,输入用户名和序列号后再在0074DC29设断(否则每在编辑框中输入一个字符都会中断一次),然后按下OK按钮。乖乖,狐狸终于被逮住了!一路单步跟进,来到了注册码计算的地方:004C51d0―004C5AB2(长达840行的代码!)。
3.注册码算法原理
先别忙看计算过程,840行的计算让你非晕死不可!看看是怎样处理用户名和假注册码的?但查找了相关的代码都找不到单独处理用户名或假注册码的地方,到是频频出现“注册码+固定字串+用户名”的字串,如输入用户名:ComputeUser,注册码:01234567-89abcdef-f9876543-210abcde,则参与计算的字串是“cdeff987000000450123DvdComposeriaMnOTaStHINKaSyOUdRUNKComputeUser”。计算过程中首先调用的是四个常数:A=01234567,B=89abcdef,C=fedcba98,D=76543210。我首先就肯定了计算是MD5算法,但是我错了!
后来一想,问题就更大了,注册码和用户名同时参与MD5计算,计算结果和谁比较?软件作者把用户名和真注册码用当前程序中的算法生成一个固定的比较字串,软件作者能设计出这样的注册机吗?如果用数学表示应该是:
F(用户名,真注册码)=正确的字串,而 F(用户名,假注册码)=不正确的字串
按数学语言,前者是“多对一”函数(即不同的用户都生成相同的字串),后者是“一对一”函数,这是不可能的。因此完全不必去分析它的计算原理,只须看它怎样处理计算结果。
在004C51D0设断,跟踪发现计算将连接的字串分成两段,前64字节和后64字节(不足添0),前64字节与前面的A、B、C、D常数运算,将结果取代ABCD,再把后64字节与新ABCD运算并再次取代ABCD,最后A|B|C|D=eax(|=or),将结果eax与esi比较,正确则注册成功。
读者可能对以上叙述设有兴趣,但破解的关键也到了。
首先关心的是esi中的数据,它与用户名没有关系,但与假注册码有关,如果注册码全是1,它也全是1(esi只用了6位),反正注册码设有用到的数字,它也不用,我把esi的6个数取代字串中的那6个0,把顺序还原后,竟然是假注册码完整的前20位!原来你向软件注册时,比较码也连同注册码一同给你发来了。这样,注册原理就清楚了。
注册时程序取出注册码的第7―12位作为比较码,用0填充取走的数,截取前20位并交换假码的顺序再连接固定字串和用户名,计算后和比较码比较,完成注册过程。
4. 注册机的实现思路
程序要求注册码不得少于20位,多余的被忽略,用户名长度不受限制,总长度大于128位的部分被忽略。注册机实现思路是:
(1)移植程序中004C51d0―004C5AB2的代码到注册机(并不轻松);
(2)随机生成20位以上的数字,分组符“-”位置任意设定但不占位;
(3)将第7―12位的数用0取代,并交换顺序连接字串和用户名,如:
随机生成01234567-89abcdef-f9876543-210abcde,载取前20位01234567-89abcdef-f987,用0取代6789ab并交换顺序成:cdeff987000000450123
连接字串DvdComposeriaMnOTaStHINKaSyOUdRUNK和用户名ComputeUser,生成长串cdeff987000000450123DvdComposeriaMnOTaStHINKaSyOUdRUNKComputeUser
(3)按前面说的算法原理,将字串分成64位长度两段,分别带入计算过程,取出计算结果;如,按上面的随机数和用户名就生成:34FEF9BE,取后6位置换随机数的第7―12位为:012345FE-F9BEcdef-f9876543-210abcde,这就是一个可用的注册码(大小写没有关系)。
说明:如果认为把程序在比较注册码的地方改为jmp,不管注册码是否正确都转跳,不是很好和爆破方法吗?如果这样,本程序一开始就会崩溃,原因是该计算和比较是一个公用通道,程序初始化时将对它附带的文件进行完整性检验,否则通过几个小时辛苦生成的DVD文件不能使用,则该软件公司就会关门了。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课