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