• 标 题:MP3 explorer 破解和注册机的制作
  • 作 者:梦醒时分
  • 时 间:2000
  • 链 接:http://bbs.pediy.com

=========================================================================
工具
=========================================================================
- Soft ice 3.23 (喜新不厌旧!)
- C++编译器
- 大脑和好听的音乐 :)

Note: 我希望你知道这些工具怎么用,否则的话,先保存这篇文章,找一些基础的文章看看
我推荐"看雪学苑"中的文章!我主页上也有连接.

=========================================================================
一,二,三 /开始!
=========================================================================

运行MP3 explorer,到帮助菜单,点击关于,你应该看到输入注册码的地方了吧!

输入名字: ACiD BuRN
假设一个密码: 12321

记得许多教程中让你一步步地跟踪调试吗?太累了,很久都不会走上路子,特别是一些新手,
这儿介绍一种新思维:使用BPR技术,可以轻易帮我们解决问题 :)


设置一个GetWindowtextA断点,回到注册窗口,点击OK! Soft ice自动跳出来!

Break due to BPX USER32!GETWINDOWTEXTA...

不要按任何键!(包括 F11 或 F12) 我们将要看一看堆栈的参数. 为了清楚地介绍,我们将看看
dword (命令 = dd) 那么,在soft ice中键入: dd esp为什么呢?让我告诉你吧:

"dd"是指: 显示 dword 和 "esp" 堆栈指针!

你键入"dd esp"之后, 在Soft-ice's中,窗口将发生变化,我们可以看到参数:

xxxx:yyyyyyyy  A    B    C    D  ................
xxxx:yyyyyyyy  E    F    G    H  ................


那些A,B,C,D,E...应该看起来象这样:  XXXXXXXX (当然XXXXXXXX只是一些数字)

你应该看到一些象这样的:

xxxx:yyyyyyyy  0044423B  00000464  015DB338  0000000A  ...........

我们将只用这些知识 :)

(你应该注意到,在这儿 A=0044423B , B=00000464, C= 015DB338...)

我们只能看到我们注册的名字结束的地方 (015DB338).

键入 D "名字结束的地址" 这儿是: D 015DB338

现在,你可以按一下F11,你就应该在地址中看到我们输入的名字(那就是名字结束的地方...)

很好,我们的路子走对了!

我们将使用一个 BPR (break on memory range). 这种断点的设置应该象这样:
bpr "开始地址" "结束地址" RW

RW 是指:  读和写.就是指将在这段地址进行读写的时候停下来.

那么在Soft-ice中, 键入:
bpr 015DB338 015DB338 + (名字的长度 - 1) RW

如 ACiD BuRN (有九个字母 -> 9 - 1 = 8)

我们的目标是 ACiD BuRN,所以我们键入 :

bpr 15DB338 015DB338+8 RW

这时候,你设置的getwindowtextA断点已经没用了!你只有按F5了,我们将直接在目标处被截下.
但是,在这个软件中,不太直接,我们落在 dll中,所以不停地按F5直到跳出去.当跳到软件的代码
时, 我们来到了好地方! 就是从那开始的: 看看我 winice.log 中的记录吧!

----------------------SNiP----- SNiP----- SNiP----------------------------

:bpx getwindowtexta
Break due to BPX USER32!GetWindowTextA  (ET=1.17 seconds)
:dd esp
:d 15f5a18
Break due to G (ET=268.99 microseconds)
:bpr 15f5a18 15f5a18+8 RW
:bd 0
Break due to BPR #0267:015F5A18 #0267:015F5A20 RW
Break due to BPR #0267:015F5A18 #0267:015F5A20 RW
Break due to BPR #0267:015F5A18 #0267:015F5A20 RW
Break due to BPR #0267:015F5A18 #0267:015F5A20 RW
Break due to BPR #0267:015F5A18 #0267:015F5A20 RW
Break due to BPR #0267:015F5A18 #0267:015F5A20 RW
Break due to BPR #0267:015F5A18 #0267:015F5A20 RW
Break due to BPR #0267:015F5A18 #0267:015F5A20 RW
Break due to BPR #0267:015F5A18 #0267:015F5A20 RW
Break due to BPR #0267:015F5A18 #0267:015F5A20 RW
:u eip l 50

注释:这儿是第一个 loop:

025F:0040A173  8B442420            MOV    EAX,[ESP+20]  ; EAX 中是我名字的地址
025F:0040A177  0FBE0C06            MOVSX  ECX,BYTE PTR [EAX+ESI] ; ECX = 第一个字母的hex值
025F:0040A17B  51                  PUSH    ECX
025F:0040A17C  E8E9BB0100          CALL    00425D6A      ; 有趣 !!!!
025F:0040A181  83C404              ADD    ESP,04
025F:0040A184  03E8                ADD    EBP,EAX      ; 把ascii值转化成hex值送到EBP中
025F:0040A186  46                  INC    ESI          ; 第二个字母!
025F:0040A187  3BF7                CMP    ESI,EDI      ; 都结束了吗 ?!
025F:0040A189  7CE8                JL      0040A173    ; 如果没有,跳回吧 !


025F:0040A18B  8B4C240C            MOV    ECX,[ESP+0C]        /
025F:0040A18F  BAC0D40100          MOV    EDX,0001D4C0        /
025F:0040A194  2BD5                SUB    EDX,EBP            /  我们一会再看这儿
025F:0040A196  33C0                XOR    EAX,EAX          /   
025F:0040A198  3BCA                CMP    ECX,EDX          /
025F:0040A19A  8D4C2420            LEA    ECX,[ESP+20]    /
025F:0040A19E  0F94C0              SETZ    AL            /


在这里, 我们看到了把每个字母的ascii值转化成hex值送到EBP中.但是,我们看到了那个Call
非常有趣!让我们进去看看 :

:u eip l 50

025F:00425D6A  53                  PUSH    EBX
025F:00425D6B  33DB                XOR    EBX,EBX        ; 使EBX=0
025F:00425D6D  391D74344800        CMP    [00483474],EBX 
025F:00425D73  7513                JNZ    00425D88
025F:00425D75  8B442408            MOV    EAX,[ESP+08]  ;把ascii值移至EAX
025F:00425D79  83F861              CMP    EAX,61        ;和 61h 比较   
025F:00425D7C  7C59                JL      00425DD7      ;如果小于 61? 跳到 425DD7
025F:00425D7E  83F87A              CMP    EAX,7A        ;和 7A 比较
025F:00425D81  7F54                JG      00425DD7      ;如果大于 7A? 跳到 425DD7
025F:00425D83  83E820              SUB    EAX,20        ;小于 7A 但大于 61 (eax-20) 
025F:00425D86  5B                  POP    EBX
025F:00425D87  C3                  RET                  ;返回!call结束!
025F:00425D88  56                  PUSH    ESI
025F:00425D89  BE88484800          MOV    ESI,00484888
025F:00425D8E  57                  PUSH    EDI
025F:00425D8F  56                  PUSH    ESI



那么,接着该怎么办呢?!它和 61 , 7A 进行比较! 61h = a 并且 7Ah = z 如果它小于7A但是大于61
它将会被减去20.其实这只是把它转化成大写字母!那么ACiD BuRN 的注册码将会和 Acid Burn, acid
burn, ACID burn...一样.那么主loop会怎么做呢? 把所有字母转化成大写接着把ascii值转化成hex值
送到EBP中... 所有的字母完成后我们将会在这儿:

025F:0040A18B  8B4C240C            MOV    ECX,[ESP+0C]  ; ECX = 我们输入的假注册码
025F:0040A18F  BAC0D40100          MOV    EDX,0001D4C0  ; EDX = 1D4C0h = 12000 
025F:0040A194  2BD5                SUB    EDX,EBP        ; EDX = EDX - EBP
025F:0040A196  33C0                XOR    EAX,EAX        ; EAX = 0
025F:0040A198  3BCA                CMP    ECX,EDX        ; 比较真假注册码
025F:0040A19A  8D4C2420            LEA    ECX,[ESP+20] 
025F:0040A19E  0F94C0              SETZ    AL           

这已经很清楚了!
步骤是这样的:

- 把所有字母转化成大写
- add all ascii values
- Subtract the result of ascii added to 12000

现在,你可以非常容易的为 MP3 Explorer 编写注册机了 !通常, 我会把我自己编写的源代码
给你 :)这儿用的是是 C++ 和 inline asm :)


-------------------------源代码 从这开始!---------------------------------

#include <stdio.h>
#include <string.h>
#include <conio.h>

int main(){
    int i,len;

    unsigned char name[100];

    unsigned long check=128;

    printf("\Mp3 Explorer Keygen By : ACiD BuRN [Immortal descendants] \n ");
    printf("\                                                          ");
    printf("\nEnter name: ");
    gets(name);
    len=strlen(name);

asm
{
      xor ecx, ecx
      xor edi, edi    
      mov edx, [len]

start1:
      movsx eax, [name+ecx]
      cmp eax, 97
      jl temp1
      cmp eax, 122
      jg temp1
      sub eax, 32

temp1:
      add edi, eax
      inc ecx
      cmp ecx, edx
      jne start1

      mov eax, 120000
      sub eax, edi
      mov [check], eax

}
   
    printf("=: %lu" ,check); /* %lu = decimal, check = serial */
    printf("\nEnjoy!");
getch();
return 0;

}

----------------------------结束---------------------------------

=======================================================================
翻译来自 "梦醒时分" 网站,欢迎访问获得更多的资料,争作中国最好的网站!      }
translate from "time of dream broken" get more information at our web.}
                    We Will Best in China!                          }
======================================================================}
http://todb.yeah.net          http://go.163.com/~yinqun2000/        }
=======================================================================