continue implementing new gui

This commit is contained in:
Akash Mozumdar 2018-07-25 21:48:18 -07:00
parent d0b1efd033
commit f3c4884660
9 changed files with 254 additions and 46 deletions

View File

@ -25,11 +25,13 @@ CONFIG += c++11
SOURCES += \ SOURCES += \
main.cpp \ main.cpp \
mainwindow.cpp \ mainwindow.cpp \
hostsignaller.cpp hostsignaller.cpp \
misc.cpp
HEADERS += \ HEADERS += \
mainwindow.h \ mainwindow.h \
hostsignaller.h hostsignaller.h \
misc.h
FORMS += \ FORMS += \
mainwindow.ui mainwindow.ui

View File

@ -1,5 +1,4 @@
#include "hostsignaller.h" #include "hostsignaller.h"
#include "../texthook/host.h"
void HostSignaller::Initialize() void HostSignaller::Initialize()
{ {

View File

@ -1,6 +1,6 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "QCoreApplication" #include <QCoreApplication>
#include "QTextBrowser" #include "QTextBrowser"
#include "QMessageBox" #include "QMessageBox"
#include "QComboBox" #include "QComboBox"
@ -8,25 +8,17 @@
#include "QInputDialog" #include "QInputDialog"
#include <QCursor> #include <QCursor>
#include <Qt> #include <Qt>
#include <unordered_set>
#include <Windows.h> #include <Windows.h>
#include <qdebug.h> #include <qdebug.h>
#include <Psapi.h> #include <Psapi.h>
#include "../texthook/host.h" #include "misc.h"
QMainWindow* mainWindow; QMainWindow* mainWindow;
QComboBox* processCombo; QComboBox* processCombo;
QComboBox* ttCombo; QComboBox* ttCombo;
QTextBrowser* textOutput; QTextBrowser* textOutput;
QString GetModuleName(DWORD processId, HMODULE module = NULL)
{
HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
wchar_t buffer[MAX_PATH];
GetModuleFileNameExW(handle, module, buffer, MAX_PATH);
CloseHandle(handle);
return QString::fromWCharArray(wcsrchr(buffer, L'\\') + 1);
}
QString ProcessString(DWORD processId) QString ProcessString(DWORD processId)
{ {
return QString("%1: %2").arg(QString::number(processId), GetModuleName(processId)); return QString("%1: %2").arg(QString::number(processId), GetModuleName(processId));
@ -66,8 +58,6 @@ MainWindow::MainWindow(QWidget *parent) :
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
Host::Close();
delete hostSignaller;
delete ui; delete ui;
} }
@ -85,7 +75,10 @@ void MainWindow::AddThread(TextThread* thread)
{ {
ttCombo->addItem( ttCombo->addItem(
TextThreadString(thread) + TextThreadString(thread) +
QString::fromWCharArray(Host::GetHookName(thread->GetThreadParameter().pid, thread->GetThreadParameter().hook).c_str()) QString::fromWCharArray(Host::GetHookName(thread->GetThreadParameter().pid, thread->GetThreadParameter().hook).c_str()) +
" (" +
GenerateHCode(Host::GetHookParam(thread->GetThreadParameter().pid, thread->GetThreadParameter().hook), thread->GetThreadParameter().pid) +
")"
); );
} }
@ -110,9 +103,25 @@ void MainWindow::ThreadOutput(TextThread* thread, QString output)
} }
} }
QVector<HookParam> MainWindow::GetAllHooks(DWORD processId)
{
std::unordered_set<DWORD> addresses;
QVector<HookParam> hooks;
for (int i = 0; i < ttCombo->count(); ++i)
if (ttCombo->itemText(i).split(":")[1].toInt() == processId &&
!addresses.count(ttCombo->itemText(i).split(":")[2].toInt(nullptr, 16)))
{
addresses.insert(ttCombo->itemText(i).split(":")[2].toInt(nullptr, 16));
hooks.push_back(Host::GetHookParam(ttCombo->itemText(i).split(":")[1].toInt(), ttCombo->itemText(i).split(":")[2].toInt(nullptr, 16)));
}
return hooks;
}
void MainWindow::on_attachButton_clicked() void MainWindow::on_attachButton_clicked()
{ {
Host::InjectProcess(QInputDialog::getInt(this, "Process ID?", "You can find this under Task Manager -> Details")); bool ok;
int processId = QInputDialog::getInt(this, "Attach Process", "Process ID?\r\nYou can find this under Task Manager -> Details", 0, 0, 100000, 1, &ok);
if (ok) Host::InjectProcess(processId);
} }
void MainWindow::on_detachButton_clicked() void MainWindow::on_detachButton_clicked()
@ -120,6 +129,30 @@ void MainWindow::on_detachButton_clicked()
Host::DetachProcess(processCombo->currentText().split(":")[0].toInt()); Host::DetachProcess(processCombo->currentText().split(":")[0].toInt());
} }
void MainWindow::on_hookButton_clicked()
{
bool ok;
QString hookCode = QInputDialog::getText(this, "Add Hook",
"Enter hook code\r\n/H{A|B|W|S|Q}[N][data_offset[*drdo]][:sub_offset[*drso]]@addr[:module]",
QLineEdit::Normal, "/H", &ok
);
if (ok) Host::InsertHook(processCombo->currentText().split(":")[0].toInt(), ParseHCode(hookCode, processCombo->currentText().split(":")[0].toInt()));
}
void MainWindow::on_unhookButton_clicked()
{
QVector<HookParam> hooks = GetAllHooks(processCombo->currentText().split(":")[0].toInt());
QStringList hookList;
for (auto i : hooks) hookList.push_back(
QString::fromWCharArray(Host::GetHookName(processCombo->currentText().split(":")[0].toInt(), i.address).c_str()) +
": " +
GenerateHCode(i, processCombo->currentText().split(":")[0].toInt())
);
bool ok;
QString hook = QInputDialog::getItem(this, "Unhook", "Which hook to remove?", hookList, 0, false, &ok);
if (ok) Host::RemoveHook(processCombo->currentText().split(":")[0].toInt(), hooks.at(hookList.indexOf(hook)).address);
}
void MainWindow::on_ttCombo_activated(int index) void MainWindow::on_ttCombo_activated(int index)
{ {
textOutput->setText(QString::fromWCharArray(Host::GetThread(ttCombo->itemText(index).split(":")[0].toInt())->GetStore().c_str())); textOutput->setText(QString::fromWCharArray(Host::GetThread(ttCombo->itemText(index).split(":")[0].toInt())->GetStore().c_str()));

View File

@ -3,7 +3,8 @@
#include <QMainWindow> #include <QMainWindow>
#include <Windows.h> #include <Windows.h>
#include "../texthook/textthread.h" #include <QVector>
#include "../texthook/host.h"
#include "hostsignaller.h" #include "hostsignaller.h"
namespace Ui namespace Ui
@ -19,18 +20,22 @@ public:
explicit MainWindow(QWidget *parent = nullptr); explicit MainWindow(QWidget *parent = nullptr);
~MainWindow(); ~MainWindow();
QString ProcessOutput(TextThread *thread, QString output);
private slots: private slots:
void on_attachButton_clicked(); void on_attachButton_clicked();
void on_detachButton_clicked(); void on_detachButton_clicked();
void on_ttCombo_activated(int index); void on_ttCombo_activated(int index);
void on_unhookButton_clicked();
void AddProcess(unsigned int processId); void AddProcess(unsigned int processId);
void RemoveProcess(unsigned int processId); void RemoveProcess(unsigned int processId);
void AddThread(TextThread* thread); void AddThread(TextThread* thread);
void RemoveThread(TextThread* thread); void RemoveThread(TextThread* thread);
void ThreadOutput(TextThread* thread, QString output); void ThreadOutput(TextThread* thread, QString output);
void on_hookButton_clicked();
private: private:
QVector<HookParam> GetAllHooks(DWORD processId);
Ui::MainWindow *ui; Ui::MainWindow *ui;
HostSignaller* hostSignaller; HostSignaller* hostSignaller;
}; };

157
GUI/misc.cpp Normal file
View File

@ -0,0 +1,157 @@
#include "misc.h"
#include "../vnrhook/include/const.h"
#include <QRegExp>
#include <Psapi.h>
QString GetModuleName(DWORD processId, HMODULE module)
{
HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
wchar_t buffer[MAX_PATH];
GetModuleFileNameExW(handle, module, buffer, MAX_PATH);
CloseHandle(handle);
return QString::fromWCharArray(wcsrchr(buffer, L'\\') + 1);
}
DWORD Hash(QString module)
{
DWORD hash = 0;
for (auto i : module) hash = _rotr(hash, 7) + i.unicode();
return hash;
}
HookParam ParseHCode(QString HCode, DWORD processId)
{
HookParam hp = {};
HCode = HCode.toUpper();
if (!HCode.startsWith("/H")) return {};
HCode.remove(0, 2);
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;
default:
return {};
}
HCode.remove(0, 1);
if (HCode.at(0).unicode() == L'N')
{
hp.type |= NO_CONTEXT;
HCode.remove(0, 1);
}
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.toLower());
}
if (hp.offset & 0x80000000)
hp.offset -= 4;
if (hp.split & 0x80000000)
hp.split -= 4;
return hp;
}
QString GenerateHCode(HookParam hp, DWORD processId)
{
QString code = "/H";
if (hp.type & USING_UNICODE)
{
if (hp.type & USING_STRING)
code += "Q";
else
code += "W";
}
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 >> 31)
code += "-" + QString::number(-(hp.offset + 4), 16);
else
code += QString::number(hp.offset, 16);
if (hp.type & DATA_INDIRECT)
{
if (hp.index >> 31)
code += "*-" + QString::number(-hp.index, 16);
else
code += "*" + QString::number(hp.index, 16);
}
if (hp.type & USING_SPLIT)
{
if (hp.split >> 31)
code += ":-" + QString::number(-(hp.split + 4), 16);
else
code += ":" + QString::number(hp.split, 16);
}
if (hp.type & SPLIT_INDIRECT)
{
if (hp.split_index >> 31)
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;
wchar_t buffer[MAX_PATH];
if (!GetModuleFileNameExW(processHandle, (HMODULE)info.AllocationBase, buffer, MAX_PATH)) return badCode;
code += QString::number(hp.address - (DWORD)info.AllocationBase, 16) + ":";
code = code.toUpper();
code += QString::fromWCharArray(wcsrchr(buffer, L'\\') + 1);
return code;
}

12
GUI/misc.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef MISC_H
#define MISC_H
#include <QString>
#include <Windows.h>
#include "../texthook/host.h"
QString GetModuleName(DWORD processId, HMODULE module = NULL);
HookParam ParseHCode(QString HCode, DWORD processId);
QString GenerateHCode(HookParam hp, DWORD processId);
#endif // MISC_H

View File

@ -39,6 +39,12 @@ void TextThread::Clear()
storage.shrink_to_fit(); storage.shrink_to_fit();
} }
std::wstring TextThread::GetStore()
{
TT_LOCK;
return storage;
}
void TextThread::AddSentence() void TextThread::AddSentence()
{ {
TT_LOCK; TT_LOCK;

View File

@ -34,13 +34,7 @@ public:
TextThread(ThreadParameter tp, unsigned int threadNumber, unsigned int splitDelay = 250); TextThread(ThreadParameter tp, unsigned int threadNumber, unsigned int splitDelay = 250);
~TextThread(); ~TextThread();
void Clear(); virtual std::wstring GetStore();
void AddText(const BYTE *con, int len);
void AddSentence();
void AddSentence(std::wstring sentence);
// Artikash 7/25/2018: Not thread-safe with Clear(), but since they should both be accessed from GUI thread, should be fine
std::wstring GetStore() { return storage; }
DWORD &Status() { return status; } DWORD &Status() { return status; }
WORD Number() const { return threadNumber; } WORD Number() const { return threadNumber; }
ThreadParameter GetThreadParameter() { return tp; } ThreadParameter GetThreadParameter() { return tp; }
@ -48,6 +42,11 @@ public:
void RegisterOutputCallBack(ThreadOutputCallback cb) { output = cb; } void RegisterOutputCallBack(ThreadOutputCallback cb) { output = cb; }
void Clear();
void AddText(const BYTE *con, int len);
void AddSentence();
void AddSentence(std::wstring sentence);
private: private:
CRITICAL_SECTION ttCs; CRITICAL_SECTION ttCs;
ThreadOutputCallback output; ThreadOutputCallback output;

View File

@ -142,32 +142,27 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID unused)
} }
//extern "C" { //extern "C" {
DWORD NewHook(const HookParam &hp, LPCSTR name, DWORD flag) DWORD NewHook(const HookParam &hp, LPCSTR lpname, DWORD flag)
{ {
CHAR str[128]; std::string name = lpname;
int current = ::current_available - ::hookman; int current = ::current_available - ::hookman;
if (current < MAX_HOOK) { if (current < MAX_HOOK) {
//flag &= 0xffff; //flag &= 0xffff;
//if ((flag & HOOK_AUXILIARY) == 0) //if ((flag & HOOK_AUXILIARY) == 0)
flag |= HOOK_ADDITIONAL; flag |= HOOK_ADDITIONAL;
if (name == NULL || name[0] == '\0') if (name[0] == '\0')
{ {
sprintf(str, "UserHook%d", user_hook_count++); name = "UserHook" + std::to_string(user_hook_count++);
}
else
{
strcpy(str, name);
} }
ConsoleOutput("vnrcli:NewHook: try inserting hook:"); ConsoleOutput(("vnrcli:NewHook: try inserting hook: " + name).c_str());
ConsoleOutput(str);
// jichi 7/13/2014: This function would raise when too many hooks added // jichi 7/13/2014: This function would raise when too many hooks added
::hookman[current].InitHook(hp, str, flag & 0xffff); ::hookman[current].InitHook(hp, name.c_str(), flag & 0xffff);
if (::hookman[current].InsertHook() == 0) { if (::hookman[current].InsertHook() == 0) {
ConsoleOutput("vnrcli:NewHook: hook inserted"); ConsoleOutput(("vnrcli:NewHook: inserted hook: " + name).c_str());
NotifyHookInsert(hp, str); NotifyHookInsert(hp, name.c_str());
} else } else
ConsoleOutput("vnrcli:NewHook:WARNING: failed to insert hook"); ConsoleOutput("vnrcli:NewHook:WARNING: failed to insert hook");
} }