• 标 题:破解accoustica 2.21(带注册机)----让高手见笑了:) (11千字)
  • 作 者:alphakk
  • 时 间:2002-3-31 13:57:51
  • 链 接:http://bbs.pediy.com

accoustica 2.21注册码算法模块分析
=================================
软件简介:
  Acoustica是一个强大的声音编辑程序,它拥
有对声音进行动态处理,实施降噪,格式转换,时
标调整,均衡,加入合唱效果、混响效果等等一些
功能。用它配合其他工具软件可以做出很不错的卡
拉OK,对于效果不好声音或卡拉OK进行处理后,可以
达到很专业的水平!可以说是Cool edit pro的精简
版!!新版本修正了一些BUG!
================================
破解工具:SOFTICE,W32DASM

注册码验证方式:用GETDLGITEMTEXT()函数取得用户名,公司名和注册码,然后在注册表的适当位置建立        Name,Company,Key三个键分别存放用户名公司名和注册码,再从注册表中将各项值取出进        行运算得出真正的注册码并与用户输入的注册码进行比较,不同则弹出注册失败对话框。
================================
分析:
用BPX REGQUARYVALUEEXA设断,用户名:alpha    公司名:ckck    注册码:98765432
拦截后跟踪至:

* Possible StringData Ref from Data Obj ->"Company"
                                  |
:0044AA08 68F7EA4900              push 0049EAF7

* Possible StringData Ref from Data Obj ->"RegisterInfo"
                                  |
:0044AA0D 68EAEA4900              push 0049EAEA
:0044AA12 50                      push eax
:0044AA13 E8E4A6FCFF              call 004150FC
:0044AA18 83C418                  add esp, 00000018
:0044AA1B 8D950CFFFFFF            lea edx, dword ptr [ebp+FFFFFF0C]
:0044AA21 8B0DEED54A00            mov ecx, dword ptr [004AD5EE]
:0044AA27 6A50                    push 00000050

* Possible Reference to Dialog: 
                                  |
:0044AA29 6811EB4900              push 0049EB11
:0044AA2E 52                      push edx

* Possible StringData Ref from Data Obj ->"Key"
                                  |
:0044AA2F 680DEB4900              push 0049EB0D

* Possible StringData Ref from Data Obj ->"RegisterInfo"
                                  |
:0044AA34 6800EB4900              push 0049EB00
:0044AA39 51                      push ecx
:0044AA3A E8BDA6FCFF              call 004150FC
:0044AA3F 83C418                  add esp, 00000018
:0044AA42 8D45AC                  lea eax, dword ptr [ebp-54]
:0044AA45 50                      push eax
:0044AA46 E81DE20300              call 00488C68            <<-----------判断是否有用户名
:0044AA4B 59                      pop ecx
:0044AA4C 8D955CFFFFFF            lea edx, dword ptr [ebp+FFFFFF5C]
:0044AA52 52                      push edx
:0044AA53 E810E20300              call 00488C68        <<-----------判断是否有公司名
:0044AA58 59                      pop ecx
==============================
以上为注册信息的初始化

继续跟踪,来到:
以下便是用户名的算法:
:0044AA59 BB01000000              mov ebx, 00000001       <<---------EBX赋初值,此时ESI=0x3AC7(初始值,与用户名,公司名无关)
:0044AA5E 8D7DAC                  lea edi, dword ptr [ebp-54]  <<---------用户名首地址->EDI
:0044AA61 EB13                    jmp 0044AA76

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0044AA82(C)
|
:0044AA63 0FBE07                  movsx eax, byte ptr [edi]   <<--------用户名第一个字符->EAX
:0044AA66 8BD3                    mov edx, ebx
:0044AA68 83E203                  and edx, 00000003
:0044AA6B 0FBE4C15FC              movsx ecx, byte ptr [ebp+edx-04]  <<-----相关数字{0xEB,0x7B,0x11,0x22}依次送入ECX(每次循环按顺序送入一个,四次之后再从头开始)
:0044AA70 F7E9                    imul ecx
:0044AA72 03F0                    add esi, eax
:0044AA74 43                      inc ebx
:0044AA75 47                      inc edi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0044AA61(U)
|
:0044AA76 8D45AC                  lea eax, dword ptr [ebp-54]  <<---------用户名首地址->EAX
:0044AA79 50                      push eax
:0044AA7A E805570300              call 00480184                  <<---------取得用户名的长度并送入EAX
:0044AA7F 59                      pop ecx
:0044AA80 3BD8                    cmp ebx, eax         <<----------用户名长度与循环次数比较
:0044AA82 76DF                    jbe 0044AA63         <<----------不大于则跳回
==================================
下面开始运算公司名
* Possible Ref to Menu: MenuID_0064, Item: "铸笙蚩(C)..."
                                  |

* Possible Reference to String Resource ID=00001: "揺?痼蚩"
                                  |
:0044AA84 BB01000000              mov ebx, 00000001      <<-----------初始化EBX,此时ESI的值为用户名运算后的结果
:0044AA89 8DBD5CFFFFFF            lea edi, dword ptr [ebp+FFFFFF5C]  <<---公司名首地址->EDI
:0044AA8F EB13                    jmp 0044AAA4
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0044AAB3(C)
|
:0044AA91 0FBE07                  movsx eax, byte ptr [edi]  <<-----------公司名的第一个字符
:0044AA94 8BD3                    mov edx, ebx
:0044AA96 83E203                  and edx, 00000003
:0044AA99 0FBE4C15FC              movsx ecx, byte ptr [ebp+edx-04]<<-----{0xEB,0x7B,0x11,0x22}
:0044AA9E F7E9                    imul ecx
:0044AAA0 03F0                    add esi, eax
:0044AAA2 43                      inc ebx
:0044AAA3 47                      inc edi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0044AA8F(U)
|
:0044AAA4 8D855CFFFFFF            lea eax, dword ptr [ebp+FFFFFF5C]
:0044AAAA 50                      push eax
:0044AAAB E8D4560300              call 00480184       <<--------取得公司名的长度并送入EAX
:0044AAB0 59                      pop ecx
:0044AAB1 3BD8                    cmp ebx, eax
:0044AAB3 76DC                    jbe 0044AA91
:0044AAB5 8BC6                    mov eax, esi
:0044AAB7 B9A0860100              mov ecx, 000186A0     <<-------常量0x186A0->ECX
:0044AABC 33D2                    xor edx, edx
:0044AABE F7F1                    div ecx                  <<------- 求余->EDX
:0044AAC0 8BDA                    mov ebx, edx
:0044AAC2 8D85BCFEFFFF            lea eax, dword ptr [ebp+FFFFFEBC]
:0044AAC8 53                      push ebx                  <<-------保存EBX
* Possible Reference to Dialog: 
                                  |
:0044AAC9 6812EB4900              push 0049EB12    前缀“AC210-”入栈
:0044AACE 50                      push eax
:0044AACF E8608E0300              call 00483934  <<------将最终运算结果转为字符串并与“AC210-”连接,成为正确注册码
:0044AAD4 83C40C                  add esp, 0000000C
:0044AAD7 8D950CFFFFFF            lea edx, dword ptr [ebp+FFFFFF0C] <<-------输入的注册码的首地址->EDX
:0044AADD 52                      push edx
:0044AADE 8D8DBCFEFFFF            lea ecx, dword ptr [ebp+FFFFFEBC]  <<-------前缀为“AC210-“的正确的注册码的首地址->ECX
:0044AAE4 51                      push ecx
* Reference To: KERNEL32.lstrcmpA, Ord:0000h
                                  |
:0044AAE5 E8344C0400              Call 0048F71E          <<--------字符串比较函数
:0044AAEA 85C0                    test eax, eax
:0044AAEC 7504                    jne 0044AAF2          <<---------不同则跳
:0044AAEE B001                    mov al, 01
:0044AAF0 EB32                    jmp 0044AB24
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0044AAEC(C)
|
:0044AAF2 53                      push ebx

* Possible StringData Ref from Data Obj ->"AC220-%d"
                                  |
:0044AAF3 681BEB4900              push 0049EB1B        <<------前缀“AC220-”入栈
:0044AAF8 8D95BCFEFFFF            lea edx, dword ptr [ebp+FFFFFEBC]
:0044AAFE 52                      push edx
:0044AAFF E8308E0300              call 00483934
:0044AB04 83C40C                  add esp, 0000000C
:0044AB07 8D8D0CFFFFFF            lea ecx, dword ptr [ebp+FFFFFF0C] <<------输入的注册码的首地址->ECX
:0044AB0D 51                      push ecx
:0044AB0E 8D85BCFEFFFF            lea eax, dword ptr [ebp+FFFFFEBC]  <<------前缀为“AC220-”的正确的注册码的首地址->EAX
:0044AB14 50                      push eax

* Reference To: KERNEL32.lstrcmpA, Ord:0000h
                                  |
:0044AB15 E8044C0400              Call 0048F71E        <<-------字符串比较函数
:0044AB1A 85C0                    test eax, eax
:0044AB1C 7504                    jne 0044AB22        <<--------不同则跳走
:0044AB1E B001                    mov al, 01
:0044AB20 EB02                    jmp 0044AB24

============================最后来到:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0044B20E(C)
|
:0044B2ED 68C8000000              push 000000C8
:0044B2F2 8D9FB6000000            lea ebx, dword ptr [edi+000000B6]
:0044B2F8 53                      push ebx

* Possible Reference to String Resource ID=09141: "@    革鑼
9M."
                                  |
:0044B2F9 68B5230000              push 000023B5
:0044B2FE 8D4704                  lea eax, dword ptr [edi+04]
:0044B301 50                      push eax
:0044B302 E8D6B80200              call 00476BDD
:0044B307 83C410                  add esp, 00000010
:0044B30A 8BD3                    mov edx, ebx
:0044B30C 8B4F66                  mov ecx, dword ptr [edi+66]
:0044B30F 8B01                    mov eax, dword ptr [ecx]
:0044B311 6A00                    push 00000000

* Possible Reference to Dialog: 
                                  |
:0044B313 6893EB4900              push 0049EB93
:0044B318 52                      push edx
:0044B319 8B500C                  mov edx, dword ptr [eax+0C]
:0044B31C 52                      push edx
:0044B31D 8B4868                  mov ecx, dword ptr [eax+68]
:0044B320 51                      push ecx
:0044B321 E818DA0100              call 00468D3E    <<------注册失败对话框
:0044B326 83C414                  add esp, 00000014
==============================
此软件的注册码算法很简单,它将用户名与公司名进行相同的运算后得出真正的注册码(有两个,不知有什么区别),其中用到了五个数字常量:{0xEB,0x7B,0x11,0x2A}和0x186A0,还有一个初始值为0x3AC7的变量。
==============================
附:注册机源程序(偷了点懒的^_^)
#include<iostream.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>

void main()
{
    int N[4]={-21,123,17,42},temp1=0,temp2=0,Name,Company,RegistCode=15047,count1,count2,LengthOftempName,LengthOftempCompany;
    char tempName[80],tempCompany[80];
    cout<<"                  KeyGen for Acoustica V2.21(Made by alpha)"<<endl;
    cout<<"Your Name:";
    while(cin.getline(tempName,80))
    {
        LengthOftempName=strlen(tempName);
        for(count1=0;count1<LengthOftempName;count1++)
        {
            if(temp1==4)
                temp1=0;
            Name=tempName[count1];
//            cout<<Name[count1]<<endl;
            Name*=N[temp1];
//            cout<<N[temp1]<<endl;
            RegistCode+=Name;
            temp1++;
        }
        break;
    }
    cout<<endl;
    cout<<"Your Company:";
    while(cin.getline(tempCompany,80))
    {
        LengthOftempCompany=strlen(tempCompany);
        for(count2=0;count2<LengthOftempCompany;count2++)
        {
            if(temp2==4)
                temp2=0;
            Company=tempCompany[count2];
            Company*=N[temp2];
            RegistCode+=Company;
            temp2++;
        }
        break;
    }
    cout<<endl;
    cout<<"Your Registration Code is:"<<"AC210-"<<RegistCode<<endl;
    cout<<"                      or:"<<"AC220-"<<RegistCode<<endl;
    cout<<"\nPress any key to terminate...";
    while(cin.get())
        exit(0);
}
            

        

======================
源程序在VC++6.0下编译通过
                                      
                                                                        CrAcKeD BY alphakk(alpha)