• 标 题:让他变成自己的注册机!财智家庭理财2001加强版(v3.2)的破解 (7千字)
  • 作 者:hsf0214
  • 时 间:2001-11-5 11:42:56
  • 链 接:http://bbs.pediy.com

财智家庭理财2001加强版(v3.2),个人理财的好软件。。。
又见到老朋友了,(想当初,我第一次下手就是对付它)这次出的是加强版,功能加强了否,我不清楚,只是注册码判断还是用的老方法,一点也没加强,:-)
这个软件没有难度,Easy类的!用wdsm也很容易静态分析它。(可是想当初,我可是用了整整两天的时间去破它的,那时真的不太懂,根本没入门,全凭毅力,当然还有兴趣和想“合法”用这个软件的欲望,才硬啃掉它的,##%%@#!多少事,都付笑谈中。。。)
下面是简单的过程:
输入注册码后,Ctrl+N调出trw2000,下断点
bpx hmemcpy
再F5回到程序,点注册按钮,程序被中断
bd
pmodule
F12按7次
F10若干次。很容易看到下面的代码,再下面是跟进51e6df处那个call里的代码
==================================================================================
016F:0051E6DC  MOV      EAX,[EBP-04]
016F:0051E6DF  CALL    0051DF34 ....>>>>关键的Call
016F:0051E6E4  TEST    AL,AL  ....>>>>判断标志
016F:0051E6E6  JZ      0051E737 ....>>>>跳则OVER!
016F:0051E6E8  MOV      EAX,[0064FF98]
016F:0051E6ED  MOV      EAX,[EAX]
016F:0051E6EF  MOV      EDX,[EBP-04] ....>>>>这里把你输入的注册码
016F:0051E6F2  CALL    004BDDD0   ....>>>>存入注册表里
====================================================================================
016F:0051DF6A 8B45F8          MOV      EAX,[EBP-08] ....>>>> d eax,可以看到正确的注册码
016F:0051DF6D E8FAFCFFFF      CALL    0051DC6C
016F:0051DF72 8BD8            MOV      EBX,EAX   .....>>>>计算后得到一个值,存在ebx中
016F:0051DF74 8B45FC          MOV      EAX,[EBP-04] ....>>>> d eax,可以看到你输入的错误的注册码
016F:0051DF77 E8F0FCFFFF      CALL    0051DC6C
016F:0051DF7C 85C0            TEST    EAX,EAX  ....>>>>错误的注册码得到eax=0,不跳
016F:0051DF7E 7504            JNZ      0051DF84
016F:0051DF80 33DB            XOR      EBX,EBX  ...>>>>ebx清零,玩完
016F:0051DF82 EB0A            JMP      SHORT 0051DF8E
016F:0051DF84 3BC3            CMP      EAX,EBX   ....>>>>两次计算结果相同吗?
016F:0051DF86 7504            JNZ      0051DF8C  ....>>>>不同,说明注册码错误,跳到玩完
016F:0051DF88 B301            MOV      BL,01    ...>>>>哦,是正确的注册码呀
016F:0051DF8A EB02            JMP      SHORT 0051DF8E ....>>>>跳到后面,避开ebx清零的这一句
016F:0051DF8C 33DB            XOR      EBX,EBX
016F:0051DF8E 33C0            XOR      EAX,EAX  ....>>>>公共的结束部分
016F:0051DF90 5A              POP      EDX
016F:0051DF91 59              POP      ECX
016F:0051DF92 59              POP      ECX
016F:0051DF93 648910          MOV      [FS:EAX],EDX
016F:0051DF96 68B0DF5100      PUSH    DWORD 0051DFB0
016F:0051DF9B 8D45F4          LEA      EAX,[EBP-0C]
016F:0051DF9E BA03000000      MOV      EDX,03
016F:0051DFA3 E83860EEFF      CALL    00403FE0
016F:0051DFA8 C3              RET   
=======================
改就很好改了,把51df74那行改成mov eax,[ebp-08]就得了。用程序自己算出的注册码放进去计算,这两次计算结果一定相同的,呵呵呵。。。
  这不是我今天想要重点说明的。这样改跟暴破没什么两样,9个月前我就是这样了,难道现在还这样?他不改变注册判断的方法,难道我也跟他一样,不改破它的方法???
  现在让我完成我以前没实现的愿望,让他(程序自己)变成自己的注册机吧!
  其实从DF6A到DF8C这一段空间,都是程序自己想要做而我们不一定想要他做的事,把这一段空间里的代码改了,改成我们希望他做的事,不就得了???
  从失败讲起,希望大家有耐心看下去。
  我们想到上面的改法,是用程序自己算出的注册码放进去计算来欺骗这个判断功能块,可“注册成功”后程序会在注册表里写入你的注册信息,这里放入的是你输入的错误注册码!!!有什么办法能让他放入正确的注册码吗?一是修改指针,让他去找注册码的时候找到的不是我们输入的错误注册码,而是程序自己算出的注册码。二是修改字符串,把正确的注册码存入错误注册码在内存中的存储空间里。
  第一种简单一些。可是分析后知道是不成功的。失败!!!
  原因如下:
  在DF6A前一句中正确注册码的存放地址的指针才出来,到DFA3这个Call后又被冲掉了,也就是说,等你判断完成后就找不到指向正确注册码的存放地址的指针了!
  如果我们把51E6EF处的指针(也就是ebp-08里的内容)在前一个CALL里面就改成指向正确注册码的存放地址的指针行不行呢?也不行。为什么不行?实践嘛。改了会出错的。另外,要注意,在CALL里面的EBP值和在外面的不一样,改的时候要计算清楚。到底改的是哪的。改的时候多看看EBP前16个字节以后的内容是怎么变化的。
  那就考虑第二种方法吧。经实践,改成了以下的内容:
==================================
016F:0051DF6A 8B45F8          MOV      EAX,[EBP-08]
016F:0051DF6D E8FAFCFFFF      CALL    0051DC6C
016F:0051DF72 8BD8            MOV      EBX,EAX      ....>>>>前三行不想去动它,为什么?尽量保持程序在这个CALL的返回时的各个值,所以让他得到ebx的值。
016F:0051DF74 8B55FC          MOV      EDX,[EBP-04] ....>>>>把你要写入的地址找到
016F:0051DF77 85D2            TEST    EDX,EDX  ....>>>>如果是0就别写,硬要往里写会出错的
016F:0051DF79 7411            JZ      0051DF8C ....>>>>不写就跳走
016F:0051DF7B 8B45F8          MOV      EAX,[EBP-08] ....>>>>把存放正确的注册码的地址找到
016F:0051DF7E 8A0401          MOV      AL,[ECX+EAX] ....>>>>把第'ecx+1'个字符取出,放入AL中
016F:0051DF81 880411          MOV      [ECX+EDX],AL ....>>>>再把它存进要写入的地址中
016F:0051DF84 41              INC      ECX   ....>>>>ecx加1,为什么前面不加初始化ecx的指令呢?因为经过51DF6D处的CALL后,ECX的值就已经是0了,不用自己去初始化,这就是不动前三行的好处了。。。
016F:0051DF85 80F90A          CMP      CL,0A  ....>>>>9个字符+1个“字符串结束标志”(也就是00,TC里的'\0'了),共10位,所以。。。
016F:0051DF88 75F1            JNZ      0051DF7B ....>>>>没传完?继续
016F:0051DF8A EB02            JMP      SHORT 0051DF8E ....>>>>跳到公共的结束部分
016F:0051DF8C 31DB            XOR      EBX,EBX  ....>>>>出错时的处理,也就是ebx清清零而已
016F:0051DF8E 33C0            XOR      EAX,EAX  ....>>>>这就是公共的结束部分
016F:0051DF90 5A              POP      EDX
016F:0051DF91 59              POP      ECX    ....>>>> ********
016F:0051DF92 59              POP      ECX
016F:0051DF93 648910          MOV      [FS:EAX],EDX
016F:0051DF96 68B0DF5100      PUSH    DWORD 0051DFB0
016F:0051DF9B 8D45F4          LEA      EAX,[EBP-0C]
016F:0051DF9E BA03000000      MOV      EDX,03
016F:0051DFA3 E83860EEFF      CALL    00403FE0
016F:0051DFA8 C3              RET
======================================
细心一点的朋友会发现,ECX在累加后并我并没有恢复他的初值,原因:1。我没地方能放下xor ecx,ecx或mov cl,0这样的语句了;2。注意到上面的标着********的那行吗?程序会从堆栈中取出ECX的值,而你在累加后的ECX的值会被冲掉。不需要你去恢复他的初值。
再细心一点的朋友会发现,我修改的比原来的程序少了一条mov bl,01这条语句。但根据我观察,没这条语句也没什么大不了,只是程序的这个CALL的返回时的EBX的值比原来的程序中的小1而已。好像没什么关系。其实我也是没地方放这条语句了。就差两个字节!如果上天再给我一次机会的话,我会说,我想要。如果非要给我的要的字节数加上一个限制的话,我希望是:Only TWO!
  如果还可以放两个字节的话,就在51DF8A处放入mov bl,01,后面的顺沿两个字节。这样就可以和原来的程序的这个CALL的返回时的各个值一模一样了。。。不过没关系,修改后的程序只是在第一次注册完后退出的时候有机会发生点小错误。不一定会发生哦。在某种特定的条件下可能会发生,比如输入的注册码长度不够时就有可能会出错。但仅限第一次,以后就再不出错了。。。我也不知道为什么,但重申一次:只在第一次时,在特定条件下有可能出错!以后就绝不出错了!!所以。。。不要紧,呵呵呵。。。
  在你随便注册成功后,程序会把正确的注册码存入注册表里。其实这时候,你就可以用原来的程序而不用修改后的程序了,如果你怕修改后的程序有什么不清楚的后遗症的话。。。其实我觉得是没有后遗症的。但你可以只把修改后的程序当个注册机用!呵呵呵,本来我就是想让他变成自己的注册机,不过光是作为注册机的话,有点太大了的感觉,3M呀!妈妈咪。。。
  好了,大功告成,打个Kiss!
                                    hsf0214于2001-11-05 AM11:21:10