1 Star 0 Fork 5

小小/Deluac

forked from 蜗牛程序员/Deluac 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
deluacore.cpp 7.29 KB
一键复制 编辑 原始数据 按行查看 历史
蜗牛程序员 提交于 2019-10-20 15:50 . 1. 增强密钥猜测逻辑;
#include "deluacore.h"
#include <QDebug>
#include <QDir>
#include <QTextCodec>
#include "xxtea.h"
void DeluacCore::startDecrypt(const DeluacArgs &args)
{
this->args = args;
this->args.isDecrypt = true;
QThread::start();
}
void DeluacCore::startGuess(const DeluacArgs &args)
{
this->args = args;
this->args.isDecrypt = false;
QThread::start();
}
void DeluacCore::run()
{
QStringList filePaths;
fetchFiles(args.searchPath, QString("*.%1").arg(args.srcExtension), filePaths);
if (args.isDecrypt)
{
runDecrypt(filePaths);
}
else
{
runGuess(filePaths);
}
}
void DeluacCore::fetchFiles(const QString &searchFolder, const QString &nameFilter, QStringList &targetList)
{
QDir fileEntry(searchFolder), folderEntry(searchFolder);
fileEntry.setNameFilters(QStringList() << nameFilter);
QStringList filePaths = fileEntry.entryList(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
QStringList folderPaths = folderEntry.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
for (const auto &folderPath : folderPaths)
{
fetchFiles(QString("%1%2%3").arg(searchFolder).arg(QDir::separator()).arg(folderPath), nameFilter, targetList);
}
for (const auto &filePath : filePaths)
{
targetList.append(QString("%1%2%3").arg(searchFolder).arg(QDir::separator()).arg(filePath));
}
}
QByteArray DeluacCore::getXxteaSign(const QString &filePath)
{
QByteArray byteText;
QFile fileEntry(filePath);
if (fileEntry.open(QIODevice::ReadOnly))
{
QByteArray content = fileEntry.readAll();
QTextCodec::ConverterState state;
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
codec->toUnicode(content, content.size(), &state);
if (state.invalidChars > 0)
{
for (int i = 0; i < content.size(); i++)
{
if (content.at(i) <= 0)
{
byteText = content.left(i);
break;
}
}
qDebug() << filePath.toStdString().c_str() << ":" <<state.invalidChars;
}
}
return byteText;
}
QByteArray DeluacCore::getXxteaKey(const QString &filePath)
{
QByteArray byteText;
if (!args.xxteaSign.isEmpty())
{
QFile fileEntry(filePath);
if (fileEntry.open(QIODevice::ReadOnly))
{
QByteArray content = fileEntry.readAll();
int from = 0;
while ((from = content.indexOf(args.xxteaSign, from)) != -1)
{
int last = from - 1;
while (last > 0 && content.at(last) == 0)
last--;
if (last < from - 1)
{
for (int i = last; i > 0; i--)
{
if (content.at(i) <= 0)
{
byteText = content.mid(i + 1, last - i);
break;
}
}
break;
}
}
}
}
return byteText;
}
void DeluacCore::runDecrypt(const QStringList &filePaths)
{
int count = 0;
int total = filePaths.size();
for (const auto &filePath : filePaths)
{
QFile fileReader(filePath);
int progressValue = (++count) * 100 / total;
if (fileReader.open(QIODevice::ReadOnly))
{
xxtea_long plainLen = 0;
QByteArray readContent = fileReader.readAll();
fileReader.close();
if (readContent.size() > args.xxteaSign.length())
{
char *usefulData = readContent.data() + args.xxteaSign.length();
int usefulLen = readContent.size() - args.xxteaSign.length();
uint8_t *plainData = xxtea_decrypt(
reinterpret_cast<uint8_t *>(usefulData),
static_cast<xxtea_long>(usefulLen),
reinterpret_cast<uint8_t *>(args.xxteaKey.toLatin1().data()),
static_cast<xxtea_long>(args.xxteaKey.toLatin1().length()),
&plainLen);
if (plainData != nullptr && plainLen > 0)
{
QFileInfo fileInfo(filePath);
QFile fileWritter(QString("%1%2%3.%4").arg(fileInfo.dir().path()).arg(QDir::separator())
.arg(fileInfo.completeBaseName()).arg(args.destExtension));
if (fileWritter.open(QIODevice::WriteOnly))
{
QByteArray plainContent(reinterpret_cast<char*>(plainData), static_cast<int>(plainLen));
fileWritter.write(plainContent);
fileWritter.close();
decryptCompleted(filePath, DeluacState::Succeed, progressValue);
continue;
}
}
}
QTextCodec::ConverterState state;
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
codec->toUnicode(readContent, readContent.size(), &state);
if (state.invalidChars == 0)
{
decryptCompleted(filePath, DeluacState::Original, progressValue);
continue;
}
}
decryptCompleted(filePath, DeluacState::Failed, progressValue);
}
}
void DeluacCore::runGuess(const QStringList &filePaths)
{
// 首先猜测签名再猜测密钥
QByteArray byteText1;
QByteArray byteText2;
QByteArray byteText3;
for (const auto &filePath : filePaths)
{
QByteArray byteText = getXxteaSign(filePath);
if (byteText1.isEmpty()) byteText1 = byteText;
else if (byteText2.isEmpty()) byteText2 = byteText;
else if (byteText3.isEmpty()) byteText3 = byteText;
if (!byteText3.isEmpty()) break; // 最后一次猜测完毕退出
}
args.xxteaSign = "⚠未检测到XXTEA签名";
args.xxteaKey = "⚠未检测到XXTEA密钥";
if (byteText1.isEmpty() || byteText2.isEmpty() || byteText3.isEmpty())
{
guessCompleted(args.xxteaSign, args.xxteaKey);
return;
}
// 取三个中长度最小的文本
int length = byteText1.length();
if (byteText2.length() < length)
{
length = byteText2.length();
}
if (byteText3.length() < length)
{
length = byteText3.length();
}
int i = 0;
for (; i < length; i++)
{
if (byteText1.at(i) != byteText2.at(i) || byteText2.at(i) != byteText3.at(i))
{
args.xxteaSign = byteText2.left(i);
break;
}
}
if (i == length)
{
args.xxteaSign = byteText3.left(length);
}
if (args.xxteaSign.isEmpty())
{
guessCompleted(args.xxteaSign, args.xxteaKey);
}
else
{
QStringList filePaths;
fetchFiles(QString("%1%2%3").arg(args.searchPath).arg(QDir::separator()).arg("lib"),
QString("*.%1").arg("so"), filePaths);
for (const auto &filePath : filePaths)
{
QByteArray byteText = getXxteaKey(filePath);
if (!byteText.isEmpty())
{
args.xxteaKey = byteText;
guessCompleted(args.xxteaSign, args.xxteaKey);
return;
}
}
guessCompleted(args.xxteaSign, args.xxteaKey);
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/youayou/Deluac.git
git@gitee.com:youayou/Deluac.git
youayou
Deluac
Deluac
master

搜索帮助