Skip to content

Commit

Permalink
Add FreeSeh module.
Browse files Browse the repository at this point in the history
  • Loading branch information
can1357 committed Oct 21, 2019
1 parent aff48e7 commit e641797
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 0 deletions.
5 changes: 5 additions & 0 deletions ByePg.sln
Expand Up @@ -11,6 +11,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InfinityHookFix", "Infinity
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ThreadTracing", "ThreadTracing (WIP)\ThreadTracing.vcxproj", "{19744122-F774-4945-882A-84F17D549CF1}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSeh", "FreeSeh\FreeSeh.vcxproj", "{9E92BC83-28B7-4878-8BC9-BE670A6335BC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Release|x64 = Release|x64
Expand All @@ -28,6 +30,9 @@ Global
{19744122-F774-4945-882A-84F17D549CF1}.Release|x64.ActiveCfg = Release|x64
{19744122-F774-4945-882A-84F17D549CF1}.Release|x64.Build.0 = Release|x64
{19744122-F774-4945-882A-84F17D549CF1}.Release|x64.Deploy.0 = Release|x64
{9E92BC83-28B7-4878-8BC9-BE670A6335BC}.Release|x64.ActiveCfg = Release|x64
{9E92BC83-28B7-4878-8BC9-BE670A6335BC}.Release|x64.Build.0 = Release|x64
{9E92BC83-28B7-4878-8BC9-BE670A6335BC}.Release|x64.Deploy.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
70 changes: 70 additions & 0 deletions FreeSeh/FreeSeh.vcxproj
@@ -0,0 +1,70 @@
<?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="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9E92BC83-28B7-4878-8BC9-BE670A6335BC}</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>ThreadTracing</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<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>
</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)'=='Release|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<OutDir>$(SolutionDir)Output\</OutDir>
<EnableInf2cat>false</EnableInf2cat>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<SDLCheck>false</SDLCheck>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ControlFlowGuard>false</ControlFlowGuard>
</ClCompile>
<Link>
<EntryPointSymbol>EntryPoint</EntryPointSymbol>
<AdditionalDependencies>$(SolutionDir)Output\ByePgLib.lib;%(AdditionalDependencies);$(KernelBufferOverflowLib);$(DDK_LIB_PATH)ntoskrnl.lib;$(DDK_LIB_PATH)hal.lib;$(DDK_LIB_PATH)wmilib.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfLdr.lib;$(KMDF_LIB_PATH)$(KMDF_VER_PATH)\WdfDriverEntry.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="NT\SEH.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
16 changes: 16 additions & 0 deletions FreeSeh/FreeSeh.vcxproj.filters
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<Filter Include="NT">
<UniqueIdentifier>{eb4c6698-ed3d-4c22-b6a5-aeaff0f08912}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="NT\SEH.h">
<Filter>NT</Filter>
</ClInclude>
</ItemGroup>
</Project>
6 changes: 6 additions & 0 deletions FreeSeh/FreeSeh.vcxproj.user
@@ -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>
116 changes: 116 additions & 0 deletions FreeSeh/NT/SEH.h
@@ -0,0 +1,116 @@
#pragma once
#include <ntimage.h>
#include <ntifs.h>
#include <intrin.h>

#define UNW_FLAG_EHANDLER 1

typedef struct _RUNTIME_FUNCTION
{
ULONG BeginAddress;
ULONG EndAddress;
ULONG UnwindData;
} RUNTIME_FUNCTION, * PRUNTIME_FUNCTION;

typedef struct _C_SCOPE_TABLE_ENTRY
{
ULONG Begin;
ULONG End;
ULONG Handler;
ULONG Target;
} C_SCOPE_TABLE_ENTRY, * PC_SCOPE_TABLE_ENTRY;

typedef struct _C_SCOPE_TABLE
{
ULONG NumEntries;
C_SCOPE_TABLE_ENTRY Table[ 1 ];
} C_SCOPE_TABLE, * PC_SCOPE_TABLE;

extern "C" NTSYSAPI PEXCEPTION_ROUTINE RtlVirtualUnwind(
LONG HandlerType,
DWORD64 ImageBase,
DWORD64 ControlPc,
PRUNTIME_FUNCTION FunctionEntry,
PCONTEXT ContextRecord,
PVOID * HandlerData,
PDWORD64 EstablisherFrame,
PVOID ContextPointers
);

extern "C" IMAGE_DOS_HEADER __ImageBase;

namespace SEH
{
static RUNTIME_FUNCTION* LookupPrivateFunctionEntry( ULONG64 Rip )
{
IMAGE_NT_HEADERS* NtHdrs = ( IMAGE_NT_HEADERS* ) ( PUCHAR( &__ImageBase ) + __ImageBase.e_lfanew );

IMAGE_DATA_DIRECTORY& ExceptionDirectory = NtHdrs->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXCEPTION ];
RUNTIME_FUNCTION* FunctionTableIt = ( RUNTIME_FUNCTION* ) ( PUCHAR( &__ImageBase ) + ExceptionDirectory.VirtualAddress );
RUNTIME_FUNCTION* FunctionTableEnd = ( RUNTIME_FUNCTION* ) ( PUCHAR( &__ImageBase ) + ExceptionDirectory.VirtualAddress + ExceptionDirectory.Size );

Rip -= ( ULONG64 ) &__ImageBase;

while ( FunctionTableIt < FunctionTableEnd )
{
if ( FunctionTableIt->BeginAddress <= Rip && Rip < FunctionTableIt->EndAddress )
return FunctionTableIt;
else
FunctionTableIt++;
}

return nullptr;
}

static LONG HandleException( CONTEXT* ContextRecord, EXCEPTION_RECORD* ExceptionRecord )
{
if ( RUNTIME_FUNCTION* RtFn = SEH::LookupPrivateFunctionEntry( ContextRecord->Rip ) )
{
ULONG ExceptionRva = ContextRecord->Rip - ( ULONG64 ) &__ImageBase;
CONTEXT ContextRecordVt = *ContextRecord;

PVOID HandlerData = nullptr;
ULONG64 EstablisherFrame = 0;
EXCEPTION_ROUTINE* Routine = RtlVirtualUnwind(
UNW_FLAG_EHANDLER,
( ULONG64 ) &__ImageBase,
ContextRecord->Rip,
RtFn,
&ContextRecordVt,
&HandlerData,
&EstablisherFrame,
nullptr
);

// Assuming Routine == jmp to _C_specific_handler
if ( Routine )
{
C_SCOPE_TABLE* ScopeTable = ( C_SCOPE_TABLE* ) HandlerData;

for ( int i = 0; i < ScopeTable->NumEntries; i++ )
{
if ( ScopeTable->Table[ i ].Begin <= ExceptionRva && ExceptionRva < ScopeTable->Table[ i ].End )
{
if ( ScopeTable->Table[ i ].Handler == 1 )
{
ContextRecordVt.Rsp -= 0x8;
*( ULONG64* ) ContextRecordVt.Rsp = ContextRecordVt.Rip;
ContextRecordVt.Rsp -= 0x28;
ContextRecordVt.Rip = ( ULONG64 ) &__ImageBase + ScopeTable->Table[ i ].Target;
ContextRecordVt.Rax = ExceptionRecord->ExceptionCode;
*ContextRecord = ContextRecordVt;
return EXCEPTION_CONTINUE_EXECUTION;
}
else
{
// No exception filter support!
__debugbreak();
}
}
}
}
}

return EXCEPTION_EXECUTE_HANDLER;
}
};
21 changes: 21 additions & 0 deletions FreeSeh/main.cpp
@@ -0,0 +1,21 @@
#include <ntifs.h>
#include <ntimage.h>
#include "..\Includes\ByePg.h"
#include "NT/SEH.h"

#define Log(...) DbgPrintEx( DPFLTR_SYSTEM_ID, DPFLTR_ERROR_LEVEL, "[ByePg] " __VA_ARGS__ )

void EntryPoint()
{
NTSTATUS ByePgStatus = ByePgInitialize( SEH::HandleException, TRUE );
ASSERT( NT_SUCCESS( ByePgStatus ) );

__try
{
__debugbreak();
}
__except ( 1 )
{
Log( "Exception code: %x!\n", GetExceptionCode() );
}
}
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -11,4 +11,5 @@ https://blog.can.ac/2019/10/19/byepg-defeating-patchguard-using-exception-hookin
- `\ByePgLib` contains the base library
- `\ExceptionHookingDemo` demonstrates the exception handler
- `\InfinityHookFix` contains a sample rendering the recent InfinityHook patch by Microsoft useless
- `\FreeSeh` contains a SEH-via-ByePg module letting you use SEH in manual mapped images bypassing PatchGuard's inverted function table checks
- `\ThreadTracing (WIP)` contains a work-in-progress module to trace context switches by abusing the #GP(0) raised when a non-cannonical address is written to IA32_FS_BASE, IA32_GS_BASE, IA32_KERNEL_GS_BASE MSRs.

0 comments on commit e641797

Please sign in to comment.