-
Notifications
You must be signed in to change notification settings - Fork 621
URL Map feature #221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
URL Map feature #221
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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 <http(s)://...>]"); | ||||||||||||||||
|
|
||||||||||||||||
| #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]; | ||||||||||||||||
|
||||||||||||||||
| driver_url = argv[urlParamIdx + 1]; | |
| driver_url = argv[urlParamIdx + 1]; | |
| if (driver_url.empty()) { | |
| kdmLog(L"[-] Empty value for --url" << std::endl); | |
| help(); | |
| return -1; | |
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,11 +1,14 @@ | ||||||||||||
| #include "utils.hpp" | ||||||||||||
| #include <Windows.h> | ||||||||||||
| #include <iostream> | ||||||||||||
| #include <vector> | ||||||||||||
| #include <fstream> | ||||||||||||
|
|
||||||||||||
| #include "nt.hpp" | ||||||||||||
|
|
||||||||||||
| #include "utils.hpp" | ||||||||||||
| #include <Windows.h> | ||||||||||||
| #include <winhttp.h> | ||||||||||||
| #include <iostream> | ||||||||||||
| #include <vector> | ||||||||||||
| #include <fstream> | ||||||||||||
|
|
||||||||||||
| #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,19 +22,138 @@ std::wstring kdmUtils::GetFullTempPath() { | |||||||||||
| return std::wstring(temp_directory); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| bool kdmUtils::ReadFileToMemory(const std::wstring& file_path, std::vector<BYTE>* out_buffer) { | ||||||||||||
| std::ifstream file_ifstream(file_path, std::ios::binary); | ||||||||||||
| bool kdmUtils::ReadFileToMemory(const std::wstring& file_path, std::vector<BYTE>* out_buffer) { | ||||||||||||
| std::ifstream file_ifstream(file_path, std::ios::binary); | ||||||||||||
|
|
||||||||||||
| if (!file_ifstream) | ||||||||||||
| return false; | ||||||||||||
|
|
||||||||||||
| out_buffer->assign((std::istreambuf_iterator<char>(file_ifstream)), std::istreambuf_iterator<char>()); | ||||||||||||
| 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<BYTE>* 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<DWORD>(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; | ||||||||||||
|
||||||||||||
| const bool useHttps = urlComponents.nScheme == INTERNET_SCHEME_HTTPS; | |
| const bool useHttps = urlComponents.nScheme == INTERNET_SCHEME_HTTPS; | |
| if (!useHttps) { | |
| kdmLog(L"[!] Warning: Downloading driver over insecure HTTP; this is vulnerable to man-in-the-middle attacks." << std::endl); | |
| } |
Copilot
AI
Mar 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the download loop encounters a failure (e.g., WinHttpQueryDataAvailable or WinHttpReadData fails), the function returns false but out_buffer may still contain partial data. While the caller currently checks the return value and doesn't use the buffer on failure, it would be safer to clear out_buffer in the cleanup path when success is false, to avoid accidentally using partial/corrupt data if the calling code changes in the future.
| WinHttpCloseHandle(hSession); | |
| WinHttpCloseHandle(hSession); | |
| if (!success && out_buffer) { | |
| out_buffer->clear(); | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new
--url "<http(s)://...>"documentation implies that mapping a driver from anhttp://URL is supported, but the implementation (kdmUtils::ReadUrlToMemory) actually allows plain HTTP for downloading the kernel driver image. Fetching kernel-mode code over unencrypted HTTP lets a network or DNS attacker tamper with the driver binary in transit and gain arbitrary kernel code execution on systems using--urlwithhttp://endpoints. This feature should be documented and implemented as HTTPS-only (rejecting or strongly warning againsthttp://), so all driver downloads are integrity-protected in transit.