好友
阅读权限25
听众
最后登录1970-1-1
|
肥牛
发表于 2017-5-29 23:42
本帖最后由 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用的不太熟,所以我只能在出现这个码的地址上下硬件断点,这样一点儿一点儿,终于找到了下面的这段代码:
[Asm] 纯文本查看 复制代码 004048FA |> \8D47 1C lea eax,dword ptr ds:[edi+0x1C]
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:[edi+0x1D]
0040490C |. 81E1 7F000080 and ecx,0x8000007F
00404912 |. 884424 30 mov byte ptr ss:[esp+0x30],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:[edi+0x24]
00404920 |. 25 7F000080 and eax,0x8000007F
00404925 |. 884C24 31 mov byte ptr ss:[esp+0x31],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:[edi+0x37]
00404933 |. 81E1 7F000080 and ecx,0x8000007F
00404939 |. 884424 32 mov byte ptr ss:[esp+0x32],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:[esp+0x33],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:[ebx+0x9A]
0040495F |. 81E1 7F000080 and ecx,0x8000007F
00404965 |. 884424 34 mov byte ptr ss:[esp+0x34],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:[ebx+0xF5]
00404976 |. 25 7F000080 and eax,0x8000007F
0040497B |. 884C24 35 mov byte ptr ss:[esp+0x35],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:[ebx+0x174]
0040498C |. 81E1 7F000080 and ecx,0x8000007F
00404992 |. 884424 36 mov byte ptr ss:[esp+0x36],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:[ebx+0x21D]
004049A3 |. 25 7F000080 and eax,0x8000007F
004049A8 |. 884C24 37 mov byte ptr ss:[esp+0x37],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:[esp+0x38],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:[edx+0x406]
004049D0 |. 81E1 7F000080 and ecx,0x8000007F
004049D6 |. 885C24 39 mov byte ptr ss:[esp+0x39],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:[edx+0x551]
004049E7 |. 25 7F000080 and eax,0x8000007F
004049EC |. 884C24 3A mov byte ptr ss:[esp+0x3A],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:[edx+0x6DE]
004049FD |. 81E1 7F000080 and ecx,0x8000007F
00404A03 |. 884424 3B mov byte ptr ss:[esp+0x3B],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:[edx+0x8B3]
00404A14 |. 25 7F000080 and eax,0x8000007F
00404A19 |. 884C24 3C mov byte ptr ss:[esp+0x3C],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:[edx+0xAD6]
00404A2A |. 81E1 7F000080 and ecx,0x8000007F
00404A30 |. 884424 3D mov byte ptr ss:[esp+0x3D],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:[esp+0x3E],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:[esp+0x3F],dl
00404A56 |. 33D2 xor edx,edx
00404A58 |. 33C9 xor ecx,ecx
00404A5A |. 8D9B 00000000 lea ebx,dword ptr ds:[ebx]
00404A60 |> 8A4414 30 /mov al,byte ptr ss:[esp+edx+0x30]
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:[eax+ecx+0x1F]
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:[esp+edx+0x30],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:[esp+0x30]
这段代码的意思就是从EDI里取值,做了一番处理后形成了码的前5位,又从EBX取值处理后形成码的中间5位,最后从EDX里取值得出码的最后6位。
OK,到现在,CodeB码是怎么生成的已经知道了,但新问题又来了——EDI、EBX、EDX又是怎么得来的呢?
从这段代码往前翻,就看到了这样的代码:
为了便于大家分析,我把代码也贴出来:
[Asm] 纯文本查看 复制代码 00404839 |. 8DA424 000000>lea esp,dword ptr ss:[esp]
00404840 |> 8B4C24 18 /mov ecx,dword ptr ss:[esp+0x18]
00404844 |. 8D6E FF |lea ebp,dword ptr ds:[esi-0x1]
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:[esp+0x14],ecx ; 保存到intTemp14中
00404858 |. DB4424 14 |fild dword ptr ss:[esp+0x14] ; 转长整型压栈,此时ST0里是转换后的整数
0040485C |. DB4424 1C |fild dword ptr ss:[esp+0x1C] ; 顺序号也压栈,这时ST0是顺序号,ST1是那个整数
00404860 |. DD5424 1C |fst qword ptr ss:[esp+0x1C] ; 把顺序号再保存,但是以双字保存
00404864 |. DEC9 |fmulp st(1),st ; ASCII码+1 乘以位数
00404866 |. E8 E5520300 |call D-Recove.00439B50 ; 取存储器中的值,保存到EAX中
0040486B |. 8B4C24 18 |mov ecx,dword ptr ss:[esp+0x18]
0040486F |. 55 |push ebp
00404870 |. 894424 18 |mov dword ptr ss:[esp+0x18],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:[esp+0x14] ; 乘以上面计算出的得数
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:[esp+0x18]
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:[esp+0x14],edx
004048A6 |. B8 02000000 |mov eax,0x2
004048AB |. DB4424 14 |fild dword ptr ss:[esp+0x14]
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:[esp+0x1C] ; 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:[esp+0x1C],esi
004048E4 |. 8BDA |mov ebx,edx
004048E6 |. 8D043B |lea eax,dword ptr ds:[ebx+edi]
004048E9 |. 99 |cdq
004048EA |. F7F9 |idiv ecx
004048EC |. 3B7424 24 |cmp esi,dword ptr ss:[esp+0x24]
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 |
|
免费评分
-
查看全部评分
本帖被以下淘专辑推荐:
- · 杂七杂八|主题: 1074, 订阅: 320
- · 优秀逆向文|主题: 238, 订阅: 93
- · 等待更新|主题: 51, 订阅: 11
|