幻影2003 V3.0註冊碼分析 (12千字)

看雪資料發表於2003-01-25

幻影2003 V3.0是一個很有特色的影像處理軟體,使用影像的處理變得簡單易用,效果很不錯.安裝完該軟體後發現它是用ASPACK壓縮的,就使用PE-SCAN對其解壓縮,然後用TRW2000開始跟蹤,很快就發現,軟體對註冊碼的比較過程非常原始,就是兩個真假註冊碼直接進行對比,所以很容易就找到了有效的註冊碼,而且真假註冊碼的位置也很接近,所以用WINHEX的記憶體編輯功能就可以很快找到註冊碼,但是分析它的註冊碼的生成過程,卻花了我很長時間,因為軟體的註冊碼並不是由軟體編號直接變化而來的,而是有一個註冊的關鍵值,軟體編號也是由此值變化而來(這個變化過程是可逆的),在註冊對話方塊出現時,註冊碼其實已經生成了.

0167:004100F1  MOV      EAX,[ESI+D0]<----此值就是註冊碼生成的關鍵值,以下記為reg
0167:004100F7  CMP      EAX,EBX
0167:004100F9  JNZ      0041015A
0167:004100FB  LEA      ECX,[ESP+38]
0167:004100FF  MOV      BYTE [ESP+B8],03
0167:00410107  CALL    `MFC42!ord_00000320`
0167:0041010C  LEA      ECX,[ESP+30]
0167:00410110  MOV      BYTE [ESP+B8],02
0167:00410118  CALL    `MFC42!ord_00000320`
0167:0041011D  LEA      ECX,[ESP+18]
0167:00410121  MOV      BYTE [ESP+B8],01
0167:00410129  CALL    `MFC42!ord_00000320`
0167:0041012E  LEA      ECX,[ESP+24]
0167:00410132  MOV      BYTE [ESP+B8],00
0167:0041013A  CALL    `MFC42!ord_00000320`
0167:0041013F  LEA      ECX,[ESP+1C]
0167:00410143  MOV      DWORD [ESP+B8],FFFFFFFF
0167:0041014E  CALL    `MFC42!ord_00000320`
0167:00410153  XOR      EAX,EAX
0167:00410155  JMP      00410504
0167:0041015A  ADD      EAX,000BCC09 <----將reg+BCC09,這是第一次變化.
0167:0041015F  PUSH    EAX
0167:00410160  LEA      EAX,[ESP+1C]
0167:00410164  PUSH    DWORD 004394C4<----指向一字串,"%8d"
0167:00410169  PUSH    EAX
0167:0041016A  CALL    `MFC42!ord_00000B02`<----相當於printf("%8d",reg);
0167:0041016F  MOV      EAX,[ESP+24]<----EAX指向生成的字串的首地址,以下記為[字串1]
0167:00410173  ADD      ESP,BYTE +0C
0167:00410176  MOV      DL,[EAX+01]<----將第2個位元組取出到DL
0167:00410179  MOV      CL,[EAX]<----將第1個位元組取出到CL
0167:0041017B  MOVSX    EAX,BYTE [EAX+02]<----取第3位元組到EAX
0167:0041017F  MOVSX    EDX,DL
0167:00410182  MOVSX    ECX,CL
0167:00410185  ADD      EAX,EDX
0167:00410187  LEA      EAX,[EAX+ECX-90]<----EAX = 第1位元組+ 第2位元組 + 第3位元組 - 90
0167:0041018E  MOV      ECX,07
0167:00410193  CDQ   
0167:00410194  IDIV    ECX
0167:00410196  LEA      ECX,[ESP+18]
0167:0041019A  ADD      DL,30 <----DL 這是EAX除7後的餘數,加上30後轉化為ASCII碼的婁數字
0167:0041019D  PUSH    EDX
0167:0041019E  PUSH    BYTE +03
0167:004101A0  CALL    `MFC42!ord_000016E0`<----此CALL將DL的值寫入字串的第4位元組處,即替換[字串1]第4位元組
0167:004101A5  MOV      EAX,[ESP+18]
0167:004101A9  MOV      DL,[EAX+05]<----取出第6位元組
0167:004101AC  MOV      CL,[EAX+04]<----取出第5位元組
0167:004101AF  MOVSX    EAX,BYTE [EAX+06]<----取出第7位元組
0167:004101B3  MOVSX    EDX,DL
0167:004101B6  MOVSX    ECX,CL
0167:004101B9  ADD      EAX,EDX
0167:004101BB  LEA      EAX,[EAX+ECX-90]<----與上面一樣處理
0167:004101C2  MOV      ECX,07
0167:004101C7  CDQ   
0167:004101C8  IDIV    ECX
0167:004101CA  ADD      DL,30<----這裡也與上面一樣處理
0167:004101CD  PUSH    EDX
0167:004101CE  PUSH    ECX
0167:004101CF  LEA      ECX,[ESP+20]
0167:004101D3  CALL    `MFC42!ord_000016E0`<----替換[字串1]中的第8位元組
0167:004101D8  MOV      EAX,[ESP+18]
0167:004101DC  MOV      CL,[EAX+02]
0167:004101DF  MOV      BL,[EAX+01]
0167:004101E2  MOV      DL,[EAX+07]
0167:004101E5  MOV      [ESP+13],CL
0167:004101E9  MOV      CL,[EAX+03]
0167:004101EC  MOV      [ESP+17],BL
0167:004101F0  MOV      BL,[EAX+04]
0167:004101F3  MOV      [ESP+15],CL
0167:004101F7  MOV      CL,[EAX+06]
0167:004101FA  MOV      [ESP+16],BL
0167:004101FE  MOV      BL,[EAX]
0167:00410200  MOV      AL,[EAX+05]
0167:00410203  MOV      [ESP+14],AL
0167:00410207  MOVSX    EAX,DL
0167:0041020A  PUSH    EAX<----到這裡註冊碼計算完成,這是最後一位註冊碼,第16位,[字串1]中的第8位
0167:0041020B  MOVSX    EAX,BYTE [ESP+17]
0167:00410210  ADD      EAX,BYTE +15
0167:00410213  PUSH    EAX                <----第15位,[字串1]中第3位+15
0167:00410214  MOVSX    EAX,BYTE [ESP+1D]
0167:00410219  PUSH    EAX                <----第14位,[字串1]中第4位
0167:0041021A  MOVSX    EAX,CL
0167:0041021D  ADD      EAX,BYTE +17
0167:00410220  PUSH    EAX                <----第13位,[字串1]中第7位+17
0167:00410221  MOVSX    EAX,BYTE [ESP+27]
0167:00410226  PUSH    EAX                <----第12位,[字串1]中第2位
0167:00410227  MOVSX    EAX,BYTE [ESP+2A]
0167:0041022C  ADD      EAX,BYTE +11
0167:0041022F  PUSH    EAX                <----第11位,[字串1]中第5位+11
0167:00410230  MOVSX    EAX,BL
0167:00410233  PUSH    EAX                <----第10位,[字串1]中第1位
0167:00410234  MOVSX    EAX,BYTE [ESP+30]
0167:00410239  ADD      EAX,BYTE +11
0167:0041023C  PUSH    EAX                <----第9位,[字串1]中第6位+11
0167:0041023D  MOVSX    EAX,CL
0167:00410240  PUSH    EAX                <----第8位,[字串1]中第7位
0167:00410241  MOVSX    EAX,BYTE [ESP+39]
0167:00410246  ADD      EAX,BYTE +13
0167:00410249  PUSH    EAX                <----第7位,[字串1]中第4位+13
0167:0041024A  MOVSX    EAX,BYTE [ESP+3E]
0167:0041024F  PUSH    EAX                <----第6位,[字串1]中第5位
0167:00410250  MOVSX    EDX,DL
0167:00410253  MOVSX    EAX,BYTE [ESP+40]
0167:00410258  ADD      EDX,BYTE +12
0167:0041025B  PUSH    EDX                <----第5位,[字串1]中第8位+12
0167:0041025C  PUSH    EAX                <----第4位,[字串1]中第6位
0167:0041025D  MOVSX    EDX,BYTE [ESP+47]
0167:00410262  MOVSX    EAX,CL
0167:00410265  MOVSX    ECX,BL
0167:00410268  ADD      EDX,BYTE +1B
0167:0041026B  ADD      ECX,BYTE +11
0167:0041026E  PUSH    EDX                <----第3位,[字串1]中第3位+1B
0167:0041026F  PUSH    EAX                <----第2位,[字串1]中第7位
0167:00410270  PUSH    ECX                <----第1位,[字串1]中第1位+11
0167:00410271  LEA      EDX,[ESP+70]
0167:00410275  PUSH    DWORD 004394A0<----指向一字串"%c%c%c%c-%c%c%c%c-%c%c%c%c-%c%c%c%c"
0167:0041027A  PUSH    EDX
0167:0041027B  CALL    `MFC42!ord_00000B02`<----相當於printf(""%c%c%c%c-%c%c%c%c-%c%c%c%c-%c%c%c%c",...),返回時ECX指向生成的註冊碼
0167:00410280  MOV      EAX,[ESP+64]
0167:00410284  ADD      ESP,BYTE +48
0167:00410287  CMP      DWORD [EAX-08],BYTE +13
0167:0041028B  JNG      004102C0
0167:0041028D  LEA      ECX,[ESP+28]
0167:00410291  PUSH    BYTE +13
0167:00410293  PUSH    ECX
0167:00410294  LEA      ECX,[ESP+24]
0167:00410298  CALL    `MFC42!ord_0000164E`
0167:0041029D  PUSH    EAX
0167:0041029E  LEA      ECX,[ESP+20]
0167:004102A2  MOV      BYTE [ESP+BC],06
0167:004102AA  CALL    `MFC42!ord_0000035A`
0167:004102AF  LEA      ECX,[ESP+28]
0167:004102B3  MOV      BYTE [ESP+B8],04
0167:004102BB  CALL    `MFC42!ord_00000320`
0167:004102C0  MOV      EDX,[ESP+30]
0167:004102C4  MOV      EAX,[ESP+1C]
0167:004102C8  PUSH    EDX
0167:004102C9  PUSH    EAX
0167:004102CA  CALL    EBP
0167:004102CC  ADD      ESP,BYTE +08
0167:004102CF  TEST    EAX,EAX
0167:004102D1  JNZ      004102E0
0167:004102D3  MOV      DWORD [ESP+2C],01
0167:004102DB  JMP      004104A8
0167:004102E0  XOR      EBX,EBX
0167:004102E2  PUSH    EBX
0167:004102E3  LEA      ECX,[ESP+44]
0167:004102E7  CALL    00408CE0
0167:004102EC  LEA      ECX,[ESP+20]
0167:004102F0  MOV      BYTE [ESP+B8],07
0167:004102F8  CALL    `MFC42!ord_0000021C`
0167:004102FD  MOV      ECX,[ESI+D0]<----取出註冊常數
0167:00410303  LEA      EDX,[ESP+20]
0167:00410307  ADD      ECX,000B4E9D<----將其加上B4E9D,所到結果以十六進位制顯示後,就是軟體編號的後面部分(這一部分從第4位元組開始)
0167:0041030D  MOV      BYTE [ESP+B8],08
0167:00410315  PUSH    ECX
0167:00410316  PUSH    DWORD 00439494
0167:0041031B  PUSH    EDX
0167:0041031C  CALL    `MFC42!ord_00000B02`
0167:00410321  ADD      ESP,BYTE +0C
0167:00410324  LEA      EAX,[ESP+34]
0167:00410328  LEA      ECX,[ESP+24]
0167:0041032C  MOV      DWORD [ESP+34],0104
0167:00410334  PUSH    EAX
0167:00410335  PUSH    DWORD 0104
0167:0041033A  CALL    `MFC42!ord_00000B63`
0167:0041033F  PUSH    EAX
0167:00410340  CALL    `KERNEL32!GetComputerNameA`<----取機器名
0167:00410346  PUSH    BYTE -01
0167:00410348  LEA      ECX,[ESP+28]
0167:0041034C  CALL    `MFC42!ord_000015C4`
0167:00410351  MOV      ECX,[ESP+24]
0167:00410355  PUSH    BYTE +03
0167:00410357  CMP      DWORD [ECX-08],BYTE +03 <----如果機器名大於3位元組,則軟體編號的前3位由機器名中取得,如果小於3位,則取軟體編號的3位.
0167:0041035B  JNL      0041038B
0167:0041035D  LEA      EDX,[ESP+2C]
0167:00410361  LEA      ECX,[ESP+24]
0167:00410365  PUSH    EDX
0167:00410366  CALL    `MFC42!ord_0000164E`
0167:0041036B  PUSH    EAX
0167:0041036C  LEA      ECX,[ESP+28]
0167:00410370  MOV      BYTE [ESP+BC],09
0167:00410378  CALL    `MFC42!ord_0000035A`
0167:0041037D  MOV      BYTE [ESP+B8],08
0167:00410385  LEA      ECX,[ESP+28]
0167:00410389  JMP      SHORT 004103B9
0167:0041038B  LEA      EAX,[ESP+2C]
0167:0041038F  PUSH    BYTE +01
0167:00410391  PUSH    EAX
0167:00410392  LEA      ECX,[ESP+30]
0167:00410396  CALL    `MFC42!ord_000010B6`
0167:0041039B  PUSH    EAX
0167:0041039C  LEA      ECX,[ESP+28]
0167:004103A0  MOV      BYTE [ESP+BC],0A
0167:004103A8  CALL    `MFC42!ord_0000035A`
0167:004103AD  MOV      BYTE [ESP+B8],08
0167:004103B5  LEA      ECX,[ESP+28]
0167:004103B9  CALL    `MFC42!ord_00000320`
0167:004103BE  LEA      ECX,[ESP+24]
0167:004103C2  CALL    `MFC42!ord_0000106A`
0167:004103C7  LEA      ECX,[ESP+20]
0167:004103CB  LEA      EDX,[ESP+24]
0167:004103CF  PUSH    ECX
0167:004103D0  LEA      EAX,[ESP+40]
0167:004103D4  PUSH    EDX
0167:004103D5  PUSH    EAX
0167:004103D6  CALL    `MFC42!ord_0000039A`
0167:004103DB  PUSH    EAX
0167:004103DC  LEA      ECX,[ESP+AC]
0167:004103E3  MOV      BYTE [ESP+BC],0B
0167:004103EB  CALL    `MFC42!ord_0000035A`
0167:004103F0  LEA      ECX,[ESP+3C]
0167:004103F4  MOV      BYTE [ESP+B8],08
0167:004103FC  CALL    `MFC42!ord_00000320`
0167:00410401  LEA      ECX,[ESP+30]
0167:00410405  PUSH    ECX
0167:00410406  LEA      ECX,[ESP+A4]
0167:0041040D  CALL    `MFC42!ord_0000035A`
0167:00410412  LEA      ECX,[ESP+40]
0167:00410416  MOV      [ESP+A4],EDI
0167:0041041D  CALL    `MFC42!ord_000009D2`<----這裡彈出"註冊"對話方塊.


--------------------------VC 序號產生器程式碼----------------------------
void CKeyGenDlg::OnOK()
{
    // TODO: Add extra validation here
    this->UpdateData(true);
    if(this->m_input == "")
    {
        this->m_output = "請輸入註冊使用者名稱";
        this->m_edit2.SetWindowText(this->m_output);
        return;
    }

//this->m_input 是輸入的使用者名稱,this->m_output 是輸出用的註冊碼。
    char buf[50];
    char regcode[20];
    unsigned long reg;
    strcpy(buf,this->m_input);
    reg = hextoi(buf+3);
    reg -= 0xb4e9d;
    reg+= 0xbcc09;
    sprintf(buf,"%8lu",reg);
    buf[3]= ((buf[0]+buf[1]+buf[2]-0x90) % 7)+0x30;
    buf[7]= ((buf[4]+buf[5]+buf[6]-0x90) % 7)+0x30;
    sprintf(regcode,"%c%c%c%c-%c%c%c%c-%c%c%c%c-%c%c%c%c",
                    buf[0]+0x11,
                     buf[6],
                     buf[2]+0x1b,
                     buf[5],
                     buf[7]+0x12,
                     buf[4],
                     buf[3]+0x13,
                     buf[6],
                     buf[5]+0x11,
                     buf[0],
                     buf[4]+0x11,
                     buf[1],
                     buf[6]+0x17,
                     buf[3],
                     buf[2]+0x15,
                     buf[7]);
    this->m_output = regcode;

//--------------------------------------------
    this->m_edit2.SetWindowText(this->m_output);
//*以下程式碼是將註冊碼寫入剪下板中。
    if(OpenClipboard())
    {
    HGLOBAL clipbuffer;
    char * buffer;
    EmptyClipboard();
    clipbuffer = GlobalAlloc(GMEM_DDESHARE, this->m_output.GetLength()+1);
    buffer = (char*)GlobalLock(clipbuffer);
    strcpy(buffer, LPCSTR(this->m_output));
    GlobalUnlock(clipbuffer);
    SetClipboardData(CF_TEXT,clipbuffer);
    CloseClipboard();
    }
//*/
}

unsigned long CKeyGenDlg::hextoi(char *str) //將十六進位制字串轉為LONG型。
{
    char n;
    int i,len;
    unsigned long sum,sum1;
    len  = strlen(str);
    sum =0;
    sum1 =1;
    for(i=0;i<len;i++)
    {
        n = str[len-i-1];
        if( n >='0' && n<='9' )
        {
            n -= '0'; //轉為數字
        }
        else
        {
            if(n >='a' && n <='f')
            {
                n-= 87; //轉為數字
            }
            else
            {
                if(n>='A' && n <='F')
                {
                    n-=55; //轉為數字
                }
                else
                { //如果都不是,則返回
                    break;
                }
            }
        }
        sum += n * sum1;
        sum1*=16;
    }
    return sum;

}

相關文章