代码拉取完成,页面将自动刷新
同步操作将从 蜗牛程序员/Deluac 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
#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);
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。