您的位置:首页 > 编程语言 > C语言/C++

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

2014-03-11 21:54 225 查看

写在前面的废话

winrar过期了老是弹窗,超恶心,今天也不想去上课,算了ri掉rar吧。


原理

winrar有40天的试用期,过了试用期就开始弹窗。因为以前用od调试过,判断试用是否过期的汇编代码是
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: