• 标 题:制作自己的内存注册机--------文件隐藏精灵注册码获取 (4千字)
  • 作 者:幸福的芝麻
  • 时 间:2003-07-20 07:37:26
  • 链 接:http://bbs.pediy.com


文件隐藏精灵是我的一个网友写的软件,很方便很实用。
这次那她开刀主要是目的是学习内存补丁技术。用动态
内存补丁取得软件真正的注册码。并且对破解软件的
思路经验进行总结,以飨读者。

下载地址:http://www.megspace.com/computers/bluenightsky/
保护方式:aspack2.12+自删除
使用工具:OllyDbg1.09C汉化版,DeDe,pe-scan,W32Dasm,VC++6.0
操作系统:win2000
破解难度:初级

      破解过程

一、解除软件保护。
文件隐藏精灵用的是ASPACK2.12的壳,手工和使用工具很容易就能脱掉。
但是脱壳后的程序会删除自己,使得DeDe不能正常对它进行反汇编。
用ollydbg跟踪发现 00477D19 > E8 A2CBF8FF CALL FILEMAGI.004048C0
如果进入这个CALL,程序就会生成一个名称为delme.bat的批处理文件,
然后调用winexec()函数,用SW_HIDE参数隐藏执行这个批处理文件达到删除自己的目的。
通过跟踪未脱壳的文件和脱壳后的文件比较发现
004573A1 . 80B8 9C000000 00  CMP BYTE PTR DS:[EAX+9C],0
004573A8  ^74 BF             JE SHORT FileMagi.00457369
未脱壳的文件这里的跳转条件一直为真,而脱壳以后第二次经过这里跳转条件就为假了。
在004573A1处看反汇编代码窗口下面的窗口:
EAX+9C指向的01101464被置为1,则CMP后Z标志被置1,JE跳转实现。
让我们看看是那里改变了01101464的值的。因为程序要初始化内存才能看到01101464
所以我们先在004573A1 CMP BYTE PTR DS:[EAX+9C],0处下断点。因为第一次循环时
01101464得值不会改变。断下后打开“内存镜像”窗口(查看-内存)找到01101464
(图片1)
鼠标右键-〉断点-〉内存写入
然后运行。程序断在了00457142
我们可以看到ESI+9C指向的地址正是01101464
00457140 |. EB 07 JMP SHORT FILEMAGI.00457149
00457142 C686 9C000000 01 MOV BYTE PTR DS:[ESI+9C],1//这里改变了01101464的值
00457149 |> 8BC3 MOV EAX,EBX
0045714B |. 5A POP EDX
关闭程序(工具栏上的X号),查看菜单-〉文件,选择脱壳后的程序文件查找
C686 9C000000 01,把01改为00,也就是改为MOV BYTE PTR DS:[ESI+9C],0就OK了。
然后DeDe就可以正常的对他进行反汇编。但是程序不能正常退出。
把004573A8   ^74 BF JE SHORT FileMagi.00457369改为
004573A8  .^EB BF JMP SHORT FileMagi.00457369
也可以效果一样。

二、对软件注册方式的分析。
这个软件是一组密码、用户名对应一个序列号的方式进行注册的。
可以一台机器上有多个用户。用户也可以在任意机器使用拷贝。
用DeDe对程序进行反汇编。
在过程-〉事件里面,找到注册按钮的事件对应的入口地址
00475DFC /. 55 PUSH EBP
然后回到OllyDbg。点工具栏上面的“前往反汇编地址”按钮,输入入口地址00475DFC。
在反汇编指令处按F2设断点。运行。帮助里面注册。
输入用户名、密码、序列号(数字)-〉确定。在OllyDbg中被断下。
按F8但步跟踪来到
00475F78 |. 8B45 C8 MOV EAX,DWORD PTR SS:[EBP-38]
00475F7B |. E8 4443F9FF CALL FILEMAGI.0040A2C4
00475F80 |. DC5D F8 FCOMP QWORD PTR SS:[EBP-8]//注册码在这里!!!!
00475F83 |. DFE0 FSTSW AX
00475F85 |. 9E SAHF
00475F86 |. 0F85 EA000000 JNZ FILEMAGI.00476076
00475F8C |. 8BC3 MOV EAX,EBX
00475F8E |. E8 5DDEFDFF CALL FILEMAGI.00453DF0
在00475F80指令处EBP-8里面就可以看到注册码了。浮点数!!!小数点前面的就是真正的注册码了。
分析算法做注册机太麻烦了用到了浮点指令,因为是明码比较。所以可以利用程序里面的算法代码。
但是也不能每次为了得到注册码就对程序跟踪一次太麻烦了。制作一个内存注册机是个很好的办法。
不受软件加壳的影响、不修改硬盘上的程序文件……

三、制作内存补丁
内存补丁我是用VC做的。由于用的是WINDOWS的API函数。所以,明白原理后用其他语言(比如:Delphi,VB)
也能做出同样的效果。
首先要在数据段找一个空隙方我们的补丁代码。用OllyDbg向下拉找到一个空白处(16进制全部为00,反汇编
代码为DB 00)我找到的是00477D53处(很大的一个房间);
首先先修改00475F80处指令,让指令跳转到我们的补丁代码处
00475F80 E9 CE1D0000 JMP FileMagi.00477D53
这个指令占用5个字节正好覆盖了
00475F80 |. DC5D F8 FCOMP QWORD PTR SS:[EBP-8]
00475F83 DFE0 FSTSW AX
为了程序能正常执行,我们要在我们的补丁代码处恢复这两条指令。
这是补丁代码处的代码
00477D53 DC5D F8 FCOMP QWORD PTR SS:[EBP-8] //比较(恢复原来的指令)
00477D56 DD45 F8 FLD QWORD PTR SS:[EBP-8] //把正确的传递到寄存器(浮点指令)
00477D59 36:DD15 6D7D4700 FST QWORD PTR SS:[477D6D] //把寄存器数值写入一个可写入地址(浮点指令)
00477D60 DFE0 FSTSW AX //(恢复原来的指令)
00477D62 ^E9 1EE2FFFF JMP FileMagi.00475F85 //跳回原来指令的下一条指令
这样运行注册以后。正确的注册码就保存在了00477D6D。我们只要读取00477D6D处的数值就可以了。

现在我们说一下注册机编写的步骤:
首先用FindWindow函数得到窗口句柄,然后用GetWindowThreadID函数从窗口句柄得到这个进程的ID
HWND hWnd=::FindWindow("tapplication","file-magic");//第一个参数是类,第二个参数是窗口标题。
GetWindowThreadProcessId(hWnd,&hProcId);//第一个参数是窗口句柄,第二个参数是进程ID为DWORD型。
接着用OpenProcess得到进程的读写权限
HANDLE nOK =OpenProcess(PROCESS_ALL_ACCESS|PROCESS_TERMINATE|PROCESS_VM_OPERATION|PROCESS_VM_READ| 
                            PROCESS_VM_WRITE,FALSE,hProcId);  //打开进程并得到读与权限
最后用WriteProcessMemory和ReadProcessMemory读写内存,然后你的内存注册机就做成啦:-) 
调试发现注册码读取需要用双精度浮点数(double)保存。
程序下载:http://202.102.229.61/zhima