-
写在前面的废话
winrar过期了老是弹窗,超恶心,今天也不想去上课,算了ri掉rar吧。
-
原理
cmp eax,28h //用eax存的天数和28h(等于40天)比较 判断是否过期
//二进制值为 0x83,0xf8,0x28
我们将上面的指令替换为:
汇编指令 对应二进制值
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;
}