Skip to content

Commit

Permalink
Updated to V4.5, improved handle hijacking routines, better start/sto…
Browse files Browse the repository at this point in the history
…p download functionality, added FakeVEH shellcode execution method, fixed symbol issue and handle hijacking crash (hopefully)
  • Loading branch information
Broihon committed Dec 18, 2021
1 parent 6f1796f commit 74dfd63
Show file tree
Hide file tree
Showing 65 changed files with 4,984 additions and 2,173 deletions.
4 changes: 2 additions & 2 deletions GH Injector Library.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29306.81
# Visual Studio Version 17
VisualStudioVersion = 17.0.31612.314
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GH Injector Library", "GH Injector Library\GH Injector Library.vcxproj", "{AC732425-E265-40FF-842F-C59CECE9A96C}"
EndProject
Expand Down
51 changes: 35 additions & 16 deletions GH Injector Library/Download Manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

#include "Download Manager.h"

DownloadManager::DownloadManager()
DownloadManager::DownloadManager(bool ForceRedownload)
{
m_hInterruptEvent = nullptr;
m_fProgress = 0.0f;
m_fOldProgress = 0.0f;
m_bForceRedownload = ForceRedownload;
}

DownloadManager::~DownloadManager()
Expand Down Expand Up @@ -40,7 +41,7 @@ HRESULT __stdcall DownloadManager::OnStartBinding(DWORD dwReserved, IBinding * p
UNREFERENCED_PARAMETER(dwReserved);
UNREFERENCED_PARAMETER(pib);

LOG(" DownloadManager: OnStartBinding\n");
LOG(2, "DownloadManager: OnStartBinding\n");

return S_OK;
}
Expand All @@ -49,7 +50,7 @@ HRESULT __stdcall DownloadManager::GetPriority(LONG * pnPriority)
{
UNREFERENCED_PARAMETER(pnPriority);

LOG(" DownloadManager: GetPriority\n");
LOG(2, "DownloadManager: GetPriority\n");

return S_OK;
}
Expand All @@ -58,7 +59,7 @@ HRESULT __stdcall DownloadManager::OnLowResource(DWORD reserved)
{
UNREFERENCED_PARAMETER(reserved);

LOG(" DownloadManager: OnLowResource\n");
LOG(2, "DownloadManager: OnLowResource\n");

return S_OK;
}
Expand All @@ -68,17 +69,28 @@ HRESULT __stdcall DownloadManager::OnStopBinding(HRESULT hresult, LPCWSTR szErro
UNREFERENCED_PARAMETER(hresult);
UNREFERENCED_PARAMETER(szError);

LOG(" DownloadManager: OnStopBinding\n");
LOG(2, "DownloadManager: OnStopBinding\n");

return S_OK;
}

HRESULT __stdcall DownloadManager::GetBindInfo(DWORD * grfBINDF, BINDINFO * pbindinfo)
{
UNREFERENCED_PARAMETER(grfBINDF);
UNREFERENCED_PARAMETER(pbindinfo);
LOG(2, "DownloadManager: GetBindInfo\n");

LOG(" DownloadManager: GetBindInfo\n");
if (m_bForceRedownload)
{
if (grfBINDF)
{
*grfBINDF = BINDF_GETNEWESTVERSION | BINDF_NEEDFILE;
}

if (pbindinfo)
{
pbindinfo->dwOptions = BINDINFO_OPTIONS_WININETFLAG;
pbindinfo->dwOptionsFlags = INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD;
}
}

return S_OK;
}
Expand All @@ -90,7 +102,7 @@ HRESULT __stdcall DownloadManager::OnDataAvailable(DWORD grfBSCF, DWORD dwSize,
UNREFERENCED_PARAMETER(pformatetc);
UNREFERENCED_PARAMETER(pstgmed);

LOG(" DownloadManager: OnDataAvailable\n");
LOG(2, "DownloadManager: OnDataAvailable\n");

return S_OK;
}
Expand All @@ -100,7 +112,7 @@ HRESULT __stdcall DownloadManager::OnObjectAvailable(const IID & riid, IUnknown
UNREFERENCED_PARAMETER(riid);
UNREFERENCED_PARAMETER(punk);

LOG(" DownloadManager: OnObjectAvailable\n");
LOG(2, "DownloadManager: OnObjectAvailable\n");

return S_OK;
}
Expand All @@ -112,7 +124,7 @@ HRESULT __stdcall DownloadManager::OnProgress(ULONG ulProgress, ULONG ulProgress

if (m_hInterruptEvent && WaitForSingleObject(m_hInterruptEvent, 0) == WAIT_OBJECT_0)
{
LOG(" DownloadManager: Interrupting download\n");
LOG(2, "DownloadManager: Interrupting download\n");

return E_ABORT;
}
Expand All @@ -123,7 +135,7 @@ HRESULT __stdcall DownloadManager::OnProgress(ULONG ulProgress, ULONG ulProgress

if (m_fProgress - m_fOldProgress >= 0.1f)
{
LOG(" DownloadManager: %2.0f%%\n", m_fProgress * 100.0f);
LOG(2, "DownloadManager: %2.0f%%\n", 100.0 * m_fProgress);
m_fOldProgress = m_fProgress;
}
}
Expand All @@ -135,15 +147,22 @@ BOOL DownloadManager::SetInterruptEvent(HANDLE hInterrupt)
{
if (m_hInterruptEvent)
{
CloseHandle(m_hInterruptEvent);
if (!CloseHandle(m_hInterruptEvent))
{
LOG(2, "Failed to close previous interrupt handle object: %08X\n", GetLastError());
}

m_hInterruptEvent = nullptr;
}

LOG(" DownloadManager: New interrupt event specified\n");
LOG(2, "DownloadManager: New interrupt event specified\n");

auto current_process = GetCurrentProcess();

return DuplicateHandle(GetCurrentProcess(), hInterrupt, GetCurrentProcess(), &m_hInterruptEvent, NULL, FALSE, DUPLICATE_SAME_ACCESS);
return DuplicateHandle(current_process, hInterrupt, current_process, &m_hInterruptEvent, NULL, FALSE, DUPLICATE_SAME_ACCESS);
}

float DownloadManager::GetDownloadProgress()
float DownloadManager::GetDownloadProgress() const
{
return m_fProgress;
}
5 changes: 3 additions & 2 deletions GH Injector Library/Download Manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ class DownloadManager : public IBindStatusCallback
HANDLE m_hInterruptEvent;
float m_fProgress;
float m_fOldProgress;
bool m_bForceRedownload;

public:

DownloadManager();
DownloadManager(bool ForceRedownload = true);

~DownloadManager();

Expand Down Expand Up @@ -42,5 +43,5 @@ class DownloadManager : public IBindStatusCallback

BOOL SetInterruptEvent(HANDLE hInterrupt);

float GetDownloadProgress();
float GetDownloadProgress() const;
};
79 changes: 52 additions & 27 deletions GH Injector Library/Eject.cpp
Original file line number Diff line number Diff line change
@@ -1,51 +1,76 @@
#include "pch.h"

#include "Eject.h"
#include "Start Routine.h"

bool EjectDll(HANDLE hTargetProc, HINSTANCE hModule)
bool EjectDll(HANDLE hTargetProc, HINSTANCE hModule, bool WOW64)
{
LOG(" EjectDll called\n");
LOG(" PID = %08X\n", GetProcessId(hTargetProc));
LOG(" hModule = %p\n", hModule);
LOG(3, "EjectDll called\n");
LOG(4, "PID = %08X\n", GetProcessId(hTargetProc));
LOG(4, "hModule = %p\n", hModule);

HANDLE hThread = nullptr;
auto ntRet = NATIVE::NtCreateThreadEx(&hThread, THREAD_ALL_ACCESS, nullptr, hTargetProc, NATIVE::LdrUnloadDll, ReCa<void *>(hModule), NULL, 0, 0, 0, nullptr);
if (FAILED(ntRet))
{
LOG(" NtCreateThreadEx failed: %08X\n", ntRet);
ERROR_DATA eject_data;
DWORD remote_ret = 0;
DWORD ret = 0;

return false;
#ifdef _WIN64
if (WOW64)
{
ret = StartRoutine_WOW64(hTargetProc, WOW64::LdrUnloadDll_WOW64, MDWD(hModule), LAUNCH_METHOD::LM_NtCreateThreadEx, NULL, remote_ret, INJ_EJECT_TIMEOUT, eject_data);
}

if (WaitForSingleObject(hThread, 500) != WAIT_OBJECT_0)
else
{
LOG(" Ejection thread timed out\n");
ret = StartRoutine(hTargetProc, ReCa<f_Routine>(NATIVE::LdrUnloadDll), hModule, LAUNCH_METHOD::LM_NtCreateThreadEx, NULL, remote_ret, INJ_EJECT_TIMEOUT, eject_data);
}
#else
UNREFERENCED_PARAMETER(WOW64);

TerminateThread(hThread, 0);
CloseHandle(hThread);
ret = StartRoutine(hTargetProc, ReCa<f_Routine>(NATIVE::LdrUnloadDll), hModule, LAUNCH_METHOD::LM_NtCreateThreadEx, NULL, remote_ret, INJ_EJECT_TIMEOUT, eject_data);
#endif

if (ret != SR_ERR_SUCCESS)
{
LOG(3, "Failed to eject dll:\n");
LOG(4, "ret = %08X\n", ret);
LOG(4, "advanced = %08X\n", eject_data.AdvErrorCode);

return false;
}

if (!GetExitCodeThread(hThread, ReCa<DWORD *>(&ntRet)))
else if (NT_FAIL(remote_ret))
{
LOG(" GetExitCodeThread failed: %08X\n", GetLastError());

CloseHandle(hThread);
LOG(3, "Failed to eject dll:\n");
LOG(4, "remote_ret = %08X:\n", remote_ret);

return false;
}

CloseHandle(hThread);
LOG(3, "Dll ejected successfully\n");

if (NT_FAIL(ntRet))
{
LOG(" LdrUnloadDll failed: %08X\n", ntRet);
return true;
}

return false;
bool EjectHijackLibrary(HANDLE hTargetProc, HINSTANCE hInjectionModuleEx, bool Interrupt)
{
LOG(2, "Ejecting hijack library\n");

if (!Interrupt)
{
return EjectDll(hTargetProc, hInjectionModuleEx);
}

LOG(" Dll ejected successfully\n");
ERROR_DATA interrupt_data;
DWORD remote_ret = 0;
DWORD ret = 0;
f_Routine pInterruptDownloadEx = ReCa<f_Routine>(ReCa<UINT_PTR>(InterruptDownloadEx) - ReCa<UINT_PTR>(g_hInjMod) + ReCa<UINT_PTR>(hInjectionModuleEx));

return true;
ret = StartRoutine(hTargetProc, pInterruptDownloadEx, nullptr, LAUNCH_METHOD::LM_NtCreateThreadEx, NULL, remote_ret, INJ_EJECT_TIMEOUT, interrupt_data);

if (ret != SR_ERR_SUCCESS)
{
LOG(2, "Failed to interrupt hijack library:\n");
LOG(3, "ret = %08X\n", ret);
LOG(3, "advanced = %08X\n", interrupt_data.AdvErrorCode);
} //try to eject even if interrupt failed

return EjectDll(hTargetProc, hInjectionModuleEx);
}
27 changes: 26 additions & 1 deletion GH Injector Library/Eject.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

#include "Import Handler.h"

bool EjectDll(HANDLE hTargetProc, HINSTANCE hModule);
#define INJ_EJECT_TIMEOUT 200

bool EjectDll(HANDLE hTargetProc, HINSTANCE hModule, bool WOW64 = false);
//Unloads a dll using LdrUnloadDll by creating a thread in the target process using NtCreateThreadEx (native only).
//
//Arguments:
Expand All @@ -15,6 +17,29 @@ bool EjectDll(HANDLE hTargetProc, HINSTANCE hModule);
/// PROCESS_VM_READ
// hModule (HINSTANCE):
/// The baseaddress of the module to unload.
// WOW64 (bool):
/// Set to true if the target process is running under WOW64 and the calling process is native.
/// If the calling process is not native this argument is ignored.
//
//Returnvalue (bool):
/// true: the module was unloaded successfully.
/// false: something went wrong, see logs

bool EjectHijackLibrary(HANDLE hTargetProc, HINSTANCE hInjectionModuleEx, bool Interrupt = true);
//Unloads the injection library from another process during handle hijacking.
//
//Arguments:
// hTargetProc (HANDLE):
/// HANDLE to the target process which needs:
/// PROCESS_CREATE_THREAD
/// PROCESS_QUERY_INFORMATION
/// PROCESS_VM_OPERATION
/// PROCESS_VM_WRITE
/// PROCESS_VM_READ
// hInjectionModuleEx (HINSTANCE):
/// The baseaddress of the injection library in the target process.
// Interrupt (bool):
/// If set to true InterruptDownloadEx is called remotely before unloading the dll.
//
//Returnvalue (bool):
/// true: the module was unloaded successfully.
Expand Down
Loading

0 comments on commit 74dfd63

Please sign in to comment.