Textractor_test/GUI/misc.cpp

271 lines
7.4 KiB
C++
Raw Normal View History

2018-07-26 12:48:18 +08:00
#include "misc.h"
2018-08-23 23:53:23 +08:00
#include "const.h"
2018-07-26 12:48:18 +08:00
#include <Psapi.h>
#include <QTextStream>
2018-07-26 12:48:18 +08:00
2018-07-27 13:42:21 +08:00
QString GetFullModuleName(DWORD processId, HMODULE module)
2018-07-26 12:48:18 +08:00
{
HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
2018-07-31 11:25:08 +08:00
wchar_t buffer[MAX_PATH] = {};
2018-07-26 12:48:18 +08:00
GetModuleFileNameExW(handle, module, buffer, MAX_PATH);
CloseHandle(handle);
2018-07-27 13:42:21 +08:00
return QString::fromWCharArray(buffer);
}
QString GetModuleName(DWORD processId, HMODULE module)
{
QString fullName = GetFullModuleName(processId, module);
return fullName.remove(0, fullName.lastIndexOf("\\") + 1);
2018-07-26 12:48:18 +08:00
}
2018-09-10 10:37:48 +08:00
QMultiHash<QString, DWORD> GetAllProcesses()
2018-07-31 11:25:08 +08:00
{
DWORD allProcessIds[0x1000];
DWORD spaceUsed;
2018-09-10 10:37:48 +08:00
QMultiHash<QString, DWORD> ret;
2018-07-31 11:25:08 +08:00
if (!EnumProcesses(allProcessIds, sizeof(allProcessIds), &spaceUsed)) return ret;
for (int i = 0; i < spaceUsed / sizeof(DWORD); ++i)
if (GetModuleName(allProcessIds[i]).size())
2018-09-10 10:37:48 +08:00
ret.insert(GetModuleName(allProcessIds[i]), allProcessIds[i]);
2018-07-31 11:25:08 +08:00
return ret;
}
2018-08-26 04:02:16 +08:00
namespace
2018-07-26 12:48:18 +08:00
{
2018-08-26 04:02:16 +08:00
std::optional<HookParam> ParseRCode(QString RCode)
2018-07-26 12:48:18 +08:00
{
2018-08-26 04:02:16 +08:00
HookParam hp = {};
hp.type |= DIRECT_READ;
// {S|Q|V}
2018-08-26 04:02:16 +08:00
switch (RCode.at(0).unicode())
{
case L'S':
break;
case L'Q':
hp.type |= USING_STRING | USING_UNICODE;
break;
case L'V':
hp.type |= USING_STRING | USING_UTF8;
break;
default:
return {};
}
RCode.remove(0, 1);
2018-10-31 08:50:50 +08:00
// [codepage#]
QRegularExpressionMatch codepage = QRegularExpression("^([0-9]+)#").match(RCode);
if (codepage.hasMatch())
{
hp.codepage = codepage.captured(1).toInt();
RCode.remove(0, codepage.captured(0).length());
}
// [*deref_offset|0]
if (RCode.at(0).unicode() == L'0') RCode.remove(0, 1); // Legacy
QRegularExpressionMatch deref = QRegularExpression("^\\*(\\-?[[:xdigit:]]+)").match(RCode);
if (deref.hasMatch())
2018-08-27 10:21:15 +08:00
{
hp.type |= DATA_INDIRECT;
hp.index = deref.captured(1).toInt(nullptr, 16);
RCode.remove(0, deref.captured(0).length());
2018-08-27 10:21:15 +08:00
}
// @addr
QRegularExpressionMatch address = QRegularExpression("^@([[:xdigit:]]+)$").match(RCode);
if (!address.hasMatch()) return {};
hp.address = address.captured(1).toULongLong(nullptr, 16);
2018-08-26 04:02:16 +08:00
return hp;
2018-07-26 12:48:18 +08:00
}
2018-08-26 04:02:16 +08:00
std::optional<HookParam> ParseHCode(QString HCode)
2018-07-26 12:48:18 +08:00
{
2018-08-26 04:02:16 +08:00
HookParam hp = {};
// {A|B|W|S|Q|V}
2018-08-26 04:02:16 +08:00
switch (HCode.at(0).unicode())
{
case L'S':
hp.type |= USING_STRING;
break;
case L'A':
hp.type |= BIG_ENDIAN;
hp.length_offset = 1;
break;
case L'B':
hp.length_offset = 1;
break;
case L'Q':
hp.type |= USING_STRING | USING_UNICODE;
break;
case L'W':
hp.type |= USING_UNICODE;
hp.length_offset = 1;
break;
case L'V':
hp.type |= USING_STRING | USING_UTF8;
break;
default:
return {};
}
2018-07-26 12:48:18 +08:00
HCode.remove(0, 1);
// [N]
2018-08-26 04:02:16 +08:00
if (HCode.at(0).unicode() == L'N')
2018-07-26 12:48:18 +08:00
{
2018-08-26 04:02:16 +08:00
hp.type |= NO_CONTEXT;
HCode.remove(0, 1);
2018-07-26 12:48:18 +08:00
}
2018-10-31 08:50:50 +08:00
// [codepage#]
QRegularExpressionMatch codepage = QRegularExpression("^([0-9]+)#").match(HCode);
if (codepage.hasMatch())
{
hp.codepage = codepage.captured(1).toInt();
HCode.remove(0, codepage.captured(0).length());
}
// data_offset
QRegularExpressionMatch dataOffset = QRegularExpression("^\\-?[[:xdigit:]]+").match(HCode);
if (!dataOffset.hasMatch()) return {};
hp.offset = dataOffset.captured(0).toInt(nullptr, 16);
HCode.remove(0, dataOffset.captured(0).length());
// [*deref_offset1]
QRegularExpressionMatch deref1 = QRegularExpression("^\\*(\\-?[[:xdigit:]]+)").match(HCode);
if (deref1.hasMatch())
2018-08-26 04:02:16 +08:00
{
hp.type |= DATA_INDIRECT;
hp.index = deref1.captured(1).toInt(nullptr, 16);
HCode.remove(0, deref1.captured(0).length());
2018-08-26 04:02:16 +08:00
}
// [:split_offset[*deref_offset2]]
QRegularExpressionMatch splitOffset = QRegularExpression("^\\:(\\-?[[:xdigit:]]+)").match(HCode);
if (splitOffset.hasMatch())
2018-08-26 04:02:16 +08:00
{
hp.type |= USING_SPLIT;
hp.split = splitOffset.captured(1).toInt(nullptr, 16);
HCode.remove(0, splitOffset.captured(0).length());
QRegularExpressionMatch deref2 = QRegularExpression("^\\*(\\-?[[:xdigit:]]+)").match(HCode);
if (deref2.hasMatch())
2018-08-26 04:02:16 +08:00
{
hp.type |= SPLIT_INDIRECT;
hp.split_index = deref2.captured(1).toInt(nullptr, 16);
HCode.remove(0, deref2.captured(0).length());
2018-08-26 04:02:16 +08:00
}
}
// @addr[:module[:func]]
QStringList addressPieces = HCode.split(":");
QRegularExpressionMatch address = QRegularExpression("^@([[:xdigit:]]+)$").match(addressPieces.at(0));
if (!address.hasMatch()) return {};
hp.address = address.captured(1).toULongLong(nullptr, 16);
if (addressPieces.size() > 1)
2018-08-26 04:02:16 +08:00
{
hp.type |= MODULE_OFFSET;
wcscpy_s<MAX_MODULE_SIZE>(hp.module, addressPieces.at(1).toStdWString().c_str());
2018-08-26 04:02:16 +08:00
}
if (addressPieces.size() > 2)
{
hp.type |= FUNCTION_OFFSET;
strcpy_s<MAX_MODULE_SIZE>(hp.function, addressPieces.at(2).toStdString().c_str());
}
// ITH has registers offset by 4 vs AGTH: need this to correct
if (hp.offset < 0) hp.offset -= 4;
if (hp.split < 0) hp.split -= 4;
2018-08-26 04:02:16 +08:00
return hp;
2018-07-26 12:48:18 +08:00
}
2018-08-05 06:01:59 +08:00
2018-10-31 08:50:50 +08:00
QString GenerateRCode(HookParam hp)
{
QString RCode = "/R";
QTextStream codeBuilder(&RCode);
if (hp.type & USING_UNICODE) codeBuilder << "Q";
else if (hp.type & USING_UTF8) codeBuilder << "V";
else codeBuilder << "S";
if (hp.codepage != SHIFT_JIS && hp.codepage != CP_UTF8) codeBuilder << hp.codepage << "#";
codeBuilder.setIntegerBase(16);
codeBuilder.setNumberFlags(QTextStream::UppercaseDigits);
if (hp.type & DATA_INDIRECT) codeBuilder << "*" << hp.index;
codeBuilder << "@" << hp.address;
return RCode;
}
2018-08-26 04:02:16 +08:00
QString GenerateHCode(HookParam hp, DWORD processId)
2018-07-26 12:48:18 +08:00
{
QString HCode = "/H";
QTextStream codeBuilder(&HCode);
2018-08-26 04:02:16 +08:00
if (hp.type & USING_UNICODE)
{
if (hp.type & USING_STRING) codeBuilder << "Q";
else codeBuilder << "W";
2018-08-26 04:02:16 +08:00
}
2018-07-26 12:48:18 +08:00
else
2018-08-26 04:02:16 +08:00
{
if (hp.type & USING_UTF8) codeBuilder << "V";
else if (hp.type & USING_STRING) codeBuilder << "S";
else if (hp.type & BIG_ENDIAN) codeBuilder << "A";
else codeBuilder << "B";
2018-08-26 04:02:16 +08:00
}
if (hp.type & NO_CONTEXT) codeBuilder << "N";
2018-10-31 08:50:50 +08:00
if (hp.codepage != SHIFT_JIS && hp.codepage != CP_UTF8) codeBuilder << hp.codepage << "#";
codeBuilder.setIntegerBase(16);
codeBuilder.setNumberFlags(QTextStream::UppercaseDigits);
2018-08-26 04:02:16 +08:00
if (hp.offset < 0) hp.offset += 4;
if (hp.split < 0) hp.split += 4;
codeBuilder << hp.offset;
if (hp.type & DATA_INDIRECT) codeBuilder << "*" << hp.index;
if (hp.type & USING_SPLIT) codeBuilder << ":" << hp.split;
if (hp.type & SPLIT_INDIRECT) codeBuilder << "*" << hp.split_index;
// Attempt to make the address relative
if (!(hp.type & MODULE_OFFSET))
2018-08-26 04:02:16 +08:00
{
HANDLE processHandle;
if (!(processHandle = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId))) goto fin;
MEMORY_BASIC_INFORMATION info;
if (!VirtualQueryEx(processHandle, (LPCVOID)hp.address, &info, sizeof(info))) goto fin;
QString moduleName = GetModuleName(processId, (HMODULE)info.AllocationBase);
if (moduleName == "") goto fin;
hp.type |= MODULE_OFFSET;
hp.address -= (uint64_t)info.AllocationBase;
wcscpy_s<MAX_MODULE_SIZE>(hp.module, moduleName.toStdWString().c_str());
2018-08-26 04:02:16 +08:00
}
fin:
codeBuilder << "@" << hp.address;
if (hp.type & MODULE_OFFSET) codeBuilder << ":" << QString::fromWCharArray(hp.module);
if (hp.type & FUNCTION_OFFSET) codeBuilder << ":" << hp.function;
return HCode;
2018-07-26 12:48:18 +08:00
}
}
2018-08-05 06:01:59 +08:00
2018-08-26 04:02:16 +08:00
std::optional<HookParam> ParseCode(QString code)
2018-08-05 06:01:59 +08:00
{
2018-08-26 04:02:16 +08:00
if (code.startsWith("/H")) return ParseHCode(code.remove(0, 2));
else if (code.startsWith("/R")) return ParseRCode(code.remove(0, 2));
else return {};
2018-08-05 06:01:59 +08:00
}
QString GenerateCode(HookParam hp, DWORD processId)
{
if (hp.type & DIRECT_READ) return GenerateRCode(hp);
else return GenerateHCode(hp, processId);
}