【著述标题】: 加密狗保护的VFP软件破解 【著述作家】: Rufus Xu 【作家邮箱】: my_home_page@163.com 【软件称呼】: 工程造价V93 【软件大小】: 43.3M 【下载地址】: 【加壳姿首】: 狗壳 【保护姿首】: 加密狗 【编写说话】: VFP 【使用用具】: OLLDBG 【操作平台】: Windows2000 【软件先容】: 建筑工程造价软件 【作家声明】: 仅仅感酷爱酷爱,莫得其他方向。虚假之处敬请各位大侠指教! -------------------------------------------------------------------------------- 【详备经过】 应一个一又友的肯求,破解一个加密狗保护的工程造价软件。夙昔一直莫得搞过加密狗,此次念念试试手, 经过长途拳交 twitter,终于贬责,但愿对被加密狗困扰的一又友有所匡助。 为了贬责这条狗我花了实在两个月的业余时分,从启动的一窍欠亨,到临了好意思满破解,走了许多弯路。此次学习的经过 主要分为三个阶段,底下详备先容。 一、外壳调试 在门径目次下有Vfp6r.dll、Vfp6rchs.dll、Vfp6renu.dll三个文献,无谓说,该门径是用VFP确立的, PEID查不到信息,深度搜索发现是用VC++写的。拿出OD,掀开要调试的门径ztc.exe,OD停在进口点: 00407049 ztc.> 55 push ebp 0040704A 8BEC mov ebp,esp 0040704C 83EC 7C sub esp,7C 0040704F 53 push ebx 00407050 56 push esi 00407051 57 push edi 00407052 C745 C8 A5A50>mov dword ptr ss:[ebp-38],0A5A5 00407059 66:C745 C0 0A>mov word ptr ss:[ebp-40],0A 0040705F E9 550D0000 jmp ztc.00407DB9 00407064 E9 4C070000 jmp ztc.004077B5 00407069 EB 01 jmp short ztc.0040706C 往下走两步,就是一个跳转,随着走,来到:00407DB9处,是一大片跳转表。 00407CE1 8B45 E0 mov eax,dword ptr ss:[ebp-20] 00407CE4 5F pop edi 00407CE5 5E pop esi 00407CE6 5B pop ebx 00407CE7 8BE5 mov esp,ebp 00407CE9 5D pop ebp 00407CEA FF20 jmp dword ptr ds:[eax] 00407CEC E9 CD000000 jmp ztc.00407DBE 00407CF1 ^ E9 E6FFFFFF jmp ztc.00407CDC 00407CF6 ^ E9 E1FFFFFF jmp ztc.00407CDC 00407CFB ^ E9 9EF3FFFF jmp ztc.0040709E 00407D00 ^ E9 D7FFFFFF jmp ztc.00407CDC 00407D05 ^ E9 A5FFFFFF jmp ztc.00407CAF 00407D0A ^ E9 14FEFFFF jmp ztc.00407B23 00407D0F ^ E9 0FFEFFFF jmp ztc.00407B23 00407D14 ^ E9 C3FFFFFF jmp ztc.00407CDC 00407D19 ^ E9 05FEFFFF jmp ztc.00407B23 00407D1E ^ E9 B9FFFFFF jmp ztc.00407CDC 00407D23 ^ E9 FBFDFFFF jmp ztc.00407B23 00407D28 ^ E9 F6FDFFFF jmp ztc.00407B23 00407D2D ^ E9 F1FDFFFF jmp ztc.00407B23 00407D32 ^ E9 DAFCFFFF jmp ztc.00407A11 00407D37 ^ E9 D8FDFFFF jmp ztc.00407B14 00407D3C ^ E9 C4FDFFFF jmp ztc.00407B05 00407D41 ^ E9 DDFDFFFF jmp ztc.00407B23 00407D46 ^ E9 E7FCFFFF jmp ztc.00407A32 00407D4B ^ E9 4EF3FFFF jmp ztc.0040709E 00407D50 ^ E9 CEFDFFFF jmp ztc.00407B23 00407D55 ^ E9 C9FDFFFF jmp ztc.00407B23 00407D5A ^ E9 3FF3FFFF jmp ztc.0040709E 00407D5F ^ E9 97FDFFFF jmp ztc.00407AFB 00407D64 ^ E9 29FAFFFF jmp ztc.00407792 00407D69 ^ E9 23FFFFFF jmp ztc.00407C91 00407D6E ^ E9 79FDFFFF jmp ztc.00407AEC 00407D73 ^ E9 46FFFFFF jmp ztc.00407CBE 00407D78 ^ E9 88FBFFFF jmp ztc.00407905 00407D7D ^ E9 1EFFFFFF jmp ztc.00407CA0 00407D82 ^ E9 55FFFFFF jmp ztc.00407CDC 00407D87 ^ E9 42F6FFFF jmp ztc.004073CE 00407D8C ^ E9 88FBFFFF jmp ztc.00407919 00407D91 ^ E9 8DFDFFFF jmp ztc.00407B23 00407D96 ^ E9 41FFFFFF jmp ztc.00407CDC 00407D9B ^ E9 3CFFFFFF jmp ztc.00407CDC 00407DA0 ^ E9 26F4FFFF jmp ztc.004071CB 00407DA5 ^ E9 32FFFFFF jmp ztc.00407CDC 00407DAA ^ E9 2DFFFFFF jmp ztc.00407CDC 00407DAF ^ E9 EAF2FFFF jmp ztc.0040709E 00407DB4 ^ E9 6AFDFFFF jmp ztc.00407B23 00407DB9 ^ E9 F7F9FFFF jmp ztc.004077B5 在最上头的一条跳转语句00407CEA处下断,F9走,OD停驻来以后,发现DS:[EAX]的值形成了00405634, 此时EAX=0040E0E0,暗示下一步就要跳到该地址了,无间: 00405634 55 push ebp ................................... 00405654 FF15 0CD14100 call dword ptr ds:[<&USER32.Messag>; USER32.MessageBoxA F9,跳出对话框,教唆莫得加密狗,门径退出。看来,门径一经加了狗壳,在最启动就检测有莫得加密狗。 左证网上的一些教程,咱们要在读狗的时候下断,读狗确定要用到CreateFileA函数,在OD的敕令插件中输入: bpx CreateFileA,让OD再行调初学径,F9,门径中断在: 0040A4CF 55 push ebp 0040A4D0 8BEC mov ebp,esp 0040A4D2 51 push ecx 0040A4D3 53 push ebx 0040A4D4 56 push esi 0040A4D5 57 push edi 0040A4D6 8B7D 08 mov edi,dword ptr ss:[ebp+8] 0040A4D9 8B9F 88000000 mov ebx,dword ptr ds:[edi+88] 0040A4DF 83C3 18 add ebx,18 0040A4E2 33F6 xor esi,esi 0040A4E4 6A 00 push 0 0040A4E6 68 80000000 push 80 0040A4EB 6A 03 push 3 0040A4ED 6A 00 push 0 0040A4EF 6A 07 push 7 0040A4F1 68 000000C0 push C0000000 0040A4F6 68 8CC44100 push zj9.0041C48C ; ASCII "\\.\LPTDI1" 0040A4FB FF15 B0D04100 call dword ptr ds:[<&KERNEL32.Crea>; kernel32.CreateFileA CTRL+F9复返,几次复返以后,来到0040943C,不错看到一些花指示,差未几到了泉源了, 0040943C 55 push ebp 0040943D 8BEC mov ebp,esp 0040943F 81EC 78010000 sub esp,178 00409445 53 push ebx 00409446 33C9 xor ecx,ecx 将0040943C处的代码改成 0040943C 33C0 XOR EAX,EAX 00409E62 C3 RETN 将蜕变保存到到文献。让OD再行加载门径,断根扫数断点,F9运行。如故教唆莫得找到加密狗。 因为00407CEA是关节跳转处,咱们来望望门径是什么时候为EAX赋值的,mov eax,dword ptr ss:[ebp-20] 在OD的敕令处输入D 0040E0E0,下硬件写入断点,再走运行,在00407A8B处断下 00407A7A E8 9D030000 call zj9.00407E1C 00407A7F 3B05 04E14000 cmp eax,dword ptr ds:[40E104] 00407A85 0F84 0A000000 je zj9.00407A95 00407A8B C705 E0E04000>mov dword ptr ds:[40E0E0],zj9.00405634<-------------------MessageBox进口 00407A85处是关节跳转,NOP掉,保存,再走运行,在00407CEA(VFP进口点),下断,F9运行。OD断下以后: 00407CEA - FF20 jmp dword ptr ds:[eax] ; ztc.00401760 一经不是00405634了,启动的壳检测狗一经跳过了。练习VFP门径的东说念主齐知说念00401760是独到的VFP门径进口点。 F9运行,门径一经不教唆无狗了,然而掀开主门径以后,如故教唆莫得注册码。看来,在VFP主文献内部还有对狗的调用。 二、VFP门径处理 在讲这部分的时候,先要补一课,就是VFP门径的结构和试验递次: VFP 编译生成的 EXE 文献主要由两部份构成,第一部份(前半部分)是一个圭臬的 PE 体式的可试验文献, 这个圭臬的 PE 体式文献又叫载入器. 第二部分(后半部分)是一个圭臬的 .app 文献, 这个 app 与在 VFP 集成确立环境中编译时采取编译为 app 文献时生成的 app 文献基本上是相同的,仅仅在这个 app 文献的尾部, 多了 14 字节的标志部份(这 14 字节的前 10 字节是 00 83 41 00 00 00 00 00 00 00,临了四字节是 app 文献 加上14 字节的标志后的长度). 因此,不错以为 VFP 编译的 EXE 文献是由一个圭臬的 EXE 文献背面附上一个 .app 文献, 再加上 14 字节的标志部份构成. 况兼, 前半部份的 EXE 与后半部分的 app 之间莫得任何策动. 前边提到的载入器的作用荒谬肤浅,主淌若查验运行环境,载入相应的 VFPxR.DLL 并调用 VFPxR.DLL 中的 DllWinMain 函数. 在调用 DllWinMain 函数时, 有两个参数, 第一个是一个串参数,必须是 VFP 编译的 EXE 文献的文献名, 第二个是一个 int 型的值,一般用十六进制的 FF 就不错. 因此,你不错用除 VFP 之外的任何编译语 言来编译写我方的载入器以达到加密门径的作用. 事实上,一但载入器调用了 VFPxR.DLL 中的 DllWinMain 函数后, VFP 就采取了门径的截止权,你就再也无法 用惯例的措施截止门径的运行经过了. 底下说一下 VFP 的 DLL 的启动经过:当先,VFPxR.DLL 会读取文献的临了 14 字节. 并左证临了四字节来定位到 app 在 EXE 文献中的位置。 好了,课补罢了,即然VFPxR.DLL要读文献,那么咱们就在读文献的时候下断,在OD的敕令处输入:bpx ReadFile, F9运行,在00405F3B处断下, 00405F3B FF15 94D04100 call dword ptr ds:[<&KERNEL32.Read>; kernel32.ReadFile 此时堆栈的数据为: 0012FA18 00000030 |hFile = 00000030 0012FA1C 0012FA40 |Buffer = 0012FA40 0012FA20 00000040 |BytesToRead = 40 (64.) 0012FA24 0012FA38 |pBytesRead = 0012FA38 0012FA28 00000000 \pOverlapped = NULL 0012FA2C 004031C0 ztc.004031C0 咱们看到BytesToRead大小为40H,不是E(14字节),F9无间,三次断下以后, 004061FF FF15 94D04100 call dword ptr ds:[<&KERNEL32.Read>; kernel32.ReadFile 此时堆栈的数据为: 0012F9E8 00000030 |hFile = 00000030 0012F9EC 0012FAE4 |Buffer = 0012FAE4 0012F9F0 0000000E |BytesToRead = E (14.) 0012F9F4 0012FABC |pBytesRead = 0012FABC 0012F9F8 00000000 \pOverlapped = NULL 这就是咱们要找的所在了,读出的数据保存在0012FAE4,F8走一步,在OD敕令行输入D 0012FAE4 0012FAE4 29 B3 CB 29 29 29 29 29 )乘))))) 0012FAEC 29 29 51 0A F3 29 ))Q.?. 然而这并不是咱们要的数据,00 83 41 00 00 00 00 00 00 00,看来一经加密过了,往下看, 00406298 FF4D F4 dec dword ptr ss:[ebp-C] 0040629B 837D F4 00 cmp dword ptr ss:[ebp-C],0 0040629F 0F8C 1F000000 jl ztc.004062C4 004062A5 8B45 F4 mov eax,dword ptr ss:[ebp-C] 004062A8 8B4D AC mov ecx,dword ptr ss:[ebp-54] 004062AB 33D2 xor edx,edx 004062AD 8A1408 mov dl,byte ptr ds:[eax+ecx] 004062B0 8A82 08E34000 mov al,byte ptr ds:[edx+40E308] 004062B6 8B4D F4 mov ecx,dword ptr ss:[ebp-C] 004062B9 8B55 AC mov edx,dword ptr ss:[ebp-54] 004062BC 880411 mov byte ptr ds:[ecx+edx],al 这就是解密经过了,从DS:[40E308]取出解密的数据,咱们望望解密以后的数据: 0012FAE4 00 83 41 00 00 00 00 00 .?..... 0012FAEC 00 00 EC 06 31 00 ..?1.. 这就是VFP的尾部数据,它指出了VFP的APP文献的大小是003106EC-E, 咱们用UE掀开主程小引件,找到29 B3 CB 29 29 29 29 29所在的位置,然后盘算出 APP的头部位置,然后就把从新部启动的大小为003106EC-E数据取出另存. 然后咱们在望望明文存放的位置,在OD的敕令行输入D 0040E038,不错看到如下数据: 0040E308 44 5D 85 5B 15 07 EF A2 D]?铫 0040E310 5A DD 06 22 A3 3F 81 4E Z?"?? 0040E318 C0 D6 73 A4 C1 F5 E9 96 乐sち蹰 咱们用UE掀开主门径搜索44 5D 85 5B 15 07 EF A2,然而找不到,看来这部分数据是 动态生成的,没关系,咱们把当今内存中的数据导出来就OK了,有OD自带的插件DUMP出数据 另存为DUMP.EXE,然后用OD掀开,再搜索44 5D 85 5B 15 07 EF A2,一经找到了.左证解 密算法,咱们把从44 5D 85 5B 15 07 EF A2启动的数据取出512字节出来,因为512背面的字 节用不到. 然后写门径把数据解密,我是用VB.NET写的, Dim mFile As File If File.Exists(Application.StartupPath & "\file1.dat") And File.Exists(Application.StartupPath & "\file2.dat") Then Dim mRFileStream1 As FileStream = mFile.OpenRead(Application.StartupPath & "\file1.dat") '密文 Dim mRFileStream2 As FileStream = mFile.OpenRead(Application.StartupPath & "\file2.dat") '明文 Dim mWFileStream As FileStream = New FileStream(Application.StartupPath & "\ztc93.app", FileMode.OpenOrCreate) Dim i As Integer For i = 0 To &H3106DD Dim mArray1(0) As Byte Dim mArray2(0) As Byte '读密文 mRFileStream1.Seek(i, SeekOrigin.Begin) mRFileStream1.Read(mArray1, 0, 1) '找对应明文 mRFileStream2.Seek(mArray1(0), SeekOrigin.Begin) mRFileStream2.Read(mArray2, 0, 1) '写入新文献 mWFileStream.Seek(i, SeekOrigin.Begin) mWFileStream.Write(mArray2, 0, 1) Next mRFileStream1.Close() mRFileStream2.Close() mWFileStream.Close() End If 取得的文献就是VFP的APP文献了,咱们拿出FOXTOOL,掀开,呵呵,雀跃啊,源代码出来了.因为我不会VFP,是以反编译出 来的代码我莫得方针再再行编译,我试了许屡次,编译欠亨过.是以得另念念方针了. 三、模拟写狗 用FOXTOOL掀开,不错看到APP文献中确实还有读狗的所在, zy4000.dll是读狗的DLL DECLARE INTEGER DogRead IN zy4000 INTEGER DogBytes, INTEGER DogAddr, STRING @Data DogAddr = 49 DogBytes = 1 Data= '12345678901123456789011' i = DogRead(DogBytes,DogAddr,@Data) if left(data,1)<> 'g' or eee = 99 thisform.Image1.width=thisform.width thisform.Image1.height=thisform.height thisform.Image1.visible=.t. thisform.refresh() do form 系列号 好了,有了源代码,模拟狗就驾轻就熟了,底下是我用VC++7.0写的DLL #include "stdafx.h" #include "string.h" short public DogRead(unsigned short DOGBYTES,unsigned short DOGADDR,char *pData ) { switch(DOGBYTES) { case 6: memcpy(pData,"999abc",6); break; case 2 : memcpy(pData,"fg",2); break; case 3 : memcpy(pData,"123",3); break; case 1: memcpy(pData,"g",1); break; case 8: memcpy(pData,"g",1); break; case 5: memcpy(pData,"g",1); break; case 15: memcpy(pData,"g",1); break; default : pData="test!!!"; break; } return 0; } 将编译好的DLL替换好zy4000.dll,运行门径,OK,一切闲居,至此,好意思满破解. -------------------------------------------------------------------------------- 【陶冶回来】 1.壳中读狗部分的处理. 2.VFP门径的结构及联系常识 3.常见的对VFP的APP的加密处理 4.模拟狗的操作. -------------------------------------------------------------------------------- 【版权声明】: 本文原创于看雪本领论坛, 转载请注明作家并保握著述的完整, 谢谢! 2006年06月24日 15:36:09
[详实]传递专科常识、拓宽行业东说念主脉——看雪讲师团队等你加入!拳交 twitter
波比在线