XX分区数据恢复软件破解过程,注册算法追踪
本帖最后由 zjh16529 于 2019-6-6 18:47 编辑待破解软件:D-RecoveryForExfat
破解工具:OD(调试用),DELPHI7(写测试用例)
===================================华丽的分割线====================================
D-RecoveryForExfat这个软件,运行起来以后,首先会弹出注册窗口请你注册,不注册的话,关于页面会显示未注册的提示。
注册码如果输入不正确的话,会有提示对话框。
有这个提示对话框,相对而言使用OD会更方便一些。
首先还是检查一下是否有壳。
显示是C++的程序,没有壳,那就应该好办了。使用OD加载,查找字符串:
很轻易地就定位到字符串了,双击打开代码部分:
好,OD已经加载了我们要破解的程序了,我的破解步骤也将慢慢展开。
因为这个软件耗费了我两天的假期时间,都是心血啊。
第一部分猜测
字符串对应的就是提示注册错误的部分,走到这里应该已经判断完注册码了,我们往上看。
从这里的代码可以分析出来,注册码的长度必须是0x1C,也就是28个字节长度。
我们在00404D32处,按下F2下断点,然后Ctrl+F2重新运行软件。在注册码框里,输入28个字节的字符,输入“1234567890ABCDEFGHIJKLMNOPQR”。点击注册按钮后,OD截获中断
注意一下右下角的堆栈区,有两个字符串比较醒目
BV2310db828-90c10a0BVXOHRADDSIK ---暂时记做CodeA
和
LMTgGa8779yDQvIH ---暂时记做CodeB
F8单步跟踪,有两段循环代码,你就会发现,程序把我们刚才输入的那一长串注册码处理成了两部分,“24680BDFHJLN”和“13579ACEGIKM”。没错,奇数位和偶数位分开。
再继续F8单步跟踪,走到00404DE2的时候,不要再走了。
这里是个CALL,后面跟一个test eax, eax,再后面就是注册失败的提示。根据经验判断,这个CALL是去校验注册码的。
我们先不着急跟进去,看一下现场,EAX里是“13579ACEGIKMOPQR”,看出来了没有,就是刚才我们输入的注册码的1、3、5……23位,再加上注册码的后四位。然后堆栈里还有一个同样长度的字符串,就是刚才那个CodeB。这个CALL是不是就是比较这两个字符串的呢?
试一下,CTRL+F2重新运行,把我们刚才输入的注册码1234567890ABCDEFGHIJKLMNOPQR,对应的位置换成LMTgGa8779yDQvIH,也就是L2M4T6g8G0aB8D7F7H9JyLDNQvIH,再注册一遍。呃,注册成功了……注册成功了……竟然注册成功了?
我靠,这么简单,你逗我玩啊?
我还没见到BOSS呢,我还没拿到装备呢,就这么结束了?好不甘心啊。可是,等等,那个LMTgGa8779yDQvIH是怎么来的?得研究明白才行啊!
第二部分 跟踪
从刚才输入的注册码就可以看出来,实际上24680BDFHJLN那些偶数位其实根本没用上。随便输点儿什么都行。那接下来我们就要去研究LMTgGa8779yDQvIH是怎么来的了。
这里就跟大家说句抱歉了,因为我也是初学,OD用的不太熟,所以我只能在出现这个码的地址上下硬件断点,这样一点儿一点儿,终于找到了下面的这段代码:
004048FA|> \8D47 1C lea eax,dword ptr ds:
004048FD|.25 7F000080 and eax,0x8000007F
00404902|.79 05 jns short D-Recove.00404909
00404904|.48 dec eax
00404905|.83C8 80 or eax,-0x80
00404908|.40 inc eax
00404909|>8D4F 1D lea ecx,dword ptr ds:
0040490C|.81E1 7F000080 and ecx,0x8000007F
00404912|.884424 30 mov byte ptr ss:,al
00404916|.79 05 jns short D-Recove.0040491D
00404918|.49 dec ecx
00404919|.83C9 80 or ecx,-0x80
0040491C|.41 inc ecx
0040491D|>8D47 24 lea eax,dword ptr ds:
00404920|.25 7F000080 and eax,0x8000007F
00404925|.884C24 31 mov byte ptr ss:,cl
00404929|.79 05 jns short D-Recove.00404930
0040492B|.48 dec eax
0040492C|.83C8 80 or eax,-0x80
0040492F|.40 inc eax
00404930|>8D4F 37 lea ecx,dword ptr ds:
00404933|.81E1 7F000080 and ecx,0x8000007F
00404939|.884424 32 mov byte ptr ss:,al
0040493D|.79 05 jns short D-Recove.00404944
0040493F|.49 dec ecx
00404940|.83C9 80 or ecx,-0x80
00404943|.41 inc ecx
00404944|>83C7 5C add edi,0x5C
00404947|.8BC7 mov eax,edi
00404949|.25 7F000080 and eax,0x8000007F
0040494E|.884C24 33 mov byte ptr ss:,cl
00404952|.79 05 jns short D-Recove.00404959
00404954|.48 dec eax
00404955|.83C8 80 or eax,-0x80
00404958|.40 inc eax
00404959|>8D8B 9A000000 lea ecx,dword ptr ds:
0040495F|.81E1 7F000080 and ecx,0x8000007F
00404965|.884424 34 mov byte ptr ss:,al
00404969|.79 05 jns short D-Recove.00404970
0040496B|.49 dec ecx
0040496C|.83C9 80 or ecx,-0x80
0040496F|.41 inc ecx
00404970|>8D83 F5000000 lea eax,dword ptr ds:
00404976|.25 7F000080 and eax,0x8000007F
0040497B|.884C24 35 mov byte ptr ss:,cl
0040497F|.79 05 jns short D-Recove.00404986
00404981|.48 dec eax
00404982|.83C8 80 or eax,-0x80
00404985|.40 inc eax
00404986|>8D8B 74010000 lea ecx,dword ptr ds:
0040498C|.81E1 7F000080 and ecx,0x8000007F
00404992|.884424 36 mov byte ptr ss:,al
00404996|.79 05 jns short D-Recove.0040499D
00404998|.49 dec ecx
00404999|.83C9 80 or ecx,-0x80
0040499C|.41 inc ecx
0040499D|>8D83 1D020000 lea eax,dword ptr ds:
004049A3|.25 7F000080 and eax,0x8000007F
004049A8|.884C24 37 mov byte ptr ss:,cl
004049AC|.79 05 jns short D-Recove.004049B3
004049AE|.48 dec eax
004049AF|.83C8 80 or eax,-0x80
004049B2|.40 inc eax
004049B3|>81C3 F6020000 add ebx,0x2F6
004049B9|.81E3 7F000080 and ebx,0x8000007F
004049BF|.884424 38 mov byte ptr ss:,al
004049C3|.79 05 jns short D-Recove.004049CA
004049C5|.4B dec ebx
004049C6|.83CB 80 or ebx,-0x80
004049C9|.43 inc ebx
004049CA|>8D8A 06040000 lea ecx,dword ptr ds:
004049D0|.81E1 7F000080 and ecx,0x8000007F
004049D6|.885C24 39 mov byte ptr ss:,bl
004049DA|.79 05 jns short D-Recove.004049E1
004049DC|.49 dec ecx
004049DD|.83C9 80 or ecx,-0x80
004049E0|.41 inc ecx
004049E1|>8D82 51050000 lea eax,dword ptr ds:
004049E7|.25 7F000080 and eax,0x8000007F
004049EC|.884C24 3A mov byte ptr ss:,cl
004049F0|.79 05 jns short D-Recove.004049F7
004049F2|.48 dec eax
004049F3|.83C8 80 or eax,-0x80
004049F6|.40 inc eax
004049F7|>8D8A DE060000 lea ecx,dword ptr ds:
004049FD|.81E1 7F000080 and ecx,0x8000007F
00404A03|.884424 3B mov byte ptr ss:,al
00404A07|.79 05 jns short D-Recove.00404A0E
00404A09|.49 dec ecx
00404A0A|.83C9 80 or ecx,-0x80
00404A0D|.41 inc ecx
00404A0E|>8D82 B3080000 lea eax,dword ptr ds:
00404A14|.25 7F000080 and eax,0x8000007F
00404A19|.884C24 3C mov byte ptr ss:,cl
00404A1D|.79 05 jns short D-Recove.00404A24
00404A1F|.48 dec eax
00404A20|.83C8 80 or eax,-0x80
00404A23|.40 inc eax
00404A24|>8D8A D60A0000 lea ecx,dword ptr ds:
00404A2A|.81E1 7F000080 and ecx,0x8000007F
00404A30|.884424 3D mov byte ptr ss:,al
00404A34|.79 05 jns short D-Recove.00404A3B
00404A36|.49 dec ecx
00404A37|.83C9 80 or ecx,-0x80
00404A3A|.41 inc ecx
00404A3B|>81C2 4D0D0000 add edx,0xD4D
00404A41|.81E2 7F000080 and edx,0x8000007F
00404A47|.884C24 3E mov byte ptr ss:,cl
00404A4B|.79 05 jns short D-Recove.00404A52
00404A4D|.4A dec edx
00404A4E|.83CA 80 or edx,-0x80
00404A51|.42 inc edx
00404A52|>885424 3F mov byte ptr ss:,dl
00404A56|.33D2 xor edx,edx
00404A58|.33C9 xor ecx,ecx
00404A5A|.8D9B 00000000 lea ebx,dword ptr ds:
00404A60|>8A4414 30 /mov al,byte ptr ss:
00404A64|.3C 30 |cmp al,0x30
00404A66|.7C 04 |jl short D-Recove.00404A6C
00404A68|.3C 39 |cmp al,0x39
00404A6A|.7E 29 |jle short D-Recove.00404A95
00404A6C|>3C 41 |cmp al,0x41
00404A6E|.7C 04 |jl short D-Recove.00404A74
00404A70|.3C 5A |cmp al,0x5A
00404A72|.7E 21 |jle short D-Recove.00404A95
00404A74|>3C 61 |cmp al,0x61
00404A76|.7C 04 |jl short D-Recove.00404A7C
00404A78|.3C 7A |cmp al,0x7A
00404A7A|.7E 19 |jle short D-Recove.00404A95
00404A7C|>0FBEC0 |movsx eax,al
00404A7F|.8D4408 1F |lea eax,dword ptr ds:
00404A83|.25 7F000080 |and eax,0x8000007F
00404A88|.79 05 |jns short D-Recove.00404A8F
00404A8A|.48 |dec eax
00404A8B|.83C8 80 |or eax,-0x80
00404A8E|.40 |inc eax
00404A8F|>884414 30 |mov byte ptr ss:,al
00404A93|.^ EB CB |jmp short D-Recove.00404A60
00404A95|>83C1 07 |add ecx,0x7
00404A98|.83C2 01 |add edx,0x1
00404A9B|.83F9 70 |cmp ecx,0x70
00404A9E|.^ 7C C0 \jl short D-Recove.00404A60
00404AA0|.8D4C24 30 lea ecx,dword ptr ss:
这段代码的意思就是从EDI里取值,做了一番处理后形成了码的前5位,又从EBX取值处理后形成码的中间5位,最后从EDX里取值得出码的最后6位。
OK,到现在,CodeB码是怎么生成的已经知道了,但新问题又来了——EDI、EBX、EDX又是怎么得来的呢?
从这段代码往前翻,就看到了这样的代码:
为了便于大家分析,我把代码也贴出来:
00404839|.8DA424 000000>lea esp,dword ptr ss:
00404840|>8B4C24 18 /mov ecx,dword ptr ss:
00404844|.8D6E FF |lea ebp,dword ptr ds:
00404847|.55 |push ebp
00404848|.FF15 D8134400 |call dword ptr ds:[<&MFC80.#865>] ;按顺序取一个字符,放在AL中
0040484E|.0FBEC8 |movsx ecx,al ;放到ECX中
00404851|.83C1 01 |add ecx,0x1 ;加1
00404854|.894C24 14 |mov dword ptr ss:,ecx ;保存到intTemp14中
00404858|.DB4424 14 |fild dword ptr ss: ;转长整型压栈,此时ST0里是转换后的整数
0040485C|.DB4424 1C |fild dword ptr ss: ;顺序号也压栈,这时ST0是顺序号,ST1是那个整数
00404860|.DD5424 1C |fst qword ptr ss: ;把顺序号再保存,但是以双字保存
00404864|.DEC9 |fmulp st(1),st ;ASCII码+1 乘以位数
00404866|.E8 E5520300 |call D-Recove.00439B50 ;取存储器中的值,保存到EAX中
0040486B|.8B4C24 18 |mov ecx,dword ptr ss:
0040486F|.55 |push ebp
00404870|.894424 18 |mov dword ptr ss:,eax
00404874|.FF15 D8134400 |call dword ptr ds:[<&MFC80.#865>] ;按顺序取一个字符,放在AL中
0040487A|.0FBEC0 |movsx eax,al ;放到EAX中
0040487D|.0FAF4424 14 |imul eax,dword ptr ss: ;乘以上面计算出的得数
00404882|.0FAFC6 |imul eax,esi ;再乘以序号
00404885|.0FAFC6 |imul eax,esi ;再乘以序号
00404888|.03C7 |add eax,edi ;加上上一轮的和,初始为0
0040488A|.99 |cdq ;去符号
0040488B|.B9 A0860100 |mov ecx,0x186A0
00404890|.F7F9 |idiv ecx ;除以0x186A0,十进制100000,余数放到EDX中
00404892|.8B4C24 18 |mov ecx,dword ptr ss:
00404896|.55 |push ebp
00404897|.8BFA |mov edi,edx
00404899 >|.FF15 D8134400 |call dword ptr ds:[<&MFC80.#865>] ;mfc80.#2451
0040489F|.0FBED0 |movsx edx,al
004048A2|.895424 14 |mov dword ptr ss:,edx
004048A6|.B8 02000000 |mov eax,0x2
004048AB|.DB4424 14 |fild dword ptr ss:
004048AF|.D9E8 |fld1
004048B1|>A8 01 |/test al,0x1
004048B3|.74 02 ||je short D-Recove.004048B7
004048B5|.D8C9 ||fmul st,st(1)
004048B7|>D1E8 ||shr eax,1
004048B9|.74 06 ||je short D-Recove.004048C1
004048BB|.D9C1 ||fld st(1)
004048BD|.DECA ||fmulp st(2),st
004048BF|.^ EB F0 |\jmp short D-Recove.004048B1
004048C1|>DDD9 |fstp st(1)
004048C3|.DC4C24 1C |fmul qword ptr ss: ;ASCII码*ASCII码*位数
004048C7|.E8 84520300 |call D-Recove.00439B50 ;取存储器中的值
004048CC|.8BC8 |mov ecx,eax
004048CE|.8BC6 |mov eax,esi
004048D0|.0FAFC3 |imul eax,ebx
004048D3|.03C1 |add eax,ecx
004048D5|.99 |cdq
004048D6|.B9 A0860100 |mov ecx,0x186A0
004048DB|.F7F9 |idiv ecx
004048DD|.83C6 01 |add esi,0x1
004048E0|.897424 1C |mov dword ptr ss:,esi
004048E4|.8BDA |mov ebx,edx
004048E6|.8D043B |lea eax,dword ptr ds:
004048E9|.99 |cdq
004048EA|.F7F9 |idiv ecx
004048EC|.3B7424 24 |cmp esi,dword ptr ss:
004048F0|.^ 0F8E 4AFFFFFF \jle D-Recove.00404840
注意看左下角我标出来的那个字符串,也就是前面提到的CodeA。也就是说,程序用这个CodeA经过运算处理后,得到的EDI、EBX、EDX这三个值。至于运算过程,这里写的也很清楚了,我都已经注释上了,很容易看懂的。
可是那个字符串BV2310db828-90c10a0BVXOHRADDSIK又是什么呢?
对这个地址使用硬件断点也无效了,经常是在系统代码里出不来。这可怎么办才好?
就在我鼓捣了一整天准备放弃的时候,突然想到,我刚才在字符串查找中看到了这样的字符串“\\.\PhysicalDrive%d”。这好像应该是DeviceIoControl函数用来取硬盘参数的。很多程序的注册码都是通过它来生成的。而且,它获取到的信息字符串,字符是两两对调的。
好吧,去看一下我的电脑硬盘参数是什么。
我这个是虚拟机,所以磁盘名是VBOX HARDDISK,如果两两对调的话,就是BVXOH RADDSIK,哦,多么令人激动啊。那前面那个字符串就应该是我的磁盘型号了。
怎么验证呢?只好自己编程了。还是用习惯的DELPHI7。
果然如此,现在所有的问题都解决了,可以写注册机了。
过程我就不写了,说几个难点吧:
1、取硬盘设备信息。使用DeviceIoControl函数可以取出来,但是在WIN10 64位系统上运行时,需要管理员权限。这显然是不合适的,你不能说做一个注册机还需要人家提升管理员权限。要不说DELPHI程序员省事呢,网上有现成的VCL控件MiTeC。用这个就可以轻易的获得磁盘设备的信息。
2、磁盘字符串的组合。因为取出来的字符串是两两对调的,如果存在多个磁盘的情况下,字符串怎么组合才能与原软件的组成一样,这是个很费脑筋的事情;
3、从磁盘字符串计算EDI、EBX、EDX。汇编里的代码转成DELPHI语言倒是不难,主要是有些汇编指令不熟悉,不知道只做什么用的。比如movsx eax, al,换成DELPHI应该怎么写?
4、从EDI、EBX、EDX生成CodeB时。难点还是在汇编指令上,不停地处理标记位,而且DELPHI没有这些标记位,怎么写才能符合原来算法的意思,搞得我头晕。
还好,最终注册机写出来了。顺利在虚拟机上已经实体电脑上注册成功。
后记:
破解这个软件,花费了我两天的时间,这三天的假期别的都没做,满脑子都是这个事情。昨天晚上睡觉前还在为获取硬盘设备信息的事情发愁,迷迷糊糊做梦都是这个事,只睡了三个钟头就爬起来继续研究。
另外,这个软件注册成功后写注册表,也写Windows\Win.ini文件,注册表里的内容删了,软件提示注册无效,但是又没有注册窗体,等于废掉了。把Win.ini文件里最后RegCode=那行删掉就可以重新注册了。
唉,累死我了。终于可以睡觉去了。
原软件下载地址:http://www.sharebank.com.cn/soft/SoftView_44264.htm Editor By.Sound
初入吾爱 发表于 2017-6-5 17:49
这个
从这里的代码可以分析出来,注册码的长度必须是0x1C,也就是28个字节长度。
什么意思啊
从这里的代码可以分析出来,注册码的长度必须是0x1C,也就是28个字节长度。
什么意思啊
00404D32 8B8C24 74020000 mov ecx,dword ptr ss:
00404D39 8379 F4 1C cmp dword ptr ds:,0x1C
这段代码中,dword ptr ss:地址存储的就是注册码,而这个地址往前12(0xC)个字节的位置,存储的就是这个注册码的长度。
那么你可能会问,你怎么就知道这个地址就是注册码,前面那个位置就是注册码长度呢?
其实我本来也不知道。
OD不是有跟踪调试的功能吗?就是一遍一遍反复跟踪得出的结果。跟踪到这个位置的是,寄存器中会显示出这个地址的内容,与我们输入的注册码是一致的。反复多试几次,就能知道这个位置就是注册码了。
我们在00404D32处,按下F2下断点
为什么在这里下断点呢
为什么在这里下断点,是因为我知道点击注册按钮后,程序必然会执行到这一条。当然,最保险的是下在00404DF2处,也就是那个错误提示的位置。注册码输入错误,这句肯定是要执行的。但是程序走到这句,前面的很多地方已经处理完了,所以我们要往前找到一个点,就是程序还没有对注册码进行处理的地方。也是通过反复的跟踪,最终我在那里下断点。当然,你可以选择其他的地方,只要有助于你对代码的分析。
再继续F8单步跟踪,走到00404DE2的时候,不要再走了
为什么走到这里不走了吗?
先看这段代码吧
00404DE2 FF15 B8134400 call dword ptr ds:[<&MFC80.#1482>] ; mfc80.#1482
00404DE8 85C0 test eax,eax
00404DEA 0F84 8D000000 je D-Recove.00404E7D
00404DF0 55 push ebp
00404DF1 55 push ebp
00404DF2 68 CC274400 push D-Recove.004427CC ; 注册码错误! 请重试输入或向开发商索取本机注册码!
00404DE2是一个函数调用,然后后面紧跟着一个判断。判断后是一个跳转,这个跳转把注册失败的提示跳过去了。很明显啊,这个函数调用是关键,非常有可能就是验证注册码对不对的地方。
所以要在00404DE2的地方下断点,为的就是下一步F7跟踪进入。
最后我要说的是,跟踪调试一个程序,不可能是一次就成功的,都是经历几十次上百次的反复试验得来的,所以破解一个程序需要花费很多的时间。很多情况我们也不知道应该在哪里下断点,这个只能靠摸索。有的是靠经验,多看看教程,多看看别人的案例,自己再实操几次,慢慢就会有心得了。 破解很赞 学习了 感谢分享十分详细了,照着思路也可以写个注册机了 继续加油 学习了,有么有成品 写的很详细啊,谢谢! 原软件下载地址:http://www.sharebank.com.cn/soft/SoftView_44264.htm 最新测试,注册机注册以后,第二天运行时又变成未注册状态,重新注册又可以。说明软件有定期联网检验机制,要么用防火墙禁止软件联网,要么把程序中联网的部分干掉。懒得做了,有兴趣的可以自己尝试下。 我破解一个软件的时候也是这样,没有破解成功,觉都睡不着,哈哈 大师来接单,辛苦楼主了!~