This commit is contained in:
Yasser Tahiri 2020-12-12 23:02:14 +01:00
parent ff64060957
commit c01b961423
12 changed files with 734 additions and 0 deletions

View file

@ -0,0 +1,68 @@
#include <utility>
#include "mem_scan.hpp"
#include "mem_iter.hpp"
#include "mem_util.hpp"
template <typename ...Args>
__forceinline void output_to_console( const char* str, Args&&... args )
{
DbgPrintEx( 77, 0, str, std::forward<Args>( args )... );
}
__forceinline void output_appended( const char* str )
{
output_to_console( "[!] watermark_disabler: %s\n", str );
}
NTSTATUS driver_entry( )
{
output_appended( "loaded" );
/* we have to attach to csrss, or any process with win32k mapped into it, because win32k is not mapped in system modules */
const auto csrss_process = impl::search_for_process( "csrss.exe" );
if ( !csrss_process )
{
output_appended( "failed to find csrss.exe" );
return STATUS_UNSUCCESSFUL;
}
impl::unique_attachment csrss_attach( csrss_process );
output_appended( "attached to csrss" );
const auto win32kfull_info = impl::search_for_module( "win32kfull.sys" );
if ( !win32kfull_info )
{
output_appended( "failed to find the win32kfull.sys module" );
return STATUS_UNSUCCESSFUL;
}
output_to_console( "[!] watermark_disabler: win32kfull.sys $ 0x%p\n", win32kfull_info->image_base );
const auto gpsi_instruction = impl::search_for_signature( win32kfull_info, "\x48\x8b\x0d\x00\x00\x00\x00\x48\x8b\x05\x00\x00\x00\x00\x0f\xba\x30\x0c", "xxx????xxx????xxxx" );
if ( !gpsi_instruction )
{
output_appended( "failed to find gpsi, signature outdated?" );
return STATUS_UNSUCCESSFUL;
}
const auto gpsi = *reinterpret_cast< std::uint64_t* >( impl::resolve_mov( gpsi_instruction ) );
if ( !gpsi )
{
output_appended( "gpsi is somehow nullptr" );
return STATUS_UNSUCCESSFUL;
}
output_to_console( "[!] watermark_disabler: gpsi $ 0x%p\n", gpsi );
*reinterpret_cast< std::uint32_t* >( gpsi + 0x874 ) = 0;
output_appended( "watermark disabled" );
return STATUS_UNSUCCESSFUL;
}

View file

@ -0,0 +1,55 @@
#pragma once
#include <cstdint>
#include <ntifs.h>
#include <stdlib.h>
namespace nt
{
struct rtl_module_info
{
char pad_0[ 0x10 ];
PVOID image_base;
ULONG image_size;
char pad_1[ 0xa ];
USHORT file_name_offset;
UCHAR full_path[ _MAX_PATH - 4 ];
};
struct rtl_modules
{
ULONG count;
rtl_module_info modules[ 1 ];
};
struct image_file_header
{
USHORT machine;
USHORT number_of_sections;
};
struct image_section_header
{
std::uint8_t name[ 8 ];
union
{
std::uint32_t physical_address;
std::uint32_t virtual_size;
} misc;
std::uint32_t virtual_address;
std::uint32_t size_of_raw_data;
std::uint32_t pointer_to_raw_data;
std::uint32_t pointer_to_relocations;
std::uint32_t pointer_to_line_numbers;
std::uint16_t number_of_relocations;
std::uint16_t number_of_line_numbers;
std::uint32_t characteristics;
};
struct image_nt_headers
{
std::uint32_t signature;
image_file_header file_header;
};
}

View file

@ -0,0 +1,79 @@
#pragma once
#include "mem_defs.hpp"
#include "util_raii.hpp"
namespace impl
{
extern "C" NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation( ULONG, PVOID, ULONG, PULONG );
extern "C" NTSYSAPI PIMAGE_NT_HEADERS NTAPI RtlImageNtHeader( PVOID );
nt::rtl_module_info* search_for_module( const char* module_name )
{
/* allocate a pool with 0x2000 bytes because we don't know how big the module list is */
auto needed_bytes = 8192ul;
impl::pool buffer_pool( ExAllocatePoolWithTag( PagedPool, needed_bytes, 'udoM' ) );
if ( !buffer_pool.get( ) )
return nullptr;
auto current_status = ZwQuerySystemInformation( 11, buffer_pool.get( ), needed_bytes, &needed_bytes );
/* keep allocating until the function returns STATUS_SUCCESS */
while ( current_status == STATUS_INFO_LENGTH_MISMATCH )
{
buffer_pool.reset( ExAllocatePoolWithTag( PagedPool, needed_bytes, 'udoM' ) );
if ( !buffer_pool )
return nullptr;
current_status = ZwQuerySystemInformation( 11, buffer_pool.get( ), needed_bytes, &needed_bytes );
}
if ( !NT_SUCCESS( current_status ) )
return nullptr;
const auto current_modules = static_cast< nt::rtl_modules* >( buffer_pool.get( ) );
if ( !current_modules )
return nullptr;
/* loop the module list, and find the needed module */
for ( auto i = 0u; i < current_modules->count; i++ )
{
const auto current_module = &current_modules->modules[ i ];
if ( !current_module )
continue;
/* file_name_offset is the offset from full_path to the actual file's name, instead of file path */
const auto file_name = reinterpret_cast< const char* >( current_module->file_name_offset + current_module->full_path );
if ( std::strcmp( file_name, module_name ) != 0 )
continue;
return current_module;
}
return nullptr;
}
nt::image_section_header* search_for_section( const nt::rtl_module_info* module, const char* section_name )
{
if ( !module )
return nullptr;
const auto nt_header = reinterpret_cast< nt::image_nt_headers* >( RtlImageNtHeader( module->image_base ) );
const auto section_header = reinterpret_cast< nt::image_section_header* >( nt_header + 1 );
for ( auto i = 0u; i < nt_header->file_header.number_of_sections; i++ )
{
const auto current_section = &section_header[ i ];
const auto current_section_name = reinterpret_cast< const char* >( current_section->name );
if ( !std::strcmp( current_section_name, section_name ) )
return current_section;
}
return nullptr;
}
}

View file

@ -0,0 +1,77 @@
#pragma once
#include "mem_util.hpp"
#include "mem_iter.hpp"
#include "util_raii.hpp"
namespace impl
{
inline bool search_for_signature_helper( const std::uint8_t* data, const std::uint8_t* signature, const char* mask )
{
// check if page is correct & readable (this internally checks PTE, PDE, ...)
if ( !MmIsAddressValid( const_cast< std::uint8_t* >( data ) ) )
return false;
// iterate through validity of the mask (mask & signature are equal
for ( ; *mask; ++mask, ++data, ++signature )
if ( *mask == 'x' && *data != *signature ) // if mask is 'x' (a match), and the current byte is not equal to the byte in the signature, then return false.
return false;
return true;
}
std::uint8_t* search_for_signature( const nt::rtl_module_info* module, const char* signature, const char* signature_mask )
{
if ( !module )
return nullptr;
const auto module_start = reinterpret_cast< std::uint8_t* >( module->image_base );
const auto module_size = module_start + module->image_size;
/* iterate the entire module */
for ( auto segment = module_start; segment < module_size; segment++ )
{
if ( search_for_signature_helper( segment, reinterpret_cast< std::uint8_t* >( const_cast< char* >( signature ) ), signature_mask ) )
return segment;
}
return nullptr;
}
extern "C" NTSYSAPI PCHAR NTAPI PsGetProcessImageFileName( PEPROCESS );
PEPROCESS search_for_process( const char* process_name )
{
const auto kernel_module_info = search_for_module( "ntoskrnl.exe" );
if ( !kernel_module_info )
return nullptr;
/* we are scanning for a conditional jump, that jumps to a call to the unexported function that we want, so we follow the jump, then follow the call to get to the function. */
const auto conditional_instruction = search_for_signature( kernel_module_info, "\x79\xdc\xe9", "xxx" );
if ( !conditional_instruction )
return nullptr;
const auto call_instruction = follow_conditional_jump( conditional_instruction );
if ( !call_instruction )
return nullptr;
const auto PsGetNextProcess = follow_call< PEPROCESS( __stdcall* )( PEPROCESS ) >( call_instruction );
if ( !PsGetNextProcess )
return nullptr;
PEPROCESS previous_process = PsGetNextProcess( nullptr );
while ( previous_process )
{
if ( !std::strcmp( PsGetProcessImageFileName( previous_process ), process_name ) )
return previous_process;
previous_process = PsGetNextProcess( previous_process );
}
return nullptr;
}
}

View file

@ -0,0 +1,74 @@
#pragma once
#include <string>
#include <memory>
#include "mem_defs.hpp"
namespace impl
{
class unique_attachment
{
private:
KAPC_STATE apc_state{};
PEPROCESS process{};
public:
explicit unique_attachment( PEPROCESS process )
{
if ( !process )
return;
KeStackAttachProcess( process, &apc_state );
}
~unique_attachment( )
{
KeUnstackDetachProcess( &apc_state );
ObfDereferenceObject( process );
}
};
bool write_to_read_only( void* destination, void* source, std::size_t size )
{
const std::unique_ptr<MDL, decltype( &IoFreeMdl )> mdl( IoAllocateMdl( destination, static_cast< ULONG >( size ), FALSE, FALSE, nullptr ), &IoFreeMdl );
if ( !mdl )
return false;
MmProbeAndLockPages( mdl.get( ), KernelMode, IoReadAccess );
const auto mapped_page = MmMapLockedPagesSpecifyCache( mdl.get( ), KernelMode, MmNonCached, nullptr, FALSE, NormalPagePriority );
if ( !mapped_page )
return false;
if ( !NT_SUCCESS( MmProtectMdlSystemAddress( mdl.get( ), PAGE_EXECUTE_READWRITE ) ) )
return false;
std::memcpy( mapped_page, source, size );
MmUnmapLockedPages( mapped_page, mdl.get( ) );
MmUnlockPages( mdl.get( ) );
return true;
}
template <typename T = std::uint8_t*>
__forceinline T follow_call( std::uint8_t* address )
{
/* + 1 is the address of the calle, + 5 is the size of a call instruction */
return ( T )( address + *reinterpret_cast< std::int32_t* >( address + 1 ) + 5 );
}
template <typename T = std::uint8_t*>
__forceinline T follow_conditional_jump( std::uint8_t* address )
{
/* + 1 is the offset of the jump, + 2 is the size of a conditional jump */
return ( T )( address + *reinterpret_cast< std::int8_t* >( address + 1 ) + 2 );
}
template <typename T = std::uint8_t*>
__forceinline T resolve_mov( std::uint8_t* address )
{
/* + 3 is the address of the source, + 7 is the size of a mov instruction */
return ( T )( address + *reinterpret_cast<std::int32_t*>( address + 3 ) + 7 );
}
}

View file

@ -0,0 +1,29 @@
#pragma once
#include <memory>
#include <ntifs.h>
namespace impl
{
struct unique_pool
{
void operator( )( void* pool )
{
if ( pool )
ExFreePoolWithTag( pool, 0 );
}
};
using pool = std::unique_ptr<void, unique_pool>;
struct unique_object
{
void operator( )( void* object )
{
if ( object )
ObfDereferenceObject( object );
}
};
template <typename T>
using object = std::unique_ptr<std::remove_pointer_t<T>, unique_object>;
}

View file

@ -0,0 +1,178 @@
<?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>{99ADE163-A416-41D2-991E-99E598476DB8}</ProjectGuid>
<TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid>
<TargetFrameworkVersion>
</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<RootNamespace>watermark_disabler</RootNamespace>
<WindowsTargetPlatformVersion>10.0.18362.0</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>
</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>
</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>
</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>
</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>
</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>
</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>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(IncludePath)</IncludePath>
<EnableInf2cat>false</EnableInf2cat>
</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)'=='Release|x64'">
<ClCompile>
<LanguageStandard>stdcpplatest</LanguageStandard>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<TreatWarningAsError>false</TreatWarningAsError>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ControlFlowGuard>false</ControlFlowGuard>
</ClCompile>
<Link>
<EntryPointSymbol>driver_entry</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="mem_defs.hpp" />
<ClInclude Include="mem_iter.hpp" />
<ClInclude Include="mem_scan.hpp" />
<ClInclude Include="mem_util.hpp" />
<ClInclude Include="util_raii.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

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

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<SignMode>Off</SignMode>
</PropertyGroup>
</Project>