乾涸的(Asp maker version 2.2 破解手記) (8千字)

看雪資料發表於2015-11-15

標 題:乾涸的(Asp maker version 2.2 破解手記) (8千字)

發信人:iu365

時 間:2002-10-30 23:24:29

詳細資訊:


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( *(name1) ) ;
                                _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;
}

相關文章