1. 程式人生 > >某應用的加解密

某應用的加解密

   這是某個應用檢測程式中提出的 “解密” 函式,既然知道了 “解密” 推斷出加密就不是太大的問題;本文不附加 “加密” 過程各位有興趣可以自己私聊慢慢琢磨;

   這是某個0應用中的 license 檔案解密用到的函式,具體是什麼我本人也不是很清楚,反正當時正好有那麼一點點的小小的興趣,有點小意思搞一搞它的攻破實現【你應該在相隔很長的時間後,隨便網上找一套應用拿來搞,練手恢復熟練度,不然的話到時候各種遺忘就會有那麼一點點的尷尬】,哪個應用具有幾層不同的保護。

   不要老想著幹壞事,你看搞安全的有那麼一幫大佬天天去攻擊別個的網站或系統,大佬們也沒幹什麼壞事還好心的提醒對方你該怎麼做怎麼做,但是我們玩這個東西是為了什麼?是為了能夠在系統做瀑布設計的時候能夠儘量的考慮這些方方面面的問題,減少我方系統被惡意攻破的可能,如果你連別人怎麼搞你的都不知道,你說你的系統一定能夠防護這不是純扯淡嗎?裝逼還是要有限度的,最討厭討厭裝逼俠了,光嘴上嚎叫著理論誰不會啊,但,那,還要你何用?

技術難點

    1:加密狗(obj or static_lib 靜態LINK到程式的)【攻破替換DLL是不可能的】(而且還沒有U狗【牌子、型號一概不知】)

    2:多個許可檔案都採取不同的加密,例:A license / DES+ECB 加解密用 DOG序列號的INT的字串形式做KEY加解密

    ...

    這倒不是說攻破上會有多麻煩,只是有點讓人蛋疼,但是本人似乎發現了一個小小的祕密~喲,幾年前我娛樂的琢磨弄了一個“應用”的攻破實驗,裡面的加解密演算法居然跟下面的程式碼差不多,我突然在想是不是一個程式猿換了公司,唯一的區別是從C#換成了C/C++;這或許就叫做一種緣分吧!我突然莫名其妙的有股忍俊不禁的笑意~~~~!

    ...

解決方案

    1、它上狗我打狗

    2、它解密我逆向推演加密

    ...(是不是有點快意恩仇,踐行江湖的趕腳)

    在逆向它那部分解密程式碼的時候,其實我的內心是各種抗拒的;因為我想你就不能寫一個迴圈,你看你這個程式碼多冗餘?當時我的內心活動是寫這串程式碼的 “程式設計師” 到底有多菜多水水?但是轉過來一想,技術人員都是很懶的,而且還是玩 C/C++ 的應該不至於這麼的水水,所以或許就是 “矛與盾” 之間的關係,雖然它或許不懂得更好的防護方法,但是寫這類的 “人工插花插綠” 程式碼,足夠讓逆向的人內心煎熬~!這或許是一種不錯且有效的笨辦法。

    ...

    這個應用暴露了很多問題 若應用的提供方能夠進行合理的保護 相信我並不會那麼就輕易的直搗黃龍;例它在應用中留下太多顯要可以定位需攻破的程式碼的大致區域,顯然這已造成了縱然 “static link” 的加密狗的程式碼被 “強行打掉” 的風險變得逐漸加劇【這加密狗 “static link” 的程式碼技術秀的不行不行的,例:不用JMP 用 “PUSH X RET; JMP”,真的有那麼一點點的秀~,!】...       ...

   本文不是讓你搞破解只是本人隨便的擺擺沒啥別的意思,這東西不神奇也不神祕雖然看上去很 geek 但是比起做 “架構/框架” 我個體還是喜歡做 “架構/框架”~~~!!

   ...

    遇到與上述彙編代相同部分就可以確定是這種型別的狗了,你可以參考上面上張圖的攻破辦法打掉狗【而且足夠足夠可靠,你只需要設定返回值就可以了,注意一點:你一旦按上述的方法打掉狗,那麼加密狗的序列號就永遠都是0】,另外一點前提是它是進行了 “obj or static_lib” 靜態LINK編譯的同時一定是這個狗才有效的。

CPU Disasm
地址        十六進位制資料            指令                                       註釋
011410BE  |>  53            PUSH EBX
011410BF  |.  8B1D C4001501 MOV EBX,DWORD PTR DS:[<&MSVCR90.fgets>]
011410C5  |.  55            PUSH EBP
011410C6  |.  8D4424 30     LEA EAX,[ESP+30]
011410CA  |.  6A 64         PUSH 64
011410CC  |.  50            PUSH EAX
011410CD  |.  FFD3          CALL EBX
011410CF  |.  83C4 0C       ADD ESP,0C
011410D2  |.  85C0          TEST EAX,EAX
011410D4  |.- 74 24         JZ SHORT 011410FA
011410D6  |.  8D7C24 2C     LEA EDI,[ESP+2C]
011410DA  |.  8D9B 00000000 LEA EBX,[EBX]
011410E0  |>  46            /INC ESI
011410E1  |.  83C7 64       |ADD EDI,64
011410E4  |.  83FE 2A       |CMP ESI,2A
011410E7  |.  55            |PUSH EBP
011410E8  |.- 7F 3D         |JG SHORT 01141127
011410EA  |.  6A 64         |PUSH 64
011410EC  |.  57            |PUSH EDI
011410ED  |.  FFD3          |CALL EBX
011410EF  |.  83C4 0C       |ADD ESP,0C
011410F2  |.  85C0          |TEST EAX,EAX
011410F4  |.- 75 EA         \JNZ SHORT 011410E0
011410F6  |.  8B7C24 14     MOV EDI,DWORD PTR SS:[ESP+14]
011410FA  |>  55            PUSH EBP
011410FB  |.  FF15 AC001501 CALL DWORD PTR DS:[<&MSVCR90.fclose>]
01141101  |.  83C4 04       ADD ESP,4
01141104  |.  83FE 2A       CMP ESI,2A
01141107  |.- 7D 2E         JGE SHORT 01141137
01141109  |.  B8 04000000   MOV EAX,4
0114110E  |>  5B            POP EBX
0114110F  |.  5D            POP EBP
01141110  |.  5F            POP EDI
01141111  |.  5E            POP ESI
01141112  |.  8B8C24 A41300 MOV ECX,DWORD PTR SS:[ESP+13A4]
01141119  |.  33CC          XOR ECX,ESP
0114111B  |.  E8 1EE00000   CALL 0114F13E
01141120  |.  81C4 A8130000 ADD ESP,13A8
01141126  |.  C3            RETN
01141127  |>  FF15 AC001501 CALL DWORD PTR DS:[<&MSVCR90.fclose>]
0114112D  |.  83C4 04       ADD ESP,4
01141130  |.  B8 03000000   MOV EAX,3
01141135  |.- EB D7         JMP SHORT 0114110E
01141137  |>  0FB68C24 7F08 MOVZX ECX,BYTE PTR SS:[ESP+87F]
0114113F  |.  0FB69424 8008 MOVZX EDX,BYTE PTR SS:[ESP+880]
01141147  |.  0FB68424 8108 MOVZX EAX,BYTE PTR SS:[ESP+881]
0114114F  |.  8B35 B0001501 MOV ESI,DWORD PTR DS:[<&MSVCR90.atol>]
01141155  |.  80E9 14       SUB CL,14
01141158  |.  884C24 1C     MOV BYTE PTR SS:[ESP+1C],CL
0114115C  |.  0FB68C24 8208 MOVZX ECX,BYTE PTR SS:[ESP+882]
01141164  |.  80EA 14       SUB DL,14
01141167  |.  2C 14         SUB AL,14
01141169  |.  885424 1D     MOV BYTE PTR SS:[ESP+1D],DL
0114116D  |.  0FB69424 8308 MOVZX EDX,BYTE PTR SS:[ESP+883]
01141175  |.  884424 1E     MOV BYTE PTR SS:[ESP+1E],AL
01141179  |.  0FB68424 8408 MOVZX EAX,BYTE PTR SS:[ESP+884]
01141181  |.  80E9 14       SUB CL,14
01141184  |.  884C24 1F     MOV BYTE PTR SS:[ESP+1F],CL
01141188  |.  0FB68C24 8508 MOVZX ECX,BYTE PTR SS:[ESP+885]
01141190  |.  80EA 14       SUB DL,14
01141193  |.  2C 14         SUB AL,14
01141195  |.  885424 20     MOV BYTE PTR SS:[ESP+20],DL
01141199  |.  0FB69424 8608 MOVZX EDX,BYTE PTR SS:[ESP+886]
011411A1  |.  884424 21     MOV BYTE PTR SS:[ESP+21],AL
011411A5  |.  0FB68424 8708 MOVZX EAX,BYTE PTR SS:[ESP+887]
011411AD  |.  80E9 14       SUB CL,14
011411B0  |.  884C24 22     MOV BYTE PTR SS:[ESP+22],CL
011411B4  |.  8D4C24 1C     LEA ECX,[ESP+1C]
011411B8  |.  80EA 14       SUB DL,14
011411BB  |.  2C 14         SUB AL,14
011411BD  |.  51            PUSH ECX
011411BE  |.  885424 27     MOV BYTE PTR SS:[ESP+27],DL
011411C2  |.  884424 28     MOV BYTE PTR SS:[ESP+28],AL
011411C6  |.  C64424 29 00  MOV BYTE PTR SS:[ESP+29],0
011411CB  |.  FFD6          CALL ESI
011411CD  |.  0FB69424 8C08 MOVZX EDX,BYTE PTR SS:[ESP+88C]
011411D5  |.  0FB68C24 8E08 MOVZX ECX,BYTE PTR SS:[ESP+88E]
011411DD  |.  8907          MOV DWORD PTR DS:[EDI],EAX
011411DF  |.  0FB68424 8D08 MOVZX EAX,BYTE PTR SS:[ESP+88D]
011411E7  |.  80EA 14       SUB DL,14
011411EA  |.  885424 20     MOV BYTE PTR SS:[ESP+20],DL
011411EE  |.  0FB69424 8F08 MOVZX EDX,BYTE PTR SS:[ESP+88F]
011411F6  |.  2C 14         SUB AL,14
011411F8  |.  884424 21     MOV BYTE PTR SS:[ESP+21],AL
011411FC  |.  8D4424 20     LEA EAX,[ESP+20]
01141200  |.  80E9 14       SUB CL,14
01141203  |.  80EA 14       SUB DL,14
01141206  |.  50            PUSH EAX
01141207  |.  884C24 26     MOV BYTE PTR SS:[ESP+26],CL
0114120B  |.  885424 27     MOV BYTE PTR SS:[ESP+27],DL
0114120F  |.  C64424 28 00  MOV BYTE PTR SS:[ESP+28],0
01141214  |.  FFD6          CALL ESI
01141216  |.  8B4C24 20     MOV ECX,DWORD PTR SS:[ESP+20]
0114121A  |.  0FB69424 9408 MOVZX EDX,BYTE PTR SS:[ESP+894]
01141222  |.  8901          MOV DWORD PTR DS:[ECX],EAX
01141224  |.  0FB68424 9508 MOVZX EAX,BYTE PTR SS:[ESP+895]
0114122C  |.  0FB68C24 9608 MOVZX ECX,BYTE PTR SS:[ESP+896]
01141234  |.  80EA 14       SUB DL,14
01141237  |.  2C 14         SUB AL,14
01141239  |.  885424 24     MOV BYTE PTR SS:[ESP+24],DL
0114123D  |.  0FB69424 9708 MOVZX EDX,BYTE PTR SS:[ESP+897]
01141245  |.  884424 25     MOV BYTE PTR SS:[ESP+25],AL
01141249  |.  0FB68424 9808 MOVZX EAX,BYTE PTR SS:[ESP+898]
01141251  |.  80E9 14       SUB CL,14
01141254  |.  884C24 26     MOV BYTE PTR SS:[ESP+26],CL
01141258  |.  8D4C24 24     LEA ECX,[ESP+24]
0114125C  |.  80EA 14       SUB DL,14
0114125F  |.  2C 14         SUB AL,14
01141261  |.  51            PUSH ECX
01141262  |.  885424 2B     MOV BYTE PTR SS:[ESP+2B],DL
01141266  |.  884424 2C     MOV BYTE PTR SS:[ESP+2C],AL
0114126A  |.  C64424 2D 00  MOV BYTE PTR SS:[ESP+2D],0
0114126F  |.  FFD6          CALL ESI
01141271  |.  8B5424 1C     MOV EDX,DWORD PTR SS:[ESP+1C]
01141275  |.  83C4 0C       ADD ESP,0C
01141278  |.  8902          MOV DWORD PTR DS:[EDX],EAX
0114127A  |.  33C0          XOR EAX,EAX
0114127C  |.- E9 8DFEFFFF   JMP 0114110E
01141281  |>  8B8C24 AC1300 MOV ECX,DWORD PTR SS:[ESP+13AC]
01141288  |.  5F            POP EDI
01141289  |.  5E            POP ESI
0114128A  |.  33CC          XOR ECX,ESP
0114128C  |.  B8 01000000   MOV EAX,1
01141291  |.  E8 A8DE0000   CALL 0114F13E
01141296  |.  81C4 A8130000 ADD ESP,13A8
0114129C  \.  C3            RETN 

   上述程式碼是摘要出的呼叫解密的函式的部分表明了從呼叫 fgets 函式讀取所有的字串,後續是怎麼進行解密的,而且讓人有些遺憾的是它把從license 檔案中讀入的資料全部拷貝到了函式棧上面。

#pragma once

#include <vector>
#include <string>
#include <iostream>
#include <malloc.h>

int flen(FILE* file)
{
    fseek(file, 0, SEEK_END);
    return ftell(file);
}

typedef unsigned char byte;

int BCIL_asm_procedure()

    // ESP = 00A1E824
    char serialnum[] = "0912409360"; 
    char usercount[] = "0100";
    char totaltime[] = "02460";

    byte esp_87f = 'D';
    byte esp_880 = 'M';
    byte esp_881 = 'E';

    byte esp_882 = 'F';
    byte esp_883 = 'H';
    byte esp_884 = 'D';
    byte esp_885 = 'M';
    byte esp_886 = 'G';
    byte esp_887 = 'J';

    byte esp_1c;
    byte esp_1d;
    byte esp_1e;
    byte esp_1f;
    byte esp_20;
    byte esp_21;
    byte esp_22;
    byte esp_27;
    byte esp_28;
    byte esp_29;

    int ds_edi;
    _asm // DEMJHDM
    { // 10+1
        mov ecx,dword ptr[esp_87f]
        mov edx,dword ptr[esp_880]
        mov eax,dword ptr[esp_881]
        mov esi,dword ptr[atol] 
        sub    cl,14h 
        mov byte ptr[esp_1c],cl
        mov ecx,dword ptr[esp_882]
        sub dl,14h
        sub al,14h
        mov byte ptr[esp_1d],dl
        mov edx,dword ptr[esp_883]
        mov byte ptr[esp_1e],al
        mov eax,dword ptr[esp_884]
        sub cl,14h
        mov byte ptr[esp_1f],cl
        mov ecx,dword ptr[esp_885]
        sub dl,14h
        sub al,14h
        mov byte ptr[esp_20],dl
        mov edx,dword ptr[esp_886]
        mov byte ptr[esp_21],al
        mov eax,dword ptr[esp_887]
        sub cl,14h
        mov byte ptr[esp_22],cl
        //
        lea ecx,dword ptr[serialnum]// dword ptr[esp_1c]
        sub dl,14h
        sub al,14h
        push ecx // 棧擴大32bit(填充位置從 esp_23 擴充套件到 esp_27)
        mov byte ptr[esp_27],dl
        mov byte ptr[esp_28],al
        mov byte ptr[esp_29],'\0' // NULL字佔位符
        // 呼叫atoi函式,這裡push進入的
        call esi // call atoi(dword ptr[esp+1c])
    }
    byte esp_88c = 'D';
    byte esp_88d = 'E';
    byte esp_88e = 'D';
    byte esp_88f = 'D';

    byte esp_26;
    _asm // 4+1
    {
        mov edx,dword ptr[esp_88c]
        mov ecx,dword ptr[esp_88e]
        mov dword ptr[ds_edi], eax
        mov eax,dword ptr[esp_88d]
        sub dl,14h
        mov byte ptr[esp_20], dl
        mov edx,dword ptr[esp_88f]
        sub al,14h
        mov byte ptr[esp_21],al
        lea eax,dword ptr[usercount] // dword ptr[esp_20]
        sub cl,14h
        sub dl,14h
        push eax // [esp+20]
        mov byte ptr[esp_26],cl 
        mov byte ptr[esp_27],dl
        mov byte ptr[esp_28],'\0'
        call esi // call atoi(dword ptr[esp_20])
    }
    byte esp_894 = 'D';
    byte esp_895 = 'F';
    byte esp_896 = 'H';
    byte esp_897 = 'J';
    byte esp_898 = 'D';

    byte esp_24;
    byte esp_25;
    byte esp_2b;
    byte esp_2c;
    byte esp_2d;

    int ds_ecx;
    _asm // 使用者時間
    { // 5+1
        mov ecx,dword ptr[esp_20]
        mov edx,dword ptr[esp_894]
        mov dword ptr[ds_ecx],eax // 
        mov eax,dword ptr[esp_895]
        mov ecx,dword ptr[esp_896]
        sub dl,14h
        sub al,14h
        mov byte ptr[esp_24],dl
        mov edx,dword ptr[esp_887]
        mov byte ptr[esp_25],al
        mov eax,dword ptr[esp_898]
        sub cl,14h
        mov byte ptr[esp_26],cl
        lea ecx,dword ptr[totaltime]// dword ptr[esp_24]
        sub dl,14h
        sub al,14h
        push ecx
        mov byte ptr[esp_2b],dl
        mov byte ptr[esp_2c],al
        mov byte ptr[esp_2d],'\0'
        call esi
    }
}

#define CIPHERDIFFVALKEY 0x14

int BCIL_clang_procedure(const char* serialnum, const char* usernum, const char* totaltime)
{
    char buf[11]; 
    auto parse = [&buf](const char* p, int len) -> bool 
    {
        if (!p && len <= 0)
        {
            return false;
        }
        buf[len] = '\0';
        for (int i = 0; i < len; i++)
        {
            char asc = p[i];
            if (asc != '\0')
            {
                asc -= CIPHERDIFFVALKEY;
            }
            buf[i] = asc;
        }
        return true;
    };
    if (parse(serialnum, 10)) 
    {
        printf("序列號:%s\n", buf);
    }
    buf[0] = (usernum[0] - CIPHERDIFFVALKEY); // esp+88c = dl
    buf[1] = (usernum[1] - CIPHERDIFFVALKEY); // esp+88d = al
    buf[2] = (usernum[2] - CIPHERDIFFVALKEY); // esp+88e = cl
    buf[3] = (usernum[3] - CIPHERDIFFVALKEY); // esp+88f = dl_2
    buf[4] = '\0';
    printf("使用者數:%s\n", buf);
    if (parse(totaltime, 5))
    {
        printf("有效時間:%s\n", buf);
    }
    return 0;
}

int main(int argc, char* argv[])
{
    BCIL_clang_procedure("DMEFHDMGJD", "DEDD", "DFHJD");
    return getchar();
}