-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinjector.cpp
More file actions
349 lines (278 loc) · 9.79 KB
/
injector.cpp
File metadata and controls
349 lines (278 loc) · 9.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
#include "injector.h"
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <tlhelp32.h>
#include <vector>
#include <windows.h>
#include "BlackBone/Asm/AsmFactory.h"
#include "BlackBone/Config.h"
#include "BlackBone/DriverControl/DriverControl.h"
#include <BlackBone/ManualMap/MMap.h>
#include <BlackBone/Misc/Utils.h>
#include <BlackBone/Patterns/PatternSearch.h>
#include <BlackBone/Process/Process.h>
#include <BlackBone/Process/ProcessModules.h>
#include <BlackBone/Process/RPC/RemoteFunction.hpp>
#include <BlackBone/Syscalls/Syscall.h>
#pragma comment(lib, "BlackBone.lib")
static std::wstring s2ws(const std::string &s)
{
if (s.empty())
return std::wstring();
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &s[0], (int)s.size(), NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &s[0], (int)s.size(), &wstrTo[0], size_needed);
return wstrTo;
}
static std::string ws2s(const std::wstring &w_str)
{
if (w_str.empty())
return std::string();
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &w_str[0], (int)w_str.size(), NULL, 0, NULL, NULL);
std::string str_to(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, &w_str[0], (int)w_str.size(), &str_to[0], size_needed, NULL, NULL);
return str_to;
}
static bool isTestModeEnabled()
{
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
if (!hNtdll)
return false;
using NtQuerySystemInfoFn = NTSTATUS(WINAPI *)(ULONG, PVOID, ULONG, PULONG);
auto pNtQuery = (NtQuerySystemInfoFn)GetProcAddress(hNtdll, "NtQuerySystemInformation");
if (!pNtQuery)
return false;
struct
{
ULONG Length;
ULONG CodeIntegrityOptions;
} sci = {0};
sci.Length = sizeof(sci);
ULONG retLen = 0;
NTSTATUS status = pNtQuery(103, &sci, sizeof(sci), &retLen);
if (status >= 0)
{
return (sci.CodeIntegrityOptions & 0x0002) != 0;
}
return false;
}
namespace injector
{
static std::string loadDriver()
{
if (!isTestModeEnabled())
{
return "driver load failed windows test mode must be enabled to use kernel methods";
}
NTSTATUS status = blackbone::Driver().EnsureLoaded();
if (NT_SUCCESS(status))
return "";
if (status == 0xC0000034)
return "driver load failed sys file not found make sure its next to the exe";
if (status == 0xC0000022)
return "driver load failed access denied please run the injector as an administrator";
return "driver load failed with unknown error code " + std::to_string(status);
}
std::string professionalManualMap(DWORD pid, const std::string &dllPath)
{
blackbone::Process proc;
NTSTATUS status = proc.Attach(pid);
if (!NT_SUCCESS(status))
return "failed to attach to process id " + std::to_string(pid);
blackbone::eLoadFlags flags = static_cast<blackbone::eLoadFlags>(blackbone::WipeHeader | blackbone::HideVAD);
auto result = proc.mmap().MapImage(s2ws(dllPath), flags);
if (!NT_SUCCESS(result.status))
return "manual mapping failed status " + std::to_string(result.status);
return "";
}
std::string standardInjection(DWORD pid, const std::string &dllPath)
{
blackbone::Process proc;
if (!NT_SUCCESS(proc.Attach(pid)))
return "failed to attach to process id " + std::to_string(pid);
auto result = proc.modules().Inject(s2ws(dllPath));
if (!NT_SUCCESS(result.status))
return "standard injection failed status " + std::to_string(result.status);
return "standard injection successful";
}
std::string pureILInjection(DWORD pid, const std::string &netVersion, const std::string &dllPath,
const std::string &methodName, const std::string &args)
{
blackbone::Process proc;
if (!NT_SUCCESS(proc.Attach(pid)))
return "failed to attach to process id " + std::to_string(pid);
DWORD returnCode = 0;
bool success =
proc.modules().InjectPureIL(s2ws(netVersion), s2ws(dllPath), s2ws(methodName), s2ws(args), returnCode);
if (!success)
return "pure il injection failed";
return "pure il injection successful return code " + std::to_string(returnCode);
}
std::string kernelStandardInjection(DWORD pid, const std::string &dllPath)
{
std::string drvErr = loadDriver();
if (!drvErr.empty())
return drvErr;
NTSTATUS status = blackbone::Driver().InjectDll(pid, s2ws(dllPath), IT_Thread, 0, L"", false, false, true);
if (!NT_SUCCESS(status))
return "kernel injection failed status " + std::to_string(status);
return "kernel injection successful";
}
std::string kernelManualMap(DWORD pid, const std::string &dllPath)
{
std::string drvErr = loadDriver();
if (!drvErr.empty())
return drvErr;
KMmapFlags flags = static_cast<KMmapFlags>(KManualImports | KWipeHeader | KHideVAD);
NTSTATUS status = blackbone::Driver().MmapDll(pid, s2ws(dllPath), flags);
if (!NT_SUCCESS(status))
return "kernel manual mapping failed status " + std::to_string(status);
return "kernel manual mapping successful";
}
std::vector<procInfo> getProcs()
{
std::vector<procInfo> procs;
auto result = blackbone::Process::EnumByNameOrPID(0, L"");
if (result)
{
for (const auto &p : result.result())
{
procInfo info;
info.pid = p.pid;
info.name = ws2s(p.imageName);
blackbone::Process tempProc;
if (NT_SUCCESS(tempProc.Attach(p.pid, PROCESS_QUERY_LIMITED_INFORMATION)))
{
info.arch = tempProc.core().isWow64() ? "x86" : "x64";
tempProc.Detach();
}
else
{
info.arch = "n/a";
}
procs.push_back(info);
}
}
return procs;
}
std::string injectApc(DWORD pID, const std::string &dllPath)
{
blackbone::Process proc;
if (!NT_SUCCESS(proc.Attach(pID)))
{
return "Failed to attach to process.";
}
std::wstring wDllPath = s2ws(dllPath);
auto expData = proc.modules().GetExport(L"kernel32.dll", "LoadLibraryW");
if (!NT_SUCCESS(expData.status))
{
return "Failed to find LoadLibraryW.";
}
size_t pathSize = (wDllPath.length() + 1) * sizeof(wchar_t);
auto memData = proc.memory().Allocate(pathSize, PAGE_READWRITE, 0, false);
if (!NT_SUCCESS(memData.status))
{
return "Memory allocation failed.";
}
memData->Write(0, pathSize, wDllPath.c_str());
auto threads = proc.threads().getAll();
if (threads.empty())
{
return "Process has no active threads.";
}
int queuedAPCs = 0;
for (auto &thd : threads)
{
if (thd->Suspended())
continue;
NTSTATUS status = proc.core().native()->QueueApcT(thd->handle(), expData->procAddress, memData->ptr());
if (NT_SUCCESS(status))
{
queuedAPCs++;
}
}
if (queuedAPCs == 0)
{
return "Failed to queue APCs: No suitable active threads found.";
}
bool successfullyLoaded = false;
for (int i = 0; i < 20; i++)
{
Sleep(50);
if (proc.modules().GetModule(wDllPath) != nullptr)
{
successfullyLoaded = true;
break;
}
}
if (!successfullyLoaded)
{
return "APCs queued, but DLL did not load within timeout. Threads may not be in an alertable wait state.";
}
return "";
}
std::string injectThreadHijack(DWORD pID, const std::string &dllPath)
{
blackbone::Process proc;
if (!NT_SUCCESS(proc.Attach(pID)))
return "failed to attach to process";
std::wstring wDllPath = s2ws(dllPath);
blackbone::ThreadPtr targetThread = nullptr;
auto threads = proc.threads().getAll();
auto mainThread = proc.threads().getMain();
uint64_t maxExecTime = 0;
for (auto &thd : threads)
{
if (mainThread && thd->id() == mainThread->id())
continue;
if (thd->Suspended())
continue;
uint64_t currentExecTime = thd->execTime();
if (currentExecTime >= maxExecTime)
{
maxExecTime = currentExecTime;
targetThread = thd;
}
}
if (!targetThread)
targetThread = mainThread;
if (!targetThread)
return "failed to locate a suitable thread to hijack";
try
{
auto result = proc.modules().Inject(wDllPath, targetThread);
if (!NT_SUCCESS(result.status))
return "hijack injection failed status " + std::to_string(result.status);
}
catch (const std::exception &e)
{
return std::string("injector crashed with exception: ") + e.what();
}
catch (...)
{
return "injector crashed with unknown memory exception";
}
return "";
}
std::string injectBlackBone(DWORD pID, const std::string &dllPath, bool erasePE, bool hideModule)
{
std::string driver_err = loadDriver();
if (!driver_err.empty())
return driver_err;
blackbone::Process proc;
if (!NT_SUCCESS(proc.Attach(pID)))
return "blackbone failed to attach to process";
blackbone::eLoadFlags flags = blackbone::CreateLdrRef;
if (erasePE)
flags |= blackbone::WipeHeader;
if (hideModule)
flags |= blackbone::HideVAD;
auto result = proc.mmap().MapImage(s2ws(dllPath), flags);
proc.Detach();
if (!result)
return "blackbone injection failed status " + std::to_string(result.status);
return "blackbone injection successful";
}
} // namespace injector