• 彩神彩票

    ROCKEY係列加密鎖 ---- 加密參考八方案

            彩神彩票通過幾年來的努力,在軟件加密方麵,總結了八套加密方案,完全斬斷了黑客之手,能有效地杜絕軟件盜版。歡迎閱後與我們聯係,做進一步探討。

            方案一:

            取得係統的時間,根據係統的時間進行加密檢測。

            例如:Function 1 內部的加密檢測是每次運行都要檢測。

            Function 2 是在軟件安裝一個月後開始檢測。

            Function 3 可以在軟件安裝半年後開始檢測。

            [要求] Function 1, Function 2, Function 3 中的加密鎖檢測子程序應該各不相同, 否則很容易被人找到一個後, 利用串匹配的方法找到所有的加密點。 如果有可能, 最好取得係統時間的函數也采用不同的方法(在DOS 下可用 INT 21 的 2A 功能或利用 I/O 檢測 CMOS 在 Win95 下可以用 GetSystemTime 和 GetLocalTime的係統服務來取得時間)。

            [優點] 這種方法的加密很難被人破解得徹底, 對於那些解密者本身不是軟件的使用者的情況能做到很好的保護。

            [缺點] 因為要實現加密鎖的多個檢測子程序, 在編程上要花費更多的時間。 而使用者可以通過修改係統時間來屏蔽檢測(可以利用記錄最後運行時間的方法來進行進一步的保護, 但對於發現了這個軟件的保護是同時間有關的解密者而言, 這種附加的保護並不能阻擋很多時間)。

            方案二:

            記錄軟件的運行次數, 根據運行次數進行加密檢測。

            例如:Function 1 內部的加密檢測是每次運行都要檢測。

            Function 2 是在軟件運行 20 次後開始檢測。

            Function 3 可以在軟運行 50 次後開始檢測。

            [要求] Function 1, Function 2, Function 3 中的加密鎖檢測子程序應該各不相同。 這種加密的運行次數應該有多份記錄, 每個加密點檢測相對獨立的記錄。 如果有可能,一個加密點可以對應多個記錄, 然後進行隨機的抽測,但一個加密點所對應的多個記錄同另一個加密點所對應的多個記錄不應有太多重疊。

            [優點] 這種方法的加密很難被人破解得徹底, 對於那些解密者本身不是軟件的使用者的情況能做到很好的保護。

            [缺點] 因為要實現加密鎖的多個檢測子程序, 在編程上要花費更多的時間。 而且需要一個附加的文件來保存這些記錄。

            方案三:

            利用鎖中記錄的數據保護功能調用。

            例如:

    int add(int a, int b){
        return(a+b);}
        int err(){
        printf("No dog\n");
    }
    void main(void){
        int (*ptr)();
        int c;
        int write_to_dog, read_from_dog; //write_to_dog = read_from_dog
        write_to_dog = add ^ err;
        ptr = err;
        ptr = ptr ^ read_from_dog;
        c = ptr(3, 4);
    }

            上麵的程序隻是一個示例說明, 不能被編譯執行, write_to_dog = add ^ err 這行由於 C/C++ 編譯器的問題必須通過匯編來實現。

            上麵的程序中例如編譯後 add 函數的地址是 0x0071df32,err 函數的地址是 0x006504f3, 那麽程序在開始的時候

    write_to_dog = 0x14dbc1

            這樣, 如果被加密的程序讀鎖正確 ptr = 0x006504f3 ^

    0x14dbc1 = 0x0071df32 就是 add 的地址, 如果讀鎖錯誤

    read_from_dog 應該為 0, 那麽 ptr = err 的地址

            [要求] write_to_dog = add ^ err; 和寫鎖的操作最好不出現在被加密的程序中, 但要注意每次編譯後 add 和 err 的地址都會變化。

            [優點] 這種方法能夠保證解密者在沒有加密鎖的情況下不可能完成解密的工作。 在加入另外一些變化後可以保證目標程序難以理解。

            [缺點] 因為寫到鎖裏的加密內容同編譯結果有關, 每次編譯後要重新寫鎖。 比較適合那些在版本升級時不做改變的固定被調用的程序。

            方案四:

            利用鎖中記錄的數據進行計算工作。

            例如:

    double SinAngle(int angle){
        PI = read_from_dog;
        return(sin(angle*PI/180))
    }

            [要求] 最好鎖裏麵存放的是浮點數, 因為浮點計算對解密的工作造成極大的困難。 而且計算算法要進可能的複雜些, 保證不被解密者能在匯編的級別上可以理解。

            [優點] 這種方法的加密所造成的錯誤不會產生很明顯的區別, 但沒有正確加密鎖的時候, 其結果肯定是錯誤的。 解密者很難找到問題的出發點。

            [缺點] 考慮到軟件鎖的硬件原因, 有可能因為軟件鎖沒插好或一些突發的打印事件造成的讀入數據的錯誤, 除了要多讀幾次外, 不建議對那些可能造成直接經濟損失的工程計算的關鍵算法進行加密。

            方案五:

            利用軟件鎖的存儲器做變量進行加密

            例如:

    int a;
    a = x + y;
    writedog(a);
    readdog(a);
    d = a+b*c;

            [要求] 這是利用軟件鎖內部的存儲單元來保存程序的變量。 因為程序運行時 a 每次都有可能不同, 所以 readdog 的返回值也會各不相同。 但由於大部分鎖中的存儲單元有寫壽命的限製, 每次運行軟件時的寫操作不應太多。

            [優點] 用這種方法加密的軟件解密者隻找到讀鎖的部分是不行的。而且如果鎖內的數據是進行不同程序之間的數據交換, 解密者除了要看懂兩段程序外, 還必須邊編製自己的仿真程序來完成這個數據交換才行。 這是一種對解密者來說極其困難的加密手段。 而且這種加密是利用每個鎖的初試化序列和密碼的不同進行的加密, 對鎖的內部數據內容沒有要求, 節約了在軟件銷售前的寫鎖時間, 特別適合那些經常升級的軟件。

            [缺點] 因為這種加密手段在程序執行過程中要對加密鎖進行寫操作, 除了要減少鎖的壽命外, 而且造成了鎖的不安全性(例如在寫鎖的時候突然停電)。 而且不能防止解密者通過購買相同型號的加密鎖後的破解。

            方案六:

            利用加密鎖進行初試化保護。

            例如:程序 a 是要被加密的文件, 程序 b 是讀鎖的文件。 程序 a 開始執行時調用程序 b。 程序 b 中進行各種鎖的檢測工作, 如果檢測成功, 生成一利用當前日期保護的數據文件 c, 回到程序 a。 程序 a 利用當前日期對數據文件c 進行解碼工作, 並用解碼後的結果進行程序的初始化工作。

            [要求] 程序 b 必須被很好的保護, 因為程序 b 是一個獨立的執行文件, 可以對這個文件進行盡可能好的保護。 如果可能的話, 最好對數據文件 c 進行某些壓縮工作。 然後在程序 a 中進行解壓縮。 而且可以在程序 b 中完成對程序 a 的完整性檢查。

            [優點] 這種方法的加密因為對象比較單一, 實現起來比較容易而且數據塊 c 可以同時帶有多個程序的初始化變量, 容易實現多模塊加密。 而且由於數據文件 c 是純的數據加密, 可以同現在成熟的數據加密算法相結合, 如 DES,RAS 而且由於程序 b 是個獨立的程序, 不會被程序升級的工作所影響。

            [缺點] 整個程序的加密重點放在了程序 b 上, 如果這個文件被解掉, 整個程序就被解了。

            方案七:

            利用種子碼功能加密。

            ROCKEY 加密鎖具備種子碼功能,它的基本原理就是,當用戶輸入一個 WORD 值,返回 4 個WORD 值,但輸入與輸出之間的關係是保密的,用戶也不知道。相同密碼的加密鎖,當輸入值相同的時候輸出值也相同,不同密碼的加密鎖輸出值不同。種子碼功能實現了加密鎖檢測的另一種手段。我們可以看看這種檢測方法同傳統的檢測方法有何不同:傳統的加密鎖檢測方案是首先根據密碼操作加密鎖,如果錯誤說明指定密碼的加密鎖不在,如果正確則從加密鎖中讀出相應的內容進行比對,進一步檢查是否是自己的加密鎖。

            例如:

    if (CheckDongle() == 1){
        ReadDongle(str);
        if (str == "My Dongle"){
            正確...
        }
        錯誤...
    }

            錯誤...

            加密者: 這種方法結構簡單,很容易被黑客找到並破解。

            黑 客: 那還用說...

            那麽我們來看看種子碼算法的例子:

    if (CheckDongle() == 1){
        seedbuf = GetSeed(xxxx);
        if (seedbuf[0] != aaaa) 錯誤...
        if (seedbuf[1] != bbbb) 錯誤...
        if (seedbuf[2] != cccc) 錯誤...
        if (seedbuf[3] != dddd) 錯誤...
        正確...
    }

            加密者: 因為輸入的 xxxx 可以是任何值, 那麽返回的值也不盡相同。同傳統的方法相比算是進了一步。

            黑 客: 太簡單了,你必須預先記錄下 aaaa, bbbb, cccc, dddd 的值用來比對,我隻要把這些判別一改就可以了,我甚至不需要加密鎖就能破解。

            那麽我們看看下麵的例子:

    if (CheckDongle() == 1){
        seedbuf = GetSeed(xxxx);
        for (i=0;i<1000;i++){
            MyData[i] = MyData[i] ^ seedbuf[i%4];
        }
    }

            加密者: 這個例子是用種子碼的結果把特定的數據變換一次。這種方法可以保證在沒有鎖的情況下,軟件不可能被解密。

            黑 客: 嗯..., 我在有軟件鎖的情況下能破解。我先在有軟件鎖的情況下運行一次,記錄下seedbuf 的返回值。然後屏蔽掉 seedbuf = GetSeed(xxxx) 一行, 而把初正確的值預先就放到 seedbuf 中。

            那麽看看這個例子:

    if (CheckDongle() == 1){
        seedbuf = GetSeed(aaaa);
        for (i=0;i<1000;i++){
            MyData[i] = MyData[i] ^ seedbuf[i%4];
        }
        seedbuf = GetSeed(bbbb);
        for (i=0;i<1000;i++){
            MyData[i] = MyData[i] ^ seedbuf[i%4];
        }
        seedbuf = GetSeed(cccc);
        for (i=0;i<1000;i++){
            MyData[i] = MyData[i] ^ seedbuf[i%4];
        }
        seedbuf = GetSeed(dddd);
        for (i=0;i<1000;i++){
            MyData[i] = MyData[i] ^ seedbuf[i%4];
        }
    }

            加密者: 這回,我的 seedbuf 反複用了 4 次,每次的內容都不同。

            黑 客: 這個...,這個...,看來我得找個空的地方來記錄一下你的 seedbuf 的值, 喂! 你的seedbuf 能不能開的大一點?

            我又有了個更好的方案:

    s = xxxx
    if (CheckDongle() == 1){
        seedbuf = GetSeed(s);
        for (i=0;i<1000;i++){
            MyData[i] = MyData[i] ^ seedbuf[i%4];
        }
        s = seedbuf[s%4];
        seedbuf = GetSeed(s);
        for (i=0;i<1000;i++){
            MyData[i] = MyData[i] ^ seedbuf[i%4];
        }
        s = seedbuf[s%4];
        seedbuf = GetSeed(s);
        for (i=0;i<1000;i++){
            MyData[i] = MyData[i] ^ seedbuf[i%4];
        }
        s = seedbuf[s%4];
        seedbuf = GetSeed(s);
        for (i=0;i<1000;i++){
            MyData[i] = MyData[i] ^ seedbuf[i%4];
        }
        s = seedbuf[s%4];
        seedbuf = GetSeed(s);
        for (i=0;i<1000;i++){
            MyData[i] = MyData[i] ^ seedbuf[i%4];
        }
    }

            加密者: 這回,我的 seedbuf 不但反複用了 4 次,而且每次 seedbuf 的內容都是依賴上次變換的結果。你還能破嗎,黑客? 黑客? 你在哪兒……?

            方案八:

            利用模塊字功能加密。

            ROCKEY 加密鎖為多模塊軟件加密引入了模塊字的概念,模塊字是為了區分同一軟件的不同模塊的加密而設立的。模塊字在有二級密碼下可以寫入,但不能讀出,必須通過對軟件鎖編程的方式來讀出模塊字。但很多用戶要加密的軟件隻是個單一模塊的軟件,不需要多模塊加密,這時候模塊字就可以用來作一些其它的加密工作了。在這裏我們設計了一套利用模塊字對單一軟件進行加密的方案。

            首先在模塊字的 0 - 11 中寫入 12 個不同的值。

            在計算1 的工作中會根據輸入的模塊號把對應模塊的值代入。這裏我們把模塊號定為月份, 例如在 1月輸入模塊號1, 2月輸入模塊號2...

            寫入的算法如下:

    A = A + G (G 就是模塊字)

            那麽寫入的算法因為模塊號的不同(也就是月份的不同), 返回的結果也不同。可以說軟件的加密算法每個月都在變。這種方法僅僅對模塊字的應用舉的一個例子。用戶可以根據自己的需要設計出更多更複雜的算法。腦筋比較快的用戶現在應該想到模塊字的遞減功能也不是僅僅控製 Demo 版軟件才能用的了。

    彩神彩票