1
0
Fork 0
mirror of https://gitlab.com/niansa/PolicyToolLib.git synced 2025-03-06 20:48:27 +01:00

Initial commit

This commit is contained in:
Nils Sauer 2023-01-18 15:57:01 +01:00
commit 4f37a51591
30 changed files with 18854 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
CMakeLists.txt.user*

20
CMakeLists.txt Normal file
View file

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.5)
project(PolicyToolLib LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED Yes)
add_subdirectory(detours)
add_library(PolicyTool SHARED
main.cpp
modules/ModuleBase.hpp
modules/LibInherit.hpp
modules/AdminImpersonate.hpp
modules/RemoteLockBreak.hpp
modules/PolicyDisable.hpp
)
target_link_libraries(PolicyTool PRIVATE Detours ntdll)
target_link_options(PolicyTool PUBLIC -static)
add_executable(PolicyToolTest test.cpp)

10
detours/.editorconfig Normal file
View file

@ -0,0 +1,10 @@
# Top-most EditorConfig file
root = true
# Use same style for all files
[*]
indent_style = space
indent_size = 4
end_of_line = crlf
insert_final_newline = false
trim_trailing_whitespace = true

41
detours/.gitignore vendored Normal file
View file

@ -0,0 +1,41 @@
# C extensions
*.so
# Unit test / coverage reports
.coverage
.tox
nosetests.xml
# Translations
*.mo
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# vim
*~
*.swp
# Visual Studio build
*.ipch
.vs/
output/
include/
*.exp
*.pdb
*.lib
*.dll
*.exe
obj.*
*.ipdb
*.iobj
*.tlog
*.log
*.obj
*.user
*.recipe
/bin.*
*.vcxproj.FileListAbsolute.txt
*.vcxprojAssemblyReference.cache

14
detours/CMakeLists.txt Normal file
View file

@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.5)
project(Detours LANGUAGES CXX)
file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/src/*.cpp)
add_library(Detours STATIC ${SRC_FILES})
# This file is included and not compiled on its own
set_property (
SOURCE ${PROJECT_SOURCE_DIR}/src/uimports.cpp
APPEND PROPERTY HEADER_FILE_ONLY true)
target_include_directories(Detours PUBLIC ${PROJECT_SOURCE_DIR}/src/)

118
detours/CREDITS.md Normal file
View file

@ -0,0 +1,118 @@
# Detours Contributor Credits
The following individuals have helped identify specific bugs and improvements
in Detours. The entire Detours community has benefited from their help.
* Jay Krell: Identified error in DetourFindPayload that caused a
incorrect failure when pcbData is NULL. (Build_342)
* Jay Krell: Identified issue with VirtualSize == 0 files created in
NT 3.1 images. (Build_339)
* Igor Odnovorov: Identified an issue with the placement of the trampoline
region when a function is detoured twice and the second
trampoline region is outside of the +/- 2GB range of
the target. (Build_337)
* Jay Krell: Identified need for some programs to enumerate the
address of IAT entries. (Build_336)
* Calvin Hsia: Identified need for some program to change the excluded
system region. (Build_336)
* Adam Smith: Identified error in failure handling when VirtualProect
cannot make pages executable because the Prohibit
Dynamic Code Generation mitigation policy has been
applied to a process. (Build_335)
* Ben Faull: Identified fix to detour_alloc_region_from_lo and
detour_alloc_region_from_hi that preserves ASLR entropy.
(Build_334)
* Shaoxiang Su: Reported errors building with Visual Studio 2015.
(Build_332)
* Jay Krell: Identified and resolved significant gaps in the X86, X64
and IA64 disassemblers for instruction found in code,
but seldom found in function prologues. (Build_331)
* Allan Murphy: Identify error in rep and jmp ds: encodings. (Build_331)
* Philip Bacon: Identified incorrect entry point return for pure
resource-only binaries. (Build_330)
* Jay Krell: Identified failure in DetourAttachEx to update nAlign.
(Build_330)
* Sumit Sarin: Helped debug error with packed binaries.
(Build_329)
* Nitya Kumar Sharma: Reported bug in DetourAfterWithDll for 32/64 agnostic
EXEs.
(Build_327)
* Richard Black: Identified a large number of typos in documentation.
(Build_326)
* Michael Bilodeau: Identified bug in DetourUpdateProcessWithDll when the
target process contains a Detours payload *after* all
valid PE binaries.
(Build_324)
* Meera Jindal: Reported bug in identification of target address in
DetourCopyInstruction for jmp[] and call[] on x86 & x64,
the ff15 and ff25 opcodes.
(Build_323)
* Ken Johnson: Assistance with SAL 2.0 annotations.
(Build_319)
* Nick Wood: Identified bug in DetourFindFunction on ARM.
(Build_314)
* Mark Russinovich: Helped debug DetourCreateProcessWithDllEx.
(Build_314)
* John Lin: Implementation idea for DetoursCreateProcessWithDllEx.
(Build_314)
* Andrew Zawadowskiy Reported an improper memory page permissions
vulnerability in Detours 2.1. (Vulnerability does not
exist in versions later than Detours 2.1.)
(Build_223)
* Nightxie: Identified bug in detour_alloc_round_up_to_region.
(Build_310)
* Diana Milirud: Identified bug in B* instructions on ARM.
(Build_309)
* Juan Carlos Identified correct MSIL entry point for unsigned MSIL.
Luciani: (Build_308)
* Lee Hunt Suggested improvements in algorithm for allocation of
Lawrence Landauer trampoline regions on x64 to avoid collisions with
Joe Laughlin: system DLLs.
(Build_307)
* Tyler Sims Identified bug in handling of "anycpu" MSIL binaries
Darren Kennedy: on x64.
(Build_307)
* Andre Vachon: Help with optimized binaries.
(Build 301)
* Chris Mann: Identified fix not forward ported from 2.2 to 3.0.
(Build_301)
* Mark Irving: Identified bug with EXEs missing second import table.
(Build_300)
* Ben Schwarz: Identified bug in handling of multi-byte NOPs.
(Build_300)
* Aaron Giles Coded initial ARM/Thumb2 disassembler.
Jared Henderson: (Build_300)
* Doug Brubacher: Coded initial x86 disassembler.
(Build_100)

23
detours/LICENSE.md Normal file
View file

@ -0,0 +1,23 @@
# Copyright (c) Microsoft Corporation
All rights reserved.
# MIT License
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.

56
detours/README.md Normal file
View file

@ -0,0 +1,56 @@
# Microsoft Research Detours Package
Detours is a software package for monitoring and instrumenting API calls on Windows. Detours
has been used by many ISVs and is also used by product teams at Microsoft. Detours is now available under
a standard open source license ([MIT](https://github.com/microsoft/Detours/blob/master/LICENSE.md)). This simplifies licensing for programmers using Detours
and allows the community to support Detours using open source tools and processes.
Detours is compatible with the Windows NT family of
operating systems: Windows NT, Windows XP, Windows Server 2003, Windows 7,
Windows 8, and Windows 10. It cannot be used by Windows Store apps
because Detours requires APIs not available to those applications.
This repo contains the source code for version 4.0.1 of Detours.
For technical documentation on Detours, see the [Detours Wiki](https://github.com/microsoft/Detours/wiki).
For directions on how to build and run samples, see the
samples [README.txt](https://github.com/Microsoft/Detours/blob/master/samples/README.TXT) file.
## Contributing
The [`Detours`](https://github.com/microsoft/detours) repository is where development is done.
Here are some ways you can participate in the project:
* [Answer questions](https://github.com/microsoft/detours/issues) about using Detours.
* [Improve the Wiki](https://github.com/microsoft/detours/wiki).
* [Submit bugs](https://github.com/microsoft/detours/issues) and help us verify fixes and changes as they are checked in.
* Review [source code changes](https://github.com/microsoft/detours/pulls).
Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that
you have the right to, and actually do, grant us the rights to use your contribution.
For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
## Issues, questions, and feedback
* Open an issue on [GitHub Issues](https://github.com/Microsoft/detours/issues).
## Mailing list for announcements
The detours-announce mailing list is a low-traffic email list for important announcements
about the project, such as the availability of new versions of Detours. To join it, send
an email to listserv@lists.research.microsoft.com with a
message body containing only the text SUBSCRIBE DETOURS-ANNOUNCE.
To leave it, send an email to listserv@lists.research.microsoft.com with a
message body containing only the text UNSUBSCRIBE DETOURS-ANNOUNCE.
## License
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the [MIT](LICENSE.md) License.

1783
detours/src/creatwth.cpp Normal file

File diff suppressed because it is too large Load diff

2604
detours/src/detours.cpp Normal file

File diff suppressed because it is too large Load diff

1233
detours/src/detours.h Normal file

File diff suppressed because it is too large Load diff

27
detours/src/detver.h Normal file
View file

@ -0,0 +1,27 @@
//////////////////////////////////////////////////////////////////////////////
//
// Common version parameters.
//
// Microsoft Research Detours Package, Version 4.0.1
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
#define _USING_V110_SDK71_ 1
#include "winver.h"
#if 0
#include <windows.h>
#include <detours.h>
#else
#ifndef DETOURS_STRINGIFY
#define DETOURS_STRINGIFY_(x) #x
#define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x)
#endif
#define VER_FILEFLAGSMASK 0x3fL
#define VER_FILEFLAGS 0x0L
#define VER_FILEOS 0x00040004L
#define VER_FILETYPE 0x00000002L
#define VER_FILESUBTYPE 0x00000000L
#endif
#define VER_DETOURS_BITS DETOURS_STRINGIFY(DETOURS_BITS)

4306
detours/src/disasm.cpp Normal file

File diff suppressed because it is too large Load diff

2
detours/src/disolarm.cpp Normal file
View file

@ -0,0 +1,2 @@
#define DETOURS_ARM_OFFLINE_LIBRARY
#include "disasm.cpp"

View file

@ -0,0 +1,2 @@
#define DETOURS_ARM64_OFFLINE_LIBRARY
#include "disasm.cpp"

View file

@ -0,0 +1,2 @@
#define DETOURS_IA64_OFFLINE_LIBRARY
#include "disasm.cpp"

2
detours/src/disolx64.cpp Normal file
View file

@ -0,0 +1,2 @@
#define DETOURS_X64_OFFLINE_LIBRARY
#include "disasm.cpp"

2
detours/src/disolx86.cpp Normal file
View file

@ -0,0 +1,2 @@
#define DETOURS_X86_OFFLINE_LIBRARY
#include "disasm.cpp"

2217
detours/src/image.cpp Normal file

File diff suppressed because it is too large Load diff

932
detours/src/modules.cpp Normal file
View file

@ -0,0 +1,932 @@
//////////////////////////////////////////////////////////////////////////////
//
// Module Enumeration Functions (modules.cpp of detours.lib)
//
// Microsoft Research Detours Package, Version 4.0.1
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Module enumeration functions.
//
// #define DETOUR_DEBUG 1
#define DETOURS_INTERNAL
#include "detours.h"
#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
#error detours.h version mismatch
#endif
#define CLR_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]
#define IAT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT]
//////////////////////////////////////////////////////////////////////////////
//
const GUID DETOUR_EXE_RESTORE_GUID = {
0xbda26f34, 0xbc82, 0x4829,
{ 0x9e, 0x64, 0x74, 0x2c, 0x4, 0xc8, 0x4f, 0xa0 } };
//////////////////////////////////////////////////////////////////////////////
//
PDETOUR_SYM_INFO DetourLoadImageHlp(VOID)
{
static DETOUR_SYM_INFO symInfo;
static PDETOUR_SYM_INFO pSymInfo = NULL;
static BOOL failed = false;
if (failed) {
return NULL;
}
if (pSymInfo != NULL) {
return pSymInfo;
}
ZeroMemory(&symInfo, sizeof(symInfo));
// Create a real handle to the process.
#if 0
DuplicateHandle(GetCurrentProcess(),
GetCurrentProcess(),
GetCurrentProcess(),
&symInfo.hProcess,
0,
FALSE,
DUPLICATE_SAME_ACCESS);
#else
symInfo.hProcess = GetCurrentProcess();
#endif
symInfo.hDbgHelp = LoadLibraryExW(L"dbghelp.dll", NULL, 0);
if (symInfo.hDbgHelp == NULL) {
abort:
failed = true;
if (symInfo.hDbgHelp != NULL) {
FreeLibrary(symInfo.hDbgHelp);
}
symInfo.pfImagehlpApiVersionEx = NULL;
symInfo.pfSymInitialize = NULL;
symInfo.pfSymSetOptions = NULL;
symInfo.pfSymGetOptions = NULL;
symInfo.pfSymLoadModule64 = NULL;
symInfo.pfSymGetModuleInfo64 = NULL;
symInfo.pfSymFromName = NULL;
return NULL;
}
symInfo.pfImagehlpApiVersionEx
= (PF_ImagehlpApiVersionEx)GetProcAddress(symInfo.hDbgHelp,
"ImagehlpApiVersionEx");
symInfo.pfSymInitialize
= (PF_SymInitialize)GetProcAddress(symInfo.hDbgHelp, "SymInitialize");
symInfo.pfSymSetOptions
= (PF_SymSetOptions)GetProcAddress(symInfo.hDbgHelp, "SymSetOptions");
symInfo.pfSymGetOptions
= (PF_SymGetOptions)GetProcAddress(symInfo.hDbgHelp, "SymGetOptions");
symInfo.pfSymLoadModule64
= (PF_SymLoadModule64)GetProcAddress(symInfo.hDbgHelp, "SymLoadModule64");
symInfo.pfSymGetModuleInfo64
= (PF_SymGetModuleInfo64)GetProcAddress(symInfo.hDbgHelp, "SymGetModuleInfo64");
symInfo.pfSymFromName
= (PF_SymFromName)GetProcAddress(symInfo.hDbgHelp, "SymFromName");
API_VERSION av;
ZeroMemory(&av, sizeof(av));
av.MajorVersion = API_VERSION_NUMBER;
if (symInfo.pfImagehlpApiVersionEx == NULL ||
symInfo.pfSymInitialize == NULL ||
symInfo.pfSymLoadModule64 == NULL ||
symInfo.pfSymGetModuleInfo64 == NULL ||
symInfo.pfSymFromName == NULL) {
goto abort;
}
symInfo.pfImagehlpApiVersionEx(&av);
if (av.MajorVersion < API_VERSION_NUMBER) {
goto abort;
}
if (!symInfo.pfSymInitialize(symInfo.hProcess, NULL, FALSE)) {
// We won't retry the initialize if it fails.
goto abort;
}
if (symInfo.pfSymGetOptions != NULL && symInfo.pfSymSetOptions != NULL) {
DWORD dw = symInfo.pfSymGetOptions();
dw &= ~(SYMOPT_CASE_INSENSITIVE |
SYMOPT_UNDNAME |
SYMOPT_DEFERRED_LOADS |
0);
dw |= (
#if defined(SYMOPT_EXACT_SYMBOLS)
SYMOPT_EXACT_SYMBOLS |
#endif
#if defined(SYMOPT_NO_UNQUALIFIED_LOADS)
SYMOPT_NO_UNQUALIFIED_LOADS |
#endif
SYMOPT_DEFERRED_LOADS |
#if defined(SYMOPT_FAIL_CRITICAL_ERRORS)
SYMOPT_FAIL_CRITICAL_ERRORS |
#endif
#if defined(SYMOPT_INCLUDE_32BIT_MODULES)
SYMOPT_INCLUDE_32BIT_MODULES |
#endif
0);
symInfo.pfSymSetOptions(dw);
}
pSymInfo = &symInfo;
return pSymInfo;
}
PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
_In_ LPCSTR pszFunction)
{
if (pszFunction == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/////////////////////////////////////////////// First, try GetProcAddress.
//
#pragma prefast(suppress:28752, "We don't do the unicode conversion for LoadLibraryExA.")
HMODULE hModule = LoadLibraryExA(pszModule, NULL, 0);
if (hModule == NULL) {
return NULL;
}
PBYTE pbCode = (PBYTE)GetProcAddress(hModule, pszFunction);
if (pbCode) {
return pbCode;
}
////////////////////////////////////////////////////// Then try ImageHelp.
//
DETOUR_TRACE(("DetourFindFunction(%hs, %hs)\n", pszModule, pszFunction));
PDETOUR_SYM_INFO pSymInfo = DetourLoadImageHlp();
if (pSymInfo == NULL) {
DETOUR_TRACE(("DetourLoadImageHlp failed: %lu\n",
GetLastError()));
return NULL;
}
if (pSymInfo->pfSymLoadModule64(pSymInfo->hProcess, NULL,
(PCHAR)pszModule, NULL,
(DWORD64)hModule, 0) == 0) {
if (ERROR_SUCCESS != GetLastError()) {
DETOUR_TRACE(("SymLoadModule64(%p) failed: %lu\n",
pSymInfo->hProcess, GetLastError()));
return NULL;
}
}
HRESULT hrRet;
CHAR szFullName[512];
IMAGEHLP_MODULE64 modinfo;
ZeroMemory(&modinfo, sizeof(modinfo));
modinfo.SizeOfStruct = sizeof(modinfo);
if (!pSymInfo->pfSymGetModuleInfo64(pSymInfo->hProcess, (DWORD64)hModule, &modinfo)) {
DETOUR_TRACE(("SymGetModuleInfo64(%p, %p) failed: %lu\n",
pSymInfo->hProcess, hModule, GetLastError()));
return NULL;
}
hrRet = StringCchCopyA(szFullName, sizeof(szFullName)/sizeof(CHAR), modinfo.ModuleName);
if (FAILED(hrRet)) {
DETOUR_TRACE(("StringCchCopyA failed: %08lx\n", hrRet));
return NULL;
}
hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), "!");
if (FAILED(hrRet)) {
DETOUR_TRACE(("StringCchCatA failed: %08lx\n", hrRet));
return NULL;
}
hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), pszFunction);
if (FAILED(hrRet)) {
DETOUR_TRACE(("StringCchCatA failed: %08lx\n", hrRet));
return NULL;
}
struct CFullSymbol : SYMBOL_INFO {
CHAR szRestOfName[512];
} symbol;
ZeroMemory(&symbol, sizeof(symbol));
//symbol.ModBase = (ULONG64)hModule;
symbol.SizeOfStruct = sizeof(SYMBOL_INFO);
#ifdef DBHLPAPI
symbol.MaxNameLen = sizeof(symbol.szRestOfName)/sizeof(symbol.szRestOfName[0]);
#else
symbol.MaxNameLength = sizeof(symbol.szRestOfName)/sizeof(symbol.szRestOfName[0]);
#endif
if (!pSymInfo->pfSymFromName(pSymInfo->hProcess, szFullName, &symbol)) {
DETOUR_TRACE(("SymFromName(%hs) failed: %lu\n", szFullName, GetLastError()));
return NULL;
}
#if defined(DETOURS_IA64)
// On the IA64, we get a raw code pointer from the symbol engine
// and have to convert it to a wrapped [code pointer, global pointer].
//
PPLABEL_DESCRIPTOR pldEntry = (PPLABEL_DESCRIPTOR)DetourGetEntryPoint(hModule);
PPLABEL_DESCRIPTOR pldSymbol = new PLABEL_DESCRIPTOR;
pldSymbol->EntryPoint = symbol.Address;
pldSymbol->GlobalPointer = pldEntry->GlobalPointer;
return (PBYTE)pldSymbol;
#elif defined(DETOURS_ARM)
// On the ARM, we get a raw code pointer, which we must convert into a
// valied Thumb2 function pointer.
return DETOURS_PBYTE_TO_PFUNC(symbol.Address);
#else
return (PBYTE)symbol.Address;
#endif
}
//////////////////////////////////////////////////// Module Image Functions.
//
HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast)
{
PBYTE pbLast = (PBYTE)hModuleLast + MM_ALLOCATION_GRANULARITY;
MEMORY_BASIC_INFORMATION mbi;
ZeroMemory(&mbi, sizeof(mbi));
// Find the next memory region that contains a mapped PE image.
//
for (;; pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
if (VirtualQuery(pbLast, &mbi, sizeof(mbi)) <= 0) {
break;
}
// Skip uncommitted regions and guard pages.
//
if ((mbi.State != MEM_COMMIT) ||
((mbi.Protect & 0xff) == PAGE_NOACCESS) ||
(mbi.Protect & PAGE_GUARD)) {
continue;
}
__try {
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pbLast;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE ||
(DWORD)pDosHeader->e_lfanew > mbi.RegionSize ||
(DWORD)pDosHeader->e_lfanew < sizeof(*pDosHeader)) {
continue;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
continue;
}
SetLastError(NO_ERROR);
return (HMODULE)pDosHeader;
}
#pragma prefast(suppress:28940, "A bad pointer means this probably isn't a PE header.")
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
continue;
}
}
return NULL;
}
PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
if (hModule == NULL) {
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
}
__try {
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return NULL;
}
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
PDETOUR_CLR_HEADER pClrHeader = NULL;
if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
if (((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.VirtualAddress != 0 &&
((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.Size != 0) {
pClrHeader = (PDETOUR_CLR_HEADER)
(((PBYTE)pDosHeader)
+ ((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.VirtualAddress);
}
}
else if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
if (((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.VirtualAddress != 0 &&
((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.Size != 0) {
pClrHeader = (PDETOUR_CLR_HEADER)
(((PBYTE)pDosHeader)
+ ((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.VirtualAddress);
}
}
if (pClrHeader != NULL) {
// For MSIL assemblies, we want to use the _Cor entry points.
HMODULE hClr = GetModuleHandleW(L"MSCOREE.DLL");
if (hClr == NULL) {
return NULL;
}
SetLastError(NO_ERROR);
return (PVOID)GetProcAddress(hClr, "_CorExeMain");
}
SetLastError(NO_ERROR);
// Pure resource DLLs have neither an entry point nor CLR information
// so handle them by returning NULL (LastError is NO_ERROR)
if (pNtHeader->OptionalHeader.AddressOfEntryPoint == 0) {
return NULL;
}
return ((PBYTE)pDosHeader) +
pNtHeader->OptionalHeader.AddressOfEntryPoint;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
}
ULONG WINAPI DetourGetModuleSize(_In_opt_ HMODULE hModule)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
if (hModule == NULL) {
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
}
__try {
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return NULL;
}
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
SetLastError(NO_ERROR);
return (pNtHeader->OptionalHeader.SizeOfImage);
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
}
HMODULE WINAPI DetourGetContainingModule(_In_ PVOID pvAddr)
{
MEMORY_BASIC_INFORMATION mbi;
ZeroMemory(&mbi, sizeof(mbi));
__try {
if (VirtualQuery(pvAddr, &mbi, sizeof(mbi)) <= 0) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
// Skip uncommitted regions and guard pages.
//
if ((mbi.State != MEM_COMMIT) ||
((mbi.Protect & 0xff) == PAGE_NOACCESS) ||
(mbi.Protect & PAGE_GUARD)) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return NULL;
}
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
SetLastError(NO_ERROR);
return (HMODULE)pDosHeader;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return NULL;
}
}
static inline PBYTE RvaAdjust(_Pre_notnull_ PIMAGE_DOS_HEADER pDosHeader, _In_ DWORD raddr)
{
if (raddr != NULL) {
return ((PBYTE)pDosHeader) + raddr;
}
return NULL;
}
BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule,
_In_opt_ PVOID pContext,
_In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport)
{
if (pfExport == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
if (hModule == NULL) {
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
}
__try {
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return FALSE;
}
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
PIMAGE_EXPORT_DIRECTORY pExportDir
= (PIMAGE_EXPORT_DIRECTORY)
RvaAdjust(pDosHeader,
pNtHeader->OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
if (pExportDir == NULL) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
PBYTE pExportDirEnd = (PBYTE)pExportDir + pNtHeader->OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
PDWORD pdwFunctions = (PDWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfFunctions);
PDWORD pdwNames = (PDWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfNames);
PWORD pwOrdinals = (PWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfNameOrdinals);
for (DWORD nFunc = 0; nFunc < pExportDir->NumberOfFunctions; nFunc++) {
PBYTE pbCode = (pdwFunctions != NULL)
? (PBYTE)RvaAdjust(pDosHeader, pdwFunctions[nFunc]) : NULL;
PCHAR pszName = NULL;
// if the pointer is in the export region, then it is a forwarder.
if (pbCode > (PBYTE)pExportDir && pbCode < pExportDirEnd) {
pbCode = NULL;
}
for (DWORD n = 0; n < pExportDir->NumberOfNames; n++) {
if (pwOrdinals[n] == nFunc) {
pszName = (pdwNames != NULL)
? (PCHAR)RvaAdjust(pDosHeader, pdwNames[n]) : NULL;
break;
}
}
ULONG nOrdinal = pExportDir->Base + nFunc;
if (!pfExport(pContext, nOrdinal, pszName, pbCode)) {
break;
}
}
SetLastError(NO_ERROR);
return TRUE;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
}
BOOL WINAPI DetourEnumerateImportsEx(_In_opt_ HMODULE hModule,
_In_opt_ PVOID pContext,
_In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
_In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK_EX pfImportFunc)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
if (hModule == NULL) {
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
}
__try {
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return FALSE;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return FALSE;
}
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
PIMAGE_IMPORT_DESCRIPTOR iidp
= (PIMAGE_IMPORT_DESCRIPTOR)
RvaAdjust(pDosHeader,
pNtHeader->OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
if (iidp == NULL) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
for (; iidp->OriginalFirstThunk != 0; iidp++) {
PCSTR pszName = (PCHAR)RvaAdjust(pDosHeader, iidp->Name);
if (pszName == NULL) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
PIMAGE_THUNK_DATA pThunks = (PIMAGE_THUNK_DATA)
RvaAdjust(pDosHeader, iidp->OriginalFirstThunk);
PVOID * pAddrs = (PVOID *)
RvaAdjust(pDosHeader, iidp->FirstThunk);
HMODULE hFile = DetourGetContainingModule(pAddrs[0]);
if (pfImportFile != NULL) {
if (!pfImportFile(pContext, hFile, pszName)) {
break;
}
}
DWORD nNames = 0;
if (pThunks) {
for (; pThunks[nNames].u1.Ordinal; nNames++) {
DWORD nOrdinal = 0;
PCSTR pszFunc = NULL;
if (IMAGE_SNAP_BY_ORDINAL(pThunks[nNames].u1.Ordinal)) {
nOrdinal = (DWORD)IMAGE_ORDINAL(pThunks[nNames].u1.Ordinal);
}
else {
pszFunc = (PCSTR)RvaAdjust(pDosHeader,
(DWORD)pThunks[nNames].u1.AddressOfData + 2);
}
if (pfImportFunc != NULL) {
if (!pfImportFunc(pContext,
nOrdinal,
pszFunc,
&pAddrs[nNames])) {
break;
}
}
}
if (pfImportFunc != NULL) {
pfImportFunc(pContext, 0, NULL, NULL);
}
}
}
if (pfImportFile != NULL) {
pfImportFile(pContext, NULL, NULL);
}
SetLastError(NO_ERROR);
return TRUE;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
}
// Context for DetourEnumerateImportsThunk, which adapts "regular" callbacks for use with "Ex".
struct _DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT
{
PVOID pContext;
PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc;
};
// Callback for DetourEnumerateImportsEx that adapts DetourEnumerateImportsEx
// for use with a DetourEnumerateImports callback -- derefence the IAT and pass the value on.
static
BOOL
CALLBACK
DetourEnumerateImportsThunk(_In_ PVOID VoidContext,
_In_ DWORD nOrdinal,
_In_opt_ PCSTR pszFunc,
_In_opt_ PVOID* ppvFunc)
{
_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const * const
pContext = (_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT*)VoidContext;
return pContext->pfImportFunc(pContext->pContext, nOrdinal, pszFunc, ppvFunc ? *ppvFunc : NULL);
}
BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule,
_In_opt_ PVOID pContext,
_In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
_In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc)
{
if (pfImportFile == NULL || pfImportFunc == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const context = { pContext, pfImportFunc };
return DetourEnumerateImportsEx(hModule,
(PVOID)&context,
pfImportFile,
&DetourEnumerateImportsThunk);
}
static PDETOUR_LOADED_BINARY WINAPI GetPayloadSectionFromModule(HMODULE hModule)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
if (hModule == NULL) {
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
}
__try {
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return NULL;
}
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
PIMAGE_SECTION_HEADER pSectionHeaders
= (PIMAGE_SECTION_HEADER)((PBYTE)pNtHeader
+ sizeof(pNtHeader->Signature)
+ sizeof(pNtHeader->FileHeader)
+ pNtHeader->FileHeader.SizeOfOptionalHeader);
for (DWORD n = 0; n < pNtHeader->FileHeader.NumberOfSections; n++) {
if (strcmp((PCHAR)pSectionHeaders[n].Name, ".detour") == 0) {
if (pSectionHeaders[n].VirtualAddress == 0 ||
pSectionHeaders[n].SizeOfRawData == 0) {
break;
}
PBYTE pbData = (PBYTE)pDosHeader + pSectionHeaders[n].VirtualAddress;
DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pbData;
if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
break;
}
if (pHeader->nDataOffset == 0) {
pHeader->nDataOffset = pHeader->cbHeaderSize;
}
SetLastError(NO_ERROR);
return (PBYTE)pHeader;
}
}
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
}
DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule)
{
PDETOUR_LOADED_BINARY pBinary = GetPayloadSectionFromModule(hModule);
if (pBinary == NULL) {
// Error set by GetPayloadSectionFromModule.
return 0;
}
__try {
DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary;
if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
SetLastError(ERROR_INVALID_HANDLE);
return 0;
}
SetLastError(NO_ERROR);
return pHeader->cbDataSize;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_INVALID_HANDLE);
return 0;
}
}
_Writable_bytes_(*pcbData)
_Readable_bytes_(*pcbData)
_Success_(return != NULL)
PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
_In_ REFGUID rguid,
_Out_opt_ DWORD *pcbData)
{
PBYTE pbData = NULL;
if (pcbData) {
*pcbData = 0;
}
PDETOUR_LOADED_BINARY pBinary = GetPayloadSectionFromModule(hModule);
if (pBinary == NULL) {
// Error set by GetPayloadSectionFromModule.
return NULL;
}
__try {
DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary;
if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return NULL;
}
PBYTE pbBeg = ((PBYTE)pHeader) + pHeader->nDataOffset;
PBYTE pbEnd = ((PBYTE)pHeader) + pHeader->cbDataSize;
for (pbData = pbBeg; pbData < pbEnd;) {
DETOUR_SECTION_RECORD *pSection = (DETOUR_SECTION_RECORD *)pbData;
if (DetourAreSameGuid(pSection->guid, rguid)) {
if (pcbData) {
*pcbData = pSection->cbBytes - sizeof(*pSection);
}
SetLastError(NO_ERROR);
return (PBYTE)(pSection + 1);
}
pbData = (PBYTE)pSection + pSection->cbBytes;
}
SetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
}
_Writable_bytes_(*pcbData)
_Readable_bytes_(*pcbData)
_Success_(return != NULL)
PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
_Out_opt_ DWORD *pcbData)
{
for (HMODULE hMod = NULL; (hMod = DetourEnumerateModules(hMod)) != NULL;) {
PVOID pvData;
pvData = DetourFindPayload(hMod, rguid, pcbData);
if (pvData != NULL) {
return pvData;
}
}
SetLastError(ERROR_MOD_NOT_FOUND);
return NULL;
}
BOOL WINAPI DetourFreePayload(_In_ PVOID pvData)
{
BOOL fSucceeded = FALSE;
// If you have any doubts about the following code, please refer to the comments in DetourCopyPayloadToProcess.
HMODULE hModule = DetourGetContainingModule(pvData);
DETOUR_ASSERT(hModule != NULL);
if (hModule != NULL) {
fSucceeded = VirtualFree(hModule, 0, MEM_RELEASE);
DETOUR_ASSERT(fSucceeded);
if (fSucceeded) {
hModule = NULL;
}
}
return fSucceeded;
}
BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
_In_ DWORD cbData)
{
PDETOUR_EXE_RESTORE pder = (PDETOUR_EXE_RESTORE)pvData;
if (pder->cb != sizeof(*pder) || pder->cb > cbData) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return FALSE;
}
DWORD dwPermIdh = ~0u;
DWORD dwPermInh = ~0u;
DWORD dwPermClr = ~0u;
DWORD dwIgnore;
BOOL fSucceeded = FALSE;
BOOL fUpdated32To64 = FALSE;
if (pder->pclr != NULL && pder->clr.Flags != ((PDETOUR_CLR_HEADER)pder->pclr)->Flags) {
// If we had to promote the 32/64-bit agnostic IL to 64-bit, we can't restore
// that.
fUpdated32To64 = TRUE;
}
if (DetourVirtualProtectSameExecute(pder->pidh, pder->cbidh,
PAGE_EXECUTE_READWRITE, &dwPermIdh)) {
if (DetourVirtualProtectSameExecute(pder->pinh, pder->cbinh,
PAGE_EXECUTE_READWRITE, &dwPermInh)) {
CopyMemory(pder->pidh, &pder->idh, pder->cbidh);
CopyMemory(pder->pinh, &pder->inh, pder->cbinh);
if (pder->pclr != NULL && !fUpdated32To64) {
if (DetourVirtualProtectSameExecute(pder->pclr, pder->cbclr,
PAGE_EXECUTE_READWRITE, &dwPermClr)) {
CopyMemory(pder->pclr, &pder->clr, pder->cbclr);
VirtualProtect(pder->pclr, pder->cbclr, dwPermClr, &dwIgnore);
fSucceeded = TRUE;
}
}
else {
fSucceeded = TRUE;
}
VirtualProtect(pder->pinh, pder->cbinh, dwPermInh, &dwIgnore);
}
VirtualProtect(pder->pidh, pder->cbidh, dwPermIdh, &dwIgnore);
}
// Delete the payload after successful recovery to prevent repeated restore
if (fSucceeded) {
DetourFreePayload(pder);
pder = NULL;
}
return fSucceeded;
}
BOOL WINAPI DetourRestoreAfterWith()
{
PVOID pvData;
DWORD cbData;
pvData = DetourFindPayloadEx(DETOUR_EXE_RESTORE_GUID, &cbData);
if (pvData != NULL && cbData != 0) {
return DetourRestoreAfterWithEx(pvData, cbData);
}
SetLastError(ERROR_MOD_NOT_FOUND);
return FALSE;
}
// End of File

333
detours/src/uimports.cpp Normal file
View file

@ -0,0 +1,333 @@
//////////////////////////////////////////////////////////////////////////////
//
// Add DLLs to a module import table (uimports.cpp of detours.lib)
//
// Microsoft Research Detours Package, Version 4.0.1
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Note that this file is included into creatwth.cpp one or more times
// (once for each supported module format).
//
#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
#error detours.h version mismatch
#endif
// UpdateImports32 aka UpdateImports64
static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
HMODULE hModule,
__in_ecount(nDlls) LPCSTR *plpDlls,
DWORD nDlls)
{
BOOL fSucceeded = FALSE;
DWORD cbNew = 0;
BYTE * pbNew = NULL;
DWORD i;
SIZE_T cbRead;
DWORD n;
PBYTE pbModule = (PBYTE)hModule;
IMAGE_DOS_HEADER idh;
ZeroMemory(&idh, sizeof(idh));
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), &cbRead)
|| cbRead < sizeof(idh)) {
DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n",
pbModule, pbModule + sizeof(idh), GetLastError()));
finish:
if (pbNew != NULL) {
delete[] pbNew;
pbNew = NULL;
}
return fSucceeded;
}
IMAGE_NT_HEADERS_XX inh;
ZeroMemory(&inh, sizeof(inh));
if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), &cbRead)
|| cbRead < sizeof(inh)) {
DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n",
pbModule + idh.e_lfanew,
pbModule + idh.e_lfanew + sizeof(inh),
GetLastError()));
goto finish;
}
if (inh.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC_XX) {
DETOUR_TRACE(("Wrong size image (%04x != %04x).\n",
inh.OptionalHeader.Magic, IMAGE_NT_OPTIONAL_HDR_MAGIC_XX));
SetLastError(ERROR_INVALID_BLOCK);
goto finish;
}
// Zero out the bound table so loader doesn't use it instead of our new table.
inh.BOUND_DIRECTORY.VirtualAddress = 0;
inh.BOUND_DIRECTORY.Size = 0;
// Find the size of the mapped file.
DWORD dwSec = idh.e_lfanew +
FIELD_OFFSET(IMAGE_NT_HEADERS_XX, OptionalHeader) +
inh.FileHeader.SizeOfOptionalHeader;
for (i = 0; i < inh.FileHeader.NumberOfSections; i++) {
IMAGE_SECTION_HEADER ish;
ZeroMemory(&ish, sizeof(ish));
if (!ReadProcessMemory(hProcess, pbModule + dwSec + sizeof(ish) * i, &ish,
sizeof(ish), &cbRead)
|| cbRead < sizeof(ish)) {
DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %lu\n",
pbModule + dwSec + sizeof(ish) * i,
pbModule + dwSec + sizeof(ish) * (i + 1),
GetLastError()));
goto finish;
}
DETOUR_TRACE(("ish[%lu] : va=%08lx sr=%lu\n", i, ish.VirtualAddress, ish.SizeOfRawData));
// If the linker didn't suggest an IAT in the data directories, the
// loader will look for the section of the import directory to be used
// for this instead. Since we put out new IMPORT_DIRECTORY outside any
// section boundary, the loader will not find it. So we provide one
// explicitly to avoid the search.
//
if (inh.IAT_DIRECTORY.VirtualAddress == 0 &&
inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress &&
inh.IMPORT_DIRECTORY.VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData) {
inh.IAT_DIRECTORY.VirtualAddress = ish.VirtualAddress;
inh.IAT_DIRECTORY.Size = ish.SizeOfRawData;
}
}
if (inh.IMPORT_DIRECTORY.VirtualAddress != 0 && inh.IMPORT_DIRECTORY.Size == 0) {
// Don't worry about changing the PE file,
// because the load information of the original PE header has been saved and will be restored.
// The change here is just for the following code to work normally
PIMAGE_IMPORT_DESCRIPTOR pImageImport = (PIMAGE_IMPORT_DESCRIPTOR)(pbModule + inh.IMPORT_DIRECTORY.VirtualAddress);
do {
IMAGE_IMPORT_DESCRIPTOR ImageImport;
if (!ReadProcessMemory(hProcess, pImageImport, &ImageImport, sizeof(ImageImport), NULL)) {
DETOUR_TRACE(("ReadProcessMemory failed: %lu\n", GetLastError()));
goto finish;
}
inh.IMPORT_DIRECTORY.Size += sizeof(IMAGE_IMPORT_DESCRIPTOR);
if (!ImageImport.Name) {
break;
}
++pImageImport;
} while (TRUE);
DWORD dwLastError = GetLastError();
OutputDebugString(TEXT("[This PE file has an import table, but the import table size is marked as 0. This is an error.")
TEXT("If it is not repaired, the launched program will not work properly, Detours has automatically repaired its import table size for you! ! !]\r\n"));
if (GetLastError() != dwLastError) {
SetLastError(dwLastError);
}
}
DETOUR_TRACE((" Imports: %p..%p\n",
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress +
inh.IMPORT_DIRECTORY.Size));
// Calculate new import directory size. Note that since inh is from another
// process, inh could have been corrupted. We need to protect against
// integer overflow in allocation calculations.
DWORD nOldDlls = inh.IMPORT_DIRECTORY.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
DWORD obRem;
if (DWordMult(sizeof(IMAGE_IMPORT_DESCRIPTOR), nDlls, &obRem) != S_OK) {
DETOUR_TRACE(("too many new DLLs.\n"));
goto finish;
}
DWORD obOld;
if (DWordAdd(obRem, sizeof(IMAGE_IMPORT_DESCRIPTOR) * nOldDlls, &obOld) != S_OK) {
DETOUR_TRACE(("DLL entries overflow.\n"));
goto finish;
}
DWORD obTab = PadToDwordPtr(obOld);
// Check for integer overflow.
if (obTab < obOld) {
DETOUR_TRACE(("DLL entries padding overflow.\n"));
goto finish;
}
DWORD stSize;
if (DWordMult(sizeof(DWORD_XX) * 4, nDlls, &stSize) != S_OK) {
DETOUR_TRACE(("String table overflow.\n"));
goto finish;
}
DWORD obDll;
if (DWordAdd(obTab, stSize, &obDll) != S_OK) {
DETOUR_TRACE(("Import table size overflow\n"));
goto finish;
}
DWORD obStr = obDll;
cbNew = obStr;
for (n = 0; n < nDlls; n++) {
if (DWordAdd(cbNew, PadToDword((DWORD)strlen(plpDlls[n]) + 1), &cbNew) != S_OK) {
DETOUR_TRACE(("Overflow adding string table entry\n"));
goto finish;
}
}
pbNew = new BYTE [cbNew];
if (pbNew == NULL) {
DETOUR_TRACE(("new BYTE [cbNew] failed.\n"));
goto finish;
}
ZeroMemory(pbNew, cbNew);
PBYTE pbBase = pbModule;
PBYTE pbNext = pbBase
+ inh.OptionalHeader.BaseOfCode
+ inh.OptionalHeader.SizeOfCode
+ inh.OptionalHeader.SizeOfInitializedData
+ inh.OptionalHeader.SizeOfUninitializedData;
if (pbBase < pbNext) {
pbBase = pbNext;
}
DETOUR_TRACE(("pbBase = %p\n", pbBase));
PBYTE pbNewIid = FindAndAllocateNearBase(hProcess, pbModule, pbBase, cbNew);
if (pbNewIid == NULL) {
DETOUR_TRACE(("FindAndAllocateNearBase failed.\n"));
goto finish;
}
PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew;
IMAGE_THUNK_DATAXX *pt = NULL;
DWORD obBase = (DWORD)(pbNewIid - pbModule);
DWORD dwProtect = 0;
if (inh.IMPORT_DIRECTORY.VirtualAddress != 0) {
// Read the old import directory if it exists.
DETOUR_TRACE(("IMPORT_DIRECTORY perms=%lx\n", dwProtect));
if (!ReadProcessMemory(hProcess,
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
&piid[nDlls],
nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR), &cbRead)
|| cbRead < nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR)) {
DETOUR_TRACE(("ReadProcessMemory(imports) failed: %lu\n", GetLastError()));
goto finish;
}
}
for (n = 0; n < nDlls; n++) {
HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]);
if (FAILED(hrRet)) {
DETOUR_TRACE(("StringCchCopyA failed: %08lx\n", hrRet));
goto finish;
}
// After copying the string, we patch up the size "??" bits if any.
hrRet = ReplaceOptionalSizeA((char*)pbNew + obStr,
cbNew - obStr,
DETOURS_STRINGIFY(DETOURS_BITS_XX));
if (FAILED(hrRet)) {
DETOUR_TRACE(("ReplaceOptionalSizeA failed: %08lx\n", hrRet));
goto finish;
}
DWORD nOffset = obTab + (sizeof(IMAGE_THUNK_DATAXX) * (4 * n));
piid[n].OriginalFirstThunk = obBase + nOffset;
// We need 2 thunks for the import table and 2 thunks for the IAT.
// One for an ordinal import and one to mark the end of the list.
pt = ((IMAGE_THUNK_DATAXX*)(pbNew + nOffset));
pt[0].u1.Ordinal = IMAGE_ORDINAL_FLAG_XX + 1;
pt[1].u1.Ordinal = 0;
nOffset = obTab + (sizeof(IMAGE_THUNK_DATAXX) * ((4 * n) + 2));
piid[n].FirstThunk = obBase + nOffset;
pt = ((IMAGE_THUNK_DATAXX*)(pbNew + nOffset));
pt[0].u1.Ordinal = IMAGE_ORDINAL_FLAG_XX + 1;
pt[1].u1.Ordinal = 0;
piid[n].TimeDateStamp = 0;
piid[n].ForwarderChain = 0;
piid[n].Name = obBase + obStr;
obStr += PadToDword((DWORD)strlen(plpDlls[n]) + 1);
}
_Analysis_assume_(obStr <= cbNew);
#if 0
for (i = 0; i < nDlls + nOldDlls; i++) {
DETOUR_TRACE(("%8d. Look=%08x Time=%08x Fore=%08x Name=%08x Addr=%08x\n",
i,
piid[i].OriginalFirstThunk,
piid[i].TimeDateStamp,
piid[i].ForwarderChain,
piid[i].Name,
piid[i].FirstThunk));
if (piid[i].OriginalFirstThunk == 0 && piid[i].FirstThunk == 0) {
break;
}
}
#endif
if (!WriteProcessMemory(hProcess, pbNewIid, pbNew, obStr, NULL)) {
DETOUR_TRACE(("WriteProcessMemory(iid) failed: %lu\n", GetLastError()));
goto finish;
}
DETOUR_TRACE(("obBaseBef = %08lx..%08lx\n",
inh.IMPORT_DIRECTORY.VirtualAddress,
inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size));
DETOUR_TRACE(("obBaseAft = %08lx..%08lx\n", obBase, obBase + obStr));
// In this case the file didn't have an import directory in first place,
// so we couldn't fix the missing IAT above. We still need to explicitly
// provide an IAT to prevent to loader from looking for one.
//
if (inh.IAT_DIRECTORY.VirtualAddress == 0) {
inh.IAT_DIRECTORY.VirtualAddress = obBase;
inh.IAT_DIRECTORY.Size = cbNew;
}
inh.IMPORT_DIRECTORY.VirtualAddress = obBase;
inh.IMPORT_DIRECTORY.Size = cbNew;
/////////////////////// Update the NT header for the new import directory.
//
if (!DetourVirtualProtectSameExecuteEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
PAGE_EXECUTE_READWRITE, &dwProtect)) {
DETOUR_TRACE(("VirtualProtectEx(inh) write failed: %lu\n", GetLastError()));
goto finish;
}
inh.OptionalHeader.CheckSum = 0;
if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
DETOUR_TRACE(("WriteProcessMemory(idh) failed: %lu\n", GetLastError()));
goto finish;
}
DETOUR_TRACE(("WriteProcessMemory(idh:%p..%p)\n", pbModule, pbModule + sizeof(idh)));
if (!WriteProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) {
DETOUR_TRACE(("WriteProcessMemory(inh) failed: %lu\n", GetLastError()));
goto finish;
}
DETOUR_TRACE(("WriteProcessMemory(inh:%p..%p)\n",
pbModule + idh.e_lfanew,
pbModule + idh.e_lfanew + sizeof(inh)));
if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
dwProtect, &dwProtect)) {
DETOUR_TRACE(("VirtualProtectEx(idh) restore failed: %lu\n", GetLastError()));
goto finish;
}
fSucceeded = TRUE;
goto finish;
}

57
main.cpp Normal file
View file

@ -0,0 +1,57 @@
#include "main.h"
#include "modules/ModuleBase.hpp"
#include "modules/LibInherit.hpp"
#include "modules/AdminImpersonate.hpp"
#include "modules/RemoteLockBreak.hpp"
#include "modules/PolicyDisable.hpp"
#include <fstream>
#include <vector>
#include <memory>
#include <windows.h>
#include <winbase.h>
#include <detours.h>
static std::vector<std::unique_ptr<ModuleBase>> modules;
std::ofstream *log_out;
char sDetourLibrary[512];
void loadModules() {
char buffer[1000];
modules.emplace_back(std::make_unique<LibInherit>());
if (GetEnvironmentVariable("__POLICYTOOL_ADMINIMPERSONATE", buffer, sizeof(buffer)) && buffer[0] == '1') {
modules.emplace_back(std::make_unique<AdminImpersonate>());
}
if (GetEnvironmentVariable("__POLICYTOOL_REMOTELOCKBREAK", buffer, sizeof(buffer)) && buffer[0] == '1') {
modules.emplace_back(std::make_unique<RemoteLockBreak>());
}
if (GetEnvironmentVariable("__POLICYTOOL_POLICYDISABLE", buffer, sizeof(buffer)) && buffer[0] == '1') {
modules.emplace_back(std::make_unique<PolicyDisable>());
}
}
EXTERN_C BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) {
if (DetourIsHelperProcess()) {
return TRUE;
}
if (dwReason == DLL_PROCESS_ATTACH) {
log_out = new std::ofstream("C:\\PolicyTool\\log"+std::to_string(getpid())+".txt", std::ios_base::out | std::ios_base::app | std::ios_base::binary);
DetourRestoreAfterWith();
GetModuleFileNameA(hinst, sDetourLibrary, ARRAYSIZE(sDetourLibrary));
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
loadModules();
DetourTransactionCommit();
} else if (dwReason == DLL_PROCESS_DETACH) {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
modules.clear();
DetourTransactionCommit();
delete log_out;
}
return TRUE;
}

7
main.h Normal file
View file

@ -0,0 +1,7 @@
#include <fstream>
#define POLICYTOOL_SIZEREQ(x,y) (offsetof(x,y) + sizeof(((x*) NULL)->y))
#define POLICYTOOL_ALIGN(x,y) ((((uintptr_t) (x)) + (((y)/CHAR_BIT)-1)) & ~(((y)/CHAR_BIT)-1))
extern char sDetourLibrary[512];
extern std::ofstream *log_out;

View file

@ -0,0 +1,53 @@
#include "../main.h"
#include "ModuleBase.hpp"
#include <windows.h>
#include <shlobj.h>
#include <detours.h>
class AdminImpersonate : public ModuleBase {
inline static decltype(&IsUserAnAdmin) TrueIsUserAnAdmin;
inline static decltype(&CheckTokenMembership) TrueCheckTokenMembership;
static
BOOL __stdcall DetourIsUserAnAdmin() {
return TRUE;
}
static
BOOL APIENTRY DetourCheckTokenMembership(_In_opt_ HANDLE TokenHandle,
_In_ PSID SidToCheck, _Out_ PBOOL IsMember) {
// fetch and allocate the local admin structure
static SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
static PSID LocalAdministratorsGroup = NULL;
AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &LocalAdministratorsGroup);
// get the real value of the function - return if failure
BOOL bRealResult = TrueCheckTokenMembership(TokenHandle, SidToCheck, IsMember);
if (bRealResult == 0) return bRealResult;
// check if the local admin group is being requested
if (EqualSid(SidToCheck, LocalAdministratorsGroup)) {
// unconditionally say this user is running as an admin
*IsMember = TRUE;
}
return bRealResult;
}
public:
AdminImpersonate() {
TrueIsUserAnAdmin = IsUserAnAdmin;
TrueCheckTokenMembership = CheckTokenMembership;
DetourAttach(&reinterpret_cast<PVOID&>(TrueIsUserAnAdmin), reinterpret_cast<void*>(IsUserAnAdmin));
DetourAttach(&reinterpret_cast<PVOID&>(TrueCheckTokenMembership), reinterpret_cast<void*>(CheckTokenMembership));
}
~AdminImpersonate() {
DetourDetach(&reinterpret_cast<PVOID&>(TrueIsUserAnAdmin), reinterpret_cast<void*>(IsUserAnAdmin));
DetourDetach(&reinterpret_cast<PVOID&>(TrueCheckTokenMembership), reinterpret_cast<void*>(CheckTokenMembership));
}
};

46
modules/LibInherit.hpp Normal file
View file

@ -0,0 +1,46 @@
#include "../main.h"
#include "ModuleBase.hpp"
#include <windows.h>
#include <detours.h>
class LibInherit : public ModuleBase {
inline static decltype(&CreateProcessA) TrueCreateProcessA;
inline static decltype(&CreateProcessW) TrueCreateProcessW;
static
BOOL WINAPI DetourCreateProcessA(_In_opt_ LPCSTR lpApplicationName, _Inout_opt_ LPSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles, _In_ DWORD dwCreationFlags, _In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCSTR lpCurrentDirectory, _In_ LPSTARTUPINFOA lpStartupInfo, _Out_ LPPROCESS_INFORMATION lpProcessInformation
) {
return DetourCreateProcessWithDllExA(lpApplicationName, lpCommandLine, lpProcessAttributes,
lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory,
lpStartupInfo, lpProcessInformation, sDetourLibrary, TrueCreateProcessA);
}
static
BOOL WINAPI DetourCreateProcessW(_In_opt_ LPCWSTR lpApplicationName, _Inout_opt_ LPWSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles, _In_ DWORD dwCreationFlags, _In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCWSTR lpCurrentDirectory, _In_ LPSTARTUPINFOW lpStartupInfo, _Out_ LPPROCESS_INFORMATION lpProcessInformation
) {
return DetourCreateProcessWithDllExW(lpApplicationName, lpCommandLine, lpProcessAttributes,
lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory,
lpStartupInfo, lpProcessInformation, sDetourLibrary, TrueCreateProcessW);
}
public:
LibInherit() {
TrueCreateProcessA = CreateProcessA;
TrueCreateProcessW = CreateProcessW;
DetourAttach(&reinterpret_cast<PVOID&>(TrueCreateProcessA), reinterpret_cast<void*>(DetourCreateProcessA));
DetourAttach(&reinterpret_cast<PVOID&>(TrueCreateProcessW), reinterpret_cast<void*>(DetourCreateProcessW));
}
~LibInherit() {
DetourDetach(&reinterpret_cast<PVOID&>(TrueCreateProcessA), reinterpret_cast<void*>(DetourCreateProcessA));
DetourDetach(&reinterpret_cast<PVOID&>(TrueCreateProcessW), reinterpret_cast<void*>(DetourCreateProcessW));
}
};

7
modules/ModuleBase.hpp Normal file
View file

@ -0,0 +1,7 @@
#ifndef _MODULEBASE_HPP
#define _MODULEBASE_HPP
class ModuleBase {
public:
virtual ~ModuleBase() {}
};
#endif

62
modules/PolicyDisable.hpp Normal file
View file

@ -0,0 +1,62 @@
#include "../main.h"
#include "ModuleBase.hpp"
#include <string>
#include <string_view>
#include <windows.h>
#include "../wine_winternl.h"
#include <ntstatus.h>
#include <detours.h>
class PolicyDisable : public ModuleBase {
inline static decltype(&NtQueryValueKey) TrueNtQueryValueKey;
static
NTSTATUS WINAPI DetourNtQueryValueKey(_In_ HANDLE KeyHandle,
_In_ PUNICODE_STRING ValueName, _In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
_Out_opt_ PVOID KeyValueInformation, _In_ ULONG Length, _Out_ PULONG ResultLength) {
// lookup the size for the key name so we can allocate space for it
DWORD iKeyNameSize;
if (NtQueryKey(KeyHandle, KeyNameInformation, NULL, 0, &iKeyNameSize) != STATUS_BUFFER_TOO_SMALL) {
// should never happen
return STATUS_INVALID_PARAMETER;
}
// allocate space for name and lookup
NTSTATUS iStatus = -1;
PKEY_NAME_INFORMATION pNameInfo = (PKEY_NAME_INFORMATION)malloc(iKeyNameSize);
if (pNameInfo != NULL && NtQueryKey(KeyHandle, KeyNameInformation, pNameInfo,
iKeyNameSize, &iKeyNameSize) == STATUS_SUCCESS) {
// get wstring_view for quick comparisations
std::wstring_view sKeyName{pNameInfo->Name, pNameInfo->NameLength/2};
// return failure if key name contains "polic", "Polic" or "POLIC"
if (sKeyName.find(L"polic") != sKeyName.npos ||
sKeyName.find(L"Polic") != sKeyName.npos ||
sKeyName.find(L"POLIC") != sKeyName.npos) {
*log_out << "Denied policy access: " << std::string_view{reinterpret_cast<char*>(pNameInfo->Name), pNameInfo->NameLength} << "\r\n";
free(pNameInfo);
*ResultLength = 0;
return STATUS_OBJECT_NAME_NOT_FOUND;
}
*log_out << "Allowed policy access: " << std::string_view{reinterpret_cast<char*>(pNameInfo->Name), pNameInfo->NameLength} << "\r\n";
}
// clean up
free(pNameInfo);
// execute real function and return its value
return TrueNtQueryValueKey(KeyHandle, ValueName, KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
}
public:
PolicyDisable() {
TrueNtQueryValueKey = reinterpret_cast<decltype(&NtQueryValueKey)>(GetProcAddress(LoadLibraryW(L"ntdll.dll"), "NtQueryValueKey"));
DetourAttach(&reinterpret_cast<PVOID&>(TrueNtQueryValueKey), reinterpret_cast<void*>(DetourNtQueryValueKey));
}
~PolicyDisable() {
DetourDetach(&reinterpret_cast<PVOID&>(TrueNtQueryValueKey), reinterpret_cast<void*>(DetourNtQueryValueKey));
}
};

View file

@ -0,0 +1,65 @@
#include "../main.h"
#include "ModuleBase.hpp"
#include <windows.h>
#include "../wine_winternl.h"
#include <detours.h>
#define STATUS_SHARING_VIOLATION 0xC0000043
#define STATUS_ACCESS_DENIED 0xC0000022
class RemoteLockBreak : public ModuleBase {
inline static decltype(&NtOpenFile) TrueNtOpenFile;
inline static decltype(&NtCreateFile) TrueNtCreateFile;
static
NTSTATUS NTAPI DetourNtOpenFile(OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG ShareAccess, IN ULONG OpenOptions) {
DWORD iStatus = TrueNtOpenFile(FileHandle, DesiredAccess, ObjectAttributes,
IoStatusBlock, ShareAccess, OpenOptions);
if (iStatus == STATUS_SHARING_VIOLATION || iStatus == STATUS_ACCESS_DENIED) {
if (CloseHandle(FileHandle)) {
// try operation again now that file is closed
iStatus = TrueNtOpenFile(FileHandle, DesiredAccess, ObjectAttributes,
IoStatusBlock, ShareAccess, OpenOptions);
}
}
return iStatus;
}
static
NTSTATUS NTAPI DetourNtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess,
IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength) {
NTSTATUS iStatus = TrueNtCreateFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize,
FileAttributes, ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength);
if (iStatus == STATUS_SHARING_VIOLATION || iStatus == STATUS_ACCESS_DENIED) {
if (CloseHandle(FileHandle)) {
// try operation again now that file is closed
iStatus = TrueNtCreateFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize,
FileAttributes, ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength);
}
}
return iStatus;
}
public:
RemoteLockBreak() {
TrueNtOpenFile = reinterpret_cast<decltype(&NtOpenFile)>(GetProcAddress(LoadLibraryW(L"ntdll.dll"), "NtOpenFile"));
TrueNtCreateFile = reinterpret_cast<decltype(&NtCreateFile)>(GetProcAddress(LoadLibraryW(L"ntdll.dll"), "NtCreateFile"));
DetourAttach(&reinterpret_cast<PVOID&>(TrueNtOpenFile), reinterpret_cast<void*>(DetourNtOpenFile));
DetourAttach(&reinterpret_cast<PVOID&>(TrueNtCreateFile), reinterpret_cast<void*>(DetourNtCreateFile));
}
~RemoteLockBreak() {
DetourDetach(&reinterpret_cast<PVOID&>(TrueNtOpenFile), reinterpret_cast<void*>(DetourNtOpenFile));
DetourDetach(&reinterpret_cast<PVOID&>(TrueNtCreateFile), reinterpret_cast<void*>(DetourNtCreateFile));
}
};

14
test.cpp Normal file
View file

@ -0,0 +1,14 @@
#include <cstdio>
#include <windows.h>
#include <libloaderapi.h>
int main() {
SetEnvironmentVariableW(L"__POLICYTOOL_ADMINIMPERSONATE", L"1");
SetEnvironmentVariableW(L"__POLICYTOOL_REMOTELOCKBREAK", L"1");
SetEnvironmentVariableW(L"__POLICYTOOL_POLICYDISABLE", L"1");
auto dll = LoadLibraryW(L"libPolicyTool.dll");
puts("Load success!");
}

4815
wine_winternl.h Normal file

File diff suppressed because it is too large Load diff