1. 如何用C語言編寫暴力破解壓縮文件解壓密碼的程序
由於有一個重要的Rar文件,極需解開,首先試用了ARPC,但是解壓的速度極慢,每秒只有30個左右,所以斷了窮舉破解的念頭,卻仍不死心,因為我從不崇尚窮舉破解的方法,除非每秒可以跑幾千萬次的,我或許可以一試,所以決定研究一下Winrar3.x密碼演算法,以期是否可以破解該密碼。查看了網路上的資料,包括看雪FAQ里的回答,都聲稱只能用窮舉法破解,起先並不理解,但通過研究,我理解了看雪前輩們在FAQ里所說的原因,不禁讓我佩服
Winrar加密思路的成熟。雖然研究的結果沒有什麼新意,但我還是決定把我的研究結果與大家一起分享,為那些仍然以為winrar密碼可以象破解注冊碼一樣的,通過修改winrar彈出框之類的更改文件流程指向可以達到跳過密碼檢驗的朋友,做一個簡要的說明。
一、Rar文件生成的流程。
Winrar加密文件時,總的分兩個步驟:
1:先把源文件壓縮,壓成一段數據段。
冊山叢2:再將壓縮完的數據段加密。
對於同一個源文件來說,不進行加密,壓縮完,其rar文件中的數據段是一模一樣的。但是如果對同一個源文件來說,即使使用同一個密碼,加密完rar文件中的數據段是不一樣的,這是由於加密的密鑰是依賴於一個Salt(8個位元組的密鑰,用來加密時使用,存放在rar文件頭中里)
所以要解密rar加密文件關鍵在於數據解密這一步,那我們接下來研究一下如何加密的。
二、加密「壓縮完的數據段」的流程
1、獲取州櫻密鑰:
將明文的密碼與Salt一起,通過HASH演算法,生成兩個16位元組的密鑰。(一個是KEY(AES演算法的參數),一個是initVector)
2、以Key和initVector來加密壓縮數據:
這里,是一個循環加密的結構,每16位元組作為一個塊,進行加密(這可能正是為什麼加密完的文件長度總為16倍數的原因)。加密採用AES演算法(RAR採用的是AES的rijndael的標准應用)。這里注意:AES加密前,有一個異或運算,是先將每16位元組塊與上一個16位元組塊加密結果進行異或,然後再進行AES演算法的。我用一個簡單的示意代碼看說明唯譽:
;===============================================
packblock[0]=packblock[i]^initVector
encryptBlock[0]=AES(packblock[0]) ;(KEY為AES的密鑰)
for i=1to 塊數量-1
packblock[i]=packblock[i]^encryptBlock[i-1]
encryptBlock[i]=AES(packblock[i]);(KEY為AES的密鑰)
next
;packblock[i]表示壓縮完的每16位元組數據
;encryptBlock[i]表示加密完的每16位元組數據
;===============================================
三、解密的過程
由於AES演算法是對稱的,所以解密的過程,是加密過程的逆運算。但解密時AES演算法過程與加密所用的不一樣(是因為解密過程中由KEY生成的子密鑰表不一樣)。仍然需要我們將密碼輸入,與salt一起生成兩個16位元組密鑰,KEY和initVector。
;===============================================
packblock[0]=AES1(encryptBlock[0]) ;(KEY為AES的密鑰)
packblock[0]=packblock[i]^initVector
for i=1to 塊數量-1
packblock[i]=AES1(encryptBlock[i]) ;(KEY為AES的密鑰)
packblock[i]=packblock[i]^encryptBlock[i-1]
next
;===============================================
那判斷密碼是否正確的在什麼地方呢?
解密的過程是解密後的數據塊進行解壓縮,然後解成源文件,對該文件進行CRC校驗,存在RAR文件中的源文件CRC校驗碼比較,相同則密碼正確,不相同則密碼錯誤。
四、無法秒破的原因
從上面,我們了解了RAR文件的整體思路。地球人都知道,解密時,肯定有個步驟是來判斷密碼的正確與否。而且,依據以往的經驗,我們也許可以將某些判斷的點移動,那樣可以縮減破解的流程思路。那RAR的這一步在哪裡?它把校驗放在了最後的一步。如果要秒破,我們該怎麼做泥?至少我認為目前是不可能的。
我們從解密過程逆反過來看看:
1、CRC檢驗這一塊修改跳轉?根本毫無意義,因為它已經是最後一步了。你可以修改RAR文件頭的CRC值,你可以將它改得和你用任意密碼解壓出來的文件CRC值一樣,但你的文件根本就不是原來的文件了。可能已經完全面目全非了。所以,對這一過程不可行。CRC校驗本身是不可逆的
2、那麼把判斷提前到壓縮完的數據?
解壓的時候,有沒有什麼來判斷壓縮數據是否正確?壓縮完的數據,有沒有固定的特徵,是否可以做為解壓的判斷,在這一步里,我們也無法找到有效的可用的固定特徵。因為這一步涉及到RAR的壓縮演算法。即使一個源文件,即使你的文件前一部分是完全相同的,只對後面的部分進行改過,那麼壓縮完,數據也是完全一樣的。因為壓縮完的數據首先是一個壓縮表,後面是編碼。文件不一樣,掃描完的壓縮表也不一樣,編碼又是依賴於壓縮表,所以,這里頭找不到壓縮完的數據有任何的固定特徵可以用來判斷的。
不管壓縮數據是什麼樣的,Winrar都一如既往地進行解壓,沒有進行壓縮數據是否有效的判斷。
3、那假如我們破解了AES了泥?
由於AES只依賴於KEY,如果AES演算法被破解了,我們知道了KEY,我們可以解出壓縮完的數據,但是這里有一個問題,還有一個initVector密鑰,用來第一個16位元組塊的異或,你沒有initVector參數,你第一個16位元組塊的數據便無法解得出來。
4、那就只能從第一步Hash的演算法入手
即使你能破解hash,但hash後的結果泥?沒有結果,你怎麼返推密碼。
所以綜上,我發現rar的加密是由hash和AES兩種演算法互相牽制,而兩種演算法當前都無法破解,至少目前還沒有辦法秒破,也理解了看雪高手講的道理。
五、對窮舉提高演算法效率的一些設想。
我用匯編寫完了RAR窮舉解密的演算法模塊,但是如何提高效率,優化窮舉的速度泥?我有如下的想法:
1、從壓縮數據里找尋特徵,省掉解壓縮、CRC檢驗代碼和生成initVector生成代碼。目前,通過多次實驗,我找到的一個特徵(不知道這個是否正確),即解密完的最後一個16位元組塊的最後一個位元組必須為0。因為經過多次的試驗,我發現有加密的數據段長度都會比未加密前的數據長,那麼,最後一個
16個位元組的數據塊解密完,多出的部分就都為0,但多出幾個位元組泥?多次實驗,長度不一,我試想著從加密數據段最後一個16個位元組塊著手,只解這一塊,看是否一個位元組為0,這樣,只解密16個位元組的數據,來大大提高效率?如果能進行到這一步了,再通過解全部數據,進行CRC校驗的判斷。
2、如果第一個特徵不成立的話,針對特定格式的壓縮文件,比如doc、jpg等,部分數據固定,壓縮完的數據是否存在相互牽制的數據?從而把判斷提前,這一步,我不知道如何找到壓縮完的數據是否存在相互牽制的數據。
2. c語言怎麼解ZIP壓縮格式呀!
為什麼一定要用C語橡茄言.直接用解壓軟梁雀察件也可以呀.
網上歲猜下載地址:
http://www.winrar.com.cn/download.htm
3. 如何用c語言壓縮解壓文件夾
壓縮是一種有效的減小數據量的方法,目前已經被廣泛應用於各種類型的信息系統之中。
一種壓縮文本文件的方法如下:
1. 原始文本文件中的非字母的字元,直接拷貝到壓縮文件中;
2.
原始文件中的詞(全部由字母組成),消閉如果是第一次出現,則將該詞加清敏入到一個詞的列表中,並拷貝到壓縮文件中;否則該詞不拷貝到壓縮文件中,而是將該詞在詞的列表中的位置拷貝到壓縮文件中。
3. 詞的列表的起始位置為 1 。 詞的定義為文本中由大小寫字母組成的最大序列。大寫字母和小寫字母認為是不同的字母,即 abc 和 Abc
是不同的詞。詞的例子如下: * x-ray 包括兩個詞 x 和 ray * mary's 包括兩個詞 mary 和 s * a c-Dec 包括三個詞 a 和
c 和 Dec 編寫一個程序,輸入為一組字元串,輸出為壓縮後的文本。
輸入:
輸入為一段文本,你可以假設輸入中不會出現數字、每行的長度不會超過 80 個字元,並且輸入文本的大小不會超過 10M。
輸出:
壓縮後的文本。
輸入:
Please, please do it--it would please Mary very,
very much.
Thanks
輸出:
Please, please do it--4 would 2 Mary very,
7 much.
Thanks
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#defineLEN1<<20
intisArabic(charc){
return('a'<=c&&c<='z')||('A'<=c&&c<='Z');
}
intmain()
{
chardict[LEN];
char*index[100000];
charbuf[82];
intnWord=0;
inti,j;
charc;
char*inFile="G:\in.txt",*outFile="G:\out.txt";
FILE*inp,*outp;
if((inp=fopen(inFile,"r"))==NULL){
printf("cannotopen ");
exit(1);
}
if((outp=fopen(outFile,"w"))==NULL){
printf("outfail ");
}
index[0]=dict;
do{
/*getaword*/
i=0;
do{
c=fgetc(inp);
buf[i++]=c;
}while(isArabic(c));
buf[i-1]=0;
/*putittodict*/
if(i>1){
for(j=0;j<nWord;j++){
if(strcmp(index[j],buf)==0){
break;
}
}
if(j==nWord){
strcpy(index[nWord],buf);
index[nWord+1]=index[nWord]+strlen(buf)+1;
nWord++;
/*printf("new:%s ",buf);*/
}else{
sprintf(buf,"%d",j+1);
/*printf("found:%s ",buf);*/
}
}
/*putittooutputfile*/
if(c!=EOF)
fprintf(outp,"%s%c",buf,c);
答橋枝else
fprintf(outp,"%s",buf);
}while(c!=EOF);
fclose(inp);
fclose(outp);
/*system("PAUSE");*/
returnEXIT_SUCCESS;
}
4. C++如何讀取壓縮文件數據
首先指出你提問的一個錯誤這個不是C++實現, 這個是純C實現的
你說的BZ2_開頭,這些只是變數名字而已,沒什麼特別的意思。
給你解釋一句吧:
BZ2_bzlibVersion=GetProcAddress(hLib,"BZ2_bzlibVersion");
要解釋這句話首先你要明白這個c程序本身是不能解鎮悄瞎壓的,他是調用了一個動態庫libbz2-1.0.2.DLL里的函數,你可以從
#define BZ2_LIBNAME "libbz2-1.0.2.DLL"
hLib=LoadLibrary(BZ2_LIBNAME);
這兩句看出來他載入了上面說的那個庫,然後回到剛才那句,BZ2_bzlibVersion是定義的一個函數指針,定義語句他省略了。這里用了C語言的defalut-int定義。
GetProcAddress用來獲得庫函數的入口地址,hLib是前面打開的庫函數文件句柄(hLib=LoadLibrary(BZ2_LIBNAME);),"BZ2_bzlibVersion"是庫函數的需要調用的函數名。
這句話最終的功能就是把原來庫函數的,"BZ2_bzlibVersion"函數地址賦值給函數指針BZ2_bzlibVersion,以後調用BZ2_bzlibVersion就可以實現庫函數,"BZ2_bzlibVersion"的功能。
後面幾句話都是一樣的,fwrite是寫文件,stdout是輸出流,這些都可以網路到。
說實話你一個新手看這個真的沒什麼意義。你問的也是些細枝末節的問題,運宴這個程序其實核心功能只有兩句話:
while((len=BZ2_bzread(BZ2fp_r,buff,0x1000))>0){
fwrite(buff,1,len,fp_w);
}
while((len=fread(buff,1,0x1000,fp_r))>0){
BZ2_bzwrite(BZ2fp_w,buff,len);
}
而這兩句話調用的是調用庫函數BZ2_bzread和BZ2_bzwrite來進行解壓fwrite和fread是寫文件和讀文件。即使你都看懂了,你就會解壓了嗎?即使看懂你還是什麼都不會,你只是會調用一個庫函數御空而已。如果你要研究這個庫函數,那就更不是一兩個問題能說清的了。建議你還是從基礎,一步一個腳印地學習C/C++
祝好運
5. 如何用C語言解壓縮文件
如果你自己設計演算法弊搭,就另當別論,如果想利陪前用第3方的演算法,我推薦用zlib,生成的壓縮包是流行的zip格式.源代蘆卜清碼很好找(www.zlib.net)
6. C語言如何直接讀取壓縮文件
c語言中沒有直接讀取壓縮文件的函數包。
7. C語言如何讀取zip文件內容
zip是壓縮後的,你直接讀取就是亂碼,沒有能直接讀取的,想讀取真實內容,必須先按解壓演算法解壓出來。
8. 怎麼用c語言將.zip文件解壓成文件夾
簡單一點的 直接調用系拿沒棗統命令
比如system("unzip ___filename___ -d target_path");
這樣做 實察山際就相當於在命令行下敲了這樣的一個命令
不過 這個要求系統內 必須安裝了unzip這個軟體 即支持這個命令
復雜一些的 你可以再網上找一個開源的gzip 很多很好消拆找的 然後看懂代碼 調用對應的介面函數
這樣做的好處不需要依賴系統環境