diff --git a/README.MD b/README.MD index afbbdfb..976bca8 100644 --- a/README.MD +++ b/README.MD @@ -11,11 +11,12 @@ Tested from **Windows 10 1607** to **Windows 11 25H2 26200.6899** :heavy_check_m ## Parameters: - --copy-header to enable the copy driver header option by commandline - --free to automatically unmap the allocated memory - --indPages to map in allocated independent pages - --PassAllocationPtr to pass allocation ptr as first param - [PDB offset based build only]: + --copy-header to enable the copy driver header option by commandline + --free to automatically unmap the allocated memory + --indPages to map in allocated independent pages + --PassAllocationPtr to pass allocation ptr as first param + --url "" to map a driver from URL directly from memory (no .sys file written to disk) + [PDB offset based build only]: --offsetsPath "FilePath" to include your own offsets file path (by default .\offsets.ini)(if FilePath contains spaces, it must be enclosed in quotation marks) --dontUpdateOffsets to execute without updating the offsets file (warning: you have to be sure that the offsets are not outdated to your current windows build, or you risk a potential BSOD) diff --git a/kdmapper/include/utils.hpp b/kdmapper/include/utils.hpp index a532039..6936522 100644 --- a/kdmapper/include/utils.hpp +++ b/kdmapper/include/utils.hpp @@ -15,10 +15,11 @@ namespace kdmUtils { std::wstring GetFullTempPath(); bool ReadFileToMemory(const std::wstring& file_path, std::vector* out_buffer); + bool ReadUrlToMemory(const std::wstring& url, std::vector* out_buffer); bool CreateFileFromMemory(const std::wstring& desired_file_path, const char* address, size_t size); uint64_t GetKernelModuleAddress(const std::string& module_name); BOOLEAN bDataCompare(const BYTE* pData, const BYTE* bMask, const char* szMask); uintptr_t FindPattern(uintptr_t dwAddress, uintptr_t dwLen, BYTE* bMask, const char* szMask); PVOID FindSection(const char* sectionName, uintptr_t modulePtr, PULONG size); std::wstring GetCurrentAppFolder(); -} \ No newline at end of file +} diff --git a/kdmapper/main.cpp b/kdmapper/main.cpp index da36e4e..18ef2c2 100644 --- a/kdmapper/main.cpp +++ b/kdmapper/main.cpp @@ -97,26 +97,27 @@ void PauseIfParentIsExplorer() { } } -void help() { - kdmLog(L"\r\n\r\n[!] Incorrect Usage!" << std::endl); - kdmLog(L"[+] Usage: kdmapper.exe [--free][--indPages][--PassAllocationPtr][--copy-header]"); - -#ifdef PDB_OFFSETS - kdmLog(L"[--dontUpdateOffsets [--offsetsPath \"FilePath\"]]"); -#endif - - kdmLog(L" driver" << std::endl); - - PauseIfParentIsExplorer(); -} - -int wmain(const int argc, wchar_t** argv) { - SetUnhandledExceptionFilter(SimplestCrashHandler); +void help() { + kdmLog(L"\r\n\r\n[!] Incorrect Usage!" << std::endl); + kdmLog(L"[+] Usage: kdmapper.exe [--free][--indPages][--PassAllocationPtr][--copy-header][--url ]"); + +#ifdef PDB_OFFSETS + kdmLog(L"[--dontUpdateOffsets [--offsetsPath \"FilePath\"]]"); +#endif + + kdmLog(L" [driver.sys]" << std::endl); + + PauseIfParentIsExplorer(); +} + +int wmain(const int argc, wchar_t** argv) { + SetUnhandledExceptionFilter(SimplestCrashHandler); bool free = paramExists(argc, argv, L"free") > 0; bool indPagesMode = paramExists(argc, argv, L"indPages") > 0; - bool passAllocationPtr = paramExists(argc, argv, L"PassAllocationPtr") > 0; - bool copyHeader = paramExists(argc, argv, L"copy-header") > 0; + bool passAllocationPtr = paramExists(argc, argv, L"PassAllocationPtr") > 0; + bool copyHeader = paramExists(argc, argv, L"copy-header") > 0; + int urlParamIdx = paramExists(argc, argv, L"url"); if (free) { kdmLog(L"[+] Free memory after driver execution enabled" << std::endl); @@ -149,27 +150,41 @@ int wmain(const int argc, wchar_t** argv) { offsetFilePath = argv[FilePathParamIdx + 1]; kdmLog("[+] Setting Offsets File Path To: " << offsetFilePath << std::endl); } -#endif - - int drvIndex = -1; - for (int i = 1; i < argc; i++) { - if (std::filesystem::path(argv[i]).extension().string().compare(".sys") == 0) { - drvIndex = i; - break; - } - } - - if (drvIndex <= 0) { - help(); - return -1; - } - - const std::wstring driver_path = argv[drvIndex]; - - if (!std::filesystem::exists(driver_path)) { - kdmLog(L"[-] File " << driver_path << L" doesn't exist" << std::endl); - PauseIfParentIsExplorer(); - return -1; +#endif + + std::wstring driver_path; + std::wstring driver_url; + + if (urlParamIdx > 0) { + if (urlParamIdx + 1 >= argc) { + kdmLog(L"[-] Missing value for --url" << std::endl); + help(); + return -1; + } + + driver_url = argv[urlParamIdx + 1]; + } + else { + int drvIndex = -1; + for (int i = 1; i < argc; i++) { + if (std::filesystem::path(argv[i]).extension().string().compare(".sys") == 0) { + drvIndex = i; + break; + } + } + + if (drvIndex <= 0) { + help(); + return -1; + } + + driver_path = argv[drvIndex]; + } + + if (driver_url.empty() && !std::filesystem::exists(driver_path)) { + kdmLog(L"[-] File " << driver_path << L" doesn't exist" << std::endl); + PauseIfParentIsExplorer(); + return -1; } #ifdef PDB_OFFSETS @@ -183,14 +198,23 @@ int wmain(const int argc, wchar_t** argv) { if (!NT_SUCCESS(intel_driver::Load())) { PauseIfParentIsExplorer(); return -1; - } - - std::vector raw_image = { 0 }; - if (!kdmUtils::ReadFileToMemory(driver_path, &raw_image)) { - kdmLog(L"[-] Failed to read image to memory" << std::endl); - intel_driver::Unload(); - PauseIfParentIsExplorer(); - return -1; + } + + std::vector raw_image = { 0 }; + if (!driver_url.empty()) { + kdmLog(L"[+] Downloading image from URL: " << driver_url << std::endl); + if (!kdmUtils::ReadUrlToMemory(driver_url, &raw_image)) { + kdmLog(L"[-] Failed to download image to memory" << std::endl); + intel_driver::Unload(); + PauseIfParentIsExplorer(); + return -1; + } + } + else if (!kdmUtils::ReadFileToMemory(driver_path, &raw_image)) { + kdmLog(L"[-] Failed to read image to memory" << std::endl); + intel_driver::Unload(); + PauseIfParentIsExplorer(); + return -1; } kdmapper::AllocationMode mode = kdmapper::AllocationMode::AllocatePool; @@ -198,13 +222,18 @@ int wmain(const int argc, wchar_t** argv) { if (indPagesMode) { mode = kdmapper::AllocationMode::AllocateIndependentPages; } - - NTSTATUS exitCode = 0; - if (!kdmapper::MapDriver(raw_image.data(), 0, 0, free, !copyHeader, mode, passAllocationPtr, callbackExample, &exitCode)) { - kdmLog(L"[-] Failed to map " << driver_path << std::endl); - intel_driver::Unload(); - PauseIfParentIsExplorer(); - return -1; + + NTSTATUS exitCode = 0; + if (!kdmapper::MapDriver(raw_image.data(), 0, 0, free, !copyHeader, mode, passAllocationPtr, callbackExample, &exitCode)) { + if (!driver_url.empty()) { + kdmLog(L"[-] Failed to map image from URL " << driver_url << std::endl); + } + else { + kdmLog(L"[-] Failed to map " << driver_path << std::endl); + } + intel_driver::Unload(); + PauseIfParentIsExplorer(); + return -1; } if (!NT_SUCCESS(intel_driver::Unload())) { @@ -215,4 +244,4 @@ int wmain(const int argc, wchar_t** argv) { } -#endif \ No newline at end of file +#endif diff --git a/kdmapper/utils.cpp b/kdmapper/utils.cpp index a0d0c7f..58cb128 100644 --- a/kdmapper/utils.cpp +++ b/kdmapper/utils.cpp @@ -1,11 +1,14 @@ -#include "utils.hpp" -#include -#include -#include -#include - -#include "nt.hpp" - +#include "utils.hpp" +#include +#include +#include +#include +#include + +#include "nt.hpp" + +#pragma comment(lib, "winhttp.lib") + std::wstring kdmUtils::GetFullTempPath() { wchar_t temp_directory[MAX_PATH + 1] = { 0 }; const uint32_t get_temp_path_ret = GetTempPathW(sizeof(temp_directory) / 2, temp_directory); @@ -19,8 +22,8 @@ std::wstring kdmUtils::GetFullTempPath() { return std::wstring(temp_directory); } -bool kdmUtils::ReadFileToMemory(const std::wstring& file_path, std::vector* out_buffer) { - std::ifstream file_ifstream(file_path, std::ios::binary); +bool kdmUtils::ReadFileToMemory(const std::wstring& file_path, std::vector* out_buffer) { + std::ifstream file_ifstream(file_path, std::ios::binary); if (!file_ifstream) return false; @@ -28,10 +31,129 @@ bool kdmUtils::ReadFileToMemory(const std::wstring& file_path, std::vector out_buffer->assign((std::istreambuf_iterator(file_ifstream)), std::istreambuf_iterator()); file_ifstream.close(); - return true; -} - -bool kdmUtils::CreateFileFromMemory(const std::wstring& desired_file_path, const char* address, size_t size) { + return true; +} + +bool kdmUtils::ReadUrlToMemory(const std::wstring& url, std::vector* out_buffer) { + out_buffer->clear(); + DWORD statusCode = 0; + DWORD statusCodeSize = sizeof(statusCode); + + URL_COMPONENTS urlComponents = {}; + urlComponents.dwStructSize = sizeof(urlComponents); + + wchar_t hostName[256] = {}; + wchar_t urlPath[2048] = {}; + wchar_t extraInfo[1024] = {}; + + urlComponents.lpszHostName = hostName; + urlComponents.dwHostNameLength = _countof(hostName); + urlComponents.lpszUrlPath = urlPath; + urlComponents.dwUrlPathLength = _countof(urlPath); + urlComponents.lpszExtraInfo = extraInfo; + urlComponents.dwExtraInfoLength = _countof(extraInfo); + + if (!WinHttpCrackUrl(url.c_str(), static_cast(url.size()), 0, &urlComponents)) { + kdmLog(L"[-] Invalid URL: " << url << std::endl); + return false; + } + + std::wstring host(hostName, urlComponents.dwHostNameLength); + std::wstring path(urlPath, urlComponents.dwUrlPathLength); + std::wstring query(extraInfo, urlComponents.dwExtraInfoLength); + std::wstring object = path + query; + if (object.empty()) { + object = L"/"; + } + + if (urlComponents.nScheme != INTERNET_SCHEME_HTTP && urlComponents.nScheme != INTERNET_SCHEME_HTTPS) { + kdmLog(L"[-] URL must use http or https" << std::endl); + return false; + } + + const bool useHttps = urlComponents.nScheme == INTERNET_SCHEME_HTTPS; + + HINTERNET hSession = WinHttpOpen(L"kdmapper/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, + WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); + if (!hSession) { + kdmLog(L"[-] WinHttpOpen failed: " << GetLastError() << std::endl); + return false; + } + + HINTERNET hConnect = WinHttpConnect(hSession, host.c_str(), urlComponents.nPort, 0); + if (!hConnect) { + kdmLog(L"[-] WinHttpConnect failed: " << GetLastError() << std::endl); + WinHttpCloseHandle(hSession); + return false; + } + + HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", object.c_str(), + nullptr, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, + useHttps ? WINHTTP_FLAG_SECURE : 0); + if (!hRequest) { + kdmLog(L"[-] WinHttpOpenRequest failed: " << GetLastError() << std::endl); + WinHttpCloseHandle(hConnect); + WinHttpCloseHandle(hSession); + return false; + } + + bool success = false; + + if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, + WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) { + kdmLog(L"[-] WinHttpSendRequest failed: " << GetLastError() << std::endl); + goto cleanup; + } + + if (!WinHttpReceiveResponse(hRequest, nullptr)) { + kdmLog(L"[-] WinHttpReceiveResponse failed: " << GetLastError() << std::endl); + goto cleanup; + } + + if (!WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, + WINHTTP_HEADER_NAME_BY_INDEX, &statusCode, &statusCodeSize, WINHTTP_NO_HEADER_INDEX)) { + kdmLog(L"[-] WinHttpQueryHeaders failed: " << GetLastError() << std::endl); + goto cleanup; + } + + if (statusCode < 200 || statusCode >= 300) { + kdmLog(L"[-] HTTP request failed with status " << statusCode << std::endl); + goto cleanup; + } + + for (;;) { + DWORD availableSize = 0; + if (!WinHttpQueryDataAvailable(hRequest, &availableSize)) { + kdmLog(L"[-] WinHttpQueryDataAvailable failed: " << GetLastError() << std::endl); + goto cleanup; + } + + if (availableSize == 0) { + break; + } + + const size_t previousSize = out_buffer->size(); + out_buffer->resize(previousSize + availableSize); + + DWORD downloadedSize = 0; + if (!WinHttpReadData(hRequest, out_buffer->data() + previousSize, availableSize, &downloadedSize)) { + kdmLog(L"[-] WinHttpReadData failed: " << GetLastError() << std::endl); + goto cleanup; + } + + out_buffer->resize(previousSize + downloadedSize); + } + + success = !out_buffer->empty(); + +cleanup: + WinHttpCloseHandle(hRequest); + WinHttpCloseHandle(hConnect); + WinHttpCloseHandle(hSession); + return success; +} + +bool kdmUtils::CreateFileFromMemory(const std::wstring& desired_file_path, const char* address, size_t size) { std::ofstream file_ofstream(desired_file_path.c_str(), std::ios_base::out | std::ios_base::binary); if (!file_ofstream.write(address, size)) { @@ -123,4 +245,4 @@ std::wstring kdmUtils::GetCurrentAppFolder() { GetModuleFileNameW(NULL, buffer, 1024); std::wstring::size_type pos = std::wstring(buffer).find_last_of(L"\\/"); return std::wstring(buffer).substr(0, pos); -} \ No newline at end of file +}