From e614f17a4f16701b593e840894d4c29935c30a2f Mon Sep 17 00:00:00 2001 From: xerox Date: Tue, 9 Jun 2020 04:53:03 +0000 Subject: [PATCH] Add new file --- loadup.hpp | 251 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 loadup.hpp diff --git a/loadup.hpp b/loadup.hpp new file mode 100644 index 0000000..664f284 --- /dev/null +++ b/loadup.hpp @@ -0,0 +1,251 @@ +#pragma once +#include +#include +#include +#include + +#pragma comment(lib, "ntdll.lib") +using nt_load_driver_t = NTSTATUS(__fastcall*)(PUNICODE_STRING); +using nt_unload_driver_t = NTSTATUS(__fastcall*)(PUNICODE_STRING); + +namespace util +{ + inline bool delete_service_entry(const std::string& service_name) + { + HKEY reg_handle; + static const std::string reg_key("System\\CurrentControlSet\\Services\\"); + + auto result = RegOpenKeyA( + HKEY_LOCAL_MACHINE, + reg_key.c_str(), + ®_handle + ); + + RegCloseKey(reg_handle); + return ERROR_SUCCESS == RegDeleteKeyA(reg_handle, service_name.data()); + } + + inline bool create_service_entry(const std::string& drv_path, const std::string& service_name) + { + HKEY reg_handle; + std::string reg_key("System\\CurrentControlSet\\Services\\"); + reg_key += service_name; + + auto result = RegCreateKeyA( + HKEY_LOCAL_MACHINE, + reg_key.c_str(), + ®_handle + ); + + if (result != ERROR_SUCCESS) + return false; + + // + // set type to 1 (kernel) + // + constexpr std::uint8_t type_value = 1; + result = RegSetValueExA( + reg_handle, + "Type", + NULL, + REG_DWORD, + &type_value, + 4u + ); + + if (result != ERROR_SUCCESS) + return false; + + // + // set error control to 3 + // + constexpr std::uint8_t error_control_value = 3; + result = RegSetValueExA( + reg_handle, + "ErrorControl", + NULL, + REG_DWORD, + &error_control_value, + 4u + ); + + if (result != ERROR_SUCCESS) + return false; + + // + // set start to 3 + // + constexpr std::uint8_t start_value = 3; + result = RegSetValueExA( + reg_handle, + "Start", + NULL, + REG_DWORD, + &start_value, + 4u + ); + + if (result != ERROR_SUCCESS) + return false; + + // + // set image path to the driver on disk + // + result = RegSetValueExA( + reg_handle, + "ImagePath", + NULL, + REG_SZ, + (std::uint8_t*) drv_path.c_str(), + drv_path.size() + ); + + if (result != ERROR_SUCCESS) + return false; + + return ERROR_SUCCESS == RegCloseKey(reg_handle); + } + + // this function was coded by paracord: https://githacks.org/snippets/4#L94 + inline bool enable_privilege(const std::wstring& privilege_name) + { + HANDLE token_handle = nullptr; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle)) + return false; + + LUID luid{}; + if (!LookupPrivilegeValueW(nullptr, privilege_name.data(), &luid)) + return false; + + TOKEN_PRIVILEGES token_state{}; + token_state.PrivilegeCount = 1; + token_state.Privileges[0].Luid = luid; + token_state.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(token_handle, FALSE, &token_state, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) + return false; + + CloseHandle(token_handle); + return true; + } + + inline std::string get_service_image_path(const std::string& service_name) + { + HKEY reg_handle; + DWORD bytes_read; + char image_path[0xFF]; + static const std::string reg_key("System\\CurrentControlSet\\Services\\"); + + auto result = RegOpenKeyA( + HKEY_LOCAL_MACHINE, + reg_key.c_str(), + ®_handle + ); + + result = RegGetValueA( + reg_handle, + "ImagePath", + service_name.c_str(), + REG_SZ, NULL, + image_path, + &bytes_read + ); + + RegCloseKey(reg_handle); + return std::string(image_path); + } +} + +namespace driver +{ + inline bool load(const std::string& drv_path, const std::string& service_name) + { + if (!util::enable_privilege(L"SeLoadDriverPrivilege")) + return false; + + if (!util::create_service_entry("\\??\\" + std::filesystem::absolute(std::filesystem::path(drv_path)).string(), service_name)) + return false; + + std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); + reg_path += service_name; + + static const auto lp_nt_load_drv = + ::GetProcAddress( + GetModuleHandleA("ntdll.dll"), + "NtLoadDriver" + ); + + if (lp_nt_load_drv) + { + ANSI_STRING driver_rep_path_cstr; + UNICODE_STRING driver_reg_path_unicode; + + RtlInitAnsiString(&driver_rep_path_cstr, reg_path.c_str()); + RtlAnsiStringToUnicodeString(&driver_reg_path_unicode, &driver_rep_path_cstr, true); + return ERROR_SUCCESS == reinterpret_cast(lp_nt_load_drv)(&driver_reg_path_unicode); + } + return false; + } + + inline std::tuple load(const std::vector& drv_buffer) + { + static const auto random_file_name = [](std::size_t length) -> std::string + { + static const auto randchar = []() -> char + { + const char charset[] = + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + const std::size_t max_index = (sizeof(charset) - 1); + return charset[rand() % max_index]; + }; + std::string str(length, 0); + std::generate_n(str.begin(), length, randchar); + return str; + }; + + const auto service_name = random_file_name(16); + const auto file_path = std::filesystem::temp_directory_path().string() + random_file_name(16); + std::ofstream output_file(file_path.c_str(), std::ios::binary); + + output_file.write((char*)drv_buffer.data(), drv_buffer.size()); + output_file.close(); + + return { load(file_path, service_name), service_name }; + } + + inline std::tuple load(const void* buffer, const std::size_t size) + { + std::vector image((std::uint8_t*)buffer, (std::uint8_t*)buffer + size); + return load(image); + } + + inline bool unload(const std::string& service_name) + { + std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); + reg_path += service_name; + + static const auto lp_nt_unload_drv = + ::GetProcAddress( + GetModuleHandleA("ntdll.dll"), + "NtUnloadDriver" + ); + + if (lp_nt_unload_drv) + { + ANSI_STRING driver_rep_path_cstr; + UNICODE_STRING driver_reg_path_unicode; + + RtlInitAnsiString(&driver_rep_path_cstr, reg_path.c_str()); + RtlAnsiStringToUnicodeString(&driver_reg_path_unicode, &driver_rep_path_cstr, true); + + const bool unload_drv = !reinterpret_cast(lp_nt_unload_drv)(&driver_reg_path_unicode); + const bool delete_drv = std::filesystem::remove(util::get_service_image_path(service_name)); + const bool delete_reg = util::delete_service_entry(service_name); + + return unload_drv && delete_drv && delete_reg; + } + return false; + } +} \ No newline at end of file