Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/evasion/windows/process_herpaderping/ProcessHerpaderping/utils.cpp
Views: 11788
#include "pch.hpp"1#include "utils.hpp"23_Use_decl_annotations_4std::wstring Utils::FormatError(uint32_t Error)5{6LPWSTR buffer;7std::wstring message;8auto length = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |9FORMAT_MESSAGE_FROM_SYSTEM |10FORMAT_MESSAGE_IGNORE_INSERTS,11nullptr,12Error,13MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),14RCAST(LPWSTR)(&buffer),150,16nullptr);17if ((buffer != nullptr) && (length > 0))18{19message = std::wstring(buffer, length);20}21else22{23length = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |24FORMAT_MESSAGE_FROM_SYSTEM |25FORMAT_MESSAGE_FROM_HMODULE |26FORMAT_MESSAGE_IGNORE_INSERTS,27GetModuleHandleA("ntdll.dll"),28Error,29MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),30RCAST(LPWSTR)(&buffer),310,32nullptr);33if ((buffer != nullptr) && (length > 0))34{35//36// NT status codes are formatted with inserts, only use the37// initial description if there is one, otherwise just use the38// string as is.39//40message = std::wstring(buffer, length);41if (message[0] == L'{')42{43auto pos = message.find(L'}', 1);44if (pos != std::wstring::npos)45{46message = std::wstring(message.begin() + 1,47message.begin() + pos);48}49}50}51}5253if (message.empty())54{55message = L"Unknown Error";56}5758std::wstringstream ss;59ss << L"0x"60<< std::hex << std::setfill(L'0') << std::setw(8) << Error61<< L" - "62<< std::move(message);6364auto res = ss.str();65EraseAll(res, { L'\r', L'\n', L'\t' });6667LocalFree(buffer);6869return res;70}7172_Use_decl_annotations_73HRESULT Utils::FillBufferWithPattern(74std::vector<uint8_t>& Buffer,75std::span<const uint8_t> Pattern)76{77if (Buffer.empty())78{79REPORT_AND_RETURN_WIN32("FillBufferWithPattern: Buffer is empty", ERROR_INVALID_PARAMETER);80}8182auto bytesRemaining = Buffer.size();83while (bytesRemaining > 0)84{85auto len = (Pattern.size() > bytesRemaining ?86bytesRemaining87:88Pattern.size());8990std::memcpy(&Buffer[Buffer.size() - bytesRemaining],91Pattern.data(),92len);9394bytesRemaining -= len;95}9697return S_OK;98}99100_Use_decl_annotations_101HRESULT Utils::GetFileSize(102handle_t FileHandle,103uint64_t& FileSize)104{105FileSize = 0;106107LARGE_INTEGER fileSize;108if (GetFileSizeEx(FileHandle, &fileSize) == 0)109{110REPORT_AND_RETURN_WIN32("GetFileSize: Error getting file size", GetLastError());111}112113if (fileSize.QuadPart < 0)114{115REPORT_AND_RETURN_WIN32("GetFileSize: Invalid file size", ERROR_FILE_INVALID);116}117118FileSize = fileSize.QuadPart;119return S_OK;120}121122_Use_decl_annotations_123HRESULT Utils::SetFilePointer(124handle_t FileHandle,125int64_t DistanceToMove,126uint32_t MoveMethod)127{128LARGE_INTEGER distance;129distance.QuadPart = DistanceToMove;130131if (SetFilePointerEx(FileHandle, distance, nullptr, MoveMethod) == 0)132{133REPORT_AND_RETURN_WIN32("SetFilePointer: Error returned by SetFilePointerEx()", GetLastError());134}135136return S_OK;137}138139_Use_decl_annotations_140HRESULT Utils::CopyFileByHandle(141handle_t SourceHandle,142handle_t TargetHandle)143{144//145// Get the file sizes.146//147uint64_t sourceSize;148if (FAILED(GetFileSize(SourceHandle, sourceSize)))149{150REPORT_AND_RETURN_WIN32("CopyFileByHandle: Error getting source file size", GetLastError());151}152153//154// Set the file pointers to the beginning of the files.155//156HRESULT hr = SetFilePointer(SourceHandle, 0, FILE_BEGIN);157if (FAILED(hr))158{159REPORT_AND_RETURN_HR("CopyFileByHandle: Error setting source file pointer", hr);160}161hr = SetFilePointer(TargetHandle, 0, FILE_BEGIN);162if (FAILED(hr))163{164REPORT_AND_RETURN_HR("CopyFileByHandle: Error setting target file pointer", hr);165}166167uint64_t bytesRemaining = sourceSize;168std::vector<uint8_t> buffer;169if (bytesRemaining > MaxFileBuffer)170{171buffer.assign(MaxFileBuffer, 0);172}173else174{175buffer.assign(SCAST(size_t)(bytesRemaining), 0);176}177178while (bytesRemaining > 0)179{180if (bytesRemaining < buffer.size())181{182buffer.assign(SCAST(size_t)(bytesRemaining), 0);183}184185DWORD bytesRead = 0;186if (ReadFile(SourceHandle, buffer.data(), SCAST(DWORD)(buffer.size()), &bytesRead, nullptr) == 0)187{188REPORT_AND_RETURN_WIN32("CopyFileByHandle: Error reading source file", GetLastError());189}190191bytesRemaining -= bytesRead;192193DWORD bytesWitten = 0;194if (WriteFile(TargetHandle, buffer.data(), SCAST(DWORD)(buffer.size()), &bytesWitten, nullptr) == 0)195{196REPORT_AND_RETURN_WIN32("CopyFileByHandle: Error writing target file", GetLastError());197}198}199200if (FlushFileBuffers(TargetHandle) == 0)201{202REPORT_AND_RETURN_WIN32("CopyFileByHandle: Error flushing target file", GetLastError());203}204if (SetEndOfFile(TargetHandle) == 0)205{206REPORT_AND_RETURN_WIN32("CopyFileByHandle: Error setting EoF on target file", GetLastError());207}208209return S_OK;210}211212_Use_decl_annotations_213HRESULT Utils::OverwriteFileContentsWithPattern(214handle_t FileHandle,215std::span<const uint8_t> Pattern)216{217uint64_t targetSize;218if (FAILED(Utils::GetFileSize(FileHandle, targetSize)))219{220REPORT_AND_RETURN_WIN32("OverwriteFileContentsWithPattern: Error getting file size", GetLastError());221}222HRESULT hr = SetFilePointer(FileHandle, 0, FILE_BEGIN);223if (FAILED(hr))224{225REPORT_AND_RETURN_HR("OverwriteFileContentsWithPattern: Error setting file pointer", hr);226}227228uint64_t bytesRemaining = targetSize;229std::vector<uint8_t> buffer;230if (bytesRemaining > MaxFileBuffer)231{232buffer.resize(MaxFileBuffer);233hr = FillBufferWithPattern(buffer, Pattern);234if (FAILED(hr))235{236REPORT_AND_RETURN_HR("OverwriteFileContentsWithPattern: Error in FillBufferWithPattern()", hr);237}238}239else240{241buffer.resize(SCAST(size_t)(bytesRemaining));242hr = FillBufferWithPattern(buffer, Pattern);243if (FAILED(hr))244{245REPORT_AND_RETURN_HR("OverwriteFileContentsWithPattern: Error in FillBufferWithPattern()", hr);246}247}248249while (bytesRemaining > 0)250{251if (bytesRemaining < buffer.size())252{253buffer.resize(SCAST(size_t)(bytesRemaining));254hr = FillBufferWithPattern(buffer, Pattern);255if (FAILED(hr))256{257REPORT_AND_RETURN_HR("OverwriteFileContentsWithPattern: Error in FillBufferWithPattern()", hr);258}259}260261DWORD bytesWritten = 0;262if (WriteFile(FileHandle, buffer.data(), SCAST(DWORD)(buffer.size()), &bytesWritten, nullptr) == 0)263{264REPORT_AND_RETURN_WIN32("OverwriteFileContentsWithPattern: Error writing to file", GetLastError());265}266267bytesRemaining -= bytesWritten;268}269270if (FlushFileBuffers(FileHandle) == 0)271{272REPORT_AND_RETURN_WIN32("OverwriteFileContentsWithPattern: Error flushing file", GetLastError());273}274275return S_OK;276}277278_Use_decl_annotations_279HRESULT Utils::OverwriteFileAfterWithPattern(280handle_t FileHandle,281uint64_t FileOffset,282std::span<const uint8_t> Pattern,283uint32_t& WrittenBytes)284{285WrittenBytes = 0;286287uint64_t targetSize;288if (FAILED(Utils::GetFileSize(FileHandle, targetSize)))289{290REPORT_AND_RETURN_WIN32("OverwriteFileAfterWithPattern: Error getting file size", GetLastError());291}292293if (FileOffset >= targetSize)294{295REPORT_AND_RETURN_WIN32("OverwriteFileAfterWithPattern: FileOffset cannot be greater than targetSize", ERROR_INVALID_PARAMETER);296}297298HRESULT hr = SetFilePointer(FileHandle, FileOffset, FILE_BEGIN);299if (FAILED(hr))300{301REPORT_AND_RETURN_HR("OverwriteFileAfterWithPattern: Error setting file pointer", hr);302}303304uint64_t bytesRemaining;305bytesRemaining = (targetSize - FileOffset);306std::vector<uint8_t> buffer;307if (bytesRemaining > MaxFileBuffer)308{309buffer.resize(MaxFileBuffer);310hr = FillBufferWithPattern(buffer, Pattern);311if (FAILED(hr))312{313REPORT_AND_RETURN_HR("OverwriteFileAfterWithPattern: Error in FillBufferWithPattern()", hr);314}315}316else317{318buffer.resize(SCAST(size_t)(bytesRemaining));319hr = FillBufferWithPattern(buffer, Pattern);320if (FAILED(hr))321{322REPORT_AND_RETURN_HR("OverwriteFileAfterWithPattern: Error in FillBufferWithPattern()", hr);323}324}325326while (bytesRemaining > 0)327{328DWORD bytesWritten = 0;329330if (bytesRemaining < buffer.size())331{332buffer.resize(SCAST(size_t)(bytesRemaining));333hr = FillBufferWithPattern(buffer, Pattern);334if (FAILED(hr))335{336REPORT_AND_RETURN_HR("OverwriteFileAfterWithPattern: Error in FillBufferWithPattern()", hr);337}338}339340if (WriteFile(FileHandle, buffer.data(), SCAST(DWORD)(buffer.size()), &bytesWritten, nullptr) == 0)341{342REPORT_AND_RETURN_WIN32("OverwriteFileAfterWithPattern: Error writing to file", GetLastError());343}344345bytesRemaining -= bytesWritten;346WrittenBytes += bytesWritten;347}348349if (FlushFileBuffers(FileHandle) == 0)350{351REPORT_AND_RETURN_WIN32("OverwriteFileAfterWithPattern: Error flushing file", GetLastError());352}353354return S_OK;355}356357_Use_decl_annotations_358HRESULT Utils::ExtendFileSecurityDirectory(359handle_t FileHandle,360uint32_t ExtendedBy)361{362uint64_t targetSize;363if (FAILED(Utils::GetFileSize(FileHandle, targetSize)))364{365REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Error getting file size", GetLastError());366}367368ULARGE_INTEGER mappingSize;369mappingSize.QuadPart = targetSize;370MappingHandle mapping;371mapping.get() = CreateFileMappingW(FileHandle,372nullptr,373PAGE_READWRITE,374mappingSize.HighPart,375mappingSize.LowPart,376nullptr);377if (!mapping.valid())378{379REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Error creating file mapping", GetLastError());380}381382mapping.view() = MapViewOfFile(mapping.get(),383FILE_MAP_READ | FILE_MAP_WRITE,3840,3850,386mappingSize.LowPart);387if (mapping.view() == nullptr)388{389REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Error returned by MapViewOfFile()", GetLastError());390}391392auto dosHeader = RCAST(PIMAGE_DOS_HEADER)(mapping.view());393if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)394{395//396// This is not a PE file, we're done.397//398REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Failed parse PE file", ERROR_INVALID_IMAGE_HASH);399}400401auto ntHeader = RCAST(PIMAGE_NT_HEADERS32)(Add2Ptr(mapping.view(), dosHeader->e_lfanew));402if (ntHeader->Signature != IMAGE_NT_SIGNATURE)403{404REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Failed parse PE NT Header (x32)", ERROR_INVALID_IMAGE_HASH);405}406407IMAGE_DATA_DIRECTORY* secDir;408if (ntHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)409{410if (ntHeader->OptionalHeader.NumberOfRvaAndSizes < IMAGE_DIRECTORY_ENTRY_SECURITY)411{412//413// No security directory, we're done.414//415return S_OK;416}417secDir = &ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY];418}419else if (ntHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)420{421auto ntHeader64 = RCAST(PIMAGE_NT_HEADERS64)(ntHeader);422if (ntHeader64->OptionalHeader.NumberOfRvaAndSizes < IMAGE_DIRECTORY_ENTRY_SECURITY)423{424//425// No security directory, we're done.426//427return S_OK;428}429secDir = &ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY];430}431else432{433REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Failed parse PE NT Header (x64)", ERROR_INVALID_IMAGE_HASH);434}435436if ((secDir->VirtualAddress) == 0 || (secDir->Size == 0))437{438//439// No security directory, we're done.440//441return S_OK;442}443444//445// Extend the security directory size.446//447secDir->Size = (secDir->Size + ExtendedBy);448449if (FlushViewOfFile(mapping.view(), mappingSize.LowPart) == 0)450{451DWORD lastError = GetLastError();452REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Error flushing view of file", lastError);453}454455mapping.close();456457if (FlushFileBuffers(FileHandle) == 0)458{459REPORT_AND_RETURN_WIN32("ExtendFileSecurityDirectory: Error flushing file", GetLastError());460}461462return S_OK;463}464465_Use_decl_annotations_466HRESULT Utils::GetImageEntryPointRva(467handle_t FileHandle,468uint32_t& EntryPointRva)469{470EntryPointRva = 0;471472uint64_t fileSize;473if (FAILED(Utils::GetFileSize(FileHandle, fileSize)))474{475REPORT_AND_RETURN_WIN32("ImageEntryPointRva: Error getting file size", GetLastError());476}477478ULARGE_INTEGER mappingSize;479mappingSize.QuadPart = fileSize;480MappingHandle mapping;481mapping.get() = CreateFileMappingW(FileHandle,482nullptr,483PAGE_READONLY,484mappingSize.HighPart,485mappingSize.LowPart,486nullptr);487if (!mapping.valid())488{489REPORT_AND_RETURN_WIN32("ImageEntryPointRva: Error creating file mapping", GetLastError());490}491492mapping.view() = MapViewOfFile(mapping.get(),493FILE_MAP_READ,4940,4950,496mappingSize.LowPart);497if (mapping.view() == nullptr)498{499REPORT_AND_RETURN_WIN32("ImageEntryPointRva: Error returned by MapViewOfFile()", GetLastError());500}501502auto dosHeader = RCAST(PIMAGE_DOS_HEADER)(mapping.view());503if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)504{505REPORT_AND_RETURN_WIN32("ImageEntryPointRva: Failed parse PE file", ERROR_INVALID_IMAGE_HASH);506}507508auto ntHeader = RCAST(PIMAGE_NT_HEADERS32)(Add2Ptr(mapping.view(), dosHeader->e_lfanew));509if (ntHeader->Signature != IMAGE_NT_SIGNATURE)510{511REPORT_AND_RETURN_WIN32("ImageEntryPointRva: Failed parse PE NT Header (x32)", ERROR_INVALID_IMAGE_HASH);512}513514if (ntHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)515{516EntryPointRva = ntHeader->OptionalHeader.AddressOfEntryPoint;517}518else if (ntHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)519{520auto ntHeader64 = RCAST(PIMAGE_NT_HEADERS64)(ntHeader);521EntryPointRva = ntHeader64->OptionalHeader.AddressOfEntryPoint;522}523else524{525REPORT_AND_RETURN_WIN32("ImageEntryPointRva: Failed parse PE NT Header (x64)", ERROR_INVALID_IMAGE_HASH);526}527528mapping.close();529530return S_OK;531}532533class OptionalUnicodeStringHelper534{535public:536537OptionalUnicodeStringHelper(538_In_opt_ const std::optional<std::wstring>& String) :539m_String(String)540{541if (m_String.has_value())542{543RtlInitUnicodeString(&m_Unicode, m_String->c_str());544}545else546{547RtlInitUnicodeString(&m_Unicode, L"");548}549}550551PUNICODE_STRING Get()552{553if (m_String.has_value())554{555return &m_Unicode;556}557return nullptr;558}559560operator PUNICODE_STRING()561{562return Get();563}564565private:566567const std::optional<std::wstring>& m_String;568UNICODE_STRING m_Unicode;569570};571572_Use_decl_annotations_573HRESULT Utils::WriteRemoteProcessParameters(574handle_t ProcessHandle,575const std::wstring ImageFileName,576const std::optional<std::wstring>& DllPath,577const std::optional<std::wstring>& CurrentDirectory,578const std::optional<std::wstring>& CommandLine,579void* EnvironmentBlock,580const std::optional<std::wstring>& WindowTitle,581const std::optional<std::wstring>& DesktopInfo,582const std::optional<std::wstring>& ShellInfo,583const std::optional<std::wstring>& RuntimeData)584{585//586// Get the basic info for the remote PEB address.587//588PROCESS_BASIC_INFORMATION pbi{};589NTSTATUS status = NtQueryInformationProcess(ProcessHandle,590ProcessBasicInformation,591&pbi,592sizeof(pbi),593nullptr);594if (!NT_SUCCESS(status))595{596REPORT_AND_RETURN_NT("WriteRemoteProcessParameters: Failed to query process info", status);597}598599//600// Generate the process parameters to write into the process.601//602UNICODE_STRING imageName;603RtlInitUnicodeString(&imageName, ImageFileName.c_str());604OptionalUnicodeStringHelper dllPath(DllPath);605OptionalUnicodeStringHelper commandLine(CommandLine);606OptionalUnicodeStringHelper currentDirectory(CurrentDirectory);607OptionalUnicodeStringHelper windowTitle(WindowTitle);608OptionalUnicodeStringHelper desktopInfo(DesktopInfo);609OptionalUnicodeStringHelper shellInfo(ShellInfo);610OptionalUnicodeStringHelper runtimeData(RuntimeData);611PRTL_USER_PROCESS_PARAMETERS params;612613//614// Generate the process parameters and do not pass615// RTL_USER_PROC_PARAMS_NORMALIZED, this will keep the process parameters616// de-normalized (pointers will be offsets instead of addresses) then617// LdrpInitializeProcess will call RtlNormalizeProcessParameters and fix618// them up when the process starts.619//620// Note: There is an exception here, the Environment pointer is not621// de-normalized - we'll fix that up ourself.622//623status = RtlCreateProcessParametersEx(¶ms,624&imageName,625dllPath,626currentDirectory,627commandLine,628EnvironmentBlock,629windowTitle,630desktopInfo,631shellInfo,632runtimeData,6330);634if (!NT_SUCCESS(status))635{636REPORT_AND_RETURN_NT("WriteRemoteProcessParameters: Failed to create process parameters", status);637}638639//640// Calculate the required length.641//642size_t len = params->MaximumLength + params->EnvironmentSize;643644//645// Allocate memory in the remote process to hold the process parameters.646//647auto remoteMemory = VirtualAllocEx(ProcessHandle,648nullptr,649len,650MEM_COMMIT | MEM_RESERVE,651PAGE_READWRITE);652if (remoteMemory == nullptr)653{654RtlDestroyProcessParameters(params);655REPORT_AND_RETURN_WIN32("WriteRemoteProcessParameters: Error allocating memory", GetLastError());656}657658659//660// Okay we have some memory in the remote process, go do the final fix-ups.661//662if (params->Environment != nullptr)663{664//665// The environment block will always be right after the length, which666// is the size of RTL_USER_PROCESS_PARAMETERS plus any extra field667// data.668//669params->Environment = Add2Ptr(remoteMemory, params->Length);670}671672//673// Write the parameters into the remote process.674//675if (WriteProcessMemory(ProcessHandle, remoteMemory, params, len, nullptr) == 0)676{677RtlDestroyProcessParameters(params);678REPORT_AND_RETURN_WIN32("WriteRemoteProcessParameters: Error writting parameters into the remote process", GetLastError());679}680681//682// Write the parameter pointer to the remote process PEB.683//684if (WriteProcessMemory(ProcessHandle,685Add2Ptr(pbi.PebBaseAddress,686FIELD_OFFSET(PEB, ProcessParameters)),687&remoteMemory,688sizeof(remoteMemory),689nullptr) == 0)690{691RtlDestroyProcessParameters(params);692REPORT_AND_RETURN_WIN32("WriteRemoteProcessParameters: Error writting the parameter pointer to the remote process PEB", GetLastError());693}694695return S_OK;696}697698#pragma optimize( "", off )699_Use_decl_annotations_700BOOL Utils::ShouldReplaceWithFile(701const char* fileName)702{703return (fileName[0] == '\0') ? FALSE : TRUE;704}705#pragma optimize( "", on )706707_Use_decl_annotations_708HRESULT Utils::GetFileName(709const char* sourceFileName,710std::wstring& finalFileName)711{712size_t cbTargetFileName = strnlen_s(sourceFileName, FILE_MAX_PATH);713int sizeNeeded = MultiByteToWideChar(CP_UTF8,7140,715sourceFileName,716(int)cbTargetFileName,717NULL,7180);719if (sizeNeeded == 0)720{721REPORT_AND_RETURN_WIN32("GetFileName: Error getting required size to convert filename to wide chars", GetLastError());722}723724std::wstring TargetFileNameTmp(sizeNeeded, 0);725if (MultiByteToWideChar(CP_UTF8,7260,727sourceFileName,728(int)cbTargetFileName,729&TargetFileNameTmp[0],730sizeNeeded) == 0)731{732REPORT_AND_RETURN_WIN32("GetFileName: Error converting filename to wide chars", GetLastError());733}734735sizeNeeded = ExpandEnvironmentStringsW(TargetFileNameTmp.c_str(), NULL, 0);736if (sizeNeeded == 0)737{738REPORT_AND_RETURN_WIN32("GetFileName: Error getting required size to expand filename", GetLastError());739}740741finalFileName.resize(((size_t)sizeNeeded) - 1, 0);742if (ExpandEnvironmentStringsW(TargetFileNameTmp.c_str(), &finalFileName[0], sizeNeeded) == 0)743{744REPORT_AND_RETURN_WIN32("GetFileName: Error expanding filename", GetLastError());745}746747return S_OK;748}749750#ifndef _WIN64751//752// Only needed for 32-bit Windows753//754_Use_decl_annotations_755HRESULT Utils::GetFileVersion(LPCWSTR lptstrFilename, PFILE_VERSION ver)756{757DWORD dwHandle;758DWORD dwLen = GetFileVersionInfoSizeW(lptstrFilename, &dwHandle);759if (dwLen == 0)760{761REPORT_AND_RETURN_WIN32("GetFileVersion: Error getting file version info size", GetLastError());762}763LPVOID lpData = new LPVOID[dwLen];764if (!GetFileVersionInfoW(lptstrFilename, 0, dwLen, lpData))765{766delete[] lpData;767REPORT_AND_RETURN_WIN32("GetFileVersion: Error getting file version info", GetLastError());768}769VS_FIXEDFILEINFO* versionInfo;770UINT uLen;771if (!VerQueryValueW(lpData, L"\\", (LPVOID*)&versionInfo, &uLen))772{773delete[] lpData;774REPORT_AND_RETURN_WIN32("GetFileVersion: Error getting version info", GetLastError());775}776777ver->MajorVersion = (versionInfo->dwProductVersionMS >> 16) & 0xFFFF;778ver->MinorVersion = versionInfo->dwProductVersionMS & 0xFFFF;779ver->BuildVersion = (versionInfo->dwProductVersionLS >> 16) & 0xFFFF;780ver->RevisionVersion = versionInfo->dwProductVersionLS & 0xFFFF;781782delete[] lpData;783784return S_OK;785}786787_Use_decl_annotations_788HRESULT Utils::IsBuggyKernel()789{790std::wstring kernelFile;791HRESULT hr = Utils::GetFileName("%SystemRoot%\\System32\\ntoskrnl.exe", kernelFile);792if (FAILED(hr))793{794REPORT_AND_RETURN_HR("Failed to retrieve the target filename", hr);795}796797FileHandle kernelHandle(kernelFile);798kernelHandle.get() = CreateFileW(kernelFile.c_str(),799GENERIC_READ,800FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,801nullptr,802OPEN_EXISTING,803FILE_ATTRIBUTE_NORMAL,804nullptr);805if (!kernelHandle.valid())806{807REPORT_AND_RETURN_WIN32("BuggyKernel: Failed to open Kernel file", GetLastError());808}809810FILE_VERSION ver;811hr = GetFileVersion(kernelFile.c_str(), &ver);812if (FAILED(hr))813{814REPORT_AND_RETURN_HR("BuggyKernel: Failed getting file version", hr);815}816dprintf("Version of %S is %hu.%hu.%hu.%hu",817kernelFile.c_str(),818ver.MajorVersion,819ver.MinorVersion,820ver.BuildVersion,821ver.RevisionVersion822);823if (ver.MajorVersion == 10 &&824ver.MinorVersion == 0 &&825ver.BuildVersion > 10240 &&826ver.BuildVersion < 16299)827{828return S_OK;829}830831return S_FALSE;832}833#endif834835836