天天看點

Qt--探讨.exe程式加密

一、前言

程式員随着代碼寫的多,難免會接到一些私活。但是又怕對方白嫖,困難總比辦法多,哦不,錯了,辦法總比困難多。為了避免被别人白嫖,我們可以給自己的程式留後手,網上查閱資料,大概有以下兩種:

1、采用遠端控制:UDP指令遠端鎖死程式;

2、采用本地加密:提取CPU和硬碟序列号,加密生成注冊碼;

以上兩種方法各有利弊,方法1可以本人自由控制,但是一旦裝置沒網,就GG了;方法2則不依賴網絡,且每台裝置的注冊碼唯一,但是本人無法直接控制。個人認為還是方法2簡單有效,是以下面就方法2進行具體分析。

二、分析

采用注冊碼機制,我們首先要生成注冊碼,Qt下擷取CPU和硬碟等系統資訊(針對windows系統)的方法如下:

windows下執行指令除了用​

​cmd​

​​之外,還有個東西叫​

​WMIC​

​,非常強大,可以通過他擷取很多資訊,包括硬體資訊。

QString Widget::getWMIC(const QString &cmd)
{
    //擷取cpu名稱:wmic cpu get Name
    //擷取cpu核心數:wmic cpu get NumberOfCores
    //擷取cpu線程數:wmic cpu get NumberOfLogicalProcessors
    //查詢cpu序列号:wmic cpu get processorid
    //查詢主機闆序列号:wmic baseboard get serialnumber
    //查詢BIOS序列号:wmic bios get serialnumber
    //檢視硬碟:wmic diskdrive get serialnumber
    QProcess p;
    p.start(cmd);
    p.waitForFinished();
    QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
    QStringList list = cmd.split(" ");
    result = result.remove(list.last(), Qt::CaseInsensitive);
    result = result.replace("\r", "");
    result = result.replace("\n", "");
    result = result.simplified();
    return result;
}
 
QString Widget::getCpuName()
{
    return getWMIC("wmic cpu get name");
}
 
QString Widget::getCpuId()
{
    return getWMIC("wmic cpu get processorid");
}
 
QString Widget::getDiskNum()
{
    return getWMIC("wmic diskdrive where index=0 get serialnumber");
}      

擷取注冊碼之後,就可以着手程式的加密了,我的政策是這樣的:

  • 如果程式沒有注冊,預設可以使用3次;
  • 如果程式注冊了,使用次數無限制;

那怎麼限制程式的使用次數呢?我的政策是這樣的:

  • 生成一個System.ini配置檔案,裡面存放程式的剩餘運作次數​

    ​RemainTime:3​

    ​;
  • 但是​

    ​RemainTime:3​

    ​當然不能直接存在System.ini中,不然一眼看出來就可以自己修改次數了;
  • 是以在對System.ini寫之前,進行加密;對System.ini讀之後,進行解密;
  • 加/解密算法可以自行選取,但是要采用可逆算法;
  • 然後判斷剩餘運作次數,如果小于等于0,則程式提示需注冊後使用,并退出;
  • 否則,剩餘運作次數減1,程式正常運作;

三、實作(核心代碼)

QString Widget::getWMIC(const QString &cmd)
{
    //擷取cpu名稱:wmic cpu get Name
    //擷取cpu核心數:wmic cpu get NumberOfCores
    //擷取cpu線程數:wmic cpu get NumberOfLogicalProcessors
    //查詢cpu序列号:wmic cpu get processorid
    //查詢主機闆序列号:wmic baseboard get serialnumber
    //查詢BIOS序列号:wmic bios get serialnumber
    //檢視硬碟:wmic diskdrive get serialnumber
    QProcess p;
    p.start(cmd);
    p.waitForFinished();
    QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
    QStringList list = cmd.split(" ");
    result = result.remove(list.last(), Qt::CaseInsensitive);
    result = result.replace("\r", "");
    result = result.replace("\n", "");
    result = result.simplified();
    return result;
}

QString Widget::getCpuId() //擷取CPU序列号
{
    return getWMIC("wmic cpu get processorid");
}

QString Widget::getDiskNum() //擷取硬碟序列号
{
    return getWMIC("wmic diskdrive where index=0 get serialnumber");
}

QString Widget::Encode(QString row) //加密,由于加/解密不是本文重點,故簡單處理一下
{
    QByteArray byteArray = row.toUtf8();
    byteArray = byteArray.toBase64();
    return  byteArray;
}
QString Widget::Decode(QString passwd) //解密
{
    QByteArray byteArray = passwd.toUtf8();
    byteArray = QByteArray::fromBase64(byteArray);
    return byteArray;
}

void Widget::Judge_Valid() //判斷程式合法性
{
    QString filePath = "System.ini";
    QFile file(filePath);

    if(!file.exists()) { //如果檔案不存在
        file.open(QIODevice::ReadWrite | QIODevice::Text); //建立檔案
        QString info = "RemainTime:"+time; //time是全局變量,QString time = "3";
        file.write(Encode(info).toUtf8()); //寫入資訊
        file.close();
         goto Here;
    }else {   //如果檔案存在
        Here:if(file.open(QFile::ReadWrite | QFile::Text)) { //打開檔案
            QString info = file.readAll(); //讀取資訊
            if(info.isEmpty()) { //如果檔案為空
                QString time_temp = "1";
                QString info = "RemainTime:"+time_temp;
                file.write(Encode(info).toUtf8()); //寫入資訊
                info = file.readAll();
            }
            info = Decode(info); //解碼
            if(info.contains(':')) {   //資訊正确
                QStringList list = info.split(':');
                if(list.length()>=1) {
                    if(list[1].toInt() <= 0) {   //程式剩餘使用次數不足
                        QMessageBox::about(this,"提示","請注冊後再使用!");
                        exit(0); //程式退出
                    }else {   //程式還有剩餘使用次數
                        file.close();
                        file.open(QFile::ReadWrite | QFile::Text | QFile::Truncate); //清空檔案内容
                        QString time_remain = QString::number(list[1].toInt()-1); //程式剩餘使用次數減1
                        QString info = "RemainTime:"+time_remain;
                        file.write(Encode(info).toUtf8()); //更新程式剩餘使用次數
                        QMessageBox::about(this,"提示","程式剩餘使用次數:"+time_remain+"次");
                    }
                }
            }
      }//Here
      file.close();

   }//如果檔案存在
}      

四、效果

Qt--探讨.exe程式加密
Qt--探讨.exe程式加密
Qt--探讨.exe程式加密
Qt--探讨.exe程式加密
Qt--探讨.exe程式加密