2018-07-21 15:40:16 -07:00
# include "mainwindow.h"
# include "ui_mainwindow.h"
2018-07-25 21:48:18 -07:00
# include <QCoreApplication>
2018-07-23 22:57:54 -07:00
# include "QTextBrowser"
2018-07-22 16:53:51 -07:00
# include "QMessageBox"
2018-07-23 22:57:54 -07:00
# include "QComboBox"
2018-07-23 12:25:02 -07:00
# include "QLineEdit"
# include "QInputDialog"
2018-07-24 10:39:02 -07:00
# include <QCursor>
# include <Qt>
2018-07-26 22:42:21 -07:00
# include <QPlainTextEdit>
# include <QDateTime>
# include <QFileDialog>
2018-07-25 21:48:18 -07:00
# include <unordered_set>
2018-07-26 22:42:21 -07:00
# include <map>
# include <unordered_map>
2018-07-22 16:53:51 -07:00
# include <Windows.h>
2018-07-23 12:25:02 -07:00
# include <qdebug.h>
# include <Psapi.h>
2018-07-26 22:42:21 -07:00
# include "extensions.h"
# include "../vnrhook/include/const.h"
2018-07-25 21:48:18 -07:00
# include "misc.h"
2018-07-21 15:40:16 -07:00
2018-07-23 22:57:54 -07:00
QMainWindow * mainWindow ;
QComboBox * processCombo ;
QComboBox * ttCombo ;
2018-07-26 22:42:21 -07:00
QComboBox * extenCombo ;
QPlainTextEdit * textOutput ;
2018-07-23 12:25:02 -07:00
2018-07-23 22:57:54 -07:00
QString ProcessString ( DWORD processId )
2018-07-23 12:25:02 -07:00
{
2018-07-25 10:46:59 -07:00
return QString ( " %1: %2 " ) . arg ( QString : : number ( processId ) , GetModuleName ( processId ) ) ;
2018-07-23 22:57:54 -07:00
}
QString TextThreadString ( TextThread * thread )
{
2018-07-25 10:46:59 -07:00
ThreadParameter tp = thread - > GetThreadParameter ( ) ;
return QString ( " %1:%2:%3:%4:%5: " ) . arg (
QString : : number ( thread - > Number ( ) ) ,
QString : : number ( tp . pid ) ,
QString : : number ( tp . hook , 16 ) ,
QString : : number ( tp . retn , 16 ) ,
QString : : number ( tp . spl , 16 )
) . toUpper ( ) ;
2018-07-23 12:25:02 -07:00
}
2018-07-21 15:40:16 -07:00
MainWindow : : MainWindow ( QWidget * parent ) :
2018-07-25 10:46:59 -07:00
QMainWindow ( parent ) ,
ui ( new Ui : : MainWindow ) ,
hostSignaller ( new HostSignaller )
2018-07-21 15:40:16 -07:00
{
2018-07-25 10:46:59 -07:00
ui - > setupUi ( this ) ;
mainWindow = this ;
processCombo = mainWindow - > findChild < QComboBox * > ( " processCombo " ) ;
ttCombo = mainWindow - > findChild < QComboBox * > ( " ttCombo " ) ;
2018-07-26 22:42:21 -07:00
extenCombo = mainWindow - > findChild < QComboBox * > ( " extenCombo " ) ;
textOutput = mainWindow - > findChild < QPlainTextEdit * > ( " textOutput " ) ;
2018-08-20 11:00:34 -04:00
QFile settings ( " NHWindow " ) ;
settings . open ( QIODevice : : ReadOnly ) ;
QDataStream reader ( & settings ) ;
QRect rect = QRect ( ) ;
reader > > rect ;
if ( rect . bottom ( ) ) this - > setGeometry ( rect ) ;
2018-07-23 12:25:02 -07:00
2018-07-25 10:46:59 -07:00
hostSignaller - > Initialize ( ) ;
connect ( hostSignaller , & HostSignaller : : AddProcess , this , & MainWindow : : AddProcess ) ;
connect ( hostSignaller , & HostSignaller : : RemoveProcess , this , & MainWindow : : RemoveProcess ) ;
connect ( hostSignaller , & HostSignaller : : AddThread , this , & MainWindow : : AddThread ) ;
connect ( hostSignaller , & HostSignaller : : RemoveThread , this , & MainWindow : : RemoveThread ) ;
2018-08-03 00:07:25 -04:00
connect ( this , & MainWindow : : ThreadOutputReceived , this , & MainWindow : : ThreadOutput ) ;
2018-08-17 14:37:37 -04:00
ReloadExtensions ( ) ;
2018-07-25 10:46:59 -07:00
Host : : Open ( ) ;
2018-08-18 15:06:14 -04:00
Host : : AddConsoleOutput ( L " NextHooker beta v2.1.3 by Artikash \r \n Source code and more information available under GPLv3 at https://github.com/Artikash/NextHooker " ) ;
2018-07-21 15:40:16 -07:00
}
MainWindow : : ~ MainWindow ( )
{
2018-08-20 11:00:34 -04:00
QFile settings ( " NHWindow " ) ;
settings . open ( QIODevice : : ReadWrite | QIODevice : : Truncate ) ;
QDataStream writer ( & settings ) ;
writer < < this - > geometry ( ) ;
2018-07-25 10:46:59 -07:00
delete ui ;
2018-07-21 15:40:16 -07:00
}
2018-07-22 16:53:51 -07:00
2018-07-24 10:39:02 -07:00
void MainWindow : : AddProcess ( unsigned int processId )
2018-07-23 22:57:54 -07:00
{
2018-07-25 10:46:59 -07:00
processCombo - > addItem ( ProcessString ( processId ) ) ;
2018-07-26 22:42:21 -07:00
QFile file ( " SavedHooks.txt " ) ;
if ( ! file . open ( QIODevice : : ReadOnly ) ) return ;
QString processName = GetFullModuleName ( processId ) ;
QString allData = file . readAll ( ) ;
QStringList allProcesses = allData . split ( " \r " , QString : : SkipEmptyParts ) ;
for ( int i = allProcesses . length ( ) - 1 ; i > = 0 ; - - i )
if ( allProcesses . at ( i ) . contains ( processName ) )
{
Sleep ( 50 ) ;
QStringList hooks = allProcesses . at ( i ) . split ( " , " ) ;
2018-07-30 20:25:08 -07:00
for ( int j = 1 ; j < hooks . length ( ) ; + + j )
{
Sleep ( 10 ) ;
2018-08-04 18:01:59 -04:00
Host : : InsertHook ( processId , ParseCode ( hooks . at ( j ) ) ) ;
2018-07-30 20:25:08 -07:00
}
2018-07-26 22:42:21 -07:00
return ;
}
2018-07-23 22:57:54 -07:00
}
2018-07-24 10:39:02 -07:00
void MainWindow : : RemoveProcess ( unsigned int processId )
2018-07-23 22:57:54 -07:00
{
2018-07-25 10:46:59 -07:00
processCombo - > removeItem ( processCombo - > findText ( QString : : number ( processId ) + " : " , Qt : : MatchStartsWith ) ) ;
2018-07-23 22:57:54 -07:00
}
2018-07-24 10:39:02 -07:00
void MainWindow : : AddThread ( TextThread * thread )
2018-07-23 22:57:54 -07:00
{
2018-07-25 10:46:59 -07:00
ttCombo - > addItem (
TextThreadString ( thread ) +
2018-08-19 17:55:50 -04:00
QString : : fromStdWString ( Host : : GetHookName ( thread - > GetThreadParameter ( ) . pid , thread - > GetThreadParameter ( ) . hook ) ) +
2018-07-25 21:48:18 -07:00
" ( " +
2018-08-04 18:01:59 -04:00
GenerateCode ( Host : : GetHookParam ( thread - > GetThreadParameter ( ) . pid , thread - > GetThreadParameter ( ) . hook ) , thread - > GetThreadParameter ( ) . pid ) +
2018-07-25 21:48:18 -07:00
" ) "
2018-07-25 10:46:59 -07:00
) ;
2018-08-03 00:07:25 -04:00
thread - > RegisterOutputCallBack ( [ & ] ( TextThread * thread , std : : wstring output )
{
2018-08-04 03:16:14 -04:00
output = DispatchSentenceToExtensions ( output , GetInfoForExtensions ( thread ) ) ;
2018-08-07 12:50:31 -04:00
output + = L " \r \n " ;
2018-08-19 17:55:50 -04:00
emit ThreadOutputReceived ( thread , QString : : fromStdWString ( output ) ) ;
2018-08-03 00:07:25 -04:00
return output ;
} ) ;
2018-07-23 22:57:54 -07:00
}
2018-07-24 10:39:02 -07:00
void MainWindow : : RemoveThread ( TextThread * thread )
2018-07-23 22:57:54 -07:00
{
2018-07-25 10:46:59 -07:00
int threadIndex = ttCombo - > findText ( QString : : number ( thread - > Number ( ) ) + " : " , Qt : : MatchStartsWith ) ;
if ( threadIndex = = ttCombo - > currentIndex ( ) )
{
ttCombo - > setCurrentIndex ( 0 ) ;
on_ttCombo_activated ( 0 ) ;
}
2018-08-02 02:17:20 -04:00
ttCombo - > removeItem ( threadIndex ) ;
2018-07-24 10:39:02 -07:00
}
void MainWindow : : ThreadOutput ( TextThread * thread , QString output )
{
2018-07-25 10:46:59 -07:00
if ( ttCombo - > currentText ( ) . startsWith ( TextThreadString ( thread ) ) )
{
textOutput - > moveCursor ( QTextCursor : : End ) ;
textOutput - > insertPlainText ( output ) ;
textOutput - > moveCursor ( QTextCursor : : End ) ;
}
2018-07-23 22:57:54 -07:00
}
2018-08-17 14:37:37 -04:00
void MainWindow : : ReloadExtensions ( )
{
extenCombo - > clear ( ) ;
std : : map < int , QString > extensions = LoadExtensions ( ) ;
for ( auto i : extensions ) extenCombo - > addItem ( QString : : number ( i . first ) + " : " + i . second ) ;
}
2018-08-04 03:16:14 -04:00
std : : unordered_map < std : : string , int > MainWindow : : GetInfoForExtensions ( TextThread * thread )
{
return
{
{ " current select " , ttCombo - > currentText ( ) . split ( " : " ) [ 0 ] . toInt ( ) = = thread - > Number ( ) ? 1 : 0 } ,
{ " text number " , thread - > Number ( ) } ,
{ " process id " , thread - > GetThreadParameter ( ) . pid } ,
{ " hook address " , ( int ) thread - > GetThreadParameter ( ) . hook } ,
{ " hook address (upper 32 bits) " , ( int ) ( thread - > GetThreadParameter ( ) . hook > > 32 ) }
} ;
}
2018-07-25 21:48:18 -07:00
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 ;
}
2018-07-23 12:25:02 -07:00
void MainWindow : : on_attachButton_clicked ( )
2018-07-22 16:53:51 -07:00
{
2018-08-20 14:30:50 -04:00
std : : unordered_map < std : : wstring , DWORD > allProcesses = GetAllProcesses ( ) ;
QStringList processList ;
for ( auto i : allProcesses )
processList . push_back ( QString : : fromStdWString ( i . first ) ) ;
processList . sort ( Qt : : CaseInsensitive ) ;
2018-07-25 21:48:18 -07:00
bool ok ;
2018-07-30 20:25:08 -07:00
QString process = QInputDialog : : getItem ( this , " Select Process " ,
2018-08-18 15:06:14 -04:00
" If you don't see the process you want to inject, try running with admin rights \r \n You can just type in the process id if you know it " ,
2018-08-20 14:30:50 -04:00
processList , 0 , true , & ok ) ;
2018-07-30 20:25:08 -07:00
if ( ! ok ) return ;
2018-08-20 14:30:50 -04:00
if ( process . toInt ( ) )
{
if ( Host : : InjectProcess ( process . toInt ( ) ) ) return ;
}
else if ( Host : : InjectProcess ( allProcesses [ process . toStdWString ( ) ] ) ) return ;
Host : : AddConsoleOutput ( L " Failed to attach " ) ;
2018-07-23 22:57:54 -07:00
}
void MainWindow : : on_detachButton_clicked ( )
{
2018-07-25 10:46:59 -07:00
Host : : DetachProcess ( processCombo - > currentText ( ) . split ( " : " ) [ 0 ] . toInt ( ) ) ;
2018-07-23 22:57:54 -07:00
}
2018-07-25 21:48:18 -07:00
void MainWindow : : on_hookButton_clicked ( )
{
bool ok ;
2018-08-04 18:01:59 -04:00
QString hookCode = QInputDialog : : getText ( this , " Add Hook " , CodeInfoDump , QLineEdit : : Normal , " " , & ok ) ;
2018-07-30 20:25:08 -07:00
if ( ! ok ) return ;
2018-08-04 18:01:59 -04:00
HookParam toInsert = ParseCode ( hookCode ) ;
2018-07-30 20:25:08 -07:00
if ( toInsert . type = = 0 & & toInsert . length_offset = = 0 )
{
2018-08-04 18:01:59 -04:00
Host : : AddConsoleOutput ( L " invalid code " ) ;
2018-07-30 20:25:08 -07:00
return ;
}
2018-08-04 18:01:59 -04:00
Host : : InsertHook ( processCombo - > currentText ( ) . split ( " : " ) [ 0 ] . toInt ( ) , ParseCode ( hookCode ) ) ;
2018-07-25 21:48:18 -07:00
}
void MainWindow : : on_unhookButton_clicked ( )
{
QVector < HookParam > hooks = GetAllHooks ( processCombo - > currentText ( ) . split ( " : " ) [ 0 ] . toInt ( ) ) ;
QStringList hookList ;
for ( auto i : hooks ) hookList . push_back (
2018-08-19 17:55:50 -04:00
QString : : fromStdWString ( Host : : GetHookName ( processCombo - > currentText ( ) . split ( " : " ) [ 0 ] . toInt ( ) , i . address ) ) +
2018-07-25 21:48:18 -07:00
" : " +
2018-08-04 18:01:59 -04:00
GenerateCode ( i , processCombo - > currentText ( ) . split ( " : " ) [ 0 ] . toInt ( ) )
2018-07-25 21:48:18 -07:00
) ;
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 ) ;
}
2018-07-26 22:42:21 -07:00
void MainWindow : : on_saveButton_clicked ( )
{
QVector < HookParam > hooks = GetAllHooks ( processCombo - > currentText ( ) . split ( " : " ) [ 0 ] . toInt ( ) ) ;
QString hookList = GetFullModuleName ( processCombo - > currentText ( ) . split ( " : " ) [ 0 ] . toInt ( ) ) ; ;
for ( auto i : hooks )
if ( ! ( i . type & HOOK_ENGINE ) )
2018-08-04 18:01:59 -04:00
hookList + = " , " + GenerateCode ( i , processCombo - > currentText ( ) . split ( " : " ) [ 0 ] . toInt ( ) ) ;
2018-07-26 22:42:21 -07:00
QFile file ( " SavedHooks.txt " ) ;
if ( ! file . open ( QIODevice : : Append | QIODevice : : Text ) ) return ;
file . write ( ( hookList + " \r \n " ) . toUtf8 ( ) ) ;
}
2018-07-23 22:57:54 -07:00
void MainWindow : : on_ttCombo_activated ( int index )
{
2018-08-20 11:00:34 -04:00
textOutput - > setPlainText ( QString : : fromStdWString ( Host : : GetThread ( ttCombo - > itemText ( index ) . split ( " : " ) [ 0 ] . toInt ( ) ) - > GetStore ( ) ) ) ;
2018-07-25 10:46:59 -07:00
textOutput - > moveCursor ( QTextCursor : : End ) ;
2018-07-22 16:53:51 -07:00
}
2018-07-26 22:42:21 -07:00
void MainWindow : : on_addExtenButton_clicked ( )
{
2018-08-03 00:07:25 -04:00
QString extenFileName = QFileDialog : : getOpenFileName ( this , " Select Extension dll " , " C: \\ " , " Extensions (*.dll) " ) ;
2018-07-28 12:41:21 -07:00
if ( ! extenFileName . length ( ) ) return ;
QString extenName = extenFileName . split ( " / " ) [ extenFileName . split ( " / " ) . count ( ) - 1 ] ;
extenName . chop ( 4 ) ;
QString copyTo = QString : : number ( extenCombo - > itemText ( extenCombo - > count ( ) - 1 ) . split ( " : " ) [ 0 ] . toInt ( ) + 1 ) + " _ " +
extenName +
" _nexthooker_extension.dll " ;
QFile : : copy ( extenFileName , copyTo ) ;
2018-08-17 14:37:37 -04:00
ReloadExtensions ( ) ;
2018-07-28 12:41:21 -07:00
}
void MainWindow : : on_rmvExtenButton_clicked ( )
{
2018-08-03 00:07:25 -04:00
if ( extenCombo - > currentText ( ) . size ( ) = = 0 ) return ;
2018-08-07 02:19:20 -04:00
QString extenFileName = extenCombo - > currentText ( ) . split ( " : " ) [ 0 ] + " _ " + extenCombo - > currentText ( ) . split ( " : " ) [ 1 ] + " _nexthooker_extension.dll " ;
2018-07-28 12:41:21 -07:00
FreeLibrary ( GetModuleHandleW ( extenFileName . toStdWString ( ) . c_str ( ) ) ) ;
2018-08-19 17:55:50 -04:00
QFile : : remove ( extenFileName ) ;
2018-08-17 14:37:37 -04:00
ReloadExtensions ( ) ;
2018-07-26 22:42:21 -07:00
}