• 标 题:干涸的(Asp maker version 2.2 破解手记) (8千字)
  • 作 者:iu365
  • 时 间:2002-10-30 23:24:29
  • 链 接:http://bbs.pediy.com

Asp maker 的主页是http://www.hkvstore.com/aspmaker/,这是一款自动生
成asp的软件


安装aspmaker之后,先得观察一下详细的注册过程。点击help菜单中的
register,马上弹出一注册窗口,要求填入license name和key。好了,
乱填一通,点击确定,窗口消失,提出注册失败(据说以前有人破解一
个软件的时候,也是乱填了一通,然后却注册成功了,真faint啊。不过
我是没有那样的运气的,如果有的话早买彩票发了)。点确定,提示框消
失,注册框又跑了出来。看来,注册过程大约是这样的(用mfc式的语法
表示)

while (CRegDialog.DoModal()==IDOK)
{
        bool b = CheckRegCode(CRegDialog.strName,CRegDialog.strKey);
        if(b)
        {
        ……
                break;
        }
        else
        {
                MessageBox(errorstr);
        }
}

用fi分析aspmaker,发现是aspack加壳的。很好,用aspackdie一下就解
了。干干净净的。再用fi分析解了后的文件,发现是用delphi写的。

当时,我立即想到了dede,抓来dede,把aspmaker给反编译了。生成了一
个工程。拿delphi7分析,我本人从没用过delphi,装了这玩意只是为了有
时候的破解需要。看了好长时间啊,发现检查注册码的那一段没有被反编
译出来!!我faint啊,花了这么多时间打水飘。

痛定思痛,决定还是用softice吧。Softice真是一个万能工具啊,难怪人
人都这么爱她。在softice 中,下命令bpx messageboxexw(注意:我的系
统是2k,在2k/xp下messageboxa ,messageboxw, messageboxexa都要调用
messageboxexw的,所以bpx messageboxexw 是最好的选择)在license
name中填入cygwin,乱填一个key,点确定,然后,弹出警告框,报错。
Faint,原来这个东东只是长的像messgebox,其实并不是messagebox。
没办法了,根据上面的猜想,只好下bpx showwindow的命令了。
Showwindow这个函数被windows中的程序调用得太多了,不能像上
面那样下命令。不过不要紧,用任务管理器查得aspmaker的pid,
转化为16进制后是564。好了,下命令bpx showwindow if(pid==564),
再输入上面的内容,点确定。

Good!总算断下来了,看来天总是要亮的啊,只是不知能不能等到太阳出
来。不停的按F10,不久,那个报错的警告框露出了一点点,然后进入了
一个"死"循环。程序总在004857a8前转来转去的。将鼠标移到004857a8
那一行,按f7。OK,softice不见了,留下一个残缺的警告框,点确定。
又回到softice中。继续按F10,不久后,那个注册框又露出来了,接着,
又进入了一个循环。居然还是在004857a8的前面!如前,在004857a8处
按F7,看到一个面目全非的注册窗口(这是在按F10的过程中被softice遮
挡弄坏的),不过不要紧,打一个记事本(或其它任何有窗口的程序),
把窗口在屏幕上拖一拖,注册框就恢复本来面目了。

任然是name栏填cygwin,在注册码栏乱填。按确定,soft停在004857a8一
行。不停的按F10,不久,来到了这么一个地方:

001B:005D3871 CALL      [EDX+000000EC]
001B:005D3877 DEC      EAX
001B:005D3878 JNZ      005D3927
001B:005D387E LEA      EDX,[EBP-010C]
001B:005D3884 MOV      EAX,[EBP-04]
001B:005D3887 MOV      EAX,[EAX+60]
001B:005D388A MOV      EAX,[EAX+00000304]
001B:005D3890 CALL      0046814C
可以看到005D3878处,有一条跳转指令。在005d3877处下断点,并把原来的
bpx showwindow的断点删掉。别高兴!!这还不是检查注册码的关键跳转。
这条指令就是检查点的是确定还是取消。不信?分别点确定和取消,
在005d3877处,你会看到,eax的值分别是1和2,这下你不能不信了吧。
在执行完005D387E后,用命令d edx可以看到刚输入的注册码,看来,
已经到了检查注册码的地带了。嗯,高兴几秒钟吧,高兴完了再继续干。
小心的按F10,注意到这里:
001B:005D38DF  LEA      EDX,[EBP-020C]
001B:005D38E5  MOV      EAX,[EBP-04]
001B:005D38E8  POP      ECX
001B:005D38E9  CALL      005D35C4
001B:005D38EE  TEST      AL,AL
001B:005D38F0  JZ        005D3910
001B:005D38F2  PUSH      00
001B:005D38F4  MOV      CX,[005D3984]
001B:005D38FB  MOV      DL,02
001B:005D38FD  MOV      EAX,005D3990
在005D38EE处和005D38F0处的两条指令太诱人了!!持行到005D38EE处,
可以看到eax=0执行命令r al=1,把al的值改成1。按下F5,怎么样?
它说Thank you for registering ASPMaker嗳!!不用说了,005D38E9
处调用的005D35C4这个函数就是检查注册码的段!!

再次持行到005D38E9处。这次不按F10,按F11跟进去(顺便说一下,
softice默认的F11键不是trace into的功能,我用VC用多了,经常
误按F11,只好把softice的F11自定义为trace into,在这里你可以
用t命令跟入。)然后小心的F10,马上发现一段嫌疑代码:

001B:005D363B  MOV      EDX,[EBP-0308]
001B:005D3641  LEA      ECX,[EBP-0304]
001B:005D3647  MOV      EAX,ESI
001B:005D3649  CALL      005D39D8
001B:005D364E  MOV      EDX,[EBP-0304]
001B:005D3654  LEA      EAX,[EBP-0300]
001B:005D365A  MOV      ECX,000000FF

单步执行到005D3654处,持行命令d edx,softice显示出一段字符
串:P0DOUC942U49。多诱人啊!!难道是注册码?拿张纸抄过来。
禁用所有断点,F5出来。在注册框中输入name:cygwin,
输入key: P0DOUC942U49,点确定。Yeah!!!注册成功了!!

本来,到了这一步,就算OK了。可以版主居然叫我写keygen,唉,还得干啊。


Key是005D39D8这个函数里生成的。现在不用softice了,改用w32dasm
反汇编,找到这个函数。本来,我想把汇编代码抓出来写个keygen的,
只是这个函数调用了很多函数,那些函数又调用了一些函数。我抓了
一段汇编,发现越抓越要干很多事,真是苦不堪言啊。没办法,后来
又改用softice跟踪,弄清了注册码的计算方法,用C写了一个keygen。

顺便说一下,这是我写的第一个keygen,所以也花了不少时间,为此,
还专门用mfc写了一个通用的keygen模型接口。以后再要写keygen,
只要写一点点代码就行了。这个程序的keygen的C源代码附后。windows图形界面
的keygen,可以在ftp.lib.pku.edu.cn找到。

嗯,大功告成了,yeah!!!

/* ====== kegen for aspmaker v2.2 by cygwin@SMTH ====== */
#include <stdio.h>
#include <string.h>

const char * l = "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ";

char * strrev(char * src)
{
        int len;
        int i;
        if(!src || !*src)return src;
        len = strlen(src)-1;
        for(i=0;(i<<1)<len;i++)
        {
                char ch = src[len-i];
                src[len-i]=src[i];
                src[i] = ch;
        }
        return src;
}

char MakeUpper(char ch)
{
        if(ch>='a' && ch<='z')
        {
                ch -= 0x20;
        }
        return ch;
}

char * step1(char *name)
{
        const int len = strlen(name);
        static char step1_code[64];
        char code[32];
        int i = len;
        int _di;
        code[0x17]=0;

        if(len==0x17)
        {
                int j;
                for(j=0;j<0x17;j++)
                        code[j]=MakeUpper(name[j]);
        }
        else if(len<0x17)
        {
                int mem;
                int i;
                _di = 0;
                for(i=1;i!=0x18;i++)
                {
                        short x = i*len/0x17;
                        if(x==0)x=1;
                        if(_di == x)
                        {
                                int iii = 0x25 - i -1 ;
                                code[i-1] = MakeUpper(l[iii]);
                        }
                        else
                        {
                                code[i-1] = MakeUpper( *(name+x-1) ) ;
                                _di = x;
                        }
                }
        }
        else
        {
                char ch;
                for(i=1;i<0x18;i++)
                {
                        ch = MakeUpper(name[i*len/0x17-1]);
                        code[i-1] = ch;
                }
        }
        i = 0;
        while(code[i])
        {
                sprintf(step1_code+i*2,"%02d",code[i]);
                i ++ ;
        }
        return step1_code;
}

char * step2(char * src)
{
        char code[6];
        short i;
        int len = strlen(src);
        char * p = src;
        char _pre_regcode[0x20];
        char * ppre;
        static char regcode[0x10];
        char * const pre_regcode = _pre_regcode+1;

        ppre = pre_regcode;
        src += len;
        pre_regcode[-1] = '\0';
        pre_regcode[0] = '\0';

        while(src >= p)
        {
                int c=0;
                memset(code,0,sizeof(code));
                strncpy(code,p,5);
                i = atoi(code);
                if(i>0)
                {
                        memset(code,0,sizeof(code));
                        while(i!=0)
                        {
                                code[c++] = l[i%0x25];
                                i = i/0x25;
                        }
                        strcat(pre_regcode,strrev(code));
                }
                p += 5;
        }
        len = strlen(pre_regcode);
        for(i=1;i<0xD;i++)
        {
                regcode[i-1] = pre_regcode[i*len/0xC-1];
        }
        regcode[0xC]='\0';
        return regcode;
}

char * keygen(char *name)
{
        return step2(step1(name));
}

void Banner()
{
        fprintf(stderr, "Keygen for ASPMaker v2.2 by CyGwIN@sMtH.\n\n");
}

int main()
{
        char name[0x100];
        char * key;

        Banner();
        do
        {
                printf("Enter Your Name: ");
                scanf("%[^\n]",name);getchar();
                key = keygen(name);
                if(*key=='\0')fprintf(stderr," Invalid Name!!\n");
        }while(*key=='\0');

        printf("Your RegCode Is:\n\t%s\n",key);
        printf("Press Enter to exit.");
        scanf("%[^\n]",name);
        return 0;
}