c/c++ 100行代碼破解winrar

  • 寫在前面的廢話

             winrar過時了總是彈窗,超噁心,今天也不想去上課,算了ri掉rar吧。 ios

  • 原理

                 winrar有40天的試用期,過了試用期就開始彈窗。由於之前用od調試過,判斷試用是否過時的彙編代碼是
cmp eax,28h  //用eax存的天數和28h(等於40天)比較 判斷是否過時
             //二進制值爲 0x83,0xf8,0x28

咱們將上面的指令替換爲: windows

   彙編指令      對應二進制值
cmp eax,eax  // 0x3b, 0xc0
nop          //	0x90
這樣eax和本身比較,就不知道是否過時了。由於cmp eax,eax只有2字節 因此後面又加上nop指令,這樣寫入文件時能夠直接覆蓋數據,而不用考慮移動其餘數據。
  • 代碼

#include <stdio.h>
#include <windows.h>
#include <string>
#include <ShlObj.h>
#include <iostream>
#include <fstream>

using namespace std;

string ChoseFolder(){
	char szPathName[MAX_PATH];
	BROWSEINFO bInfo={0}; 
	bInfo.hwndOwner=GetForegroundWindow();//父窗口 
	bInfo.lpszTitle=TEXT("請選擇winrar安裝路徑"); 
	bInfo.ulFlags=1; 
	LPITEMIDLIST lpDlist; 
	lpDlist=SHBrowseForFolder(&bInfo); 
	if (lpDlist!=NULL){//單擊了肯定按鈕  
		SHGetPathFromIDList(lpDlist,szPathName);
		return string(szPathName);
	}else{
		return string();
	}
}

int backups( const string filename){
	string sfilename(filename+".beifen");
	const char *pfilename = sfilename.c_str();
	if( CopyFile(filename.c_str(),pfilename,false) != true ){
		return -1;//CopyFile error
	}
	return 0;//copy success
}

int rollback(const string filename){
	string sfilename(filename+".beifen");
	const char *pfilename = sfilename.c_str();
	if( CopyFile(pfilename,filename.c_str(),false) != 0 ){
		return -1;//CopyFile error
	}
	return 0;//copy success
}

int check(string filename){
	ifstream filein(filename.c_str(), ios::binary);
	if( filein==NULL ){
		return -1;
	}
	filein.close();
	return 0;
} 

int process(string filename){
	FILE *fp;
	unsigned long filesize;
	fp = fopen(filename.c_str(),"rb+");
	if( !fp ){
		printf("open file error");
		return -1;
	}
	//rewind(fp);
	fseek(fp,0,SEEK_END);
	filesize=ftell(fp);

	fseek(fp,0,SEEK_SET);
	unsigned char ch;
	unsigned char *data = (unsigned char*)malloc(filesize);
	size_t count = fread(data,sizeof(char),filesize, fp);
	if( count != filesize ){
		cout << "count=" << count << endl;
		printf("read file error\n");
	//	return -2;
	}
	
	unsigned char symbol[3] = { 0x83, 0xf8, 0x28 };	//cmp eax,28h
	unsigned char cover[3] = {0x3b, 0xc0,	//cmp eax,eax
							  0x90 };		//nop
	//cmp eax,28h 用來判斷軟件使用時間是否超過40天
	//咱們用 cmp eax,eax 替換這個指令,軟件就老是覺得咱們試用40天還沒過時
	//由於cmp eax,eax 只佔2字節 而cmp eax,28h 佔3字節,爲了方便處理 
	//直接在cmp eax,eax 後加上nop指令。如今要替換的數據也是3字節了。
	//在文件中找到symbol的位置 而後用cover直接覆蓋便可。  
	int index = -1;
	for(int i=0; i<filesize; i++){
		if(memcmp(&data[i], symbol, sizeof(symbol)) == 0 ){
			index = i;
			break;
		}
	}
	if( index!= -1 ){
		fseek(fp,index,SEEK_SET);
		fwrite(cover, sizeof(char), sizeof(cover), fp);
	}else{
		return -3;
	}
	fclose(fp);
	return 0;
}
int main(){
	char *filename;
	string path;
	
	//選擇程序安裝路徑
	path = ChoseFolder();
	if( path.length()==0 ){
		cout << "ChoseFolder error" << endl;
		return -1;
	}

	//檢查文件是否打開正常
	string fullpath( path + "\\WinRAR.exe" );
	if( check(fullpath) != 0 ){
		cout << "check error" << endl;
		return -2;		
	}
	
	//備份文件 以便恢復
	if( backups(fullpath) != 0 ){
		cout << "backups error" << endl;
		return -3;	
	}

	//打開文件處理
	if( process(fullpath)!=0 ){
		cout << "process fail" << endl;
		rollback(fullpath);			//處理失敗回滾
		return -4;
	}

	cout << "process success" << endl;
	return 0;
}
相關文章
相關標籤/搜索