淺析CRC算法在軟件加密保護(hù)中的應(yīng)用
CRC(CyclicRedundancyCheck,直譯:循環(huán)冗余校驗(yàn))技術(shù)是一項(xiàng)很成熟的技術(shù),在眾多領(lǐng)域有廣泛的應(yīng)用,在數(shù)據(jù)存儲和通信傳輸應(yīng)用中處處都可以看到它的身影。最常用的CRC校驗(yàn)形式有CRC-16,CRC-32兩種形式,采用CRC-16校驗(yàn),可以保證在1014 位碼元中只含有一位未被檢測出的錯誤,采用CRC-32校驗(yàn)的出錯概率比CRC-16還低105 倍。CRC的主要特點(diǎn)就是:檢錯能力極強(qiáng),開銷很小,易于實(shí)現(xiàn)。從性能和開銷上綜合考慮,其遠(yuǎn)遠(yuǎn)優(yōu)于奇偶校驗(yàn)及算術(shù)和校驗(yàn)等方式。因此,很多軟件在加密保護(hù)時(shí)都將CRC技術(shù)應(yīng)用其中。本文擬從CRC校驗(yàn)的原理解剖入手,用實(shí)際代碼和應(yīng)用給大家解析CRC校驗(yàn)在軟件加密中的實(shí)際應(yīng)用,希望能給您的軟件加密保護(hù)提供一些幫助和建議。

CRC 校驗(yàn)的原理解析
在實(shí)際應(yīng)用中,根據(jù)環(huán)境和需求的變化,CRC形成了多種變形方式。比如:通訊協(xié)議X.25的幀檢錯序列采用的是CRC-CCITT方式,ARJ、LHA、ZIP等壓縮軟件采用的是CRC-32方式,磁盤驅(qū)動器的讀寫采用的是CRC-16方式,GIF、TIFF等圖像存儲格式也使用CRC作為檢錯技術(shù)。
目前,比較流行的CRC形式主要是:CRC-16(CRC-CCITT)、CRC-32兩種,CRC-4、CRC-8、CRC-12等形式的應(yīng)用比較少見。其實(shí),雖然有這么多種變形方式,但其原理是完全相同的,只是在實(shí)現(xiàn)上有一點(diǎn)變化而已,下面我們就對其原理進(jìn)行一番解剖,希求通透。
CRC算法本質(zhì)是(模-2)除法的余數(shù)運(yùn)算,使用的除數(shù)不同,CRC的類型也就不一樣。怎么樣,不好理解吧?沒關(guān)系,我們繼續(xù)講解:CRC的算法其實(shí)是采用了多項(xiàng)式編碼的方法,您可以將要被處理的數(shù)據(jù)塊M看成一個(gè)n階的二進(jìn)制多項(xiàng)式,其形式如下:
a 是對應(yīng)的階數(shù)(位數(shù))的值;
x是對應(yīng)的“模(進(jìn)制)”數(shù),由于我們處理的都是二進(jìn)制數(shù),所以x就是2 了。(模-2)的意思現(xiàn)在您明白了吧?
下面我們用一個(gè)數(shù)進(jìn)行解釋吧:
有一個(gè)二進(jìn)制數(shù)M=10010101,其對應(yīng)的多項(xiàng)式就可以表示為:
CRC校驗(yàn)就是基于這種多項(xiàng)式進(jìn)行的運(yùn)算,其乘除法運(yùn)算過程與普通代數(shù)多項(xiàng)式的乘除法相同,其加減法運(yùn)算以2為模,加減時(shí)不進(jìn)(借)位,實(shí)際上與邏輯異或(XOR)運(yùn)算是一致的。
通常,根據(jù)多項(xiàng)表達(dá)(運(yùn)算)式的不同,就形成了不同的CRC形式,以下是各種常用的多項(xiàng)表達(dá)(運(yùn)算)式:
這些多項(xiàng)表達(dá)式的值就是(模-2)除法的除數(shù),只要能確定使用哪一種多項(xiàng)式(也就是對應(yīng)除數(shù)),您就可以很簡單的獲取CRC檢驗(yàn)碼了。下面就給您介紹CRC檢驗(yàn)碼的計(jì)算過程(看起來麻煩,其實(shí)簡單):
1、先確定您要使用的CRC校驗(yàn)形式,以此確定對應(yīng)除數(shù)(用G來表示)和選定階數(shù)(用r來表示)。(如果選擇CRC-4的話,r就等于4,選擇CRC-16話,r就等于16,以此類推。)
2、在待處理的數(shù)據(jù)塊M'后附加上r個(gè)0。假設(shè)原始數(shù)據(jù)塊的長度是m位的話,附加之后的長度就變成m+r位了,我們用M來代表附加后的值。
3、用第一步選擇的生成多項(xiàng)式的值(即對應(yīng)除數(shù)G)來除第二步附加0后生成的值(M),循環(huán)計(jì)算,一直到余數(shù)的階數(shù)小于等于r-1,這時(shí)所得到的余數(shù)(用Y表示)就是原始數(shù)據(jù)M'經(jīng)過所選擇的CRC校驗(yàn)形式所生成的CRC校驗(yàn)碼。
●如果您想將生成的校驗(yàn)碼與原始數(shù)據(jù)進(jìn)行復(fù)合,只需要用第二步生成的(M)以模2的方法減去得到的CRC校驗(yàn)碼(Y),所得到的值就是包含了CRC校驗(yàn)碼的數(shù)據(jù)串M''。(不過在
軟件加密過程中可能用不到這一步)。
怎么樣,很簡單吧,只需要三步,就可以得到CRC 的校驗(yàn)碼。還不明白?舉個(gè)例子吧:
設(shè)原始數(shù)據(jù)M'=1100110100
選擇CRC-4的形式,則G=24+2+1=19=10011(二進(jìn)制)
r =G 的二進(jìn)制位數(shù)減1=5-1=4
對原始數(shù)據(jù)M'進(jìn)行處理,在其尾部附加r個(gè)0,即:
M=M'+0000=11001101000000
再用G 循環(huán)除M:
其實(shí)校驗(yàn)碼生成的過程就是一個(gè)循環(huán)移位的運(yùn)算,位與位之間就是異或(XOR)運(yùn)算。
◆一個(gè)數(shù)據(jù)的校驗(yàn)過程是這樣的,如果有大量數(shù)據(jù)(比如說一個(gè)可執(zhí)行程序或一個(gè)壓縮包)將如何進(jìn)行校驗(yàn)?zāi)??其?shí)很簡單,只要將一個(gè)文件看成一個(gè)被一些數(shù)字分割的很長的位字串就可以了,只是這個(gè)位字串比較TA而已,你只要按標(biāo)準(zhǔn)的方式對這個(gè)比較長的位字串進(jìn)行(模-2)除法運(yùn)算,就一定會得到一個(gè)余數(shù)---CRC校驗(yàn)碼,而這個(gè)校驗(yàn)碼就是這個(gè)文件的CRC校驗(yàn)值。
CRC 校驗(yàn)的代碼實(shí)現(xiàn)
好了,理論上的準(zhǔn)備是很多了,現(xiàn)在要用進(jìn)入實(shí)踐了。下面,我們將給您提供一段很簡單而實(shí)用的代碼,用來實(shí)現(xiàn)CRC-32校驗(yàn),最終,我會用這段代碼實(shí)現(xiàn)軟件加密保護(hù)。
大家可以看到,上面生成CRC校驗(yàn)碼的過程中,使用了大量的位運(yùn)算和邏輯操作。而我想告訴大家的是,基于位運(yùn)算的算法是非常慢的而且效率很低。因此,在實(shí)際使用中不推薦使用“計(jì)算法”來生成CRC校驗(yàn)碼,而建議使用“查表法”來進(jìn)行CRC校驗(yàn)碼計(jì)算。查表法又是什么方法呢?這里我不做過多的分析,簡單的說,它是利用預(yù)先計(jì)算出的標(biāo)準(zhǔn)碼表(對應(yīng)不同的校驗(yàn)形式有不同的碼表,見附表1、2),用簡單的移位和XOR操作,快速計(jì)算出CRC校驗(yàn)碼的方法。具體的算法就是:
(1)將上次計(jì)算出的CRC校驗(yàn)碼右移一個(gè)字節(jié);
(2)將移出的這個(gè)字節(jié)與新的要校驗(yàn)的字節(jié)進(jìn)行XOR 運(yùn)算;
(3)用運(yùn)算出的值在預(yù)先生成碼表中進(jìn)行索引,獲取對應(yīng)的值(稱為余式);
(4)用獲取的值與第(1)步右移后的值進(jìn)行XOR 運(yùn)算;
(5)如果要校驗(yàn)的數(shù)據(jù)已經(jīng)處理完,則第(4)步的結(jié)果就是最終的CRC校驗(yàn)碼。如果還有數(shù)據(jù)要進(jìn)行處理,則再轉(zhuǎn)到第(1)步運(yùn)行。
看上面的過程是十分簡單的,不好理解的可能是“預(yù)先生成的碼表”。其實(shí)這個(gè)碼表就是2^8 的數(shù)組,為什么是8次方呢?因?yàn)槲覀兪怯米止?jié)來進(jìn)行運(yùn)算的,而一個(gè)字節(jié)是8位,所以就是2的8次方了。因此這個(gè)碼表就是擁有256值的數(shù)組,對應(yīng)的每個(gè)值實(shí)際上就是0-255以對應(yīng)的CRC多項(xiàng)表達(dá)式(見原理分析)為權(quán)的CRC碼。如CRC-16的多項(xiàng)表達(dá)式就是,CRC-32的多項(xiàng)表達(dá)式就是:
CRC 校驗(yàn)在軟件加密保護(hù)中的攻與防
上面用大篇幅介紹CRC的原理與實(shí)現(xiàn),都是為現(xiàn)在的實(shí)戰(zhàn)打基礎(chǔ),現(xiàn)在我們就要用實(shí)戰(zhàn)來校驗(yàn)了。
大家已經(jīng)知道,CRC校驗(yàn)生成的結(jié)果只是一個(gè)Long型的整數(shù),市面上一些軟件是如何將這個(gè)整數(shù)應(yīng)用在軟件加密保護(hù)中呢?這里我給大家介紹兩種常用的方式:
1、是對程序自身的進(jìn)行保護(hù)。首先對原始可執(zhí)行程序進(jìn)行CRC校驗(yàn),同時(shí)保存校驗(yàn)結(jié)果(可以保存在注冊表、配置文件或可執(zhí)行程序本身)。在程序運(yùn)行時(shí),對程序自身進(jìn)行CRC校驗(yàn),并將運(yùn)算出的結(jié)果與保存的原始結(jié)果進(jìn)行比較,如果不相同,就說明程序已經(jīng)被修改(最有可能是被破解或被病毒感染)。即使只有1Bit的修改,都會被CRC檢查出來,所以用CRC做自校驗(yàn)相當(dāng)有效。
2、用CRC校驗(yàn)算法,對注冊名和注冊碼進(jìn)行變形運(yùn)算和判斷,以此做為注冊保護(hù)和授權(quán)的手段。
這兩種方式在軟件保護(hù)上的運(yùn)用十分廣泛。可以說,每一種軟件加殼(加密)保護(hù)軟件(如upx,Aspack,FSG等)都使用了CRC進(jìn)行自身校驗(yàn)保護(hù)。
為了證明CRC在軟件加密保護(hù)上的效果,我制作了一套測試用例,大家可以在http://www.xxx.com上下載CRCTest.rar壓縮包,按本文進(jìn)行測試和分析。
壓縮包中有兩個(gè)可執(zhí)行程序:crctest.exe和Makecrc.exe。其中crctest.exe就是我們要進(jìn)行分析的對象,界面如下:
軟件已經(jīng)進(jìn)行了CRC外殼校驗(yàn)保護(hù),同時(shí),使用CRC-32算法做注冊碼校驗(yàn),可以說將CRC在軟件加密保護(hù)上的應(yīng)用全部發(fā)揮出來了。
MakeCrc.exe是配套工具,用來給上面的程序注入CRC保護(hù)碼和計(jì)算注冊碼。
現(xiàn)在,可以打開crctest.exe 文件,并隨意輸入注冊名和注冊碼,看一看!
您也可以用16進(jìn)制編輯器(如:Hiew,010Editor,RTA等),將crctest.exe的最后一個(gè)字節(jié)00修改成0F保存修改后,再運(yùn)行程序,程序會提示被修改。
怎么樣,這就是CRC保護(hù)的效果。如果您試圖強(qiáng)行暴破來完成注冊的話,就必須修改原始文件,但是軟件將會在自校驗(yàn)時(shí)發(fā)現(xiàn)自己被修改了,然后自動退出。除非您得到正確的注冊碼或注冊算法,而軟件使用的注冊算法也是由CRC算法變形實(shí)現(xiàn)的。如果在不知道具體算法的情況,想要強(qiáng)行暴破是比較麻煩的,這就是CRC的威力。市面上大多數(shù)軟件大多是這樣做的,畢竟誰也不想自己的軟件被人破解或修改,難道您不這么認(rèn)為嗎?






