Textractor/GUI/misc.cpp

243 lines
6.1 KiB
C++
Raw Normal View History

2018-07-25 21:48:18 -07:00
#include "misc.h"
2018-08-23 11:53:23 -04:00
#include "const.h"
2018-07-25 21:48:18 -07:00
#include <QRegExp>
#include <Psapi.h>
2018-07-26 22:42:21 -07:00
QString GetFullModuleName(DWORD processId, HMODULE module)
2018-07-25 21:48:18 -07:00
{
HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
2018-07-30 20:25:08 -07:00
wchar_t buffer[MAX_PATH] = {};
2018-07-25 21:48:18 -07:00
GetModuleFileNameExW(handle, module, buffer, MAX_PATH);
CloseHandle(handle);
2018-07-26 22:42:21 -07: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-25 21:48:18 -07:00
}
2018-08-20 14:30:50 -04:00
std::unordered_map<std::wstring, DWORD> GetAllProcesses()
2018-07-30 20:25:08 -07:00
{
DWORD allProcessIds[0x1000];
DWORD spaceUsed;
2018-08-20 14:30:50 -04:00
std::unordered_map<std::wstring, DWORD> ret;
2018-07-30 20:25:08 -07:00
if (!EnumProcesses(allProcessIds, sizeof(allProcessIds), &spaceUsed)) return ret;
for (int i = 0; i < spaceUsed / sizeof(DWORD); ++i)
if (GetModuleName(allProcessIds[i]).size())
2018-08-20 14:30:50 -04:00
ret[GetModuleName(allProcessIds[i]).toStdWString()] = allProcessIds[i];
2018-07-30 20:25:08 -07:00
return ret;
}
2018-08-25 16:02:16 -04:00
namespace
2018-07-25 21:48:18 -07:00
{
2018-08-25 16:02:16 -04:00
DWORD Hash(QString module)
2018-08-04 18:01:59 -04:00
{
2018-08-25 16:02:16 -04:00
module = module.toLower();
DWORD hash = 0;
for (auto i : module) hash = _rotr(hash, 7) + i.unicode();
return hash;
2018-08-04 18:01:59 -04:00
}
2018-08-25 16:02:16 -04:00
std::optional<HookParam> ParseRCode(QString RCode)
2018-07-25 21:48:18 -07:00
{
2018-08-25 16:02:16 -04:00
HookParam hp = {};
hp.type |= DIRECT_READ;
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);
QRegExp stringGap("^\\-?[\\dA-F]+");
if (stringGap.indexIn(RCode) == -1) return {};
hp.offset = stringGap.cap(0).toInt(nullptr, 16);
RCode.remove(0, stringGap.cap(0).length());
if (RCode.at(0).unicode() != L'@') return {};
RCode.remove(0, 1);
QRegExp address("[\\dA-F]+$");
if (address.indexIn(RCode) == -1) return {};
hp.address = address.cap(0).toULongLong(nullptr, 16);
return hp;
2018-07-25 21:48:18 -07:00
}
2018-08-25 16:02:16 -04:00
std::optional<HookParam> ParseHCode(QString HCode)
2018-07-25 21:48:18 -07:00
{
2018-08-25 16:02:16 -04:00
HookParam hp = {};
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-25 21:48:18 -07:00
HCode.remove(0, 1);
2018-08-25 16:02:16 -04:00
if (HCode.at(0).unicode() == L'N')
2018-07-25 21:48:18 -07:00
{
2018-08-25 16:02:16 -04:00
hp.type |= NO_CONTEXT;
HCode.remove(0, 1);
2018-07-25 21:48:18 -07:00
}
2018-08-25 16:02:16 -04:00
QRegExp dataOffset("^\\-?[\\dA-F]+");
if (dataOffset.indexIn(HCode) == -1) return {};
hp.offset = dataOffset.cap(0).toInt(nullptr, 16);
HCode.remove(0, dataOffset.cap(0).length());
QRegExp dataIndirect("^\\*(\\-?[\\dA-F]+)");
if (dataIndirect.indexIn(HCode) != -1)
{
hp.type |= DATA_INDIRECT;
hp.index = dataIndirect.cap(1).toInt(nullptr, 16);
HCode.remove(0, dataIndirect.cap(0).length());
}
QRegExp split("^\\:(\\-?[\\dA-F]+)");
if (split.indexIn(HCode) != -1)
{
hp.type |= USING_SPLIT;
hp.split = split.cap(1).toInt(nullptr, 16);
HCode.remove(0, split.cap(0).length());
QRegExp splitIndirect("^\\*(\\-?[\\dA-F]+)");
if (splitIndirect.indexIn(HCode) != -1)
{
hp.type |= SPLIT_INDIRECT;
hp.split_index = splitIndirect.cap(1).toInt(nullptr, 16);
HCode.remove(0, splitIndirect.cap(0).length());
}
}
if (HCode.at(0).unicode() != L'@') return {};
HCode.remove(0, 1);
QRegExp address("^([\\dA-F]+):?");
if (address.indexIn(HCode) == -1) return {};
hp.address = address.cap(1).toInt(nullptr, 16);
HCode.remove(address.cap(0));
if (HCode.length())
{
hp.type |= MODULE_OFFSET;
hp.module = Hash(HCode);
}
if (hp.offset < 0)
hp.offset -= 4;
if (hp.split < 0)
hp.split -= 4;
return hp;
2018-07-25 21:48:18 -07:00
}
2018-08-04 18:01:59 -04:00
2018-08-25 16:02:16 -04:00
QString GenerateHCode(HookParam hp, DWORD processId)
2018-07-25 21:48:18 -07:00
{
2018-08-25 16:02:16 -04:00
QString code = "/H";
if (hp.type & USING_UNICODE)
{
if (hp.type & USING_STRING)
code += "Q";
else
code += "W";
}
2018-07-25 21:48:18 -07:00
else
2018-08-25 16:02:16 -04:00
{
if (hp.type & USING_UTF8)
code += "V";
else if (hp.type & USING_STRING)
code += "S";
else if (hp.type & BIG_ENDIAN)
code += "A";
else
code += "B";
}
if (hp.type & NO_CONTEXT)
code += "N";
if (hp.offset < 0) hp.offset += 4;
if (hp.split < 0) hp.split += 4;
if (hp.offset < 0)
code += "-" + QString::number(-hp.offset, 16);
else
code += QString::number(hp.offset, 16);
if (hp.type & DATA_INDIRECT)
{
if (hp.index < 0)
code += "*-" + QString::number(-hp.index, 16);
else
code += "*" + QString::number(hp.index, 16);
}
if (hp.type & USING_SPLIT)
{
if (hp.split < 0)
code += ":-" + QString::number(-hp.split, 16);
else
code += ":" + QString::number(hp.split, 16);
}
if (hp.type & SPLIT_INDIRECT)
{
if (hp.split_index < 0)
code += "*-" + QString::number(-hp.split_index, 16);
else
code += "*" + QString::number(hp.split_index, 16);
}
code += "@";
QString badCode = (code + QString::number(hp.address, 16)).toUpper();
HANDLE processHandle;
if (!(processHandle = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId))) return badCode;
MEMORY_BASIC_INFORMATION info;
if (!VirtualQueryEx(processHandle, (LPCVOID)hp.address, &info, sizeof(info))) return badCode;
QString moduleName = GetModuleName(processId, (HMODULE)info.AllocationBase);
if (moduleName.size() == 0) return badCode;
code += QString::number(hp.address - (DWORD)info.AllocationBase, 16) + ":";
code = code.toUpper();
code += moduleName;
return code;
2018-07-25 21:48:18 -07:00
}
2018-08-25 16:02:16 -04:00
QString GenerateRCode(HookParam hp)
2018-07-25 21:48:18 -07:00
{
2018-08-25 16:02:16 -04:00
QString code = "/R";
if (hp.type & USING_UNICODE)
code += "Q";
else if (hp.type & USING_UTF8)
2018-08-03 01:48:57 -04:00
code += "V";
2018-07-25 21:48:18 -07:00
else
2018-08-25 16:02:16 -04:00
code += "S";
2018-07-25 21:48:18 -07:00
code += QString::number(hp.offset, 16);
2018-08-25 16:02:16 -04:00
code += "@";
code += QString::number(hp.address, 16);
return code.toUpper();
2018-07-25 21:48:18 -07:00
}
}
2018-08-04 18:01:59 -04:00
2018-08-25 16:02:16 -04:00
std::optional<HookParam> ParseCode(QString code)
2018-08-04 18:01:59 -04:00
{
2018-08-25 16:02:16 -04:00
code = code.toUpper();
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-04 18:01:59 -04:00
}
QString GenerateCode(HookParam hp, DWORD processId)
{
if (hp.type & DIRECT_READ) return GenerateRCode(hp);
else return GenerateHCode(hp, processId);
}