Skip to content

Commit

Permalink
Updated to 4.8
Browse files Browse the repository at this point in the history
  • Loading branch information
Broihon committed Feb 23, 2023
1 parent 748e5d1 commit e7c4a6a
Show file tree
Hide file tree
Showing 67 changed files with 3,271 additions and 1,076 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ GH Injector SM/GH Injector SM/x86/
Release/
Debug/
GH Injector Library/Debug/
GH Injector DNP/Release/
GH Injector DNP/x64/
GH Injector DNP/Debug/
237 changes: 237 additions & 0 deletions GH Injector DNP/DotNetInjection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
#include "pch.h"

#include "DotNetInjection.h"
#include "FindModule.h"

HRESULT LoadDotNetDll(const std::wstring & FilePath, const std::wstring & Version, const std::wstring & TypeName, const std::wstring & MethodName, const std::wstring & Argument, HINSTANCE & ModuleBase, DWORD & ReturnValue);
void Log(const std::wstring & path, DWORD error, HINSTANCE base);

DWORD __stdcall LoadDotNetBinary(void * pArg)
{
UNREFERENCED_PARAMETER(pArg);

if (!g_hModuleBase)
{
CONSOLE_LOG("Invalid modules base\n");

return 0;
}

wchar_t szInfoPath[MAX_PATH * 2]{ 0 };
size_t max_size = sizeof(szInfoPath) / sizeof(wchar_t);

DWORD dwRet = GetModuleFileNameW(g_hModuleBase, szInfoPath, (DWORD)max_size);
if (!dwRet || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
CONSOLE_LOG("GetModuleFileNameW failed: %08X\n", dwRet);

return 0;
}

std::wstring InfoPath = szInfoPath;
auto pos = InfoPath.find_last_of('\\');
if (pos == std::wstring::npos)
{
CONSOLE_LOG("Invalid InfoPath\n");

return 0;
}

InfoPath.erase(pos, InfoPath.back());
InfoPath += FILENAME;

std::wifstream File(InfoPath);
if (!File.good())
{
CONSOLE_LOG("Failed to open InfoPath\n");

File.close();

DeleteFileW(InfoPath.c_str());

Log(InfoPath, DNP_ERR_CANT_OPEN_FILE, NULL);

return 0;
}

std::wstringstream info_raw;
info_raw << File.rdbuf();

File.close();

DeleteFileW(InfoPath.c_str());

std::wstring info = info_raw.str();
std::vector<std::wstring> dot_net_data;

size_t current_position = info.find('\n');
while (current_position != std::wstring::npos)
{
dot_net_data.push_back(info.substr(0, current_position));
info.erase(0, current_position + sizeof('\n'));

current_position = info.find('\n');
}

dot_net_data.push_back(info);

if (dot_net_data.size() < 6)
{
CONSOLE_LOG("Invalid info: %d arguments provided (6 expected)\n", (DWORD)dot_net_data.size());

Log(InfoPath, DNP_ERR_INVALID_DATA, NULL);

return 0;
}

auto & dll_path = dot_net_data[0];
auto & dot_net_version = dot_net_data[1];
auto & info_typename = dot_net_data[2].append(std::wstring(L".").append(dot_net_data[3]));
auto & info_method = dot_net_data[4];
auto & info_argument = dot_net_data[5];

DWORD ReturnValue = 0;
HINSTANCE ModuleBase = NULL;
auto hRet = LoadDotNetDll(dll_path, dot_net_version, info_typename, info_method, info_argument, ModuleBase, ReturnValue);

if (hRet == S_OK)
{
Log(InfoPath, DNP_ERR_SUCCESS, ModuleBase);
}
else
{
Log(InfoPath, (DWORD)hRet, (HINSTANCE)DNP_ERR_HRESULT);
}

return 0;
}

HRESULT LoadDotNetDll(const std::wstring & FilePath, const std::wstring & Version, const std::wstring & TypeName, const std::wstring & MethodName, const std::wstring & Argument, HINSTANCE & ModuleBase, DWORD & ReturnValue)
{
//I stole the following code years ago somewhere and am unable to fine the original source, I'm sorry :c

ICLRMetaHost * MetaHost = nullptr;
IEnumUnknown * RuntimeEnum = nullptr;
ICLRRuntimeInfo * RuntimeInfo = nullptr;
ICLRRuntimeHost * RuntimeHost = nullptr;

bool AlreadyLoaded = false;

HRESULT hRet = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, reinterpret_cast<void **>(&MetaHost));
if (hRet != S_OK)
{
CONSOLE_LOG("CLRCreateInstance failed: %08X\n", hRet);

return hRet;
}

hRet = MetaHost->EnumerateLoadedRuntimes(GetCurrentProcess(), &RuntimeEnum);
if (hRet == S_OK)
{
ICLRRuntimeInfo * current_runtime = nullptr;

ULONG count = 0;
wchar_t current_runtime_version[MAX_PATH]{ 0 };

auto enum_ret = RuntimeEnum->Next(1, reinterpret_cast<IUnknown **>(&current_runtime), &count);
while (enum_ret == S_OK)
{
DWORD size = MAX_PATH;

hRet = current_runtime->GetVersionString(current_runtime_version, &size);
if (hRet == S_OK)
{
if (!Version.compare(current_runtime_version))
{
RuntimeInfo = current_runtime;
AlreadyLoaded = true;

CONSOLE_LOG("Runtime version %ls already loaded\n", Version.c_str());

break;
}
}

current_runtime->Release();

enum_ret = RuntimeEnum->Next(1, reinterpret_cast<IUnknown **>(&current_runtime), &count);
}

RuntimeEnum->Release();
}

if (!AlreadyLoaded)
{
hRet = MetaHost->GetRuntime(Version.c_str(), IID_ICLRRuntimeInfo, reinterpret_cast<void **>(&RuntimeInfo));
if (hRet != S_OK)
{
CONSOLE_LOG("ICLRMetaHost::GetRuntime failed: %08X\n", hRet);

MetaHost->Release();

return hRet;
}
}

hRet = RuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, reinterpret_cast<void **>(&RuntimeHost));
if (hRet != S_OK)
{
CONSOLE_LOG("ICLRRuntimeInfo::GetInterface failed: %08X\n", hRet);

RuntimeInfo->Release();
MetaHost->Release();

return hRet;
}

if (!AlreadyLoaded)
{
hRet = RuntimeHost->Start();
if (hRet != S_OK)
{
CONSOLE_LOG("ICLRRuntimeHost::Start failed: %08X\n", hRet);

RuntimeHost->Release();
RuntimeInfo->Release();
MetaHost->Release();

return hRet;
}
}

hRet = RuntimeHost->ExecuteInDefaultAppDomain(FilePath.c_str(), TypeName.c_str(), MethodName.c_str(), Argument.c_str(), &ReturnValue);
if (hRet == S_OK)
{
DWORD dwRet = FindModuleW(FilePath, ModuleBase);
if (dwRet != ERROR_SUCCESS)
{
CONSOLE_LOG("FindModuleW failed: %08X\n", dwRet);

hRet = (HRESULT)dwRet;
}
}
else
{
CONSOLE_LOG("ICLRRuntimeHost::ExecuteInDefaultAppDomain failed: %08X\n", hRet);
}

RuntimeHost->Release();
RuntimeInfo->Release();
MetaHost->Release();

return hRet;
}

void Log(const std::wstring & path, DWORD error, HINSTANCE base)
{
std::wofstream File(path);
if (!File.good())
{
return;
}

File << std::hex << base << std::endl;
File << std::hex << error << std::endl;

File.close();
}
16 changes: 16 additions & 0 deletions GH Injector DNP/DotNetInjection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include "pch.h"

#define FILENAME L"\\DNPD.txt"

DWORD __stdcall LoadDotNetBinary(void * pArg);

#define DNP_ERR_SUCCESS 0x00000000

#define DNP_ERR_CANT_OPEN_FILE 0x60000001
#define DNP_ERR_EMPTY_FILE 0x60000002
#define DNP_ERR_OUT_OF_MEMORY 0x60000003
#define DNP_ERR_INVALID_DATA 0x60000004
#define DNP_ERR_HRESULT 0x60000005
#define DNP_ERR_CANT_FIND_MODULE 0x60000006
68 changes: 68 additions & 0 deletions GH Injector DNP/FindModule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include "pch.h"

#include "FindModule.h"

void StdWStringToLower(std::wstring & String)
{
std::transform(String.begin(), String.end(), String.begin(),
[](wchar_t c)
{
return std::towlower(c);
}
);
}

DWORD FindModuleW(const std::wstring & ModulePath, HINSTANCE & hOut)
{
//Gotta VirtualQuery this shit because .NET files aren't linked to the PEB so normal methods like TH32 snapshots or GetModuleHandle don't work

auto ModuleNamePos = ModulePath.find_last_of('\\');
if (ModuleNamePos == std::wstring::npos)
{
CONSOLE_LOG("ModulePath is invalid\n");

return ERROR_INVALID_PARAMETER;
}

auto ModuleName = ModulePath.substr(ModuleNamePos + 1);
auto hCurrentProcess = GetCurrentProcess();

StdWStringToLower(ModuleName);

MEMORY_BASIC_INFORMATION MBI{ 0 };
wchar_t NameBuffer[MAX_PATH * 2]{ 0 };

while (VirtualQuery(MBI.BaseAddress, &MBI, sizeof(MBI)))
{
if ((MBI.Type == MEM_IMAGE) && (MBI.State & MEM_COMMIT))
{
if (K32GetMappedFileNameW(hCurrentProcess, MBI.BaseAddress, NameBuffer, sizeof(NameBuffer) / sizeof(wchar_t)))
{
auto FilePath = std::wstring(NameBuffer);
auto FileNamePos = FilePath.find_last_of('\\');

if (FileNamePos != std::wstring::npos)
{
auto FileName = FilePath.substr(FileNamePos + 1);
StdWStringToLower(FileName);

if (FileName.compare(ModuleName) == 0)
{
hOut = reinterpret_cast<HINSTANCE>(MBI.BaseAddress);

return ERROR_SUCCESS;
}
else
{
CONSOLE_LOG("%ls - %ls\n", FileName.c_str(), ModuleName.c_str());

}
}
}
}

MBI.BaseAddress = reinterpret_cast<BYTE *>(MBI.BaseAddress) + MBI.RegionSize;
}

return ERROR_MOD_NOT_FOUND;
}
5 changes: 5 additions & 0 deletions GH Injector DNP/FindModule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include "pch.h"

DWORD FindModuleW(const std::wstring & ModulePath, HINSTANCE & hOut);
Binary file added GH Injector DNP/GH Injector DNP.aps
Binary file not shown.
Binary file added GH Injector DNP/GH Injector DNP.rc
Binary file not shown.
Loading

0 comments on commit e7c4a6a

Please sign in to comment.