Extract into library

This commit is contained in:
Maurice Heumann 2022-12-27 16:27:33 +01:00
parent f8f636a829
commit 28dd94f2ef
31 changed files with 279 additions and 237 deletions

View File

@ -1,3 +1,4 @@
add_subdirectory(shared) add_subdirectory(shared)
add_subdirectory(driver) add_subdirectory(driver)
add_subdirectory(library)
add_subdirectory(runner) add_subdirectory(runner)

View File

@ -37,13 +37,16 @@ target_link_options(driver PRIVATE
"/IGNORE:4210" "/IGNORE:4210"
) )
set_target_properties(driver PROPERTIES OUTPUT_NAME "hyperhook")
################################################ ################################################
set(DRIVER_FILE "$<TARGET_FILE:driver>") set(DRIVER_FILE "$<TARGET_FILE:driver>")
set(DRIVER_NAME "$<TARGET_FILE_NAME:driver>")
file (GENERATE file (GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/driver_file.h" OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<LOWER_CASE:$<CONFIG>>/driver_file.h"
CONTENT "#define DRIVER_FILE \"${DRIVER_FILE}\"\n" CONTENT "#define DRIVER_FILE \"${DRIVER_FILE}\"\n#define DRIVER_NAME \"${DRIVER_NAME}\"\n"
) )
add_library(driver_file INTERFACE) add_library(driver_file INTERFACE)

View File

@ -70,7 +70,10 @@ private:
{ {
if (type == process_callback::type::destroy) if (type == process_callback::type::destroy)
{ {
this->hypervisor_.handle_process_termination(process_id); if (this->hypervisor_.cleanup_process(process_id))
{
debug_log("Handled termination of %X\n", process_id);
}
} }
} }
}; };

View File

@ -635,7 +635,7 @@ namespace vmx
return this->access_records; return this->access_records;
} }
bool ept::handle_process_termination(const process_id process) bool ept::cleanup_process(const process_id process)
{ {
bool changed = false; bool changed = false;

View File

@ -90,7 +90,7 @@ namespace vmx
uint64_t* get_access_records(size_t* count); uint64_t* get_access_records(size_t* count);
bool handle_process_termination(process_id process); bool cleanup_process(process_id process);
private: private:
DECLSPEC_PAGE_ALIGN pml4 epml4[EPT_PML4E_ENTRY_COUNT]; DECLSPEC_PAGE_ALIGN pml4 epml4[EPT_PML4E_ENTRY_COUNT];

View File

@ -261,15 +261,15 @@ hypervisor* hypervisor::get_instance()
return instance; return instance;
} }
void hypervisor::handle_process_termination(const process_id process) bool hypervisor::cleanup_process(const process_id process)
{ {
if (!this->ept_->handle_process_termination(process)) if (!this->ept_->cleanup_process(process))
{ {
return; return false;
} }
debug_log("Handled termination of %X\n", process);
this->invalidate_cores(); this->invalidate_cores();
return true;
} }
void hypervisor::enable() void hypervisor::enable()

View File

@ -33,7 +33,7 @@ public:
static hypervisor* get_instance(); static hypervisor* get_instance();
void handle_process_termination(process_id process); bool cleanup_process(process_id process);
private: private:
uint32_t vm_state_count_{0}; uint32_t vm_state_count_{0};

View File

@ -0,0 +1,23 @@
file(GLOB_RECURSE library_sources CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file(GLOB_RECURSE library_headers CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp)
add_library(library SHARED
${library_sources}
${library_headers}
)
target_precompile_headers(library PRIVATE
std_include.hpp
)
target_link_libraries(library PRIVATE
shared
driver_file
)
set_source_files_properties(resource.rc PROPERTIES LANGUAGE RC)
target_sources(library PRIVATE
resource.rc
)
set_target_properties(library PROPERTIES OUTPUT_NAME "hyperhook")

View File

@ -4,6 +4,7 @@
class driver class driver
{ {
public: public:
driver() = default;
driver(const std::filesystem::path& driver_file, const std::string& service_name); driver(const std::filesystem::path& driver_file, const std::string& service_name);
~driver(); ~driver();

View File

@ -4,6 +4,7 @@
class driver_device class driver_device
{ {
public: public:
driver_device() = default;
driver_device(const std::string& driver_device); driver_device(const std::string& driver_device);
~driver_device() = default; ~driver_device() = default;
@ -13,6 +14,11 @@ public:
driver_device(driver_device&& obj) noexcept = default; driver_device(driver_device&& obj) noexcept = default;
driver_device& operator=(driver_device&& obj) noexcept = default; driver_device& operator=(driver_device&& obj) noexcept = default;
operator bool() const
{
return this->device_;
}
using data = std::vector<uint8_t>; using data = std::vector<uint8_t>;
bool send(DWORD ioctl_code, const data& input) const; bool send(DWORD ioctl_code, const data& input) const;
bool send(DWORD ioctl_code, const data& input, data& output) const; bool send(DWORD ioctl_code, const data& input, data& output) const;

84
src/library/main.cpp Normal file
View File

@ -0,0 +1,84 @@
#include "std_include.hpp"
#include <iostream>
#include <conio.h>
#include <set>
#include "driver.hpp"
#include "driver_device.hpp"
#include <driver_file.h>
#include <irp_data.hpp>
#include "resource.hpp"
#include "utils/io.hpp"
void patch_data(const driver_device& driver_device, const uint32_t pid, const uint64_t address, const uint8_t* buffer,
const size_t length)
{
hook_request hook_request{};
hook_request.process_id = pid;
hook_request.target_address = reinterpret_cast<void*>(address);
hook_request.source_data = buffer;
hook_request.source_data_size = length;
driver_device::data input{};
input.assign(reinterpret_cast<uint8_t*>(&hook_request),
reinterpret_cast<uint8_t*>(&hook_request) + sizeof(hook_request));
(void)driver_device.send(HOOK_DRV_IOCTL, input);
}
driver_device create_driver_device()
{
return driver_device{R"(\\.\HyperHook)"};
}
driver create_driver()
{
return driver{std::filesystem::absolute(DRIVER_NAME), "HyperHook"};
}
driver_device& get_driver_device()
{
static driver hypervisor{};
static driver_device device{};
if (device)
{
return device;
}
try
{
device = create_driver_device();
}
catch (...)
{
hypervisor = create_driver();
device = create_driver_device();
}
return device;
}
extern "C" __declspec(dllexport)
int hyperhook_write(const unsigned int process_id, const unsigned long long address, const void* data,
const unsigned long long size)
{
try
{
const auto& device = get_driver_device();
if (device)
{
patch_data(device, process_id, address, static_cast<const uint8_t*>(data), size);
return 1;
}
}
catch (const std::exception& e)
{
printf("%s\n", e.what());
}
return 0;
}

1
src/library/resource.hpp Normal file
View File

@ -0,0 +1 @@
#pragma once

95
src/library/resource.rc Normal file
View File

@ -0,0 +1,95 @@
// Microsoft Visual C++ generated resource script.
//
#pragma code_page(65001)
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "windows.h"
#include "resource.hpp"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"#include ""windows.h""\r\n"
"\0"
END
2 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE VFT_DLL
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "momo5502"
VALUE "FileDescription", "HyperHook"
VALUE "FileVersion", "1.0.0.0"
VALUE "InternalName", "HyperHook"
VALUE "LegalCopyright", "All rights reserved."
VALUE "OriginalFilename", "hyperhook.dll"
VALUE "ProductName", "hyperhook"
VALUE "ProductVersion", "1.0.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -0,0 +1,14 @@
#pragma once
#include <string>
#include <vector>
#include <mutex>
#include <filesystem>
#include <functional>
#include <Windows.h>
#include <Shlwapi.h>
#include <ShlObj.h>
#include <Psapi.h>
#pragma comment(lib, "Shlwapi.lib")

View File

@ -6,15 +6,14 @@ add_executable(runner #WIN32
${runner_headers} ${runner_headers}
) )
target_precompile_headers(runner target_precompile_headers(runner PRIVATE
PRIVATE std_include.hpp std_include.hpp
) )
set_property(TARGET runner APPEND_STRING PROPERTY LINK_FLAGS " /MANIFESTUAC:\"level='requireAdministrator'\"") set_property(TARGET runner APPEND_STRING PROPERTY LINK_FLAGS " /MANIFESTUAC:\"level='requireAdministrator'\"")
target_link_libraries(runner target_link_libraries(runner PRIVATE
shared library
driver_file
) )
set_source_files_properties(resource.rc PROPERTIES LANGUAGE RC) set_source_files_properties(resource.rc PROPERTIES LANGUAGE RC)

View File

@ -1,110 +1,28 @@
#include "std_include.hpp" #include "std_include.hpp"
#include <iostream> #include <iostream>
#include <filesystem>
#include <conio.h> #include <conio.h>
#include <fstream>
#include <set> #include <set>
#include "driver.hpp"
#include "driver_device.hpp"
#include "process.hpp"
#include <irp_data.hpp>
#include "resource.hpp" #include "resource.hpp"
#include "utils/io.hpp"
#include "utils/nt.hpp"
#pragma comment(lib, "Shlwapi.lib") extern "C" __declspec(dllimport)
int hyperhook_write(unsigned int process_id, unsigned long long address, const void* data,
unsigned long long size);
void patch_data(const driver_device& driver_device, const uint32_t pid, const uint64_t addr, const uint8_t* buffer, bool patch_data(const uint32_t process_id, const uint64_t address, const void* buffer,
const size_t length) const size_t length)
{ {
hook_request hook_request{}; return hyperhook_write(process_id, address, buffer, length) != 0;
hook_request.process_id = pid;
hook_request.target_address = reinterpret_cast<void*>(addr);
hook_request.source_data = buffer;
hook_request.source_data_size = length;
driver_device::data input{};
input.assign(reinterpret_cast<uint8_t*>(&hook_request),
reinterpret_cast<uint8_t*>(&hook_request) + sizeof(hook_request));
(void)driver_device.send(HOOK_DRV_IOCTL, input);
} }
void insert_nop(const driver_device& driver_device, const uint32_t pid, const uint64_t addr, const size_t length) bool insert_nop(const uint32_t process_id, const uint64_t address, const size_t length)
{ {
std::vector<uint8_t> buffer{}; std::vector<uint8_t> buffer{};
buffer.resize(length); buffer.resize(length);
memset(buffer.data(), 0x90, buffer.size()); memset(buffer.data(), 0x90, buffer.size());
patch_data(driver_device, pid, addr, buffer.data(), buffer.size()); return patch_data(process_id, address, buffer.data(), buffer.size());
}
void remove_hooks(const driver_device& driver_device)
{
(void)driver_device.send(UNHOOK_DRV_IOCTL, driver_device::data{});
}
std::vector<uint8_t> load_resource(const int id)
{
auto* const res = FindResource(GetModuleHandleA(nullptr), MAKEINTRESOURCE(id), RT_RCDATA);
if (!res) return {};
auto* const handle = LoadResource(nullptr, res);
if (!handle) return {};
const auto* data_ptr = static_cast<uint8_t*>(LockResource(handle));
const auto data_size = SizeofResource(nullptr, res);
std::vector<uint8_t> data{};
data.assign(data_ptr, data_ptr + data_size);
return data;
}
std::filesystem::path extract_driver()
{
const auto data = load_resource(DRIVER_BINARY);
auto driver_file = std::filesystem::temp_directory_path() / "driver.sys";
std::ofstream out_file{};
out_file.open(driver_file.generic_string(), std::ios::out | std::ios::binary);
out_file.write(reinterpret_cast<const char*>(data.data()), static_cast<std::streamsize>(data.size()));
out_file.close();
return driver_file;
}
std::vector<std::pair<size_t, size_t>> find_executable_regions(const std::string& pe_file)
{
std::string data{};
if (!utils::io::read_file(pe_file, &data))
{
return {};
}
const utils::nt::library library(reinterpret_cast<HMODULE>(data.data()));
if (!library.is_valid())
{
return {};
}
const auto section_headers = library.get_section_headers();
std::vector<std::pair<size_t, size_t>> regions{};
for (const auto& section_header : section_headers)
{
if (section_header->Characteristics & IMAGE_SCN_MEM_EXECUTE)
{
regions.emplace_back(section_header->VirtualAddress, section_header->Misc.VirtualSize);
}
}
return regions;
} }
uint32_t get_process_id() uint32_t get_process_id()
@ -116,152 +34,50 @@ uint32_t get_process_id()
return atoi(pid_str.data()); return atoi(pid_str.data());
} }
void watch_regions(const driver_device& driver_device, const uint32_t pid, const HMODULE module, void activate_patches(const uint32_t pid)
const std::vector<std::pair<size_t, size_t>>& regions)
{ {
std::vector<watch_region> watch_regions{};
watch_regions.reserve(regions.size());
for (const auto& region : regions)
{
watch_region watch_region{};
watch_region.virtual_address = reinterpret_cast<uint8_t*>(module) + region.first;
watch_region.length = region.second;
watch_regions.push_back(watch_region);
}
watch_request request{};
request.process_id = pid;
request.watch_regions = watch_regions.data();
request.watch_region_count = watch_regions.size();
driver_device::data out{};
size_t out_len = 0;
driver_device.send(WATCH_DRV_IOCTL, &request, sizeof(request), out.data(), &out_len);
}
std::vector<uint64_t> query_records(const driver_device& driver_device, const size_t current_size = 0)
{
std::vector<uint64_t> result{};
result.resize(std::max(size_t(1024), current_size * 2));
while (true)
{
char in[1];
constexpr auto element_len = sizeof(decltype(result)::value_type);
const size_t initial_len = result.size() * element_len;
size_t out_len = initial_len;
if (!driver_device.send(GET_RECORDS_DRV_IOCTL, in, 0, result.data(), &out_len))
{
return {};
}
//if (out_len <= initial_len)
if (result.back() == 0)
{
//result.resize(out_len / element_len);
break;
}
//result.resize((out_len / element_len) + 10);
//const auto new_size = result.size() * 2;
result = {};
result.resize(result.size() * 2);
}
// Shrink
size_t i;
for (i = result.size(); i > 0; --i)
{
if (result[i - 1] != 0)
{
break;
}
}
result.resize(i);
return result;
}
void report_records(const std::atomic_bool& flag, const driver_device& driver_device, const uint32_t pid,
const HMODULE target_module, const std::vector<std::pair<size_t, size_t>>& regions)
{
std::set<uint64_t> access_addresses{};
int i = 0;
while (!flag)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
const auto new_records = query_records(driver_device, access_addresses.size());
for (const auto& new_record : new_records)
{
if (access_addresses.emplace(new_record).second)
{
printf("%p\n", reinterpret_cast<void*>(new_record));
}
}
if ((++i) % 5 == 0)
{
watch_regions(driver_device, pid, target_module, regions);
}
}
}
void unsafe_main(const int /*argc*/, char* /*argv*/[])
{
const auto driver_file = extract_driver();
driver driver{driver_file, "HyperHook"};
const driver_device driver_device{R"(\\.\HyperHook)"};
const auto pid = get_process_id();
printf("Opening process...\n");
auto proc = process::open(pid, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ);
if (!proc)
{
printf("Failed to open process...\n");
return;
}
// IW5 // IW5
insert_nop(driver_device, pid, 0x4488A8, 2); // Force calling CG_DrawFriendOrFoeTargetBoxes insert_nop(pid, 0x4488A8, 2); // Force calling CG_DrawFriendOrFoeTargetBoxes
insert_nop(driver_device, pid, 0x47F6C7, 2); // Ignore blind-eye perks insert_nop(pid, 0x47F6C7, 2); // Ignore blind-eye perks
//insert_nop(driver_device, pid, 0x44894C, 2); // Miniconsole //insert_nop(driver_device, pid, 0x44894C, 2); // Miniconsole
// Always full alpha // Always full alpha
constexpr uint8_t data1[] = {0xD9, 0xE8, 0xC3}; constexpr uint8_t data1[] = {0xD9, 0xE8, 0xC3};
patch_data(driver_device, pid, 0x47F0D0, data1, sizeof(data1)); patch_data(pid, 0x47F0D0, data1, sizeof(data1));
// Compass show enemies // Compass show enemies
constexpr uint8_t data2[] = {0xEB, 0x13}; constexpr uint8_t data2[] = {0xEB, 0x13};
patch_data(driver_device, pid, 0x4437A8, data2, sizeof(data2)); patch_data(pid, 0x4437A8, data2, sizeof(data2));
// Enemy arrows // Enemy arrows
constexpr uint8_t data3[] = {0xEB}; constexpr uint8_t data3[] = {0xEB};
patch_data(driver_device, pid, 0x443A2A, data3, sizeof(data3)); patch_data(pid, 0x443A2A, data3, sizeof(data3));
patch_data(driver_device, pid, 0x443978, data3, sizeof(data3)); patch_data(pid, 0x443978, data3, sizeof(data3));
}
printf("Press any key to disable all hooks!\n"); int safe_main(const int /*argc*/, char* /*argv*/[])
(void)_getch(); {
const auto pid = get_process_id();
remove_hooks(driver_device); while (true)
{
activate_patches(pid);
printf("Press any key to exit!\n"); printf("Press any key to exit!\n");
(void)_getch(); if (_getch() != 'r')
{
break;
}
}
return 0;
} }
int main(const int argc, char* argv[]) int main(const int argc, char* argv[])
{ {
try try
{ {
unsafe_main(argc, argv); return safe_main(argc, argv);
return 0;
} }
catch (std::exception& e) catch (std::exception& e)
{ {

View File

@ -1,3 +1 @@
#pragma once #pragma once
#define DRIVER_BINARY 300

View File

@ -9,7 +9,6 @@
// //
#include "windows.h" #include "windows.h"
#include "resource.hpp" #include "resource.hpp"
#include <driver_file.h>
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS #undef APSTUDIO_READONLY_SYMBOLS
@ -63,12 +62,12 @@ BEGIN
BLOCK "040904b0" BLOCK "040904b0"
BEGIN BEGIN
VALUE "CompanyName", "momo5502" VALUE "CompanyName", "momo5502"
VALUE "FileDescription", "Open-IW5" VALUE "FileDescription", "HyperHook Runner"
VALUE "FileVersion", "1.0.0.0" VALUE "FileVersion", "1.0.0.0"
VALUE "InternalName", "Open-IW5" VALUE "InternalName", "HyperHook Runner"
VALUE "LegalCopyright", "All rights reserved." VALUE "LegalCopyright", "All rights reserved."
VALUE "OriginalFilename", "open-iw5.exe" VALUE "OriginalFilename", "hyperhook.exe"
VALUE "ProductName", "open-iw5" VALUE "ProductName", "hyperhook"
VALUE "ProductVersion", "1.0.0.0" VALUE "ProductVersion", "1.0.0.0"
END END
END END
@ -84,7 +83,6 @@ END
// //
102 ICON "resources/icon.ico" 102 ICON "resources/icon.ico"
DRIVER_BINARY RCDATA DRIVER_FILE