- added some of the code I used to reverse engineer this cheat.

master
xerox 4 years ago
parent 1295fb6a8e
commit 875422af0d

@ -1,5 +1,5 @@
<img src="https://imgur.com/InS9ZOY.png"/>
# kdstinker
# unfairgame
Driver dumper for manually mapped drivers mapped with Kdmapper. Kdmapper is used by thousands of cheats to map unsigned code into the kernel. This tool was created to easily intercept and dump to disk manually mapped drivers for analysis.
All modules have been sent to both EAC and BattlEye, I am choosing not to release valorant modules.
<img src="https://imgur.com/OJIaVTI.png"/>

@ -0,0 +1,109 @@
#include "crt.h"
int strcmp(const char* p1, const char* p2)
{
const unsigned char* s1 = (const unsigned char*)p1;
const unsigned char* s2 = (const unsigned char*)p2;
unsigned char c1, c2;
do
{
c1 = (unsigned char)*s1++;
c2 = (unsigned char)*s2++;
if (c1 == '\0')
return c1 - c2;
} while (c1 == c2);
return c1 - c2;
}
size_t strlen(const char* str)
{
const char* char_ptr;
const unsigned long int* longword_ptr;
unsigned long int longword, himagic, lomagic;
/* Handle the first few characters by reading one character at a time.
Do this until CHAR_PTR is aligned on a longword boundary. */
for (char_ptr = str; ((unsigned long int) char_ptr
& (sizeof(longword) - 1)) != 0;
++char_ptr)
if (*char_ptr == '\0')
return char_ptr - str;
/* All these elucidatory comments refer to 4-byte longwords,
but the theory applies equally well to 8-byte longwords. */
longword_ptr = (unsigned long int*) char_ptr;
/* Bits 31, 24, 16, and 8 of this number are zero. Call these bits
the "holes." Note that there is a hole just to the left of
each byte, with an extra at the end:
bits: 01111110 11111110 11111110 11111111
bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
The 1-bits make sure that carries propagate to the next 0-bit.
The 0-bits provide holes for carries to fall into. */
himagic = 0x80808080L;
lomagic = 0x01010101L;
if (sizeof(longword) > 4)
{
/* 64-bit version of the magic. */
/* Do the shift in two steps to avoid a warning if long has 32 bits. */
himagic = ((himagic << 16) << 16) | himagic;
lomagic = ((lomagic << 16) << 16) | lomagic;
}
if (sizeof(longword) > 8)
abort();
/* Instead of the traditional loop which tests each character,
we will test a longword at a time. The tricky part is testing
if *any of the four* bytes in the longword in question are zero. */
for (;;)
{
longword = *longword_ptr++;
if (((longword - lomagic) & ~longword & himagic) != 0)
{
/* Which of the bytes was the zero? If none of them were, it was
a misfire; continue the search. */
const char* cp = (const char*)(longword_ptr - 1);
if (cp[0] == 0)
return cp - str;
if (cp[1] == 0)
return cp - str + 1;
if (cp[2] == 0)
return cp - str + 2;
if (cp[3] == 0)
return cp - str + 3;
if (sizeof(longword) > 4)
{
if (cp[4] == 0)
return cp - str + 4;
if (cp[5] == 0)
return cp - str + 5;
if (cp[6] == 0)
return cp - str + 6;
if (cp[7] == 0)
return cp - str + 7;
}
}
}
}
void* operator new(std::size_t size)
{
return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
}
void operator delete(void* addr, std::size_t size)
{
VirtualFree(addr, size, NULL);
}
size_t wcslen(const wchar_t* s)
{
size_t len = 0;
while (s[len] != L'\0')
{
if (s[++len] == L'\0')
return len;
if (s[++len] == L'\0')
return len;
if (s[++len] == L'\0')
return len;
++len;
}
return len;
}

@ -0,0 +1,10 @@
#pragma once
#include <cstddef>
#include <Windows.h>
int strcmp(const char* p1, const char* p2);
size_t strlen(const char* str);
void* operator new(std::size_t size);
void operator delete(void* addr, std::size_t size);
size_t wcslen(const wchar_t* s);

@ -0,0 +1,44 @@
#include <stdio.h>
#include <Windows.h>
#include "unload.h"
#include "hooks.h"
void __cdecl main_entry(pimage_data process_image_data)
{
LoadLibraryA("user32.dll");
MessageBoxA(NULL, "injected into notepad", "INFO", NULL);
OFSTRUCT data;
hooks::winhttp_log_handle =
reinterpret_cast<HANDLE>(
::OpenFile(
"WinHttp.log",
&data,
OF_CREATE
));
MessageBoxA(NULL, "created logs for WinHttp & Kernel32 functions.", "INFO", NULL);
auto result = hooks::iat_hook(
process_image_data->image_base,
"WinHttpOpen",
&hooks::win_http_open
);
if(result)
MessageBoxA(NULL, "hooked WinHttpOpen.", "INFO", NULL);
else
MessageBoxA(NULL, "failed to hook WinHttpOpen.", "INFO", NULL);
result = hooks::iat_hook(
process_image_data->image_base,
"GetModuleHandleA",
&hooks::get_module_handle
);
if (result)
MessageBoxA(NULL, "hooked GetModuleHandleA.", "INFO", NULL);
else
MessageBoxA(NULL, "failed to hook GetModuleHandleA.", "INFO", NULL);
MessageBoxA(NULL, "hooked WinHttpOpen & Kernel32 functions.", "INFO", NULL);
}

@ -0,0 +1,259 @@
#include "hooks.h"
#include "crt.h"
namespace hooks
{
HINTERNET win_http_open(
LPCWSTR agent,
DWORD access_type,
LPCWSTR proxy,
LPCWSTR proxy_bypass,
DWORD flags
)
{
MessageBoxA(NULL, "WinHttpOpen Called", "INFO", NULL);
DWORD bytes_written;
::WriteFile(
winhttp_log_handle,
L"user-agent: ",
::wcslen(L"user-agent: "),
&bytes_written,
NULL
);
::WriteFile(
winhttp_log_handle,
agent,
::wcslen(agent),
&bytes_written,
NULL
);
::WriteFile(
winhttp_log_handle,
L"\n\n",
::wcslen(L"\n\n"),
&bytes_written,
NULL
);
return reinterpret_cast<decltype(&win_http_open)>(GetProcAddress(LoadLibraryA("Winhttp.dll"), "WinHttpOpen"))
(
agent,
access_type,
proxy,
proxy_bypass,
flags
);
}
HINTERNET win_http_open_req(
IN HINTERNET conn,
IN LPCWSTR verb,
IN LPCWSTR obj_name,
IN LPCWSTR version,
IN LPCWSTR referrer,
IN LPCWSTR* accepted_types,
IN DWORD flags
)
{
MessageBoxA(NULL, "WinHttpOpenRequest Called", "INFO", NULL);
DWORD bytes_written;
::WriteFile(
winhttp_log_handle,
L"downloading: ",
::wcslen(L"downloading: "),
&bytes_written,
NULL
);
::WriteFile(
winhttp_log_handle,
obj_name,
::wcslen(obj_name),
&bytes_written,
NULL
);
::WriteFile(
winhttp_log_handle,
L"\n\n",
::wcslen(L"\n\n"),
&bytes_written,
NULL
);
return reinterpret_cast<decltype(&win_http_open_req)>(GetProcAddress(LoadLibraryA("winhttp.dll"), "WinHttpOpenRequest"))
(
conn,
verb,
obj_name,
version,
referrer,
accepted_types,
flags
);
}
HINTERNET win_http_connect(
IN HINTERNET session,
IN LPCWSTR server_name,
IN INTERNET_PORT server_port,
IN DWORD reserve
)
{
MessageBoxA(NULL, "WinHttpConnect Called", "INFO", NULL);
DWORD bytes_written;
::WriteFile(
winhttp_log_handle,
L"connecting: ",
::wcslen(L"connecting: "),
&bytes_written,
NULL
);
::WriteFile(
winhttp_log_handle,
server_name,
::wcslen(server_name),
&bytes_written,
NULL
);
::WriteFile(
winhttp_log_handle,
L"\n\n",
::wcslen(L"\n\n"),
&bytes_written,
NULL
);
return reinterpret_cast<decltype(&win_http_connect)>(GetProcAddress(LoadLibraryA("winhttp.dll"), "WinHttpConnect"))
(session, server_name, server_port, reserve);
}
HMODULE get_module_handle(
LPCSTR module_name
)
{
MessageBoxA(NULL, module_name, "Getting module handle of this module", NULL);
DWORD bytes_written;
::WriteFile(
winhttp_log_handle,
L"getting module: ",
::wcslen(L"getting module: "),
&bytes_written,
NULL
);
::WriteFile(
winhttp_log_handle,
module_name,
::strlen(module_name),
&bytes_written,
NULL
);
::WriteFile(
winhttp_log_handle,
L"\n\n",
::wcslen(L"\n\n"),
&bytes_written,
NULL
);
return GetModuleHandleA(module_name);
}
FARPROC get_proc_addr(
HMODULE module_handle,
LPCSTR proc_name
)
{
MessageBoxA(NULL, proc_name, "Getting address of this proc", NULL);
DWORD bytes_written;
::WriteFile(
winhttp_log_handle,
L"getting proc name: ",
::wcslen(L"getting proc name: "),
&bytes_written,
NULL
);
::WriteFile(
winhttp_log_handle,
proc_name,
::strlen(proc_name),
&bytes_written,
NULL
);
::WriteFile(
winhttp_log_handle,
L"\n\n",
::wcslen(L"\n\n"),
&bytes_written,
NULL
);
return GetProcAddress(module_handle, proc_name);
}
void* iat_hook(void* base_addr, const char* import, void* func_addr)
{
if (!base_addr || *(short*)base_addr != 0x5A4D || !import || !func_addr)
return NULL;
PIMAGE_DOS_HEADER dos_headers =
reinterpret_cast<PIMAGE_DOS_HEADER>(base_addr);
PIMAGE_NT_HEADERS nt_headers =
reinterpret_cast<PIMAGE_NT_HEADERS>(
reinterpret_cast<DWORD_PTR>(base_addr) + dos_headers->e_lfanew);
IMAGE_DATA_DIRECTORY import_dir =
nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
PIMAGE_IMPORT_DESCRIPTOR import_des =
reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(import_dir.VirtualAddress + (DWORD_PTR)base_addr);
LPCSTR lib_name = NULL;
PVOID result = NULL;
PIMAGE_IMPORT_BY_NAME func_name = NULL;
if (!import_des)
return NULL;
while (import_des->Name != NULL)
{
lib_name = (LPCSTR)import_des->Name + (DWORD_PTR)base_addr;
if (GetModuleHandleA(lib_name))
{
PIMAGE_THUNK_DATA org_first_thunk = NULL, first_thunk = NULL;
org_first_thunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)base_addr + import_des->OriginalFirstThunk);
first_thunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)base_addr + import_des->FirstThunk);
while (org_first_thunk->u1.AddressOfData != NULL)
{
func_name = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)base_addr + org_first_thunk->u1.AddressOfData);
if (strcmp(func_name->Name, import) == 0)
{
// save old function pointer
result = reinterpret_cast<PVOID>(first_thunk->u1.Function);
DWORD old_protect;
VirtualProtect(&first_thunk->u1.Function, 8, PAGE_READWRITE, &old_protect);
// swap address
first_thunk->u1.Function = reinterpret_cast<ULONG64>(func_addr);
VirtualProtect(&first_thunk->u1.Function, 8, old_protect, &old_protect);
return result;
}
++org_first_thunk;
++first_thunk;
}
}
++import_des;
}
return NULL;
}
}

@ -0,0 +1,48 @@
#pragma once
#include <Windows.h>
#include <winhttp.h>
#include "crt.h"
namespace hooks
{
inline HANDLE winhttp_log_handle = NULL;
HINTERNET win_http_open(
LPCWSTR agent,
DWORD access_type,
LPCWSTR proxy,
LPCWSTR proxy_bypass,
DWORD flags
);
HMODULE get_module_handle(
LPCSTR module_name
);
FARPROC get_proc_addr(
HMODULE module_handle,
LPCSTR proc_name
);
HINTERNET win_http_open_req(
IN HINTERNET conn,
IN LPCWSTR verb,
IN LPCWSTR obj_name,
IN LPCWSTR version,
IN LPCWSTR referrer,
IN LPCWSTR* accepted_types,
IN DWORD flags
);
HINTERNET win_http_connect(
IN HINTERNET session,
IN LPCWSTR server_name,
IN INTERNET_PORT server_port,
IN DWORD reserve
);
void* iat_hook(
void* base_addr,
const char* import,
void* func_addr
);
}

@ -0,0 +1,181 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{2630aa4f-ea72-46f3-9292-6a528b768190}</ProjectGuid>
<RootNamespace>unfairgamedll</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>ClangCL</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;UNFAIRGAMEDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;UNFAIRGAMEDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;UNFAIRGAMEDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>false</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;UNFAIRGAMEDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<StringPooling>false</StringPooling>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<EntryPointSymbol>main_entry</EntryPointSymbol>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<AdditionalDependencies>vcruntime.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="crt.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="hooks.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="crt.h" />
<ClInclude Include="hooks.h" />
<ClInclude Include="unload.h" />
</ItemGroup>
<ItemGroup>
<MASM Include="unload.asm">
<FileType>Document</FileType>
</MASM>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
</ImportGroup>
</Project>

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{6095107d-70f1-45aa-b687-05264fcdd9a2}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hooks.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="crt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="unload.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="hooks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="crt.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<MASM Include="unload.asm">
<Filter>Source Files</Filter>
</MASM>
</ItemGroup>
</Project>

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

@ -0,0 +1,8 @@
.code
; void unload_and_free(void* base, std::size_t size, void* zero_memory, void* return_addr);
unload_and_free proc
push r9 ; return to whatever was calling the function that called this routine.
jmp r8 ; address of zero memory
unload_and_free endp
public unload_and_free
end

@ -0,0 +1,14 @@
#pragma once
#include <Windows.h>
#include <cstddef>
#include <intrin.h>
extern "C" void unload_and_free(void* base, std::size_t size, void* zero_memory, void* return_addr);
#define ZERO_DLL(image_base, image_size) \
unload_and_free(image_base, image_size, GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlZeroMemory"), _ReturnAddress());
typedef struct _image_data
{
void* image_base;
std::size_t image_size;
}image_data, * pimage_data;

@ -0,0 +1,59 @@
#include <iostream>
#include <Windows.h>
#include "nozzle.hpp"
int __cdecl main(int argc, char** argv)
{
if (argc < 3)
{
std::cerr << "[!] please specify a executable path and a dll path" << std::endl;
return -1;
}
SECURITY_ATTRIBUTES sec_attr{};
STARTUPINFOA start_info{};
PROCESS_INFORMATION process_info;
auto result = CreateProcessA(
argv[1],
NULL,
&sec_attr,
&sec_attr,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&start_info,
&process_info
);
if (!result)
return -1;
Sleep(1000);
SuspendThread(process_info.hThread);
std::cout << "[+] started new process, pid: " << process_info.dwProcessId << std::endl;
std::cout << "[+] injecting into: " << process_info.dwProcessId << std::endl;
nozzle::injector injector(argv[2], process_info.dwProcessId);
const auto base_addr =
util::get_module_base(
process_info.dwProcessId,
"loader.exe"
);
std::cout << "[+] base address of loader: " << base_addr << std::endl;
std::cin.get();
//
// inject into suspended process and run entry.
//
std::cout << "[+] injected into: " << injector.inject() << std::endl;
std::cout << "[+] thread handle: " << injector.call_entry(base_addr) << std::endl;
//
// resume process.
//
ResumeThread(process_info.hThread);
std::cin.get();
}

@ -0,0 +1,563 @@
/*
MIT License
Copyright (c) 2020 xerox
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <Windows.h>
#include <cstdint>
#include <string>
#include <vector>
#include <fstream>
#include <filesystem>
#include <Psapi.h>
#include <cassert>
#include <DbgHelp.h>
#include <functional>
#include <locale>
#include <codecvt>
#include <string>
#include <TlHelp32.h>
#pragma comment(lib, "Dbghelp.lib")
#define FIND_NT_HEADER(x) reinterpret_cast<PIMAGE_NT_HEADERS>( uint64_t(x) + reinterpret_cast<PIMAGE_DOS_HEADER>(x)->e_lfanew )
#define RET_CHK(x)\
if (!x)\
{\
LOG_LAST_ERROR();\
return false;\
}\
//
// coded by paracord.
// see: https://github.com/haram/splendid_implanter/blob/master/splendid_implanter/win_utils.hpp
//
namespace util
{
using uq_handle = std::unique_ptr<void, decltype(&CloseHandle)>;
inline void open_binary_file(const std::string& file, std::vector<uint8_t>& data)
{
std::ifstream fstr(file, std::ios::binary);
fstr.unsetf(std::ios::skipws);
fstr.seekg(0, std::ios::end);
const auto file_size = fstr.tellg();
fstr.seekg(NULL, std::ios::beg);
data.reserve(static_cast<uint32_t>(file_size));
data.insert(data.begin(), std::istream_iterator<uint8_t>(fstr), std::istream_iterator<uint8_t>());
}
inline void* get_module_base(DWORD pid, const char* module_name)
{
HANDLE h_snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
DWORD mod_base = 0;
if (h_snap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 mod_entry = { 0 };
mod_entry.dwSize = sizeof(MODULEENTRY32);
if (Module32First(h_snap, &mod_entry))
do
if (strcmp(mod_entry.szModule, module_name) == 0)
{
CloseHandle(h_snap);
return mod_entry.modBaseAddr;
}
while (Module32Next(h_snap, &mod_entry));
}
return nullptr;
}
inline std::uint32_t get_pid(const std::string_view proc_name)
{
PROCESSENTRY32 proc_info = { sizeof(PROCESSENTRY32) };
proc_info.dwSize = sizeof(proc_info);
auto snapshot = std::unique_ptr < std::remove_pointer_t<HANDLE>,
decltype(&::CloseHandle) >(
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL), &::CloseHandle);
if (snapshot.get() == INVALID_HANDLE_VALUE)
return NULL;
do
if (!strcmp(proc_info.szExeFile, proc_name.data()))
return proc_info.th32ProcessID;
while (Process32Next(snapshot.get(), &proc_info));
return NULL;
}
inline std::pair<void*, std::wstring> get_module_data(HANDLE process_handle, const std::wstring_view module_name)
{
auto loaded_modules = std::make_unique<HMODULE[]>(64);
DWORD loaded_module_sz = 0;
// enumerate all modules by handle, using size of 512 since the required size is in bytes, and an HMODULE is 8 bytes large.
if (!EnumProcessModules(process_handle, loaded_modules.get(), 512, &loaded_module_sz))
return {};
for (auto i = 0u; i < loaded_module_sz / 8u; i++)
{
wchar_t file_name[MAX_PATH] = L"";
// get the full working path for the current module
if (!GetModuleFileNameExW(process_handle, loaded_modules.get()[i], file_name, _countof(file_name)))
continue;
// module name returned will be a full path, check only for file name sub string.
if (std::wcsstr(file_name, module_name.data()) != nullptr)
return { loaded_modules.get()[i], file_name };
}
return {};
}
inline std::vector<uint8_t> get_file_data(const HANDLE file_handle, const std::wstring_view file_path)
{
const auto file_size = std::filesystem::file_size(file_path);
std::vector<uint8_t> file_bytes{};
file_bytes.resize(file_size);
DWORD bytes_read = 0;
if (!ReadFile(file_handle, file_bytes.data(), static_cast<DWORD>(file_size), &bytes_read, nullptr))
return {};
return file_bytes;
}
inline bool enable_privilege(const std::wstring_view 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;
}
}
namespace nozzle
{
//
// class programmed by wlan
// link: https://github.com/not-wlan/drvmap/blob/master/drvmap/drv_image.hpp
//
class pe_image
{
std::vector<uint8_t> m_image;
std::vector<uint8_t> m_image_mapped;
PIMAGE_DOS_HEADER m_dos_header = nullptr;
PIMAGE_NT_HEADERS64 m_nt_headers = nullptr;
PIMAGE_SECTION_HEADER m_section_header = nullptr;
public:
pe_image() {};
pe_image(std::uint8_t* image, std::size_t size);
pe_image(std::vector<uint8_t> image);
size_t size() const;
uintptr_t entry_point() const;
void map();
static bool process_relocation(size_t image_base_delta, uint16_t data, uint8_t* relocation_base);
void relocate(uintptr_t base) const;
template<typename T>
__forceinline T* get_rva(const unsigned long offset)
{
return (T*)::ImageRvaToVa(m_nt_headers, m_image.data(), offset, nullptr);
}
void fix_imports(const std::function<uintptr_t(std::string_view)> get_module, const std::function<uintptr_t(uintptr_t, const char*)> get_function);
void* data();
size_t header_size();
};
pe_image::pe_image(std::uint8_t* image, std::size_t size)
{
m_image = std::vector<std::uint8_t>(image, image + size);
m_dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(image);
m_nt_headers = reinterpret_cast<PIMAGE_NT_HEADERS64>((uintptr_t)m_dos_header + m_dos_header->e_lfanew);
m_section_header = reinterpret_cast<IMAGE_SECTION_HEADER*>((uintptr_t)(&m_nt_headers->OptionalHeader) + m_nt_headers->FileHeader.SizeOfOptionalHeader);
}
pe_image::pe_image(std::vector<uint8_t> image)
: m_image(std::move(image))
{
m_dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(m_image.data());
m_nt_headers = reinterpret_cast<PIMAGE_NT_HEADERS64>((uintptr_t)m_dos_header + m_dos_header->e_lfanew);
m_section_header = reinterpret_cast<IMAGE_SECTION_HEADER*>((uintptr_t)(&m_nt_headers->OptionalHeader) + m_nt_headers->FileHeader.SizeOfOptionalHeader);
}
size_t pe_image::size() const
{
return m_nt_headers->OptionalHeader.SizeOfImage;
}
uintptr_t pe_image::entry_point() const
{
return m_nt_headers->OptionalHeader.AddressOfEntryPoint;
}
void pe_image::map()
{
m_image_mapped.clear();
m_image_mapped.resize(m_nt_headers->OptionalHeader.SizeOfImage);
std::copy_n(m_image.begin(), m_nt_headers->OptionalHeader.SizeOfHeaders, m_image_mapped.begin());
for (size_t i = 0; i < m_nt_headers->FileHeader.NumberOfSections; ++i)
{
const auto& section = m_section_header[i];
const auto target = (uintptr_t)m_image_mapped.data() + section.VirtualAddress;
const auto source = (uintptr_t)m_dos_header + section.PointerToRawData;
std::copy_n(m_image.begin() + section.PointerToRawData, section.SizeOfRawData, m_image_mapped.begin() + section.VirtualAddress);
}
}
bool pe_image::process_relocation(uintptr_t image_base_delta, uint16_t data, uint8_t* relocation_base)
{
#define IMR_RELOFFSET(x) (x & 0xFFF)
switch (data >> 12 & 0xF)
{
case IMAGE_REL_BASED_HIGH:
{
const auto raw_address = reinterpret_cast<int16_t*>(relocation_base + IMR_RELOFFSET(data));
*raw_address += static_cast<unsigned long>(HIWORD(image_base_delta));
break;
}
case IMAGE_REL_BASED_LOW:
{
const auto raw_address = reinterpret_cast<int16_t*>(relocation_base + IMR_RELOFFSET(data));
*raw_address += static_cast<unsigned long>(LOWORD(image_base_delta));
break;
}
case IMAGE_REL_BASED_HIGHLOW:
{
const auto raw_address = reinterpret_cast<size_t*>(relocation_base + IMR_RELOFFSET(data));
*raw_address += static_cast<size_t>(image_base_delta);
break;
}
case IMAGE_REL_BASED_DIR64:
{
auto UNALIGNED raw_address = reinterpret_cast<DWORD_PTR UNALIGNED*>(relocation_base + IMR_RELOFFSET(data));
*raw_address += image_base_delta;
break;
}
case IMAGE_REL_BASED_ABSOLUTE: // No action required
case IMAGE_REL_BASED_HIGHADJ: // no action required
{
break;
}
default:
{
throw std::runtime_error("gay relocation!");
return false;
}
}
#undef IMR_RELOFFSET
return true;
}
void pe_image::relocate(uintptr_t base) const
{
if (m_nt_headers->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
return;
ULONG total_count_bytes;
const auto nt_headers = ImageNtHeader((void*)m_image_mapped.data());
auto relocation_directory = (PIMAGE_BASE_RELOCATION)::ImageDirectoryEntryToData(nt_headers, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &total_count_bytes);
auto image_base_delta = static_cast<uintptr_t>(static_cast<uintptr_t>(base) - (nt_headers->OptionalHeader.ImageBase));
auto relocation_size = total_count_bytes;
void* relocation_end = reinterpret_cast<uint8_t*>(relocation_directory) + relocation_size;
while (relocation_directory < relocation_end)
{
auto relocation_base = ::ImageRvaToVa(nt_headers, (void*)m_image_mapped.data(), relocation_directory->VirtualAddress, nullptr);
auto num_relocs = (relocation_directory->SizeOfBlock - 8) >> 1;
auto relocation_data = reinterpret_cast<PWORD>(relocation_directory + 1);
for (unsigned long i = 0; i < num_relocs; ++i, ++relocation_data)
{
if (process_relocation(image_base_delta, *relocation_data, (uint8_t*)relocation_base) == FALSE)
return;
}
relocation_directory = reinterpret_cast<PIMAGE_BASE_RELOCATION>(relocation_data);
}
}
template<typename T>
__forceinline T* ptr_add(void* base, uintptr_t offset)
{
return (T*)(uintptr_t)base + offset;
}
void pe_image::fix_imports(const std::function<std::uintptr_t(std::string_view)> get_module, const std::function<uintptr_t(uintptr_t, const char*)> get_function)
{
ULONG size;
auto import_descriptors = static_cast<PIMAGE_IMPORT_DESCRIPTOR>(::ImageDirectoryEntryToData(m_image.data(), FALSE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size));
if (!import_descriptors)
return;
for (; import_descriptors->Name; import_descriptors++)
{
IMAGE_THUNK_DATA* image_thunk_data;
const auto module_name = get_rva<char>(import_descriptors->Name);
const auto module_base = get_module(module_name);
if (import_descriptors->OriginalFirstThunk)
image_thunk_data = get_rva<IMAGE_THUNK_DATA>(import_descriptors->OriginalFirstThunk);
else
image_thunk_data = get_rva<IMAGE_THUNK_DATA>(import_descriptors->FirstThunk);
auto image_func_data = get_rva<IMAGE_THUNK_DATA64>(import_descriptors->FirstThunk);
for (; image_thunk_data->u1.AddressOfData; image_thunk_data++, image_func_data++)
{
uintptr_t function_address;
const auto image_import_by_name = get_rva<IMAGE_IMPORT_BY_NAME>(*(DWORD*)image_thunk_data);
const auto name_of_import = static_cast<char*>(image_import_by_name->Name);
function_address = get_function(module_base, name_of_import);
image_func_data->u1.Function = function_address;
}
}
}
void* pe_image::data()
{
return m_image_mapped.data();
}
size_t pe_image::header_size()
{
return m_nt_headers->OptionalHeader.SizeOfHeaders;
}
class injector
{
public:
injector()
{};
injector(void* pe_image, std::size_t size, unsigned pid);
injector(std::vector<std::uint8_t> image_buffer, unsigned pid);
injector(char* path, unsigned pid);
void* inject();
HANDLE call_entry(void* process_base);
void set_target(unsigned pid);
void set_target(std::string proc_name);
void* get_pe_image() const;
void* get_allocated_base() const;
unsigned get_target() const;
private:
pe_image image;
unsigned target_pid;
std::vector<std::uint8_t> image_buffer;
HANDLE target_handle;
void* alloc_base;
void write(void* addr, void* buffer, std::size_t size);
void read(void* addr, void* buffer, std::size_t size);
template <class T>
T read(void* addr)
{
if (!addr)
return {};
T buffer;
read(addr, &buffer, sizeof(T));
return buffer;
}
template <class T>
void write(void* addr, const T& data)
{
if (!addr)
return;
write(addr, (void*)&data, sizeof(T));
}
};
injector::injector(void* pe_image, std::size_t size, unsigned pid)
:
target_pid(pid),
target_handle(::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid))
{}
injector::injector(char* path, unsigned pid)
:
target_pid(pid),
target_handle(::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid))
{
std::vector<std::uint8_t> image_buffer;
util::open_binary_file(path, image_buffer);
this->image_buffer = image_buffer;
}
injector::injector(std::vector<std::uint8_t> image_buffer, unsigned pid)
:
image_buffer(image_buffer),
target_pid(pid),
target_handle(::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid))
{}
void* injector::inject()
{
image = pe_image(image_buffer);
//
// only resolves globally mapped dll imports.
//
static const auto _get_module = [](std::string_view module_name) -> std::uintptr_t
{
return reinterpret_cast<std::uintptr_t>(LoadLibraryA(module_name.data()));
};
//
// only resolves ntdll.dll, kernel32.dll, and user32.dll imports
//
static const auto _get_function = [](std::uintptr_t module_base, const char* module_name) -> std::uintptr_t
{
return reinterpret_cast<std::uintptr_t>(GetProcAddress(reinterpret_cast<HMODULE>(module_base), module_name));
};
alloc_base = VirtualAllocEx(
target_handle,
NULL,
image.size(),
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
if (!alloc_base)
return NULL;
image.fix_imports(_get_module, _get_function);
image.map();
image.relocate(reinterpret_cast<std::uintptr_t>(alloc_base));
write(alloc_base, image.data(), image.size());
return alloc_base;
}
//
// modified to pass the base address of the process instead of the base address of the newly allocated module.
//
HANDLE injector::call_entry(void* process_base)
{
//
// create thread to call entry point.
//
SECURITY_ATTRIBUTES sec_attr{};
DWORD tid;
struct image_data
{
void* image_base;
std::size_t image_size;
};
const image_data this_image_data{ process_base, NULL };
const auto remote_param =
VirtualAllocEx(
target_handle,
NULL,
sizeof(image_data),
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE
);
write<image_data>(remote_param, this_image_data);
return CreateRemoteThread(
target_handle,
&sec_attr,
NULL,
(LPTHREAD_START_ROUTINE)(reinterpret_cast<std::uintptr_t>(alloc_base) + image.entry_point()),
remote_param,
NULL,
&tid
);
}
void* injector::get_allocated_base() const
{
return alloc_base;
}
void injector::set_target(unsigned pid)
{
target_pid = pid;
}
void injector::set_target(std::string proc_name)
{
target_pid = util::get_pid(proc_name);
}
void* injector::get_pe_image() const
{
return (void*)image_buffer.data();
}
unsigned injector::get_target() const
{
return target_pid;
}
void injector::write(void* addr, void* buffer, std::size_t size)
{
SIZE_T bytes_written;
::WriteProcessMemory(
target_handle,
addr,
buffer,
size,
&bytes_written
);
}
void injector::read(void* addr, void* buffer, std::size_t size)
{
SIZE_T bytes_read;
::ReadProcessMemory(
target_handle,
addr,
buffer,
size,
&bytes_read
);
}
}

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{5db9a6a4-6864-48cc-a649-3823d4df7265}</ProjectGuid>
<RootNamespace>unfairgameinjector</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="nozzle.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="nozzle.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

@ -0,0 +1,12 @@
#include <iostream>
#include <filesystem>
#include "shithook.hpp"
int __cdecl main(int argc, char** argv)
{
if (argc < 2)
{
std::cerr << "[!] please specify a windows executable" << std::endl;
return -1;
}
}

@ -0,0 +1,170 @@
/*
MIT License
Copyright (c) 2020 xerox
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <Windows.h>
#include <map>
#include <atomic>
#include <memory>
#if _M_IX86
#define OFFSET_TO_ADDRESS 0x1
#elif _M_X64
#define OFFSET_TO_ADDRESS 0x2
#endif
namespace hook
{
inline void write_to_readonly(void* addr, void* data, int size)
{
DWORD old_flags;
if (!VirtualProtect(
addr,
size,
PAGE_EXECUTE_READWRITE,
&old_flags
)) return;
memcpy(addr, data, size);
VirtualProtect(
addr,
size,
old_flags,
&old_flags
);
}
class detour
{
public:
detour(void* addr_to_hook, void* jmp_to, bool enable = true)
: hook_addr(addr_to_hook), detour_addr(jmp_to), hook_installed(false)
{
//setup hook
memcpy(
jmp_code + OFFSET_TO_ADDRESS,
&jmp_to,
sizeof(jmp_to)
);
//save bytes
memcpy(
org_bytes,
hook_addr,
sizeof(org_bytes)
);
if (enable)
install();
}
void install()
{
if (hook_installed.load())
return;
write_to_readonly(hook_addr, jmp_code, sizeof(jmp_code));
hook_installed.exchange(true);
}
void uninstall()
{
if (!hook_installed.load())
return;
write_to_readonly(hook_addr, org_bytes, sizeof(org_bytes));
hook_installed.exchange(false);
}
~detour() { uninstall(); }
bool installed() { return hook_installed; }
void* hook_address() { return hook_addr; }
void* detour_address() { return detour_addr; }
private:
std::atomic<bool> hook_installed;
void* hook_addr, * detour_addr;
#if _M_IX86
/*
0: b8 ff ff ff ff mov eax, 0xffffffff
5: ff e0 jmp eax
*/
unsigned char jmp_code[7] = {
0xb8, 0x0, 0x0, 0x0, 0x0,
0xFF, 0xE0
};
#elif _M_X64
/*
0: 48 c7 c0 ff ff ff ff mov rax,0xffffffffffffffff
7: ff e0 jmp rax
*/
unsigned char jmp_code[12] = {
0x48, 0xb8,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0xff, 0xe0
};
#endif
std::uint8_t org_bytes[sizeof(jmp_code)];
};
inline std::map<void*, std::unique_ptr<detour>> hooks{};
inline void make_hook(void* addr_to_hook, void* jmp_to_addr, bool enable = true)
{
if (!addr_to_hook)
return;
hooks.insert({
addr_to_hook,
std::make_unique<detour>(
addr_to_hook,
jmp_to_addr,
enable
) }
);
}
inline void enable(void* addr)
{
if (!addr)
return;
hooks.at(addr)->install();
}
inline void disable(void* addr)
{
if (!addr)
return;
hooks.at(addr)->uninstall();
}
inline void remove(void* addr)
{
if (!addr)
return;
hooks.erase(addr);
}
}

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{34f7e5b5-a062-4be8-a446-0081ad7f34c0}</ProjectGuid>
<RootNamespace>unfairgameloader</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="shithook.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="shithook.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

@ -0,0 +1,79 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30011.22
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unfairgame", "unfairgame\unfairgame.vcxproj", "{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unfairgame-injector", "unfairgame-injector\unfairgame-injector.vcxproj", "{5DB9A6A4-6864-48CC-A649-3823D4DF7265}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unfairgame-dll", "unfairgame-dll\unfairgame-dll.vcxproj", "{2630AA4F-EA72-46F3-9292-6A528B768190}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|ARM = Release|ARM
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Debug|ARM.ActiveCfg = Debug|ARM
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Debug|ARM.Build.0 = Debug|ARM
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Debug|ARM.Deploy.0 = Debug|ARM
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Debug|ARM64.ActiveCfg = Debug|ARM64
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Debug|ARM64.Build.0 = Debug|ARM64
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Debug|ARM64.Deploy.0 = Debug|ARM64
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Debug|x64.ActiveCfg = Debug|x64
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Debug|x64.Build.0 = Debug|x64
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Debug|x64.Deploy.0 = Debug|x64
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Debug|x86.ActiveCfg = Debug|Win32
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Debug|x86.Build.0 = Debug|Win32
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Debug|x86.Deploy.0 = Debug|Win32
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Release|ARM.ActiveCfg = Release|ARM
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Release|ARM.Build.0 = Release|ARM
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Release|ARM.Deploy.0 = Release|ARM
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Release|ARM64.ActiveCfg = Release|ARM64
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Release|ARM64.Build.0 = Release|ARM64
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Release|ARM64.Deploy.0 = Release|ARM64
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Release|x64.ActiveCfg = Release|x64
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Release|x64.Build.0 = Release|x64
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Release|x64.Deploy.0 = Release|x64
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Release|x86.ActiveCfg = Release|Win32
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Release|x86.Build.0 = Release|Win32
{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}.Release|x86.Deploy.0 = Release|Win32
{5DB9A6A4-6864-48CC-A649-3823D4DF7265}.Debug|ARM.ActiveCfg = Debug|Win32
{5DB9A6A4-6864-48CC-A649-3823D4DF7265}.Debug|ARM64.ActiveCfg = Debug|Win32
{5DB9A6A4-6864-48CC-A649-3823D4DF7265}.Debug|x64.ActiveCfg = Debug|x64
{5DB9A6A4-6864-48CC-A649-3823D4DF7265}.Debug|x64.Build.0 = Debug|x64
{5DB9A6A4-6864-48CC-A649-3823D4DF7265}.Debug|x86.ActiveCfg = Debug|Win32
{5DB9A6A4-6864-48CC-A649-3823D4DF7265}.Debug|x86.Build.0 = Debug|Win32
{5DB9A6A4-6864-48CC-A649-3823D4DF7265}.Release|ARM.ActiveCfg = Release|Win32
{5DB9A6A4-6864-48CC-A649-3823D4DF7265}.Release|ARM64.ActiveCfg = Release|Win32
{5DB9A6A4-6864-48CC-A649-3823D4DF7265}.Release|x64.ActiveCfg = Release|x64
{5DB9A6A4-6864-48CC-A649-3823D4DF7265}.Release|x64.Build.0 = Release|x64
{5DB9A6A4-6864-48CC-A649-3823D4DF7265}.Release|x86.ActiveCfg = Release|Win32
{5DB9A6A4-6864-48CC-A649-3823D4DF7265}.Release|x86.Build.0 = Release|Win32
{2630AA4F-EA72-46F3-9292-6A528B768190}.Debug|ARM.ActiveCfg = Debug|Win32
{2630AA4F-EA72-46F3-9292-6A528B768190}.Debug|ARM64.ActiveCfg = Debug|Win32
{2630AA4F-EA72-46F3-9292-6A528B768190}.Debug|x64.ActiveCfg = Debug|x64
{2630AA4F-EA72-46F3-9292-6A528B768190}.Debug|x64.Build.0 = Debug|x64
{2630AA4F-EA72-46F3-9292-6A528B768190}.Debug|x86.ActiveCfg = Debug|Win32
{2630AA4F-EA72-46F3-9292-6A528B768190}.Debug|x86.Build.0 = Debug|Win32
{2630AA4F-EA72-46F3-9292-6A528B768190}.Release|ARM.ActiveCfg = Release|Win32
{2630AA4F-EA72-46F3-9292-6A528B768190}.Release|ARM64.ActiveCfg = Release|Win32
{2630AA4F-EA72-46F3-9292-6A528B768190}.Release|x64.ActiveCfg = Release|x64
{2630AA4F-EA72-46F3-9292-6A528B768190}.Release|x64.Build.0 = Release|x64
{2630AA4F-EA72-46F3-9292-6A528B768190}.Release|x86.ActiveCfg = Release|Win32
{2630AA4F-EA72-46F3-9292-6A528B768190}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7DEC848B-E4D5-4C7F-A4B8-55379682BBDE}
EndGlobalSection
EndGlobal

@ -0,0 +1,32 @@
#include "callback.h"
namespace callback
{
void on_image_load(
PUNICODE_STRING image_path,
HANDLE pid,
PIMAGE_INFO image_info
)
{
if (!pid)
{
DBG_PRINT("base address: 0x%p", image_info->ImageBase);
DBG_PRINT("driver loaded from: %ws", image_path->Buffer);
DBG_PRINT(" - driver timestamp: 0x%p", driver_util::get_file_header(image_info->ImageBase)->TimeDateStamp);
//
// driver gets deleted after loading
//
driver_util::copy_driver(image_path);
if (driver_util::get_file_header(image_info->ImageBase)->TimeDateStamp == UNFAIR_TIMESTAMP)
{
DBG_PRINT("unfair driver loaded...");
detour get_proc_hook(
(void*)(((char*)image_info->ImageBase) + UNFAIR_GETPROC_ADDR_OFFSET),
&hooks::get_addr_hook
);
DBG_PRINT("hooked get proc address....");
}
}
}
}

@ -0,0 +1,14 @@
#pragma once
#include "types.h"
#include "driver_util.h"
#include "hooks.h"
#include "detour.hpp"
namespace callback
{
void on_image_load(
PUNICODE_STRING image_path,
HANDLE pid,
PIMAGE_INFO image_info
);
}

@ -0,0 +1,117 @@
#pragma once
#include "types.h"
#if _M_IX86
#define OFFSET_TO_ADDRESS 0x1
#elif _M_X64
#define OFFSET_TO_ADDRESS 0x2
#endif
inline void write_to_readonly(void* addr, void* data, int size)
{
if(!addr || !data || !size)
return;
{
//
// disable write protection.
//
auto cr0 = __readcr0();
cr0 &= 0xfffffffffffeffff;
__writecr0(cr0);
_disable();
}
memcpy(addr, data, size);
{
//
// enable write protection.
//
auto cr0 = __readcr0();
cr0 |= 0x10000;
_enable();
__writecr0(cr0);
}
}
class detour
{
public:
detour() {};
detour(void* addr_to_hook, void* jmp_to, bool enable = true)
: hook_addr(addr_to_hook), detour_addr(jmp_to), hook_installed(false)
{ init(addr_to_hook, jmp_to, enable); }
void init(void* addr_to_hook, void* jmp_to, bool enable = true)
{
//setup hook
memcpy(
jmp_code + OFFSET_TO_ADDRESS,
&jmp_to,
sizeof(jmp_to)
);
//save bytes
memcpy(
org_bytes,
hook_addr,
sizeof(org_bytes)
);
if (enable)
install();
}
void install()
{
if (hook_installed)
return;
write_to_readonly(hook_addr, jmp_code, sizeof(jmp_code));
hook_installed = true;
}
void uninstall()
{
if (!hook_installed)
return;
write_to_readonly(hook_addr, org_bytes, sizeof(org_bytes));
hook_installed = false;
}
bool installed() { return hook_installed; }
void* hook_address() { return hook_addr; }
void* detour_address() { return detour_addr; }
private:
bool hook_installed;
void* hook_addr, * detour_addr;
#if _M_IX86
/*
0: b8 ff ff ff ff mov eax, 0xffffffff
5: ff e0 jmp eax
*/
unsigned char jmp_code[7] = {
0xb8, 0x0, 0x0, 0x0, 0x0,
0xFF, 0xE0
};
#elif _M_X64
/*
0: 48 c7 c0 ff ff ff ff mov rax,0xffffffffffffffff
7: ff e0 jmp rax
*/
unsigned char jmp_code[12] = {
0x48, 0xb8,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0xff, 0xe0
};
#endif
unsigned char org_bytes[sizeof(jmp_code)];
};

@ -0,0 +1,370 @@
#include "driver_util.h"
namespace driver_util
{
void* get_driver_base(const char* module_name)
{
ULONG bytes{};
NTSTATUS status = ZwQuerySystemInformation(
SystemModuleInformation,
NULL,
bytes,
&bytes
);
if (!bytes)
return NULL;
PRTL_PROCESS_MODULES modules =
(PRTL_PROCESS_MODULES)ExAllocatePool(NonPagedPool, bytes);
if (modules)
{
status = ZwQuerySystemInformation(
SystemModuleInformation,
modules,
bytes,
&bytes
);
if (!NT_SUCCESS(status))
{
ExFreePool(modules);
return NULL;
}
PRTL_PROCESS_MODULE_INFORMATION module = modules->Modules;
PVOID module_base{}, module_size{};
for (ULONG i = 0; i < modules->NumberOfModules; i++)
{
//DBG_PRINT("Driver File: %s", module[i].FullPathName + module[i].OffsetToFileName);
if (strcmp(reinterpret_cast<char*>(module[i].FullPathName + module[i].OffsetToFileName), module_name) == 0)
{
module_base = module[i].ImageBase;
module_size = (PVOID)module[i].ImageSize;
break;
}
}
ExFreePool(modules);
return module_base;
}
return NULL;
}
void* get_kmode_export(const char* mod_name, const char* proc_name)
{
if (!mod_name || !proc_name)
return NULL;
void* result = get_driver_base(mod_name);
if (!result)
return NULL;
return RtlFindExportedRoutineByName(result, proc_name);
}
PIMAGE_FILE_HEADER get_file_header(void* base_addr)
{
if (!base_addr || *(short*)base_addr != 0x5A4D)
return NULL;
PIMAGE_DOS_HEADER dos_headers =
reinterpret_cast<PIMAGE_DOS_HEADER>(base_addr);
PIMAGE_NT_HEADERS nt_headers =
reinterpret_cast<PIMAGE_NT_HEADERS>(
reinterpret_cast<DWORD_PTR>(base_addr) + dos_headers->e_lfanew);
return &nt_headers->FileHeader;
}
void* iat_hook(void* base_addr, const char* import, void* func_addr)
{
if (!base_addr || *(short*)base_addr != 0x5A4D || !import || !func_addr)
return NULL;
PIMAGE_DOS_HEADER dos_headers =
reinterpret_cast<PIMAGE_DOS_HEADER>(base_addr);
PIMAGE_NT_HEADERS nt_headers =
reinterpret_cast<PIMAGE_NT_HEADERS>(
reinterpret_cast<DWORD_PTR>(base_addr) + dos_headers->e_lfanew);
IMAGE_DATA_DIRECTORY import_dir =
nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
PIMAGE_IMPORT_DESCRIPTOR import_des =
reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(import_dir.VirtualAddress + (DWORD_PTR)base_addr);
LPCSTR lib_name = NULL;
PVOID result = NULL;
PIMAGE_IMPORT_BY_NAME func_name = NULL;
if (!import_des)
return NULL;
while (import_des->Name != NULL)
{
lib_name = (LPCSTR)import_des->Name + (DWORD_PTR)base_addr;
if (get_driver_base(lib_name))
{
PIMAGE_THUNK_DATA org_first_thunk = NULL, first_thunk = NULL;
org_first_thunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)base_addr + import_des->OriginalFirstThunk);
first_thunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)base_addr + import_des->FirstThunk);
while (org_first_thunk->u1.AddressOfData != NULL)
{
func_name = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)base_addr + org_first_thunk->u1.AddressOfData);
if (strcmp(func_name->Name, import) == 0)
{
// save old function pointer
result = reinterpret_cast<PVOID>(first_thunk->u1.Function);
{
//
// disable write protection
//
auto cr0 = __readcr0();
cr0 &= 0xfffffffffffeffff;
__writecr0(cr0);
_disable();
}
// swap address
first_thunk->u1.Function = reinterpret_cast<ULONG64>(func_addr);
{
//
// enable write protection
//
auto cr0 = __readcr0();
cr0 |= 0x10000;
_enable();
__writecr0(cr0);
}
return result;
}
++org_first_thunk;
++first_thunk;
}
}
++import_des;
}
return NULL;
}
PDRIVER_OBJECT get_drv_obj(PUNICODE_STRING driver_name)
{
HANDLE handle{};
OBJECT_ATTRIBUTES attributes{};
UNICODE_STRING directory_name{};
PVOID directory{};
BOOLEAN success = FALSE;
RtlInitUnicodeString(&directory_name, L"\\Driver");
InitializeObjectAttributes(
&attributes,
&directory_name,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
// open OBJECT_DIRECTORY for \\Driver
auto status = ZwOpenDirectoryObject(
&handle,
DIRECTORY_ALL_ACCESS,
&attributes
);
if (!NT_SUCCESS(status))
{
DBG_PRINT("ZwOpenDirectoryObject Failed");
return NULL;
}
// Get OBJECT_DIRECTORY pointer from HANDLE
status = ObReferenceObjectByHandle(
handle,
DIRECTORY_ALL_ACCESS,
nullptr,
KernelMode,
&directory,
nullptr
);
if (!NT_SUCCESS(status))
{
DBG_PRINT("ObReferenceObjectByHandle Failed");
ZwClose(handle);
return NULL;
}
const auto directory_object = POBJECT_DIRECTORY(directory);
if (!directory_object)
return NULL;
ExAcquirePushLockExclusiveEx(&directory_object->Lock, 0);
// traverse hash table with 37 entries
// when a new object is created, the object manager computes a hash value in the range zero to 36 from the object name and creates an OBJECT_DIRECTORY_ENTRY.
// http://www.informit.com/articles/article.aspx?p=22443&seqNum=7
for (auto entry : directory_object->HashBuckets)
{
if (!entry)
continue;
while (entry && entry->Object)
{
auto driver = PDRIVER_OBJECT(entry->Object);
if (!driver)
continue;
if (wcscmp(driver->DriverExtension->ServiceKeyName.Buffer, driver_name->Buffer) == 0)
return driver;
}
}
ExReleasePushLockExclusiveEx(&directory_object->Lock, 0);
// Release the acquired resources back to the OS
ObDereferenceObject(directory);
ZwClose(handle);
//TODO remove
return NULL;
}
void copy_driver(PUNICODE_STRING image_path)
{
HANDLE h_file;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK status_block;
LARGE_INTEGER offset;
UNICODE_STRING name;
FILE_STANDARD_INFORMATION standard_info;
RtlZeroMemory(&standard_info, sizeof(standard_info));
InitializeObjectAttributes(
&attr,
image_path,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, NULL
);
NTSTATUS status = ZwCreateFile(
&h_file,
GENERIC_READ,
&attr,
&status_block,
NULL,
FILE_ATTRIBUTE_NORMAL,
NULL,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
NULL
);
ZwQueryInformationFile(
h_file,
&status_block,
&standard_info,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation
);
void* drv_buffer = ExAllocatePool(
NonPagedPool,
standard_info.AllocationSize.QuadPart
);
status = ZwReadFile(
h_file,
NULL,
NULL,
NULL,
&status_block,
drv_buffer,
standard_info.AllocationSize.QuadPart,
&offset,
NULL
);
RtlInitUnicodeString(&name, L"\\DosDevices\\C:\\last_load_drv.sys");
InitializeObjectAttributes(&attr, &name,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, NULL
);
ZwCreateFile(
&h_file,
GENERIC_WRITE,
&attr,
&status_block,
NULL,
FILE_ATTRIBUTE_NORMAL,
NULL,
FILE_OVERWRITE_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
NULL
);
ZwWriteFile(
h_file,
NULL,
NULL,
NULL,
&status_block,
drv_buffer,
standard_info.AllocationSize.QuadPart,
&offset,
NULL
);
ZwClose(h_file);
ExFreePool(drv_buffer);
}
void mem_dump(void* base_addr, unsigned len)
{
if (!base_addr || !len)
return;
HANDLE h_file;
UNICODE_STRING name;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK status_block;
LARGE_INTEGER offset{ NULL };
RtlInitUnicodeString(&name, L"\\DosDevices\\C:\\dump.bin");
InitializeObjectAttributes(&attr, &name,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, NULL
);
auto status = ZwCreateFile(
&h_file,
GENERIC_WRITE,
&attr,
&status_block,
NULL,
FILE_ATTRIBUTE_NORMAL,
NULL,
FILE_OVERWRITE_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
NULL
);
status = ZwWriteFile(
h_file,
NULL,
NULL,
NULL,
&status_block,
base_addr,
len,
&offset,
NULL
);
ZwClose(h_file);
}
}

@ -0,0 +1,14 @@
#pragma once
#include "types.h"
namespace driver_util
{
void* get_driver_base(const char* module_name);
void* iat_hook(void* base_addr, const char* import, void* func_addr);
void mem_dump(void* base_addr, unsigned len);
void* get_kmode_export(const char* mod_name, const char* proc_name);
void copy_driver(PUNICODE_STRING image_path);
PDRIVER_OBJECT get_drv_obj(PUNICODE_STRING driver_name);
PIMAGE_FILE_HEADER get_file_header(void* base_addr);
}

@ -0,0 +1,153 @@
#include "hooks.h"
namespace hooks
{
void* get_addr_hook(void* base_addr, const char* func_name)
{
DBG_PRINT("");
DBG_PRINT("=============== %s ==============", __FUNCTION__);
DBG_PRINT("func_name: %s", func_name);
if (!strcmp(func_name, "MmMapIoSpace"))
return &map_io_space;
else if (!strcmp(func_name, "MmUnmapIoSpace"))
return &unmap_io_space;
else if (!strcmp(func_name, "MmGetPhysicalAddress"))
return &get_phys_addr;
else if (!strcmp(func_name, "IoCreateSymbolicLink"))
return &create_sym_link;
else if (!strcmp(func_name, "IoCreateDevice"))
return &create_device;
return driver_util::get_kmode_export("ntoskrnl.exe", func_name);
}
PHYSICAL_ADDRESS get_phys_addr(
void* base_addr
)
{
DBG_PRINT("");
DBG_PRINT("=============== %s ==============", __FUNCTION__);
DBG_PRINT("getting physical address of: 0x%p", base_addr);
DBG_PRINT("base_addr value: 0x%p", *(ULONG64*)base_addr);
auto result = MmGetPhysicalAddress(base_addr);
DBG_PRINT("physical address: 0x%p", result);
return result;
}
void* map_io_space(
PHYSICAL_ADDRESS phys_addr,
SIZE_T size,
MEMORY_CACHING_TYPE cache_type
)
{
DBG_PRINT("");
DBG_PRINT("=============== %s ==============", __FUNCTION__);
DBG_PRINT("mapping physical memory 0x%p of size 0x%x", phys_addr, size);
mapped_io_space_addr = MmMapIoSpace(phys_addr, size, cache_type);
DBG_PRINT("mapped io space 0x%p, value: 0x%p", mapped_io_space_addr, *(ULONG64*)mapped_io_space_addr);
last_mapped_ptr = (void*)(*(ULONG64*)mapped_io_space_addr);
return mapped_io_space_addr;
}
void* allocate_pool(
POOL_TYPE pool_type,
SIZE_T size
)
{
DBG_PRINT("");
DBG_PRINT("=============== %s ==============", __FUNCTION__);
DBG_PRINT("allocating size: 0x%p", size);
auto lp_pool = ExAllocatePool(pool_type, size);
DBG_PRINT("pool allocated at 0x%p", lp_pool);
return lp_pool;
}
void unmap_io_space(
void* base_addr,
SIZE_T size
)
{
DBG_PRINT("");
DBG_PRINT("=============== %s ==============", __FUNCTION__);
DBG_PRINT("value of 0x%p is 0x%p", base_addr, *(ULONG64*)base_addr);
MmUnmapIoSpace(base_addr, size);
}
NTSTATUS device_control(
PDEVICE_OBJECT device_obj,
PIRP irp
)
{
auto irp_stack = IoGetCurrentIrpStackLocation(irp);
auto ioctl_code = irp_stack->Parameters.Read.ByteOffset.LowPart;
auto master_irp = irp->AssociatedIrp.MasterIrp;
DBG_PRINT("");
DBG_PRINT("=============== %s ==============", __FUNCTION__);
DBG_PRINT("ioctl called with ioctl code: 0x%p", ioctl_code);
DBG_PRINT("ioctl called from: 0x%x", PsGetCurrentProcessId());
if (ioctl_code == WRITE_MEMORY_IOCTL)
{
DBG_PRINT("master_irp->MdlAddress: 0x%p", master_irp->MdlAddress);
DBG_PRINT("master_irp->Type: 0x%p", (__m128i*) master_irp->Type);
DBG_PRINT("master_irp->Flags: 0x%p", master_irp->Flags);
*(ULONG64*)mapped_io_space_addr = (ULONG64)&allocate_pool;
}
return reinterpret_cast<decltype(&device_control)>(orig_irp_ioctl)(device_obj, irp);
}
NTSTATUS create_sym_link(
PUNICODE_STRING sym_link,
PUNICODE_STRING device_name
)
{
DBG_PRINT("");
DBG_PRINT("=============== %s ==============", __FUNCTION__);
DBG_PRINT("creating symbolic link of device %ws to %ws", device_name->Buffer, sym_link->Buffer);
DBG_PRINT("IRP_MJ_DEVICE_CONTROL: 0x%p", unfair_drv_obj->MajorFunction[IRP_MJ_DEVICE_CONTROL]);
//
// right before we return from driver entry we want to hook the ioctl.
//
orig_irp_ioctl = unfair_drv_obj->MajorFunction[IRP_MJ_DEVICE_CONTROL];
unfair_drv_obj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = &device_control;
//
// swap unload pointers
//
orig_driver_unload = unfair_drv_obj->DriverUnload;
unfair_drv_obj->DriverUnload = &driver_unload;
return IoCreateSymbolicLink(sym_link, device_name);
}
NTSTATUS create_device(
PDRIVER_OBJECT drv_obj,
ULONG drv_ext,
PUNICODE_STRING device_name,
DEVICE_TYPE device_type,
ULONG device_char,
BOOLEAN exclusive,
PDEVICE_OBJECT* device_obj
)
{
unfair_drv_obj = drv_obj;
return IoCreateDevice(
drv_obj,
drv_ext,
device_name,
device_type,
device_char,
exclusive,
device_obj
);
}
void driver_unload(
PDRIVER_OBJECT drv_obj
)
{
DBG_PRINT("unfairgame driver unloading....");
return reinterpret_cast<decltype(&driver_unload)>(orig_driver_unload)(drv_obj);
}
}

@ -0,0 +1,64 @@
#pragma once
#include <ntifs.h>
#include "driver_util.h"
#include "types.h"
#include "detour.hpp"
namespace hooks
{
inline void* orig_irp_ioctl = NULL;
inline void* orig_driver_unload = NULL;
inline void* last_mapped_ptr = NULL;
inline void* mapped_io_space_addr = NULL;
inline PDRIVER_OBJECT unfair_drv_obj = NULL;
void* get_addr_hook(
void* base_addr,
const char* func_name
);
void unmap_io_space(
void* base_addr,
SIZE_T size
);
void* map_io_space(
PHYSICAL_ADDRESS phys_addr,
SIZE_T size,
MEMORY_CACHING_TYPE cache_type
);
PHYSICAL_ADDRESS get_phys_addr(
void* base_addr
);
NTSTATUS create_sym_link(
PUNICODE_STRING sym_link,
PUNICODE_STRING device_name
);
NTSTATUS device_control(
PDEVICE_OBJECT device_obj,
PIRP irp
);
NTSTATUS create_device(
PDRIVER_OBJECT drv_obj,
ULONG drv_ext,
PUNICODE_STRING device_name,
DEVICE_TYPE device_type,
ULONG device_char,
BOOLEAN exclusive,
PDEVICE_OBJECT* device_obj
);
void driver_unload(
PDRIVER_OBJECT drv_obj
);
void* allocate_pool(
POOL_TYPE pool_type,
SIZE_T size
);
}

@ -0,0 +1,40 @@
#include "types.h"
#include "callback.h"
#include "hooks.h"
void driver_unload(
DRIVER_OBJECT* driver_obj
)
{
UNREFERENCED_PARAMETER(driver_obj);
PsRemoveLoadImageNotifyRoutine(&callback::on_image_load);
}
NTSTATUS driver_close(
IN PDEVICE_OBJECT device_obj,
IN PIRP lp_irp
)
{
UNREFERENCED_PARAMETER(device_obj);
lp_irp->IoStatus.Status = STATUS_SUCCESS;
lp_irp->IoStatus.Information = NULL;
IoCompleteRequest(lp_irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
//
// This driver is not to be manually mapped in its current form.
// If you choose to manually map this driver please remove "driver_close" and "driver_unload".
//
NTSTATUS __cdecl driver_entry(
_In_ PDRIVER_OBJECT driver_obj,
_In_ PUNICODE_STRING reg_path
)
{
UNREFERENCED_PARAMETER(reg_path);
driver_obj->MajorFunction[IRP_MJ_CLOSE] = &driver_close;
driver_obj->DriverUnload = &driver_unload;
DBG_PRINT("callbacks registered, waiting for unfairgame driver....");
return PsSetLoadImageNotifyRoutine(&callback::on_image_load);
}

@ -0,0 +1,292 @@
#pragma once
#include <ntifs.h>
#include <intrin.h>
#if true
#define DBG_PRINT(...) DbgPrintEx( DPFLTR_SYSTEM_ID, DPFLTR_ERROR_LEVEL, "[unfairgame]" __VA_ARGS__);
#else
#define DBG_PRINT(...)
#endif
#ifndef DWORD
#define DWORD unsigned
#endif
#ifndef WORD
#define WORD unsigned short
#endif
#ifndef uint64_t
#define uint64_t ULONGLONG
#endif
#ifndef uint32_t
#define uint32_t DWORD
#endif
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory
#define UNFAIR_TIMESTAMP 0x5EB9B094
#define UNFAIR_GETPROC_ADDR_OFFSET 0x1550
#define UNFAIR_MEMCPY_FUNCTION 0x1680
#define WIN32KBASE_VTABLE 0x1A5660
#define UNFAIR_UNKNOWN_IOCTL_1 0x2028C804
#define WRITE_MEMORY_IOCTL 0x2028C808
typedef struct unfairgame_imports
{
void* map_io_space;
void* unmap_io_space;
void* complete_request;
void* create_device;
void* create_symbolic_link;
void* delete_device;
void* get_phys_addr;
}unfairgame_imports, *punfair_vtable;
extern "C" NTSTATUS ZwQuerySystemInformation(
ULONG InfoClass,
PVOID Buffer,
ULONG Length,
PULONG ReturnLength
);
extern "C" NTKERNELAPI
PVOID
NTAPI
RtlFindExportedRoutineByName(
_In_ PVOID ImageBase,
_In_ PCCH RoutineName
);
extern "C" NTSTATUS ZwQueryDirectoryObject(
IN HANDLE DirectoryHandle,
OUT PVOID Buffer,
IN ULONG BufferLength,
IN BOOLEAN ReturnSingleEntry,
IN BOOLEAN RestartScan,
IN OUT PULONG Context,
OUT PULONG ReturnLength OPTIONAL
);
typedef struct _OBJECT_DIRECTORY_ENTRY
{
_OBJECT_DIRECTORY_ENTRY* ChainLink;
PVOID Object;
ULONG HashValue;
} OBJECT_DIRECTORY_ENTRY, * POBJECT_DIRECTORY_ENTRY;
typedef struct _OBJECT_DIRECTORY
{
POBJECT_DIRECTORY_ENTRY HashBuckets[37];
EX_PUSH_LOCK Lock;
void* DeviceMap;
ULONG SessionId;
PVOID NamespaceEntry;
ULONG Flags;
} OBJECT_DIRECTORY, * POBJECT_DIRECTORY;
typedef struct _COPY_MEMORY_BUFFER_INFO
{
uint64_t case_number;
uint64_t reserved;
void* source;
void* destination;
uint64_t length;
}COPY_MEMORY_BUFFER_INFO, * PCOPY_MEMORY_BUFFER_INFO;
typedef struct _FILL_MEMORY_BUFFER_INFO
{
uint64_t case_number;
uint64_t reserved1;
uint32_t value;
uint32_t reserved2;
uint64_t destination;
uint64_t length;
}FILL_MEMORY_BUFFER_INFO, * PFILL_MEMORY_BUFFER_INFO;
typedef struct _GET_PHYS_ADDRESS_BUFFER_INFO
{
uint64_t case_number;
uint64_t reserved;
uint64_t return_physical_address;
uint64_t address_to_translate;
}GET_PHYS_ADDRESS_BUFFER_INFO, * PGET_PHYS_ADDRESS_BUFFER_INFO;
typedef struct _MAP_IO_SPACE_BUFFER_INFO
{
uint64_t case_number;
uint64_t reserved;
uint64_t return_value;
uint64_t return_virtual_address;
uint64_t physical_address_to_map;
uint32_t size;
}MAP_IO_SPACE_BUFFER_INFO, * PMAP_IO_SPACE_BUFFER_INFO;
typedef struct _UNMAP_IO_SPACE_BUFFER_INFO
{
uint64_t case_number;
uint64_t reserved1;
uint64_t reserved2;
uint64_t virt_address;
uint64_t reserved3;
uint32_t number_of_bytes;
}UNMAP_IO_SPACE_BUFFER_INFO, * PUNMAP_IO_SPACE_BUFFER_INFO;
typedef struct _RTL_PROCESS_MODULE_INFORMATION
{
HANDLE Section;
PVOID MappedBase;
PVOID ImageBase;
ULONG ImageSize;
ULONG Flags;
USHORT LoadOrderIndex;
USHORT InitOrderIndex;
USHORT LoadCount;
USHORT OffsetToFileName;
UCHAR FullPathName[256];
} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;
typedef struct _RTL_PROCESS_MODULES
{
ULONG NumberOfModules;
RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation,
SystemProcessorInformation,
SystemPerformanceInformation,
SystemTimeOfDayInformation,
SystemPathInformation,
SystemProcessInformation,
SystemCallCountInformation,
SystemDeviceInformation,
SystemProcessorPerformanceInformation,
SystemFlagsInformation,
SystemCallTimeInformation,
SystemModuleInformation = 0x0B
} SYSTEM_INFORMATION_CLASS, * PSYSTEM_INFORMATION_CLASS;
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
USHORT e_magic; // Magic number
USHORT e_cblp; // Bytes on last page of file
USHORT e_cp; // Pages in file
USHORT e_crlc; // Relocations
USHORT e_cparhdr; // Size of header in paragraphs
USHORT e_minalloc; // Minimum extra paragraphs needed
USHORT e_maxalloc; // Maximum extra paragraphs needed
USHORT e_ss; // Initial (relative) SS value
USHORT e_sp; // Initial SP value
USHORT e_csum; // Checksum
USHORT e_ip; // Initial IP value
USHORT e_cs; // Initial (relative) CS value
USHORT e_lfarlc; // File address of relocation table
USHORT e_ovno; // Overlay number
USHORT e_res[4]; // Reserved words
USHORT e_oemid; // OEM identifier (for e_oeminfo)
USHORT e_oeminfo; // OEM information; e_oemid specific
USHORT e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
typedef struct _IMAGE_FILE_HEADER {
short Machine;
short NumberOfSections;
unsigned TimeDateStamp;
unsigned PointerToSymbolTable;
unsigned NumberOfSymbols;
short SizeOfOptionalHeader;
short Characteristics;
} IMAGE_FILE_HEADER, * PIMAGE_FILE_HEADER;
typedef struct _IMAGE_DATA_DIRECTORY {
unsigned VirtualAddress;
unsigned Size;
} IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY;
typedef struct _IMAGE_OPTIONAL_HEADER64 {
short Magic;
unsigned char MajorLinkerVersion;
unsigned char MinorLinkerVersion;
unsigned SizeOfCode;
unsigned SizeOfInitializedData;
unsigned SizeOfUninitializedData;
unsigned AddressOfEntryPoint;
unsigned BaseOfCode;
ULONGLONG ImageBase;
unsigned SectionAlignment;
unsigned FileAlignment;
short MajorOperatingSystemVersion;
short MinorOperatingSystemVersion;
short MajorImageVersion;
short MinorImageVersion;
short MajorSubsystemVersion;
short MinorSubsystemVersion;
unsigned Win32VersionValue;
unsigned SizeOfImage;
unsigned SizeOfHeaders;
unsigned CheckSum;
short Subsystem;
short DllCharacteristics;
ULONGLONG SizeOfStackReserve;
ULONGLONG SizeOfStackCommit;
ULONGLONG SizeOfHeapReserve;
ULONGLONG SizeOfHeapCommit;
unsigned LoaderFlags;
unsigned NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[16];
} IMAGE_OPTIONAL_HEADER64, * PIMAGE_OPTIONAL_HEADER64;
typedef struct _IMAGE_NT_HEADERS64 {
unsigned Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, * PIMAGE_NT_HEADERS64;
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics; // 0 for terminating null import descriptor
DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
} DUMMYUNIONNAME;
DWORD TimeDateStamp; // 0 if not bound,
// -1 if bound, and real date\time stamp
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
// O.W. date/time stamp of DLL bound to (Old BIND)
DWORD ForwarderChain; // -1 if no forwarders
DWORD Name;
DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED* PIMAGE_IMPORT_DESCRIPTOR;
typedef struct _IMAGE_IMPORT_BY_NAME {
WORD Hint;
CHAR Name[1];
} IMAGE_IMPORT_BY_NAME, * PIMAGE_IMPORT_BY_NAME;
typedef struct _IMAGE_THUNK_DATA64 {
union {
ULONGLONG ForwarderString; // PBYTE
ULONGLONG Function; // PDWORD
ULONGLONG Ordinal;
ULONGLONG AddressOfData; // PIMAGE_IMPORT_BY_NAME
} u1;
} IMAGE_THUNK_DATA64, * PIMAGE_THUNK_DATA64;
typedef PIMAGE_THUNK_DATA64 PIMAGE_THUNK_DATA;
typedef union _virt_addr_t
{
void* value;
struct
{
ULONG64 offset : 12;
ULONG64 pt_index : 9;
ULONG64 pd_index : 9;
ULONG64 pdpt_index : 9;
ULONG64 pml4_index : 9;
ULONG64 reserved : 16;
};
} virt_addr_t, * pvirt_addr_t;

@ -0,0 +1,242 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{30E2F686-FC9D-4A2E-8AD2-FD8E9E5229E1}</ProjectGuid>
<TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<RootNamespace>kdstinker</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<SpectreMitigation>false</SpectreMitigation>
<Driver_SpectreMitigation>false</Driver_SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<Link>
<EntryPointSymbol>driver_entry</EntryPointSymbol>
</Link>
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<Link>
<EntryPointSymbol>driver_entry</EntryPointSymbol>
</Link>
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<Link>
<EntryPointSymbol>driver_entry</EntryPointSymbol>
</Link>
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<Link>
<EntryPointSymbol>driver_entry</EntryPointSymbol>
</Link>
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
<EntryPointSymbol>driver_entry</EntryPointSymbol>
</Link>
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Link>
<EntryPointSymbol>driver_entry</EntryPointSymbol>
</Link>
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
<EntryPointSymbol>driver_entry</EntryPointSymbol>
</Link>
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Link>
<EntryPointSymbol>driver_entry</EntryPointSymbol>
</Link>
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="callback.h" />
<ClInclude Include="detour.hpp" />
<ClInclude Include="driver_util.h" />
<ClInclude Include="hooks.h" />
<ClInclude Include="types.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="callback.cpp" />
<ClCompile Include="driver_util.cpp" />
<ClCompile Include="hooks.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="callback.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="types.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="driver_util.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="hooks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="detour.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="callback.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="driver_util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hooks.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
Loading…
Cancel
Save