• 标 题:破解HappyEO电子琴203版的注册码。 (7千字)
  • 作 者:大波罗
  • 时 间:2001-9-28 18:14:04
  • 链 接:http://bbs.pediy.com

HappyEO电子琴的新版本2.40中,注册码可以直接从内存中找到,而在HappyEO203这个老版本中,却要通过计算才能得出,不知道作者是怎么想的,算法比较简单,很适合初学者学习,有兴趣的朋友可以拿它来练手,我们开始吧:
1.    运行TRW2K
2.  用户名输入:wdfdiablo  注册码:7878787878
3.  下断bpx hmemcpy,后回到主程序,点注册,被拦下,用bd *清除断点,下pmodule回到HappyEO的领空,按F10数次,来到:
:51084189 E8F2FCF7FF              call 51003E80
:5108418E 8D85C0FEFFFF            lea eax, dword ptr [ebp+FFFFFEC0]
:51084194 50                        push eax
:51084195 8D95B8FDFFFF            lea edx, dword ptr [ebp+FFFFFDB8]
:5108419B A1D4630D51              mov eax, dword ptr [510D63D4]
:510841A0 8B00                    mov eax, dword ptr [eax]
:510841A2 8B80D0020000            mov eax, dword ptr [eax+000002D0]
:510841A8 E89BCDFAFF              call 51030F48
:510841AD 8B95B8FDFFFF            mov edx, dword ptr [ebp+FFFFFDB8]
:510841B3 8D85BCFDFFFF            lea eax, dword ptr [ebp+FFFFFDBC]
:510841B9 B9FF000000              mov ecx, 000000FF
:510841BE E8BDFCF7FF              call 51003E80
:510841C3 8D85BCFDFFFF            lea eax, dword ptr [ebp+FFFFFDBC]  ;D EAX,看见wdfdiablo
:510841C9 5A                      pop edx                          ;D EDX,看见7878787878
:510841CA E881EEFFFF              call 51083050                    ;算注册码的CALL,F8进入
:510841CF 84C0                    test al, al
:510841D1 0F849C000000            je 51084273                      ;若al为0,则注册失败
:510841D7 A188600D51              mov eax, dword ptr [510D6088]
:510841DC C60001                  mov byte ptr [eax], 01
:510841DF 8D95B4FDFFFF            lea edx, dword ptr [ebp+FFFFFDB4]
:510841E5 A1D4630D51              mov eax, dword ptr [510D63D4]
:510841EA 8B00                    mov eax, dword ptr [eax]

进入算注册码的CALL:
* Referenced by a CALL at Address:
|:510841CA 
|
:51083050 53                      push ebx
:51083051 56                      push esi
:51083052 57                      push edi                ;保存现场
:51083053 83C4CC                  add esp, FFFFFFCC
:51083056 8BF2                    mov esi, edx            ;EDX=.7878787878,其中的“.”是0xA,即注册码的位数为10位
:51083058 8D3C24                  lea edi, dword ptr [esp
:5108305B 33C9                    xor ecx, ecx            ;计数器清0
:5108305D 8A0E                    mov cl, byte ptr [esi]    ;将注册码位数放入cl
:5108305F 80F908                  cmp cl, 08              ;位数是否大于8
:51083062 7202                    jb 51083066            ;不大于则开始下一步
:51083064 B108                    mov cl, 08            ;若大于8,则只取前8位

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:51083062(C)
|
:51083066 880F                    mov byte ptr [edi], cl    ;将位数放在EDI所指位址中
:51083068 46                      inc esi                ;指向注册码第一位
:51083069 47                      inc edi                ;指向存放注册码最后一位的下一位址
:5108306A F3A4                    repz movsb            ;将ESI位址内的内容挎贝到EDI所指位址上,每次取1个Byte,共循环8次(cl=8),即78787878
:5108306C 8BF0                    mov esi, eax            ;D ESI=.wdfdiablo,其中的“.”是0x9,即用户名的位数为9位

:5108306E 8D7C240A                lea edi, dword ptr [esp+0A] ;
:51083072 33C9                    xor ecx, ecx              ;计数器清0
:51083074 8A0E                    mov cl, byte ptr [esi]
:51083076 80F928                  cmp cl, 28
:51083079 7202                    jb 5108307D
:5108307B B128                    mov cl, 28                ;若用户名位数大于40位,则只取40位

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:51083079(C)
|
:5108307D 880F                    mov byte ptr [edi], cl
:5108307F 46                      inc esi
:51083080 47                      inc edi
:51083081 F3A4                  repz movsb                ;同上,挎贝用户名
:51083083 C644240900              mov [esp+09], 00         
:51083088 8A44240A                mov al, byte ptr [esp+0A]  ;将用户名位数放入al
:5108308C 3C04                    cmp al, 04              ;用户名位数是否为4
:5108308E 723D                    jb 510830CD            ;小于则注册失败
:51083090 803C2408                cmp byte ptr [esp], 08      ;注册码位数是否为8
:51083094 7537                    jne 510830CD            ;小于则注册失败
:51083096 33C9                    xor ecx, ecx            ;计数器清0
:51083098 25FF000000              and eax, 000000FF        ;将EAX高16位清0,即EAX=9(用户名位数)
:5108309D 85C0                    test eax, eax           
:5108309F 7E0C                    jle 510830AD            ;EAX若为0,则注册失败
:510830A1 8D54240B                lea edx, dword ptr [esp+0B] ;EDX指向用户名第一个字母

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:510830AB(C)
|
:510830A5 8A1A                    mov bl, byte ptr [edx]      ;取用户名第一个字母“w”
:510830A7 02CB                    add cl, bl                        ;将“w”的ASCII值加入cl
:510830A9 42                      inc edx                              ;指向用户名下一个字母“d”
:510830AA 48                      dec eax                            ;用户名位数减1
:510830AB 75F8                    jne 510830A5                ;共循环9次,将所有用户名字母的ASCII和相加放
                                                                                入cl,注意,因cl是8个位,故总和只取低8位,即1个字节,
                                                                                这里得出cl=0xAC
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:5108309F(C)
|
:510830AD 33D2                    xor edx, edx                ;EDX初始化为0
:510830AF 33C0                    xor eax, eax                  ;EAX初始化为0
:510830B1 8A0424                mov al, byte ptr [esp]  ;注册码位数放al,al=8
:510830B4 85C0                    test eax, eax                  ;以下和算用户名的方法相同,不再赘述
:510830B6 7E0C                    jle 510830C4
:510830B8 8D742401            lea esi, dword ptr [esp+01]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:510830C2(C)
|
:510830BC 8A1E                    mov bl, byte ptr [esi]
:510830BE 02D3                    add dl, bl
:510830C0 46                      inc esi
:510830C1 48                      dec eax
:510830C2 75F8                    jne 510830BC           

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:510830B6(C)
|
:510830C4 3AD1                    cmp dl, cl                ;用户名每个字母ACSII值的和与假注册码每个ASCII的和的低8位作比较
:510830C6 7505                    jne 510830CD              ;若不正确则注册失败
:510830C8 C644240901              mov [esp+09], 01            ;注册成功的标志

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:5108308E(C), :51083094(C), :510830C6(C)
|
:510830CD 8A442409                mov al, byte ptr [esp+09]    ;返回的al值为1
:510830D1 83C434                  add esp, 00000034
:510830D4 5F                      pop edi
:510830D5 5E                      pop esi
:510830D6 5B                      pop ebx                  ;恢复算注册码前的现场,返回主程序
:510830D7 C3                      ret

可以看出,注册码有很多,只要满足最后的比较条件即可,这里我算出一个:
用户名:wdfdiablo    注册码:55555559

大波罗破解
我的主页http://wdfdiablo.myetang.com
转载请保持完整,谢谢。
2001.9.20

  • 标 题:搞定!HappyEO203的注册码算法和注册机(经整理后献给和我一样迷茫的初学者) (8千字)
  • 作 者:大波罗
  • 时 间:2001-9-28 23:43:17
  • 链 接:http://bbs.pediy.com

HappyEO203的注册码算法和注册机

HappyEO电子琴的新版本2.40中,注册码可以直接从内存中找到,而在HappyEO203这个老版本中,却要通过计算才能得出,不知道作者是怎么想的,算法比较简单,很适合初学者学习,我作了详细的解释,有兴趣的朋友可以拿它来练手,我们开始吧:
1.    运行TRW2K
2.    用户名输入:wdfdiablo  注册码:7878787878
3.    下断bpx hmemcpy,后回到主程序,点注册,被拦下,用bd *清除断点,下pmodule回到HappyEO的领空,按F10数次,来到:
:51084189 E8F2FCF7FF              call 51003E80
:5108418E 8D85C0FEFFFF            lea eax, dword ptr [ebp+FFFFFEC0]
:51084194 50                        push eax
:51084195 8D95B8FDFFFF            lea edx, dword ptr [ebp+FFFFFDB8]
:5108419B A1D4630D51              mov eax, dword ptr [510D63D4]
:510841A0 8B00                    mov eax, dword ptr [eax]
:510841A2 8B80D0020000            mov eax, dword ptr [eax+000002D0]
:510841A8 E89BCDFAFF              call 51030F48
:510841AD 8B95B8FDFFFF            mov edx, dword ptr [ebp+FFFFFDB8]
:510841B3 8D85BCFDFFFF            lea eax, dword ptr [ebp+FFFFFDBC]
:510841B9 B9FF000000              mov ecx, 000000FF
:510841BE E8BDFCF7FF              call 51003E80
:510841C3 8D85BCFDFFFF            lea eax, dword ptr [ebp+FFFFFDBC]  ;D EAX,看见wdfdiablo
:510841C9 5A                      pop edx                          ;D EDX,看见7878787878
:510841CA E881EEFFFF              call 51083050                    ;算注册码的CALL,F8进入
:510841CF 84C0                    test al, al
:510841D1 0F849C000000            je 51084273                      ;若al为0,则注册失败
:510841D7 A188600D51              mov eax, dword ptr [510D6088]
:510841DC C60001                  mov byte ptr [eax], 01
:510841DF 8D95B4FDFFFF          lea edx, dword ptr [ebp+FFFFFDB4]
:510841E5 A1D4630D51              mov eax, dword ptr [510D63D4]
:510841EA 8B00                    mov eax, dword ptr [eax]

进入算注册码的CALL:
* Referenced by a CALL at Address:
|:510841CA 
|
:51083050 53                      push ebx
:51083051 56                      push esi
:51083052 57                      push edi                ;保存现场
:51083053 83C4CC                  add esp, FFFFFFCC
:51083056 8BF2                    mov esi, edx            ;EDX=.7878787878,其中的“.”是0xA,即注册码的位数为10位
:51083058 8D3C24                  lea edi, dword ptr [esp
:5108305B 33C9                    xor ecx, ecx            ;计数器清0
:5108305D 8A0E                    mov cl, byte ptr [esi]    ;将注册码位数放入cl
:5108305F 80F908                  cmp cl, 08              ;位数是否大于8
:51083062 7202                    jb 51083066            ;不大于则开始下一步
:51083064 B108                    mov cl, 08            ;若大于8,则只取前8位

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:51083062(C)
|
:51083066 880F                    mov byte ptr [edi], cl      ;将位数放在EDI所指位址中
:51083068 46                      inc esi                  ;指向注册码第一位
:51083069 47                      inc edi                  ;指向存放注册码最后一位的下一位址
:5108306A F3A4                    repz movsb            ;将ESI位址内的内容挎贝到EDI所指位址上,每次取1个Byte,共循环8次(cl=8),即78787878
:5108306C 8BF0                    mov esi, eax            ;D ESI=.wdfdiablo,其中的“.”是0x9,即用户名的位数为9位

:5108306E 8D7C240A                lea edi, dword ptr [esp+0A]
:51083072 33C9                    xor ecx, ecx              ;计数器清0
:51083074 8A0E                    mov cl, byte ptr [esi]
:51083076 80F928                  cmp cl, 28
:51083079 7202                    jb 5108307D
:5108307B B128                    mov cl, 28                ;若用户名位数大于40位,则只取40位

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:51083079(C)
|
:5108307D 880F                    mov byte ptr [edi], cl
:5108307F 46                      inc esi
:51083080 47                      inc edi
:51083081 F3A4                  repz movsb                ;同上,挎贝用户名
:51083083 C644240900              mov [esp+09], 00         
:51083088 8A44240A                mov al, byte ptr [esp+0A]  ;将用户名位数放入al
:5108308C 3C04                    cmp al, 04              ;用户名位数是否为4
:5108308E 723D                    jb 510830CD            ;小于则注册失败
:51083090 803C2408                cmp byte ptr [esp], 08      ;注册码位数是否为8
:51083094 7537                    jne 510830CD            ;小于则注册失败
:51083096 33C9                    xor ecx, ecx              ;计数器清0
:51083098 25FF000000              and eax, 000000FF        ;将EAX高16位清0,即EAX=9(用户名位数)
:5108309D 85C0                    test eax, eax           
:5108309F 7E0C                    jle 510830AD            ;EAX若为0,则注册失败
:510830A1 8D54240B                lea edx, dword ptr [esp+0B] ;EDX指向用户名第一个字母

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:510830AB(C)
|
:510830A5 8A1A                    mov bl, byte ptr [edx]      ;取用户名第一个字母“w”
:510830A7 02CB                    add cl, bl                ;将“w”的ASCII值加入cl
:510830A9 42                      inc edx                  ;指向用户名下一个字母“d”
:510830AA 48                      dec eax                ;用户名位数减1
:510830AB 75F8                    jne 510830A5            ;共循环9次,将所有用户名字母的ASCII和相加放
                                                          入cl,注意,因cl是8个位,故总和只取低8位,即1个字节,这里得出cl=0xAC
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:5108309F(C)
|
:510830AD 33D2                  xor edx, edx            ;EDX初始化为0
:510830AF 33C0                    xor eax, eax              ;EAX初始化为0
:510830B1 8A0424                  mov al, byte ptr [esp]      ;注册码位数放al,al=8
:510830B4 85C0                    test eax, eax              ;以下和算用户名的方法相同,不再赘述
:510830B6 7E0C                    jle 510830C4
:510830B8 8D742401                lea esi, dword ptr [esp+01]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:510830C2(C)
|
:510830BC 8A1E                    mov bl, byte ptr [esi]
:510830BE 02D3                    add dl, bl
:510830C0 46                      inc esi
:510830C1 48                      dec eax
:510830C2 75F8                    jne 510830BC           

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:510830B6(C)
|
:510830C4 3AD1                    cmp dl, cl                ;用户名每个字母ACSII值的和与假注册码每个ASCII的和的低8位作比较
:510830C6 7505                    jne 510830CD              ;若不正确则注册失败
:510830C8 C644240901              mov [esp+09], 01            ;注册成功的标志

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:5108308E(C), :51083094(C), :510830C6(C)
|
:510830CD 8A442409                mov al, byte ptr [esp+09]    ;返回的al值为1
:510830D1 83C434                  add esp, 00000034
:510830D4 5F                      pop edi
:510830D5 5E                      pop esi
:510830D6 5B                      pop ebx                  ;恢复算注册码前的现场,返回主程序
:510830D7 C3                      ret

可以看出,注册码有很多,只要满足最后的比较条件即可,这里我算出一个:
用户名:wdfdiablo    注册码:55555559

下面是C写的注册机:
#include <stdio.h>
#include <stdlib.h>
main()
{
int var1=0;
int var2=0;
int n=0;
int b,i,num;
char username[40];
int result[7];
printf("********  The HappyEO203 cracked by wdfdiablo  ********\n");
printf("********  http://wdfdiablo.myetang.com  ***************\n");
printf("please enter your name:");
gets(username);
for(num=0;username[num]!='\0';++num)
  { b=username[num];
    var1=b+var1;}                /*计算用户名各位的ASCII值之和*/
loop:
do{
i=random(10);                   
i=i+48;                          /*将数字转为字符*/
result[n]=i;
var2=i+var2;
n=n+1;
}while(n<8);
var2=reg(var2);                  /*注册码各位和的低8位值*/
var1=reg(var1);                  /*用户名各位和的低8位值*/
if(var2==var1)
{
    printf("Regcode is: ");
    for(n=0;n<8;n++)
    { printf("%c",result[n]); }
    printf("\n\nBye!");            /*如果和相等则打印注册码*/
    }
else
{n=0;
var2=0;
goto loop;}                      /*若不相等则继续寻找注册码*/
}
int reg(int var3)                  /*取和低8位的函数*/
{
asm mov cx,var3
    return(_CL);
}
程序中内嵌行汇编,在命令行TCC下编译通过。

大波罗破解
我的主页 http://wdfdiablo.myetang.com 
转载请保持完整,谢谢。
2001.9.28