Skip to content

Commit e7c4a6a

Browse files
committed
Updated to 4.8
1 parent 748e5d1 commit e7c4a6a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+3271
-1076
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ GH Injector SM/GH Injector SM/x86/
55
Release/
66
Debug/
77
GH Injector Library/Debug/
8+
GH Injector DNP/Release/
9+
GH Injector DNP/x64/
10+
GH Injector DNP/Debug/

GH Injector DNP/DotNetInjection.cpp

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
#include "pch.h"
2+
3+
#include "DotNetInjection.h"
4+
#include "FindModule.h"
5+
6+
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);
7+
void Log(const std::wstring & path, DWORD error, HINSTANCE base);
8+
9+
DWORD __stdcall LoadDotNetBinary(void * pArg)
10+
{
11+
UNREFERENCED_PARAMETER(pArg);
12+
13+
if (!g_hModuleBase)
14+
{
15+
CONSOLE_LOG("Invalid modules base\n");
16+
17+
return 0;
18+
}
19+
20+
wchar_t szInfoPath[MAX_PATH * 2]{ 0 };
21+
size_t max_size = sizeof(szInfoPath) / sizeof(wchar_t);
22+
23+
DWORD dwRet = GetModuleFileNameW(g_hModuleBase, szInfoPath, (DWORD)max_size);
24+
if (!dwRet || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
25+
{
26+
CONSOLE_LOG("GetModuleFileNameW failed: %08X\n", dwRet);
27+
28+
return 0;
29+
}
30+
31+
std::wstring InfoPath = szInfoPath;
32+
auto pos = InfoPath.find_last_of('\\');
33+
if (pos == std::wstring::npos)
34+
{
35+
CONSOLE_LOG("Invalid InfoPath\n");
36+
37+
return 0;
38+
}
39+
40+
InfoPath.erase(pos, InfoPath.back());
41+
InfoPath += FILENAME;
42+
43+
std::wifstream File(InfoPath);
44+
if (!File.good())
45+
{
46+
CONSOLE_LOG("Failed to open InfoPath\n");
47+
48+
File.close();
49+
50+
DeleteFileW(InfoPath.c_str());
51+
52+
Log(InfoPath, DNP_ERR_CANT_OPEN_FILE, NULL);
53+
54+
return 0;
55+
}
56+
57+
std::wstringstream info_raw;
58+
info_raw << File.rdbuf();
59+
60+
File.close();
61+
62+
DeleteFileW(InfoPath.c_str());
63+
64+
std::wstring info = info_raw.str();
65+
std::vector<std::wstring> dot_net_data;
66+
67+
size_t current_position = info.find('\n');
68+
while (current_position != std::wstring::npos)
69+
{
70+
dot_net_data.push_back(info.substr(0, current_position));
71+
info.erase(0, current_position + sizeof('\n'));
72+
73+
current_position = info.find('\n');
74+
}
75+
76+
dot_net_data.push_back(info);
77+
78+
if (dot_net_data.size() < 6)
79+
{
80+
CONSOLE_LOG("Invalid info: %d arguments provided (6 expected)\n", (DWORD)dot_net_data.size());
81+
82+
Log(InfoPath, DNP_ERR_INVALID_DATA, NULL);
83+
84+
return 0;
85+
}
86+
87+
auto & dll_path = dot_net_data[0];
88+
auto & dot_net_version = dot_net_data[1];
89+
auto & info_typename = dot_net_data[2].append(std::wstring(L".").append(dot_net_data[3]));
90+
auto & info_method = dot_net_data[4];
91+
auto & info_argument = dot_net_data[5];
92+
93+
DWORD ReturnValue = 0;
94+
HINSTANCE ModuleBase = NULL;
95+
auto hRet = LoadDotNetDll(dll_path, dot_net_version, info_typename, info_method, info_argument, ModuleBase, ReturnValue);
96+
97+
if (hRet == S_OK)
98+
{
99+
Log(InfoPath, DNP_ERR_SUCCESS, ModuleBase);
100+
}
101+
else
102+
{
103+
Log(InfoPath, (DWORD)hRet, (HINSTANCE)DNP_ERR_HRESULT);
104+
}
105+
106+
return 0;
107+
}
108+
109+
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)
110+
{
111+
//I stole the following code years ago somewhere and am unable to fine the original source, I'm sorry :c
112+
113+
ICLRMetaHost * MetaHost = nullptr;
114+
IEnumUnknown * RuntimeEnum = nullptr;
115+
ICLRRuntimeInfo * RuntimeInfo = nullptr;
116+
ICLRRuntimeHost * RuntimeHost = nullptr;
117+
118+
bool AlreadyLoaded = false;
119+
120+
HRESULT hRet = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, reinterpret_cast<void **>(&MetaHost));
121+
if (hRet != S_OK)
122+
{
123+
CONSOLE_LOG("CLRCreateInstance failed: %08X\n", hRet);
124+
125+
return hRet;
126+
}
127+
128+
hRet = MetaHost->EnumerateLoadedRuntimes(GetCurrentProcess(), &RuntimeEnum);
129+
if (hRet == S_OK)
130+
{
131+
ICLRRuntimeInfo * current_runtime = nullptr;
132+
133+
ULONG count = 0;
134+
wchar_t current_runtime_version[MAX_PATH]{ 0 };
135+
136+
auto enum_ret = RuntimeEnum->Next(1, reinterpret_cast<IUnknown **>(&current_runtime), &count);
137+
while (enum_ret == S_OK)
138+
{
139+
DWORD size = MAX_PATH;
140+
141+
hRet = current_runtime->GetVersionString(current_runtime_version, &size);
142+
if (hRet == S_OK)
143+
{
144+
if (!Version.compare(current_runtime_version))
145+
{
146+
RuntimeInfo = current_runtime;
147+
AlreadyLoaded = true;
148+
149+
CONSOLE_LOG("Runtime version %ls already loaded\n", Version.c_str());
150+
151+
break;
152+
}
153+
}
154+
155+
current_runtime->Release();
156+
157+
enum_ret = RuntimeEnum->Next(1, reinterpret_cast<IUnknown **>(&current_runtime), &count);
158+
}
159+
160+
RuntimeEnum->Release();
161+
}
162+
163+
if (!AlreadyLoaded)
164+
{
165+
hRet = MetaHost->GetRuntime(Version.c_str(), IID_ICLRRuntimeInfo, reinterpret_cast<void **>(&RuntimeInfo));
166+
if (hRet != S_OK)
167+
{
168+
CONSOLE_LOG("ICLRMetaHost::GetRuntime failed: %08X\n", hRet);
169+
170+
MetaHost->Release();
171+
172+
return hRet;
173+
}
174+
}
175+
176+
hRet = RuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, reinterpret_cast<void **>(&RuntimeHost));
177+
if (hRet != S_OK)
178+
{
179+
CONSOLE_LOG("ICLRRuntimeInfo::GetInterface failed: %08X\n", hRet);
180+
181+
RuntimeInfo->Release();
182+
MetaHost->Release();
183+
184+
return hRet;
185+
}
186+
187+
if (!AlreadyLoaded)
188+
{
189+
hRet = RuntimeHost->Start();
190+
if (hRet != S_OK)
191+
{
192+
CONSOLE_LOG("ICLRRuntimeHost::Start failed: %08X\n", hRet);
193+
194+
RuntimeHost->Release();
195+
RuntimeInfo->Release();
196+
MetaHost->Release();
197+
198+
return hRet;
199+
}
200+
}
201+
202+
hRet = RuntimeHost->ExecuteInDefaultAppDomain(FilePath.c_str(), TypeName.c_str(), MethodName.c_str(), Argument.c_str(), &ReturnValue);
203+
if (hRet == S_OK)
204+
{
205+
DWORD dwRet = FindModuleW(FilePath, ModuleBase);
206+
if (dwRet != ERROR_SUCCESS)
207+
{
208+
CONSOLE_LOG("FindModuleW failed: %08X\n", dwRet);
209+
210+
hRet = (HRESULT)dwRet;
211+
}
212+
}
213+
else
214+
{
215+
CONSOLE_LOG("ICLRRuntimeHost::ExecuteInDefaultAppDomain failed: %08X\n", hRet);
216+
}
217+
218+
RuntimeHost->Release();
219+
RuntimeInfo->Release();
220+
MetaHost->Release();
221+
222+
return hRet;
223+
}
224+
225+
void Log(const std::wstring & path, DWORD error, HINSTANCE base)
226+
{
227+
std::wofstream File(path);
228+
if (!File.good())
229+
{
230+
return;
231+
}
232+
233+
File << std::hex << base << std::endl;
234+
File << std::hex << error << std::endl;
235+
236+
File.close();
237+
}

GH Injector DNP/DotNetInjection.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#pragma once
2+
3+
#include "pch.h"
4+
5+
#define FILENAME L"\\DNPD.txt"
6+
7+
DWORD __stdcall LoadDotNetBinary(void * pArg);
8+
9+
#define DNP_ERR_SUCCESS 0x00000000
10+
11+
#define DNP_ERR_CANT_OPEN_FILE 0x60000001
12+
#define DNP_ERR_EMPTY_FILE 0x60000002
13+
#define DNP_ERR_OUT_OF_MEMORY 0x60000003
14+
#define DNP_ERR_INVALID_DATA 0x60000004
15+
#define DNP_ERR_HRESULT 0x60000005
16+
#define DNP_ERR_CANT_FIND_MODULE 0x60000006

GH Injector DNP/FindModule.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include "pch.h"
2+
3+
#include "FindModule.h"
4+
5+
void StdWStringToLower(std::wstring & String)
6+
{
7+
std::transform(String.begin(), String.end(), String.begin(),
8+
[](wchar_t c)
9+
{
10+
return std::towlower(c);
11+
}
12+
);
13+
}
14+
15+
DWORD FindModuleW(const std::wstring & ModulePath, HINSTANCE & hOut)
16+
{
17+
//Gotta VirtualQuery this shit because .NET files aren't linked to the PEB so normal methods like TH32 snapshots or GetModuleHandle don't work
18+
19+
auto ModuleNamePos = ModulePath.find_last_of('\\');
20+
if (ModuleNamePos == std::wstring::npos)
21+
{
22+
CONSOLE_LOG("ModulePath is invalid\n");
23+
24+
return ERROR_INVALID_PARAMETER;
25+
}
26+
27+
auto ModuleName = ModulePath.substr(ModuleNamePos + 1);
28+
auto hCurrentProcess = GetCurrentProcess();
29+
30+
StdWStringToLower(ModuleName);
31+
32+
MEMORY_BASIC_INFORMATION MBI{ 0 };
33+
wchar_t NameBuffer[MAX_PATH * 2]{ 0 };
34+
35+
while (VirtualQuery(MBI.BaseAddress, &MBI, sizeof(MBI)))
36+
{
37+
if ((MBI.Type == MEM_IMAGE) && (MBI.State & MEM_COMMIT))
38+
{
39+
if (K32GetMappedFileNameW(hCurrentProcess, MBI.BaseAddress, NameBuffer, sizeof(NameBuffer) / sizeof(wchar_t)))
40+
{
41+
auto FilePath = std::wstring(NameBuffer);
42+
auto FileNamePos = FilePath.find_last_of('\\');
43+
44+
if (FileNamePos != std::wstring::npos)
45+
{
46+
auto FileName = FilePath.substr(FileNamePos + 1);
47+
StdWStringToLower(FileName);
48+
49+
if (FileName.compare(ModuleName) == 0)
50+
{
51+
hOut = reinterpret_cast<HINSTANCE>(MBI.BaseAddress);
52+
53+
return ERROR_SUCCESS;
54+
}
55+
else
56+
{
57+
CONSOLE_LOG("%ls - %ls\n", FileName.c_str(), ModuleName.c_str());
58+
59+
}
60+
}
61+
}
62+
}
63+
64+
MBI.BaseAddress = reinterpret_cast<BYTE *>(MBI.BaseAddress) + MBI.RegionSize;
65+
}
66+
67+
return ERROR_MOD_NOT_FOUND;
68+
}

GH Injector DNP/FindModule.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#pragma once
2+
3+
#include "pch.h"
4+
5+
DWORD FindModuleW(const std::wstring & ModulePath, HINSTANCE & hOut);

GH Injector DNP/GH Injector DNP.aps

2.77 KB
Binary file not shown.

GH Injector DNP/GH Injector DNP.rc

4.34 KB
Binary file not shown.

0 commit comments

Comments
 (0)