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 **>(¤t_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 **>(¤t_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+ }
0 commit comments