Initial commit

This commit is contained in:
us3r-syn
2025-06-02 14:56:57 +02:00
commit a5bd97941c
17 changed files with 2766 additions and 0 deletions
+106
View File
@@ -0,0 +1,106 @@
---
AccessModifierOffset: '-4'
# AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveMacros: 'true'
AlignConsecutiveAssignments: 'true'
AlignConsecutiveDeclarations: 'true'
AlignEscapedNewlines: Right
AlignOperands: 'true'
AlignTrailingComments: 'true'
AllowAllArgumentsOnNextLine: 'false'
AllowAllConstructorInitializersOnNextLine: 'false'
AllowAllParametersOfDeclarationOnNextLine: 'false'
AllowShortBlocksOnASingleLine: 'true'
# AllowShortCaseLabelsOnASingleLine: 'false'
AllowShortCaseLabelsOnASingleLine: 'true'
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: 'false'
# AllowShortLambdasOnASingleLine: Inline
# AllowShortLoopsOnASingleLine: 'true'
AllowShortLoopsOnASingleLine: 'false'
AlwaysBreakAfterDefinitionReturnType: 'false'
AlwaysBreakAfterReturnType: None
# AlwaysBreakBeforeMultilineStrings: 'false'
# AlwaysBreakTemplateDeclarations: 'No'
BinPackArguments: 'false'
BinPackParameters: 'false'
BraceWrapping:
# AfterCaseLabel: 'true'
AfterClass: 'true'
AfterControlStatement: 'true'
AfterEnum: 'true'
AfterFunction: 'true'
AfterNamespace: 'true'
AfterObjCDeclaration: 'true'
AfterStruct: 'true'
AfterUnion: 'true'
AfterExternBlock: 'false'
BeforeCatch: 'true'
BeforeElse: 'true'
IndentBraces: 'false'
SplitEmptyFunction: 'true'
SplitEmptyRecord: 'true'
SplitEmptyNamespace: 'true'
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: 'false'
BreakConstructorInitializers: AfterColon
# BreakInheritanceList: AfterColon
# BreakStringLiterals: 'true'
ColumnLimit: '0'
CommentPragmas: Suppress
CompactNamespaces: 'false'
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
ConstructorInitializerIndentWidth: '2'
ContinuationIndentWidth: '2'
Cpp11BracedListStyle: 'false'
DerivePointerAlignment: 'false'
# DisableFormat: 'false'
# ExperimentalAutoDetectBinPacking: 'false'
FixNamespaceComments: 'false'
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^.*(precomp:pch:stdafx)'
Priority: -1
- Regex: '^".*"'
Priority: 1
- Regex: '^<.*>'
Priority: 2
- Regex: '.*'
Priority: 3
IndentCaseLabels: 'true'
# IndentExternBlock: 'false'
IndentPPDirectives: None
IndentWidth: '2'
IndentWrappedFunctionNames: 'false'
KeepEmptyLinesAtTheStartOfBlocks: 'false'
# Language: Cpp
MacroBlockBegin: "BEGIN_TEST_METHOD_PROPERTIES|BEGIN_MODULE|BEGIN_TEST_CLASS|BEGIN_TEST_METHOD"
MacroBlockEnd: "END_TEST_METHOD_PROPERTIES|END_MODULE|END_TEST_CLASS|END_TEST_METHOD"
MaxEmptyLinesToKeep: '1'
NamespaceIndentation: All
PointerAlignment: Left
ReflowComments: 'false'
SortIncludes: 'false'
SortUsingDeclarations: 'true'
SpaceAfterCStyleCast: 'false'
# SpaceAfterLogicalNot: 'false'
SpaceAfterTemplateKeyword: 'false'
SpaceBeforeAssignmentOperators: 'true'
# SpaceBeforeCpp11BracedList: 'true'
# SpaceBeforeCtorInitializerColon: 'false'
# SpaceBeforeInheritanceColon: 'false'
SpaceBeforeParens: ControlStatements
# SpaceBeforeRangeBasedForLoopColon: 'false'
SpaceInEmptyParentheses: 'false'
SpacesBeforeTrailingComments: '1'
SpacesInAngles: 'false'
# SpacesInContainerLiterals: 'false'
SpacesInCStyleCastParentheses: 'false'
SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false'
Standard: Cpp11
TabWidth: '2'
UseTab: Never
...
+5
View File
@@ -0,0 +1,5 @@
.vscode/
bin/
build/
build32/
build64/
+79
View File
@@ -0,0 +1,79 @@
cmake_minimum_required(VERSION 3.10)
project(shadow_stack LANGUAGES C ASM)
enable_language(ASM_MASM)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
find_package(WDK REQUIRED)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${ARCH})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${ARCH})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${ARCH})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /WX")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 /WX")
set(SIGNTOOL_PATH ${WDK_ROOT}/bin/${WDK_VERSION}/x64/signtool.exe)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
include_directories(src)
wdk_add_driver(
shadow_stack_driver
# [WINVER <winver_version>]
NTDDI_VERSION 0x0A00000E
${CMAKE_SOURCE_DIR}/src/driver.c
${CMAKE_SOURCE_DIR}/src/driver/ioctl.c
${CMAKE_SOURCE_DIR}/src/driver/utils.c
)
target_link_options(
shadow_stack_driver
PRIVATE
"/CETCOMPAT"
)
add_custom_command(
TARGET shadow_stack_driver
POST_BUILD
COMMAND ${SIGNTOOL_PATH} sign /fd SHA256 $<TARGET_FILE:shadow_stack_driver>
)
add_executable(
shadow_stack_client
${CMAKE_SOURCE_DIR}/src/client.c
${CMAKE_SOURCE_DIR}/src/client/utils.c
)
target_link_options(
shadow_stack_client
PRIVATE
"/CETCOMPAT"
)
add_library(
asm_target
STATIC
${CMAKE_SOURCE_DIR}/src/driver/utils.asm
)
target_compile_options(
shadow_stack_driver
PRIVATE
"/Od"
)
target_link_libraries(
shadow_stack_driver
asm_target
)
+221
View File
@@ -0,0 +1,221 @@
# Redistribution and use is allowed under the OSI-approved 3-clause BSD license.
# Copyright (c) 2018 Sergey Podobry (sergey.podobry at gmail.com). All rights reserved.
#.rst:
# FindWDK
# ----------
#
# This module searches for the installed Windows Development Kit (WDK) and
# exposes commands for creating kernel drivers and kernel libraries.
#
# Output variables:
# - `WDK_FOUND` -- if false, do not try to use WDK
# - `WDK_ROOT` -- where WDK is installed
# - `WDK_VERSION` -- the version of the selected WDK
# - `WDK_WINVER` -- the WINVER used for kernel drivers and libraries
# (default value is `0x0601` and can be changed per target or globally)
# - `WDK_NTDDI_VERSION` -- the NTDDI_VERSION used for kernel drivers and libraries,
# if not set, the value will be automatically calculated by WINVER
# (default value is left blank and can be changed per target or globally)
#
# Example usage:
#
# find_package(WDK REQUIRED)
#
# wdk_add_library(KmdfCppLib STATIC KMDF 1.15
# KmdfCppLib.h
# KmdfCppLib.cpp
# )
# target_include_directories(KmdfCppLib INTERFACE .)
#
# wdk_add_driver(KmdfCppDriver KMDF 1.15
# Main.cpp
# )
# target_link_libraries(KmdfCppDriver KmdfCppLib)
#
if(DEFINED ENV{WDKContentRoot})
file(GLOB WDK_NTDDK_FILES
"$ENV{WDKContentRoot}/Include/*/km/ntddk.h" # WDK 10
"$ENV{WDKContentRoot}/Include/km/ntddk.h" # WDK 8.0, 8.1
)
else()
file(GLOB WDK_NTDDK_FILES
"C:/Program Files*/Windows Kits/*/Include/*/km/ntddk.h" # WDK 10
"C:/Program Files*/Windows Kits/*/Include/km/ntddk.h" # WDK 8.0, 8.1
)
endif()
if(WDK_NTDDK_FILES)
if (NOT CMAKE_VERSION VERSION_LESS 3.18.0)
list(SORT WDK_NTDDK_FILES COMPARE NATURAL) # sort to use the latest available WDK
endif()
list(GET WDK_NTDDK_FILES -1 WDK_LATEST_NTDDK_FILE)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(WDK REQUIRED_VARS WDK_LATEST_NTDDK_FILE)
if(NOT WDK_LATEST_NTDDK_FILE)
return()
endif()
get_filename_component(WDK_ROOT ${WDK_LATEST_NTDDK_FILE} DIRECTORY)
get_filename_component(WDK_ROOT ${WDK_ROOT} DIRECTORY)
get_filename_component(WDK_VERSION ${WDK_ROOT} NAME)
get_filename_component(WDK_ROOT ${WDK_ROOT} DIRECTORY)
if (NOT WDK_ROOT MATCHES ".*/[0-9][0-9.]*$") # WDK 10 has a deeper nesting level
get_filename_component(WDK_ROOT ${WDK_ROOT} DIRECTORY) # go up once more
set(WDK_LIB_VERSION "${WDK_VERSION}")
set(WDK_INC_VERSION "${WDK_VERSION}")
else() # WDK 8.0, 8.1
set(WDK_INC_VERSION "")
foreach(VERSION winv6.3 win8 win7)
if (EXISTS "${WDK_ROOT}/Lib/${VERSION}/")
set(WDK_LIB_VERSION "${VERSION}")
break()
endif()
endforeach()
set(WDK_VERSION "${WDK_LIB_VERSION}")
endif()
message(STATUS "WDK_ROOT: " ${WDK_ROOT})
message(STATUS "WDK_VERSION: " ${WDK_VERSION})
set(WDK_WINVER "0x0601" CACHE STRING "Default WINVER for WDK targets")
set(WDK_NTDDI_VERSION "" CACHE STRING "Specified NTDDI_VERSION for WDK targets if needed")
set(WDK_ADDITIONAL_FLAGS_FILE "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/wdkflags.h")
file(WRITE ${WDK_ADDITIONAL_FLAGS_FILE} "#pragma runtime_checks(\"suc\", off)")
set(WDK_COMPILE_FLAGS
"/Zp8" # set struct alignment
"/GF" # enable string pooling
"/GR-" # disable RTTI
"/Gz" # __stdcall by default
"/kernel" # create kernel mode binary
"/FIwarning.h" # disable warnings in WDK headers
"/FI${WDK_ADDITIONAL_FLAGS_FILE}" # include file to disable RTC
"/Oi" # enable intrinsic functions so that you can use functions like _disable or _enable
)
set(WDK_COMPILE_DEFINITIONS "WINNT=1")
set(WDK_COMPILE_DEFINITIONS_DEBUG "MSC_NOOPT;DEPRECATE_DDK_FUNCTIONS=1;DBG=1")
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
list(APPEND WDK_COMPILE_DEFINITIONS "_X86_=1;i386=1;STD_CALL")
set(WDK_PLATFORM "x86")
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8 AND CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "ARM64")
list(APPEND WDK_COMPILE_DEFINITIONS "_ARM64_;ARM64;_USE_DECLSPECS_FOR_SAL=1;STD_CALL")
set(WDK_PLATFORM "arm64")
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
list(APPEND WDK_COMPILE_DEFINITIONS "_AMD64_;AMD64")
set(WDK_PLATFORM "x64")
else()
message(FATAL_ERROR "Unsupported architecture")
endif()
string(CONCAT WDK_LINK_FLAGS
"/MANIFEST:NO " #
"/DRIVER " #
"/OPT:REF " #
"/INCREMENTAL:NO " #
"/OPT:ICF " #
"/SUBSYSTEM:NATIVE " #
"/MERGE:_TEXT=.text;_PAGE=PAGE " #
"/NODEFAULTLIB " # do not link default CRT
"/SECTION:INIT,d " #
"/VERSION:10.0 " #
)
# Generate imported targets for WDK lib files
file(GLOB WDK_LIBRARIES "${WDK_ROOT}/Lib/${WDK_LIB_VERSION}/km/${WDK_PLATFORM}/*.lib")
foreach(LIBRARY IN LISTS WDK_LIBRARIES)
get_filename_component(LIBRARY_NAME ${LIBRARY} NAME_WE)
string(TOUPPER ${LIBRARY_NAME} LIBRARY_NAME)
add_library(WDK::${LIBRARY_NAME} INTERFACE IMPORTED)
set_property(TARGET WDK::${LIBRARY_NAME} PROPERTY INTERFACE_LINK_LIBRARIES ${LIBRARY})
endforeach(LIBRARY)
unset(WDK_LIBRARIES)
function(wdk_add_driver _target)
cmake_parse_arguments(WDK "" "KMDF;WINVER;NTDDI_VERSION" "" ${ARGN})
add_executable(${_target} ${WDK_UNPARSED_ARGUMENTS})
set_target_properties(${_target} PROPERTIES SUFFIX ".sys")
set_target_properties(${_target} PROPERTIES COMPILE_OPTIONS "${WDK_COMPILE_FLAGS}")
set_target_properties(${_target} PROPERTIES COMPILE_DEFINITIONS
"${WDK_COMPILE_DEFINITIONS};$<$<CONFIG:Debug>:${WDK_COMPILE_DEFINITIONS_DEBUG}>;_WIN32_WINNT=${WDK_WINVER}"
)
set_target_properties(${_target} PROPERTIES LINK_FLAGS "${WDK_LINK_FLAGS}")
if(WDK_NTDDI_VERSION)
target_compile_definitions(${_target} PRIVATE NTDDI_VERSION=${WDK_NTDDI_VERSION})
endif()
target_include_directories(${_target} SYSTEM PRIVATE
"${WDK_ROOT}/Include/${WDK_INC_VERSION}/shared"
"${WDK_ROOT}/Include/${WDK_INC_VERSION}/km"
"${WDK_ROOT}/Include/${WDK_INC_VERSION}/km/crt"
)
target_link_libraries(${_target} WDK::NTOSKRNL WDK::HAL WDK::WMILIB)
if(WDK::BUFFEROVERFLOWK)
target_link_libraries(${_target} WDK::BUFFEROVERFLOWK) # to support Windows 7 and Vista
else()
target_link_libraries(${_target} WDK::BUFFEROVERFLOWFASTFAILK)
endif()
if(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "ARM64")
target_link_libraries(${_target} "arm64rt.lib")
endif()
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
target_link_libraries(${_target} WDK::MEMCMP)
endif()
if(DEFINED WDK_KMDF)
target_include_directories(${_target} SYSTEM PRIVATE "${WDK_ROOT}/Include/wdf/kmdf/${WDK_KMDF}")
target_link_libraries(${_target}
"${WDK_ROOT}/Lib/wdf/kmdf/${WDK_PLATFORM}/${WDK_KMDF}/WdfDriverEntry.lib"
"${WDK_ROOT}/Lib/wdf/kmdf/${WDK_PLATFORM}/${WDK_KMDF}/WdfLdr.lib"
)
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS "/ENTRY:FxDriverEntry@8")
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS "/ENTRY:FxDriverEntry")
endif()
else()
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS "/ENTRY:GsDriverEntry@8")
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS "/ENTRY:GsDriverEntry")
endif()
endif()
endfunction()
function(wdk_add_library _target)
cmake_parse_arguments(WDK "" "KMDF;WINVER;NTDDI_VERSION" "" ${ARGN})
add_library(${_target} ${WDK_UNPARSED_ARGUMENTS})
set_target_properties(${_target} PROPERTIES COMPILE_OPTIONS "${WDK_COMPILE_FLAGS}")
set_target_properties(${_target} PROPERTIES COMPILE_DEFINITIONS
"${WDK_COMPILE_DEFINITIONS};$<$<CONFIG:Debug>:${WDK_COMPILE_DEFINITIONS_DEBUG};>_WIN32_WINNT=${WDK_WINVER}"
)
if(WDK_NTDDI_VERSION)
target_compile_definitions(${_target} PRIVATE NTDDI_VERSION=${WDK_NTDDI_VERSION})
endif()
target_include_directories(${_target} SYSTEM PRIVATE
"${WDK_ROOT}/Include/${WDK_INC_VERSION}/shared"
"${WDK_ROOT}/Include/${WDK_INC_VERSION}/km"
"${WDK_ROOT}/Include/${WDK_INC_VERSION}/km/crt"
)
if(DEFINED WDK_KMDF)
target_include_directories(${_target} SYSTEM PRIVATE "${WDK_ROOT}/Include/wdf/kmdf/${WDK_KMDF}")
endif()
endfunction()
+82
View File
@@ -0,0 +1,82 @@
# Proof of Concepts
This project aims to highlight certain aspects of the shadow stack mitigation implemented by Microsoft in Windows 11.
The code is specifically focused on Windows 11 24H2.
**It may not work on other version of Windows 11, due to the kernel offset management**.
The project is divided into two parts: a client and a driver.
Communication between them is handled through the IOCTL mechanism.
The client requests the driver to perform actions at the kernel level.
## Features
- Increment one of the kernel return addresses of the current thread to misalign it and trigger a BSOD.
- Skip one of the kernel stack frames of the current thread to highlight the resilience of the shadow stack.
- Enable/disable CET in the current `CR4` register, leading to a BSOD
- Write to MSR registers, which typically leads to a BSOD
- Write to the shadow stack, which results in a BSOD
- Write the shadow stack PTE, triggering a BSOD
- Perform divisions to highlight `try/except` and shadow stack behaviors during a division by zero
## Build
Use `build.bat`.
### Prerequisites
As a prerequisite, the following kits have to be for the same Windows build:
- Microsoft Windows SDK (Software Development Kit)
- Microsoft WDK (Windows Driver Kit)
Note:
The POC have been tested with the version `10.0.26100.0` of the kits.
## Target Machine Configuration
To activate the kernel shadow stack mitigation, the following values have to be added or set in the `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceGuard\` key:
| Name | Type | Data
| --- | --- | ---
| EnableVirtualizationBasedSecurity | REG_DWORD | 1
| Scenarios\HypervisorEnforcedCodeIntegrity\Enabled | REG_DWORD | 1
| Scenarios\KernelShadowStacks\Enabled | REG_DWORD | 1
Also, in order to load a test-signed driver, the following command have to be run in an administrator console:
```console
bcdedit /set testsigning on
```
Then, a reboot is required.
## Usage
### Driver Loading
To load the driver, the following commands have to be entered in an administrator console:
```console
sc create shadow type= kernel binPath= ABSOLUTE_PATH_TO_THE_DRIVER
sc start shadow
```
### Client
The client has the following options:
| Option | Description
| --- | ---
| inc | Increment the return address to the caller by 1
| skip | Patch RSP in order to point on the previous stack frame
| cdisable | Disable CET in CR4
| cenable | Enable CET in CR4
| wrmsr REGISTER VALUE | Write the REGISTER with the given VALUE
| wrshsk | Write into the shadow stack
| wrshskpte | Rewrite the shadow stack PTE
| div DIVIDEND DIVISOR | Perfom integer division in kernel space
## Credits
SergiusTheBest for its [FindWDK](https://github.com/SergiusTheBest/FindWDK).
+3
View File
@@ -0,0 +1,3 @@
cmake . -Bbuild
cmake --build build --config Release
+4
View File
@@ -0,0 +1,4 @@
rmdir bin /S /Q
rmdir build /S /Q
rmdir build32 /S /Q
rmdir build64 /S /Q
+134
View File
@@ -0,0 +1,134 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <windows.h>
#include "client/utils.h"
#include "common/utils.h"
void usage()
{
printf("Options:\n");
printf(" inc Increment the return address to the caller\n");
printf(" by 1\n");
printf(" skip Patch RSP in order to point on the previous\n");
printf(" stack frame\n");
printf(" cdisable Disable CET in CR4\n");
printf(" cenable Enable CET in CR4\n");
printf(" wrmsr REGISTER VALUE Write the REGISTER with the given VALUE\n");
printf(" wrshsk Write into the shadow stack\n");
printf(" wrshskpte Rewrite the shadow stack PTE\n");
printf(" div DIVIDEND DIVISOR Perfom integer division in kernel space\n");
}
int32_t main(int32_t argc, char* argv[])
{
if (2 > argc)
{
printf("Missing arguments\n\n");
usage();
goto EXIT;
}
if (EXIT_SUCCESS != OpenExposedDevice())
{
printf("[!] " __FUNCTION__ " failed\n");
goto EXIT;
}
if (!strcmp("inc", argv[1]))
{
if (IncRetAddr())
{
printf("[!] " __FUNCTION__ ": IncRetAddr failed\n");
goto EXIT;
}
}
else if (!strcmp("skip", argv[1]))
{
if (SkipNextFrame())
{
printf("[!] " __FUNCTION__ ": SkipNextFrame failed\n");
goto EXIT;
}
printf("Stack returned\n");
}
else if (!strcmp("cdisable", argv[1]))
{
if (WriteCr4(0))
{
printf("[!] " __FUNCTION__ ": WriteCr4 failed\n");
goto EXIT;
}
printf("Kernel shadow stack disabled in CR4\n");
}
else if (!strcmp("cenable", argv[1]))
{
if (WriteCr4(1))
{
printf("[!] " __FUNCTION__ ": WriteCr4 failed\n");
goto EXIT;
}
printf("Kernel shadow stack enabled in CR4\n");
}
else if (!strcmp("wrmsr", argv[1]))
{
if (4 > argc)
{
printf("[!] wrmsr: Missing arguments");
goto EXIT;
}
if (WriteMsr(strtoul(argv[2], NULL, 0), strtoull(argv[3], NULL, 0)))
{
printf("[!] " __FUNCTION__ ": WriteMsr failed\n");
goto EXIT;
}
}
else if (!strcmp("wrshsk", argv[1]))
{
if (WriteShadowStack())
{
printf("[!] " __FUNCTION__ ": WriteShadowStack failed\n");
goto EXIT;
}
}
else if (!strcmp("wrshskpte", argv[1]))
{
if (WriteShadowStackPte())
{
printf("[!] " __FUNCTION__ ": WriteShadowStackPte failed\n");
goto EXIT;
}
}
else if (!strcmp("div", argv[1]))
{
if (4 > argc)
{
printf("[!] div: Missing arguments");
goto EXIT;
}
if (DivInteger(strtol(argv[2], NULL, 0), strtol(argv[3], NULL, 0)))
{
printf("[!] " __FUNCTION__ ": DivInteger failed\n");
goto EXIT;
}
}
else
{
usage();
goto EXIT;
}
EXIT:
CloseExposedDevice();
return EXIT_SUCCESS;
}
+412
View File
@@ -0,0 +1,412 @@
#include "client/utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
// ===========================================================================
// Inner global declarations
// ===========================================================================
static HANDLE gDevice = INVALID_HANDLE_VALUE;
// ===========================================================================
// Function definitions
// ===========================================================================
void CloseExposedDevice()
{
if (INVALID_HANDLE_VALUE != gDevice)
{
CloseHandle(gDevice);
gDevice = INVALID_HANDLE_VALUE;
}
}
int32_t DivInteger(int32_t Dividend, int32_t Divisor)
{
int32_t ExitCode = EXIT_FAILURE;
IoctlDivInteger_t di = { 0 };
if (INVALID_HANDLE_VALUE == gDevice)
{
printf("[-] " __FUNCTION__ ": Device not opened\n");
goto EXIT;
}
__try
{
di.Quotient = Dividend / Divisor;
}
__except (1)
{
printf("[-] Divided by zero\n");
}
di.Dividend = Dividend;
di.Divisor = Divisor;
if (!DeviceIoControl(
gDevice,
IOCTL_DIV_INTEGER,
&di,
sizeof(IoctlDivInteger_t),
&di,
sizeof(IoctlDivInteger_t),
NULL,
NULL))
{
printf("[-] " __FUNCTION__ ": DeviceIoControl failed (0x%08x)\n",
GetLastError());
goto EXIT;
}
printf("Division: %i / %i => %i\n", di.Dividend, di.Divisor, di.Quotient);
ExitCode = EXIT_SUCCESS;
EXIT:
return ExitCode;
}
int32_t IncRetAddr()
{
int32_t ExitCode = EXIT_FAILURE;
if (INVALID_HANDLE_VALUE == gDevice)
{
printf("[-] " __FUNCTION__ ": Device not opened\n");
goto EXIT;
}
if (!DeviceIoControl(
gDevice,
IOCTL_INC_RET_ADDR,
NULL,
0,
NULL,
0,
NULL,
NULL))
{
printf("[-] " __FUNCTION__ ": DeviceIoControl failed (0x%08x)\n",
GetLastError());
goto EXIT;
}
printf("Stack incremented\n");
ExitCode = EXIT_SUCCESS;
EXIT:
return ExitCode;
}
int32_t OpenExposedDevice()
{
int32_t ExitCode = EXIT_FAILURE;
if (EXIT_SUCCESS != OpenExposedDeviceEx(CLIENT_DEVICE_NAME))
{
printf("[!] " __FUNCTION__ " failed\n");
goto EXIT;
}
ExitCode = EXIT_SUCCESS;
EXIT:
return ExitCode;
}
int32_t OpenExposedDeviceEx(char* DeviceName)
{
int32_t ExitCode = EXIT_FAILURE;
if (!DeviceName)
{
printf("[-] " __FUNCTION__ ": Invalid device name\n");
goto EXIT;
}
if (INVALID_HANDLE_VALUE != gDevice)
{
printf("[!] " __FUNCTION__ ": Device already opened\n");
goto EXIT;
}
gDevice = CreateFile(
DeviceName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (INVALID_HANDLE_VALUE == gDevice)
{
printf("[-] " __FUNCTION__ ": CreateFile failed (0x%08x)\n", GetLastError());
goto EXIT;
}
ExitCode = EXIT_SUCCESS;
EXIT:
return ExitCode;
}
void PrintCr4Flags(Cr4Flags_t Flags)
{
printf("CR4 (0x%llx):\n", *(uint64_t*)&Flags);
printf(" VME: %s\n", Flags.VME ? "TRUE" : "FALSE");
printf(" PVI: %s\n", Flags.PVI ? "TRUE" : "FALSE");
printf(" TSD: %s\n", Flags.TSD ? "TRUE" : "FALSE");
printf(" DE: %s\n", Flags.DE ? "TRUE" : "FALSE");
printf(" PSE: %s\n", Flags.PSE ? "TRUE" : "FALSE");
printf(" PAE: %s\n", Flags.PAE ? "TRUE" : "FALSE");
printf(" MCE: %s\n", Flags.MCE ? "TRUE" : "FALSE");
printf(" PGE: %s\n", Flags.PGE ? "TRUE" : "FALSE");
printf(" PCE: %s\n", Flags.PCE ? "TRUE" : "FALSE");
printf(" OSFXSR: %s\n", Flags.OSFXSR ? "TRUE" : "FALSE");
printf(" OSXMMEXCPT: %s\n", Flags.OSXMMEXCPT ? "TRUE" : "FALSE");
printf(" UMIP: %s\n", Flags.UMIP ? "TRUE" : "FALSE");
printf(" LA57: %s\n", Flags.LA57 ? "TRUE" : "FALSE");
printf(" VMXE: %s\n", Flags.VMXE ? "TRUE" : "FALSE");
printf(" SMXE: %s\n", Flags.SMXE ? "TRUE" : "FALSE");
printf(" Reserved0: %s\n", Flags.Reserved0 ? "TRUE" : "FALSE");
printf(" FSGSBASE: %s\n", Flags.FSGSBASE ? "TRUE" : "FALSE");
printf(" PCIDE: %s\n", Flags.PCIDE ? "TRUE" : "FALSE");
printf(" OSXSAVE: %s\n", Flags.OSXSAVE ? "TRUE" : "FALSE");
printf(" KL: %s\n", Flags.KL ? "TRUE" : "FALSE");
printf(" SMEP: %s\n", Flags.SMEP ? "TRUE" : "FALSE");
printf(" SMAP: %s\n", Flags.SMAP ? "TRUE" : "FALSE");
printf(" PKE: %s\n", Flags.PKE ? "TRUE" : "FALSE");
printf(" CET: %s\n", Flags.CET ? "TRUE" : "FALSE");
printf(" PKS: %s\n", Flags.PKS ? "TRUE" : "FALSE");
printf(" UINTR: %s\n", Flags.UINTR ? "TRUE" : "FALSE");
printf(" Reserved1: 0x%llx\n", Flags.Reserved1);
}
void PrintMiscFlags(MiscFlags_t Flags)
{
printf("Misc flags (0x%x):\n", *(uint32_t*)&Flags);
printf(" AutoBoostActive: %s\n", Flags.AutoBoostActive ? "TRUE" : "FALSE");
printf(" ReadyTransition: %s\n", Flags.ReadyTransition ? "TRUE" : "FALSE");
printf(" WaitNext: %s\n", Flags.WaitNext ? "TRUE" : "FALSE");
printf(" SystemAffinityActive: %s\n",
Flags.SystemAffinityActive ? "TRUE" : "FALSE");
printf(" Alertable: %s\n", Flags.Alertable ? "TRUE" : "FALSE");
printf(" UserStackWalkActive: %s\n",
Flags.UserStackWalkActive ? "TRUE" : "FALSE");
printf(" ApcInterruptRequest: %s\n",
Flags.ApcInterruptRequest ? "TRUE" : "FALSE");
printf(" QuantumEndMigrate: %s\n",
Flags.QuantumEndMigrate ? "TRUE" : "FALSE");
printf(" SecureThread: %s\n", Flags.SecureThread ? "TRUE" : "FALSE");
printf(" TimerActive: %s\n", Flags.TimerActive ? "TRUE" : "FALSE");
printf(" SystemThread: %s\n", Flags.SystemThread ? "TRUE" : "FALSE");
printf(" ProcessDetachActive: %s\n",
Flags.ProcessDetachActive ? "TRUE" : "FALSE");
printf(" CalloutActive: %s\n", Flags.CalloutActive ? "TRUE" : "FALSE");
printf(" ScbReadyQueue: %s\n", Flags.ScbReadyQueue ? "TRUE" : "FALSE");
printf(" ApcQueueable: %s\n", Flags.ApcQueueable ? "TRUE" : "FALSE");
printf(" ReservedStackInUse: %s\n",
Flags.ReservedStackInUse ? "TRUE" : "FALSE");
printf(" Spare: %s\n", Flags.Spare ? "TRUE" : "FALSE");
printf(" TimerSuspended: %s\n", Flags.TimerSuspended ? "TRUE" : "FALSE");
printf(" SuspendedWaitMode: %s\n",
Flags.SuspendedWaitMode ? "TRUE" : "FALSE");
printf(" SuspendSchedulerApcWait: %s\n",
Flags.SuspendSchedulerApcWait ? "TRUE" : "FALSE");
printf(" CetUserShadowStack: %s\n",
Flags.CetUserShadowStack ? "TRUE" : "FALSE");
printf(" BypassProcessFreeze: %s\n",
Flags.BypassProcessFreeze ? "TRUE" : "FALSE");
printf(" CetKernelShadowStack: %s\n",
Flags.CetKernelShadowStack ? "TRUE" : "FALSE");
printf(" StateSaveAreaDecoupled: %s\n",
Flags.StateSaveAreaDecoupled ? "TRUE" : "FALSE");
printf(" Reserved: 0x%02x\n", Flags.Reserved);
}
void PrintMsrCet(MsrCetFlags_t Flags)
{
printf("MSR CET flags (0x%llx):\n", *(uint64_t*)&Flags);
printf(" SH_STK_EN: %s\n", Flags.SH_STK_EN ? "TRUE" : "FALSE");
printf(" WR_SHSTK_EN: %s\n", Flags.WR_SHSTK_EN ? "TRUE" : "FALSE");
printf(" ENDBR_EN: %s\n", Flags.ENDBR_EN ? "TRUE" : "FALSE");
printf(" LEG_IW_EN: %s\n", Flags.LEG_IW_EN ? "TRUE" : "FALSE");
printf(" NO_TRACK_EN: %s\n", Flags.NO_TRACK_EN ? "TRUE" : "FALSE");
printf(" SUPPRESS_DIS: %s\n", Flags.SUPPRESS_DIS ? "TRUE" : "FALSE");
printf(" Reserved: 0x%llx\n", Flags.Reserved);
printf(" SUPPRESS: %s\n", Flags.SUPPRESS ? "TRUE" : "FALSE");
printf(" TRACKER: %s\n", Flags.TRACKER ? "TRUE" : "FALSE");
printf(" EB_LEG_BITMAP_BASE: 0x%llx\n", Flags.EB_LEG_BITMAP_BASE);
}
int32_t WriteCr4(uint8_t Value)
{
int32_t ExitCode = EXIT_FAILURE;
if (INVALID_HANDLE_VALUE == gDevice)
{
printf("[-] " __FUNCTION__ ": Device not opened\n");
goto EXIT;
}
if (!DeviceIoControl(
gDevice,
IOCTL_WRITE_CR4,
&Value,
sizeof(Value),
NULL,
0,
NULL,
NULL))
{
printf("[-] " __FUNCTION__ ": DeviceIoControl failed (0x%08x)\n",
GetLastError());
goto EXIT;
}
ExitCode = EXIT_SUCCESS;
EXIT:
return ExitCode;
}
int32_t SkipNextFrame()
{
int32_t ExitCode = EXIT_FAILURE;
if (INVALID_HANDLE_VALUE == gDevice)
{
printf("[-] " __FUNCTION__ ": Device not opened\n");
goto EXIT;
}
if (!DeviceIoControl(
gDevice,
IOCTL_SKIP_NEXT_FRAME,
NULL,
0,
NULL,
0,
NULL,
NULL))
{
printf("[-] " __FUNCTION__ ": DeviceIoControl failed (0x%08x)\n",
GetLastError());
goto EXIT;
}
ExitCode = EXIT_SUCCESS;
EXIT:
return ExitCode;
}
int32_t WriteMsr(uint32_t Register, uint64_t Value)
{
int32_t ExitCode = EXIT_FAILURE;
Msr_t Msr = { 0 };
if (INVALID_HANDLE_VALUE == gDevice)
{
printf("[-] " __FUNCTION__ ": Device not opened\n");
goto EXIT;
}
Msr.Register = Register;
Msr.Value = Value;
if (!DeviceIoControl(
gDevice,
IOCTL_WRITE_MSR,
&Msr,
sizeof(Msr_t),
NULL,
0,
NULL,
NULL))
{
printf("[-] " __FUNCTION__ ": DeviceIoControl failed (0x%08x)\n",
GetLastError());
goto EXIT;
}
printf("Register [0x%04x] <= 0x%016llx", Register, Value);
ExitCode = EXIT_SUCCESS;
EXIT:
return ExitCode;
}
int32_t WriteShadowStack()
{
int32_t ExitCode = EXIT_FAILURE;
IoctlWriteShadowStack_t wss = { 0 };
if (INVALID_HANDLE_VALUE == gDevice)
{
printf("[-] " __FUNCTION__ ": Device not opened\n");
goto EXIT;
}
wss.Offset = -0x200;
wss.Address = 0x4141414141414141;
if (!DeviceIoControl(
gDevice,
IOCTL_WRITE_CURRENT_SHADOW_STACK,
&wss,
sizeof(IoctlWriteShadowStack_t),
NULL,
0,
NULL,
NULL))
{
printf("[-] " __FUNCTION__ ": DeviceIoControl failed (0x%08x)\n",
GetLastError());
goto EXIT;
}
ExitCode = EXIT_SUCCESS;
EXIT:
return ExitCode;
}
int32_t WriteShadowStackPte()
{
int32_t ExitCode = EXIT_FAILURE;
PageEntry64_t PageEntry = { 0 };
if (INVALID_HANDLE_VALUE == gDevice)
{
printf("[-] " __FUNCTION__ ": Device not opened\n");
goto EXIT;
}
PageEntry.Write = 1;
if (!DeviceIoControl(
gDevice,
IOCTL_WRITE_CURRENT_SHADOW_STACK_PTE,
&PageEntry,
sizeof(PageEntry64_t),
NULL,
0,
NULL,
NULL))
{
printf("[-] " __FUNCTION__ ": DeviceIoControl failed (0x%08x)\n",
GetLastError());
goto EXIT;
}
ExitCode = EXIT_SUCCESS;
EXIT:
return ExitCode;
}
+122
View File
@@ -0,0 +1,122 @@
#ifndef __CLIENT_UTILS_H__
#define __CLIENT_UTILS_H__
#include <stdint.h>
#include "common/utils.h"
// ===========================================================================
// Function declarations
// ===========================================================================
/**
* \brief Closes the current opened device
*/
void CloseExposedDevice();
/**
* \brief Permforms an integer division in kernel space
*
* \param Dividend Value to divide
* \param Divisor Value used to divide
*
* \return EXIT_SUCCESS on success, otherwise EXIT_FAILURE
*/
int32_t DivInteger(
int32_t Dividend,
int32_t Divisor);
/**
* \brief Increments the kernel return address to the caller in order to
* trigger a mismatch with the shadow stack
*
* \return EXIT_SUCCESS on success, otherwise EXIT_FAILURE
*/
int32_t IncRetAddr();
/**
* \brief Opens the device related to "\??\ShadowStack"
*
* \return EXIT_SUCCESS on success, otherwise EXIT_FAILURE
*/
int32_t OpenExposedDevice();
/**
* \brief Opens the device related to the given name
*
* \param DeviceName Pointer to the device name of the device to be opened
*
* \return EXIT_SUCCESS on success, otherwise EXIT_FAILURE
*/
int32_t OpenExposedDeviceEx(
char* DeviceName);
/**
* \brief Prints the fields of the given CR4 flags
*
* \param Flags CR4 flags to print
*/
void PrintCr4Flags(
Cr4Flags_t Flags);
/**
* \brief Prints the fields of the given misc flags
*
* \param Flags Misc flags to print
*/
void PrintMiscFlags(
MiscFlags_t Flags);
/**
* \brief Prints the fields of the given MSR CET flags
*
* \param Flags MSR CET flags to print
*/
void PrintMsrCet(
MsrCetFlags_t Flags);
/**
* \brief Sets the CET flag of the current CR4 register
*
* \param Value CET value to set
*
* \return EXIT_SUCCESS on success, otherwise EXIT_FAILURE
*/
int32_t WriteCr4(
uint8_t Value);
/**
* \brief Skips the next stack frames in order to trigger a valid mismatch
* between the stack and the shadow stack
*
* \return EXIT_SUCCESS on success, otherwise EXIT_FAILURE
*/
int32_t SkipNextFrame();
/**
* \brief Writes the given value to the given register address
*
* \param Register Register address where to write
* \param Value Value to set
*
* \return EXIT_SUCCESS on success, otherwise EXIT_FAILURE
*/
int32_t WriteMsr(
uint32_t Register,
uint64_t Value);
/**
* \brief Writes data into the current shadow stack
*
* \return EXIT_SUCCESS on success, otherwise EXIT_FAILURE
*/
int32_t WriteShadowStack();
/**
* \brief Sets the write flag of the shadow stack PTE
*
* \return EXIT_SUCCESS on success, otherwise EXIT_FAILURE
*/
int32_t WriteShadowStackPte();
#endif // __CLIENT_UTILS_H__
+164
View File
@@ -0,0 +1,164 @@
#ifndef __COMMON_UTILS_H__
#define __COMMON_UTILS_H__
#include <stdint.h>
#ifndef _MAX_PATH_
#define _MAX_PATH_ (0x200)
#endif
#define countof(arr) (sizeof(arr) / sizeof(arr[0]))
#define BASE_NAME "ShadowStack"
#define CLIENT_DEVICE_NAME "\\??\\" BASE_NAME
#define DRIVER_DEVICE_NAME L"\\Device\\" BASE_NAME
#define DOS_DEVICE_NAME L"\\DosDevices\\" BASE_NAME
#define DEVICE_IOCTL_TYPE 4000
#define IOCTL_INC_RET_ADDR \
CTL_CODE(DEVICE_IOCTL_TYPE, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SKIP_NEXT_FRAME \
CTL_CODE(DEVICE_IOCTL_TYPE, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_WRITE_CURRENT_SHADOW_STACK \
CTL_CODE(DEVICE_IOCTL_TYPE, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_WRITE_CR4 \
CTL_CODE(DEVICE_IOCTL_TYPE, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_WRITE_MSR \
CTL_CODE(DEVICE_IOCTL_TYPE, 0x904, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_WRITE_CURRENT_SHADOW_STACK_PTE \
CTL_CODE(DEVICE_IOCTL_TYPE, 0x905, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DIV_INTEGER \
CTL_CODE(DEVICE_IOCTL_TYPE, 0x906, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IA32_U_CET_REGISTER (0x6a0)
#define IA32_S_CET_REGISTER (0x6a2)
#define IA32_PL0_SSP_REGISTER (0x6a4)
#define IA32_PL1_SSP_REGISTER (0x6a5)
#define IA32_PL2_SSP_REGISTER (0x6a6)
#define IA32_PL3_SSP_REGISTER (0x6a7)
// ===========================================================================
// Structure definitions
// ===========================================================================
typedef struct _Cr4Flags
{
uint64_t VME : 1;
uint64_t PVI : 1;
uint64_t TSD : 1;
uint64_t DE : 1;
uint64_t PSE : 1;
uint64_t PAE : 1;
uint64_t MCE : 1;
uint64_t PGE : 1;
uint64_t PCE : 1;
uint64_t OSFXSR : 1;
uint64_t OSXMMEXCPT : 1;
uint64_t UMIP : 1;
uint64_t LA57 : 1;
uint64_t VMXE : 1;
uint64_t SMXE : 1;
uint64_t Reserved0 : 1;
uint64_t FSGSBASE : 1;
uint64_t PCIDE : 1;
uint64_t OSXSAVE : 1;
uint64_t KL : 1;
uint64_t SMEP : 1;
uint64_t SMAP : 1;
uint64_t PKE : 1;
uint64_t CET : 1;
uint64_t PKS : 1;
uint64_t UINTR : 1;
uint64_t Reserved1 : 38;
} Cr4Flags_t;
typedef struct _MiscFlags
{
uint32_t AutoBoostActive : 1;
uint32_t ReadyTransition : 1;
uint32_t WaitNext : 1;
uint32_t SystemAffinityActive : 1;
uint32_t Alertable : 1;
uint32_t UserStackWalkActive : 1;
uint32_t ApcInterruptRequest : 1;
uint32_t QuantumEndMigrate : 1;
uint32_t SecureThread : 1;
uint32_t TimerActive : 1;
uint32_t SystemThread : 1;
uint32_t ProcessDetachActive : 1;
uint32_t CalloutActive : 1;
uint32_t ScbReadyQueue : 1;
uint32_t ApcQueueable : 1;
uint32_t ReservedStackInUse : 1;
uint32_t Spare : 1;
uint32_t TimerSuspended : 1;
uint32_t SuspendedWaitMode : 1;
uint32_t SuspendSchedulerApcWait : 1;
uint32_t CetUserShadowStack : 1;
uint32_t BypassProcessFreeze : 1;
uint32_t CetKernelShadowStack : 1;
uint32_t StateSaveAreaDecoupled : 1;
uint32_t Reserved : 8;
} MiscFlags_t;
typedef struct _Msr
{
uint32_t Register;
uint64_t Value;
} Msr_t;
typedef struct _MsrCetFlags
{
uint64_t SH_STK_EN : 1;
uint64_t WR_SHSTK_EN : 1;
uint64_t ENDBR_EN : 1;
uint64_t LEG_IW_EN : 1;
uint64_t NO_TRACK_EN : 1;
uint64_t SUPPRESS_DIS : 1;
uint64_t Reserved : 4;
uint64_t SUPPRESS : 1;
uint64_t TRACKER : 1;
uint64_t EB_LEG_BITMAP_BASE : 52;
} MsrCetFlags_t;
typedef struct _PageEntry64
{
uint64_t Valid : 1;
uint64_t Write : 1;
uint64_t Owner : 1;
uint64_t WriteThrough : 1;
uint64_t CacheDisabled : 1;
uint64_t Accessed : 1;
uint64_t Dirty : 1;
uint64_t LargePage : 1;
uint64_t Global : 1;
uint64_t CopyOnWrite : 1;
uint64_t PrototypeSoft : 1;
uint64_t WriteSoft : 1;
uint64_t Pfn : 36;
uint64_t Reserved : 15;
uint64_t NoExecute : 1;
} PageEntry64_t;
typedef struct _IoctlDivInteger
{
int32_t Dividend;
int32_t Divisor;
int32_t Quotient;
} IoctlDivInteger_t;
typedef struct _IoctlOpenFileDesc
{
uint32_t Length;
char Name[_MAX_PATH_];
} IoctlOpenFileDesc_t;
typedef struct _IoctlWriteShadowStack
{
int32_t Offset;
uint64_t Address;
} IoctlWriteShadowStack_t;
#endif // __COMMON_UTILS_H__
+193
View File
@@ -0,0 +1,193 @@
#include <wdm.h>
#include "common/utils.h"
#include "common/utils.h"
#include "driver/ioctl.h"
#include "driver/utils.h"
void DriverUnload(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
DoRun = 0;
DeleteExposedDevice(DriverObject);
DbgPrint("Driver unloaded!\n");
}
NTSTATUS DispatchCreateClose(DEVICE_OBJECT* DeviceObject, IRP* Irp)
{
NTSTATUS Status = STATUS_SUCCESS;
UNREFERENCED_PARAMETER(DeviceObject);
switch (Irp->Tail.Overlay.CurrentStackLocation->MajorFunction)
{
case IRP_MJ_CREATE:
DbgPrint("Device opened\n");
break;
case IRP_MJ_CLOSE:
DbgPrint("Device closed\n");
break;
default:
Status = STATUS_UNSUCCESSFUL;
break;
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS DispatchDeviceControl(DEVICE_OBJECT* DeviceObject, IRP* Irp)
{
IO_STACK_LOCATION* csl = NULL;
NTSTATUS Status = STATUS_SUCCESS;
uint32_t WrittenBytes = 0;
void* Buffer = NULL;
DbgPrint("Entering " __FUNCTION__ "\n");
UNREFERENCED_PARAMETER(DeviceObject);
csl = Irp->Tail.Overlay.CurrentStackLocation;
Buffer = Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL: 0x%08x\n", csl->Parameters.DeviceIoControl.IoControlCode);
switch (csl->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_INC_RET_ADDR:
Status = IoctlIncRetAddr();
if (!NT_SUCCESS(Status))
{
DbgPrint("IoctlIncRetAddr failed\n");
goto EXIT;
}
break;
case IOCTL_SKIP_NEXT_FRAME:
Status = IoctlSkipNextFrame();
if (!NT_SUCCESS(Status))
{
DbgPrint("IoctlSkipNextFrame failed\n");
goto EXIT;
}
break;
case IOCTL_WRITE_CURRENT_SHADOW_STACK:
Status = IoctlWriteShadowStack(
Buffer,
csl->Parameters.DeviceIoControl.InputBufferLength);
if (!NT_SUCCESS(Status))
{
DbgPrint("IoctlWriteShadowStack failed\n");
goto EXIT;
}
break;
case IOCTL_WRITE_CR4:
Status = IoctlWriteCr4(
Buffer,
csl->Parameters.DeviceIoControl.InputBufferLength);
if (!NT_SUCCESS(Status))
{
DbgPrint("IoctlWriteCr4 failed\n");
goto EXIT;
}
break;
case IOCTL_WRITE_MSR:
Status = IoctlWriteMsr(
Buffer,
csl->Parameters.DeviceIoControl.InputBufferLength);
if (!NT_SUCCESS(Status))
{
DbgPrint("IoctlWriteMsr failed\n");
goto EXIT;
}
break;
case IOCTL_WRITE_CURRENT_SHADOW_STACK_PTE:
Status = IoctlWriteShadowStackPte(
Buffer,
csl->Parameters.DeviceIoControl.InputBufferLength);
if (!NT_SUCCESS(Status))
{
DbgPrint("IoctlWriteShadowStackPte failed\n");
goto EXIT;
}
break;
case IOCTL_DIV_INTEGER:
if (sizeof(IoctlDivInteger_t) >
csl->Parameters.DeviceIoControl.OutputBufferLength)
{
DbgPrint("IoctlDivInteger output buffer to small\n");
Status = STATUS_BUFFER_TOO_SMALL;
goto EXIT;
}
Status = IoctlDivInteger(
Buffer,
csl->Parameters.DeviceIoControl.InputBufferLength);
if (!NT_SUCCESS(Status))
{
DbgPrint("IoctlDivInteger failed\n");
goto EXIT;
}
WrittenBytes = csl->Parameters.DeviceIoControl.OutputBufferLength;
break;
default:
Status = STATUS_UNSUCCESSFUL;
break;
}
EXIT:
Irp->IoStatus.Information = WrittenBytes;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("Leaving " __FUNCTION__ "\n");
return Status;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
NTSTATUS Status = STATUS_SUCCESS;
UNREFERENCED_PARAMETER(RegistryPath);
Status = DbgSetDebugFilterState(0x100, 3, TRUE);
if (!NT_SUCCESS(Status))
{
DbgPrint("Failed to set debug filter state\n");
goto EXIT;
}
DbgPrint("Driver loading...\n");
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
DriverObject->DriverUnload = DriverUnload;
Status = CreateExposedDevice(DriverObject);
if (!NT_SUCCESS(Status))
{
DbgPrint("CreateExposedDevice failed\n");
goto EXIT;
}
EXIT:
return Status;
}
+262
View File
@@ -0,0 +1,262 @@
#include <ntifs.h>
#include "driver/ioctl.h"
#include <intrin.h>
#include "common/utils.h"
#include "driver/utils.h"
// ===========================================================================
// Offsets 24h2
// ===========================================================================
#define KI_KERNEL_CET_AUDIT_MODE_ENABLED_OFFSET_24H2 0x01201843
#define KI_KERNEL_CET_ENABLED_OFFSET_24H2 0x01201841
#define KI_KERNEL_CET_LOGGING_OFFSET_24H2 0x00fc6050
// ===========================================================================
// Offsets 24h2
// ===========================================================================
#define KI_KERNEL_CET_AUDIT_MODE_ENABLED_OFFSET KI_KERNEL_CET_AUDIT_MODE_ENABLED_OFFSET_24H2
#define KI_KERNEL_CET_ENABLED_OFFSET KI_KERNEL_CET_ENABLED_OFFSET_24H2
#define KI_KERNEL_CET_LOGGING_OFFSET KI_KERNEL_CET_LOGGING_OFFSET_24H2
int32_t DoRun = 1;
// ===========================================================================
// Function definitions
// ===========================================================================
int32_t _DivZeroFilter()
{
DbgPrint(__FUNCTION__ "\n");
return EXCEPTION_EXECUTE_HANDLER;
}
NTSTATUS IoctlDivInteger(void* Buffer, uint32_t Length)
{
IoctlDivInteger_t* di = NULL;
NTSTATUS Status = STATUS_INVALID_PARAMETER;
DbgPrintEnter();
if (!Buffer)
{
DbgPrint("Invalid buffer\n");
goto EXIT;
}
if (sizeof(IoctlDivInteger_t) > Length)
{
DbgPrint("Invalid length\n");
Status = STATUS_BUFFER_TOO_SMALL;
goto EXIT;
}
di = (IoctlDivInteger_t*)Buffer;
try
{
Status = DivInteger(di->Dividend, di->Divisor);
if (!NT_SUCCESS(Status))
{
DbgPrint("[-] " __FUNCTION__ ": DivInteger\n");
goto EXIT;
}
}
except(_DivZeroFilter())
{
DbgPrint("A division by zero occurred\n");
Status = STATUS_INTEGER_DIVIDE_BY_ZERO;
goto EXIT;
}
Status = STATUS_SUCCESS;
EXIT:
DbgPrintLeave();
return Status;
}
NTSTATUS IoctlIncRetAddr()
{
DbgPrintEnter();
IncRetAddr();
DbgPrintLeave();
return STATUS_SUCCESS;
}
NTSTATUS IoctlWriteCr4(void* Buffer, uint32_t Length)
{
Cr4Flags_t* Flags = NULL;
NTSTATUS Status = STATUS_INVALID_PARAMETER;
uint8_t* Value = NULL;
uint64_t cr4 = 0;
DbgPrintEnter();
if (!Buffer)
{
DbgPrint("Invalid buffer\n");
goto EXIT;
}
if (sizeof(uint8_t) > Length)
{
DbgPrint("Invalid length\n");
Status = STATUS_BUFFER_TOO_SMALL;
goto EXIT;
}
Value = (uint8_t*)Buffer;
Flags = (Cr4Flags_t*)&cr4;
cr4 = __readcr4();
DbgPrint("Reading CR4 = 0x%016llx\n", cr4);
Flags->CET = *Value & 1;
DbgPrint("Writing CR4 = 0x%016llx\n", cr4);
__writecr4(cr4);
Status = STATUS_SUCCESS;
EXIT:
DbgPrintLeave();
return Status;
}
NTSTATUS IoctlSkipNextFrame()
{
DbgPrintEnter();
SkipNextFrame();
DbgPrintLeave();
return STATUS_SUCCESS;
}
NTSTATUS IoctlWriteMsr(void* Buffer, uint32_t Length)
{
Msr_t* Msr = NULL;
NTSTATUS Status = STATUS_INVALID_PARAMETER;
DbgPrintEnter();
if (!Buffer)
{
DbgPrint("Invalid buffer\n");
goto EXIT;
}
if (sizeof(Msr_t) > Length)
{
DbgPrint("Invalid length\n");
Status = STATUS_BUFFER_TOO_SMALL;
goto EXIT;
}
Msr = (Msr_t*)Buffer;
DbgPrint("Reading MSR[0x%04x] = 0x%016llx\n",
Msr->Register,
__readmsr(Msr->Register));
DbgPrint("Writing MSR[0x%04x] = 0x%016llx\n",
Msr->Register,
Msr->Value);
__writemsr(Msr->Register, Msr->Value);
EXIT:
DbgPrintLeave();
return Status;
}
NTSTATUS IoctlWriteShadowStack(void* Buffer, uint32_t Length)
{
IoctlWriteShadowStack_t* wss = NULL;
NTSTATUS Status = STATUS_INVALID_PARAMETER;
uint8_t* u8ShadowStack = NULL;
uint64_t* u64ShadowStack = NULL;
DbgPrintEnter();
if (!Buffer)
{
DbgPrint("Invalid buffer\n");
goto EXIT;
}
if (sizeof(IoctlWriteShadowStack_t) > Length)
{
DbgPrint("Invalid length\n");
Status = STATUS_BUFFER_TOO_SMALL;
goto EXIT;
}
wss = (IoctlWriteShadowStack_t*)Buffer;
u8ShadowStack = GetThreadKernelShadowStack(KeGetCurrentThread());
u64ShadowStack = (uint64_t*)(u8ShadowStack + wss->Offset);
DbgPrint("Reading -> %p = %p\n", u64ShadowStack, *u64ShadowStack);
DbgPrint("Writing -> %p = %p\n", u64ShadowStack, wss->Address);
*u64ShadowStack = wss->Address;
EXIT:
DbgPrintLeave();
return Status;
}
NTSTATUS IoctlWriteShadowStackPte(void* Buffer, uint32_t Length)
{
NTSTATUS Status = STATUS_INVALID_PARAMETER;
PageEntry64_t* PageEntry = NULL;
PageEntry64_t* ShadowPageEntry = NULL;
void* ShadowStack = NULL;
DbgPrintEnter();
if (!Buffer)
{
DbgPrint("Invalid buffer\n");
goto EXIT;
}
if (sizeof(PageEntry64_t) > Length)
{
DbgPrint("Invalid length\n");
Status = STATUS_BUFFER_TOO_SMALL;
goto EXIT;
}
PageEntry = (PageEntry64_t*)Buffer;
ShadowStack = GetThreadKernelShadowStack(KeGetCurrentThread());
ShadowPageEntry = (PageEntry64_t*)GetShadowPteAddress(ShadowStack);
DbgPrint("Shadow Page Entry: %p -> %p\n", ShadowPageEntry, *ShadowPageEntry);
ShadowPageEntry->Write = PageEntry->Write;
for (uint64_t i = 0; i < 0xfffffffffffffff0; ++i)
{
}
DbgPrint("New Shadow Page Entry: %p -> %p\n", ShadowPageEntry, *ShadowPageEntry);
Status = STATUS_SUCCESS;
EXIT:
DbgPrintLeave();
return Status;
}
+94
View File
@@ -0,0 +1,94 @@
#ifndef __DRIVER_IOCTL_H__
#define __DRIVER_IOCTL_H__
#include <stdint.h>
#include <wdm.h>
#include "common/utils.h"
extern int32_t DoRun;
// ===========================================================================
// Function declarations
// ===========================================================================
/**
* \brief Permforms an integer division
*
* \param Buffer Pointer to the buffer which contains the values for the
* division the register address and the
* \param Length Length of the input buffer
*
* \return STATUS_SUCCESS on success, otherwise error code
*/
NTSTATUS IoctlDivInteger(
void* Buffer,
uint32_t Length);
/**
* \brief Increments the return address to the caller by 1
*
* \return STATUS_SUCCESS
*/
NTSTATUS IoctlIncRetAddr();
/**
* \brief Sets the CET field in the current CR4 register
* process
*
* \param Buffer Pointer to the buffer which contains the CET value to set
* \param Length Length of the input buffer
*
* \return STATUS_SUCCESS on success, otherwise error code
*/
NTSTATUS IoctlWriteCr4(
void* Buffer,
uint32_t Length);
/**
* \brief Patches its own return address in order to return on the next return
* address in the stack
*
* \return STATUS_SUCCESS always
*/
NTSTATUS IoctlSkipNextFrame();
/**
* \brief Writes the given MSR register with the given value
*
* \param Buffer Pointer to the buffer which contains the register address and
* the value to be written
* \param Length Length of the input buffer
*
* \return STATUS_SUCCESS on success, otherwise error code
*/
NTSTATUS IoctlWriteMsr(
void* Buffer,
uint32_t Length);
/**
* \brief Writes the given value into the shadow stack at the given offset
*
* \param Buffer Pointer to the buffer which contains the offset and value to
* write
* \param Length Length of the input buffer
*
* \return STATUS_SUCCESS on success, otherwise error code
*/
NTSTATUS IoctlWriteShadowStack(
void* Buffer,
uint32_t Length);
/**
* \brief Rewrites the shadow stack PTE with the given PTE write flag
*
* \param Buffer Pointer to the buffer which contains the PTE to use
* \param Length Length of the input buffer
*
* \return STATUS_SUCCESS on success, otherwise error code
*/
NTSTATUS IoctlWriteShadowStackPte(
void* Buffer,
uint32_t Length);
#endif // __DRIVER_IOCTL_H__
+8
View File
@@ -0,0 +1,8 @@
.code
setRsp PROC
mov rsp, rcx
ret
setRsp ENDP
END
+544
View File
@@ -0,0 +1,544 @@
#include "driver/utils.h"
#include <ntstrsafe.h>
#define KERNEL_ADDR_MASK (0xfffffffffff00000)
#define MASK_KERNEL_ADDR(addr) ((addr)&KERNEL_ADDR_MASK)
// ===========================================================================
// Offsets 24h2 - KTHREAD
// ===========================================================================
static uint32_t KernelShadowStack_offset = 0x408;
static uint32_t KernelShadowStackBase_offset = 0x418;
static uint32_t KernelShadowStackInitial_offset = 0x410;
static uint32_t KernelShadowStackLimit_offset = 0x420;
static uint32_t MiscFlags_offset = 0x074;
static uint32_t Process_offset = 0x220;
static uint32_t ThreadListEntry_offset = 0x2f8;
// ===========================================================================
// Offsets 24h2 - EPROCESS
// ===========================================================================
static uint32_t ImageFileName_offset = 0x338;
static uint32_t ThreadListHead_offset = 0x30;
// static uint32_t ThreadListHead_offset = 0x370;
// ===========================================================================
// Extern declarations
// ===========================================================================
extern void setRsp(void*);
// ===========================================================================
// Function definitions
// ===========================================================================
NTSTATUS CreateExposedDevice(DRIVER_OBJECT* DriverObject)
{
NTSTATUS Status = STATUS_INVALID_PARAMETER;
DbgPrintEnter();
if (!DriverObject)
{
DbgPrint("Invalid drive object\n");
goto EXIT;
}
Status = CreateExposedDeviceEx(
DriverObject,
DRIVER_DEVICE_NAME,
DOS_DEVICE_NAME);
if (!NT_SUCCESS(Status))
{
DbgPrint("CreateExposedDeviceEx failed\n");
goto EXIT;
}
Status = STATUS_SUCCESS;
EXIT:
DbgPrintLeave();
return Status;
}
NTSTATUS CreateExposedDeviceEx(
DRIVER_OBJECT* DriverObject,
wchar_t* DeviceName,
wchar_t* SymlinkName)
{
DEVICE_OBJECT* DeviceObject = NULL;
NTSTATUS Status = STATUS_INVALID_PARAMETER;
UNICODE_STRING uDeviceName = { 0 };
UNICODE_STRING uSymlinkName = { 0 };
DbgPrintEnter();
if (!DriverObject)
{
DbgPrint("Invalid drive object\n");
goto EXIT;
}
if (!DeviceName)
{
DbgPrint("Invalid device name\n");
goto EXIT;
}
if (!SymlinkName)
{
DbgPrint("Invalid symbolic link name\n");
goto EXIT;
}
RtlInitUnicodeString(&uDeviceName, DeviceName);
RtlInitUnicodeString(&uSymlinkName, SymlinkName);
Status = IoCreateDevice(
DriverObject,
0,
&uDeviceName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&DeviceObject);
if (!NT_SUCCESS(Status))
{
DbgPrint("Failed to create device object\n");
goto EXIT;
}
Status = IoCreateSymbolicLink(&uSymlinkName, &uDeviceName);
if (!NT_SUCCESS(Status))
{
DbgPrint("Failed to create symbolic link\n");
goto EXIT;
}
Status = STATUS_SUCCESS;
EXIT:
if (!NT_SUCCESS(Status) && DeviceObject)
{
IoDeleteDevice(DeviceObject);
}
DbgPrintLeave();
return Status;
}
void DeleteExposedDevice(DRIVER_OBJECT* DriverObject)
{
DbgPrintEnter();
if (!DriverObject)
{
DbgPrint("Invalid driver object\n");
goto EXIT;
}
DeleteExposedDeviceEx(DriverObject, DOS_DEVICE_NAME);
EXIT:
DbgPrintLeave();
}
void DeleteExposedDeviceEx(DRIVER_OBJECT* DriverObject, wchar_t* SymlinkName)
{
UNICODE_STRING uSymlinkName = { 0 };
DbgPrintEnter();
if (!DriverObject)
{
DbgPrint("Invalid driver object\n");
goto EXIT;
}
if (!SymlinkName)
{
DbgPrint("Invalid symbolic link name\n");
goto EXIT;
}
RtlInitUnicodeString(&uSymlinkName, SymlinkName);
IoDeleteSymbolicLink(&uSymlinkName);
if (DriverObject->DeviceObject)
{
IoDeleteDevice(DriverObject->DeviceObject);
}
EXIT:
DbgPrintLeave();
}
int32_t DivInteger(int32_t Dividend, int32_t Divisor)
{
int32_t Quotient = 0;
DbgPrintEnter();
Quotient = Dividend / Divisor;
DbgPrintLeave();
return Quotient;
}
void IncRetAddr()
{
uintptr_t* placeholder = NULL;
DbgPrintEnter();
placeholder = (uintptr_t*)&placeholder;
DbgPrint("Legitimate return address: %p\n", placeholder[3]);
placeholder[3]++;
DbgPrint("Incremented return address: %p\n", placeholder[3]);
DbgPrintLeave();
}
void* GetCurrentThreadKernelShadowStack()
{
return GetThreadKernelShadowStack(KeGetCurrentThread());
}
void* GetCurrentThreadKernelShadowStackBase()
{
return GetThreadKernelShadowStackBase(KeGetCurrentThread());
}
void* GetCurrentThreadKernelShadowStackInitial()
{
return GetThreadKernelShadowStackInitial(KeGetCurrentThread());
}
void* GetCurrentThreadKernelShadowStackLimit()
{
return GetThreadKernelShadowStackLimit(KeGetCurrentThread());
}
MiscFlags_t GetCurrentThreadMiscFlags()
{
return GetThreadMiscFlags(KeGetCurrentThread());
}
void* GetKernelBase()
{
return GetModuleBase((void*)ExAllocatePool2);
}
void* GetMmShadowPfnDatabase()
{
UNICODE_STRING ustr = { 0 };
uintptr_t MmGetVirtualForPhysical = 0;
uintptr_t MmShadowPfnDatabase = 0;
RtlInitUnicodeString(&ustr, L"MmGetVirtualForPhysical");
MmGetVirtualForPhysical = (uintptr_t)MmGetSystemRoutineAddress(&ustr);
MmShadowPfnDatabase = *(uintptr_t*)(MmGetVirtualForPhysical + 0x22);
MmShadowPfnDatabase &= ~(uintptr_t)0xff;
return (void*)MmShadowPfnDatabase;
}
void* GetModuleBase(void* Address)
{
char* addr = Address;
for (addr = (char*)((uintptr_t)addr & 0xffffffffffff0000);; addr -= 0x10000)
{
if (addr[0] == 'M' && addr[1] == 'Z')
{
DbgPrint("Module found: %p\n", addr);
break;
}
}
return addr;
}
void* GetShadowPteAddress(void* Address)
{
uintptr_t Address_ = 0;
uintptr_t MmShadowPfnDatabase = 0;
uintptr_t PteAddress = 0;
// uintptr_t PdeAddress = 0;
// uintptr_t PdpeAddress = 0;
// uintptr_t Pml4Address = 0;
if (Address)
{
Address_ = (uintptr_t)Address;
MmShadowPfnDatabase = (uintptr_t)GetMmShadowPfnDatabase();
PteAddress = ((Address_ >> 9) & 0x7FFFFFFFF8LL) + MmShadowPfnDatabase;
// PdeAddress = ((PteAddress >> 9) & 0x7FFFFFFFF8LL) + MmShadowPfnDatabase;
// PdpeAddress = ((PdeAddress >> 9) & 0x7FFFFFFFF8LL) + MmShadowPfnDatabase;
// Pml4Address = ((PdpeAddress >> 9) & 0x7FFFFFFFF8LL) + MmShadowPfnDatabase;
}
return (void*)PteAddress;
}
MiscFlags_t GetThreadMiscFlags(PKTHREAD Thread)
{
MiscFlags_t Flags = { 0 };
if (!Thread)
{
DbgPrint(__FUNCTION__ ": Invalid thread\n");
goto EXIT;
}
Flags = *(MiscFlags_t*)((char*)Thread + MiscFlags_offset);
EXIT:
return Flags;
}
void* GetThreadKernelShadowStack(PKTHREAD Thread)
{
void* Stack = NULL;
if (!Thread)
{
DbgPrint("Invalid thread\n");
goto EXIT;
}
Stack = *(void**)((char*)Thread + KernelShadowStack_offset);
DbgPrint("Kernel Shadow Stack: %p\n", Stack);
EXIT:
return Stack;
}
void* GetThreadKernelShadowStackBase(PKTHREAD Thread)
{
void* Stack = NULL;
if (!Thread)
{
DbgPrint("Invalid thread\n");
goto EXIT;
}
Stack = *(void**)((char*)Thread + KernelShadowStackBase_offset);
DbgPrint("Kernel Shadow Stack Base: %p\n", Stack);
EXIT:
return Stack;
}
void* GetThreadKernelShadowStackInitial(PKTHREAD Thread)
{
void* Stack = NULL;
if (!Thread)
{
DbgPrint("Invalid thread\n");
goto EXIT;
}
Stack = *(void**)((char*)Thread + KernelShadowStackInitial_offset);
DbgPrint("Kernel Shadow Stack Initial: %p\n", Stack);
EXIT:
return Stack;
}
void* GetThreadKernelShadowStackLimit(PKTHREAD Thread)
{
void* Stack = NULL;
if (!Thread)
{
DbgPrint("Invalid thread\n");
goto EXIT;
}
Stack = *(void**)((char*)Thread + KernelShadowStackLimit_offset);
DbgPrint("Kernel Shadow Stack Limit: %p\n", Stack);
EXIT:
return Stack;
}
void PrintCetKernelShadowStack(PKTHREAD Thread)
{
MiscFlags_t* Flags = NULL;
Flags = (MiscFlags_t*)((char*)Thread + MiscFlags_offset);
DbgPrint("Thread: %p\n", Thread);
DbgPrint(" CetUserShadowStack: %s\n",
Flags->CetUserShadowStack ? "TRUE" : "FALSE");
DbgPrint(" CetKernelShadowStack: %s\n",
Flags->CetKernelShadowStack ? "TRUE" : "FALSE");
}
NTSTATUS PrintCetKernelShadowStackCallback(PKTHREAD Thread, void* Context)
{
UNREFERENCED_PARAMETER(Context);
PrintCetKernelShadowStack(Thread);
return STATUS_SUCCESS;
}
void PrintThreadProcessName(PKTHREAD Thread)
{
PKPROCESS Process = NULL;
if (Thread)
{
Process = *(void**)((char*)Thread + Process_offset);
DbgPrint("Thread: %p >> %s\n",
Thread,
(char*)Process + ImageFileName_offset);
}
}
NTSTATUS PrintThreadProcessNameCallback(PKTHREAD Thread, void* Context)
{
UNREFERENCED_PARAMETER(Context);
PrintThreadProcessName(Thread);
return STATUS_SUCCESS;
}
void SetThreadCetKernelShadowStack(PKTHREAD Thread, uint8_t Value)
{
MiscFlags_t* Flags = NULL;
if (Thread)
{
DbgPrint("Thread: %p\n", Thread);
Flags = (MiscFlags_t*)((char*)Thread + MiscFlags_offset);
Flags->CetKernelShadowStack = Value & 1;
}
}
NTSTATUS SetThreadCetKernelShadowStackCallback(PKTHREAD Thread, void* Context)
{
if (!Thread)
{
DbgPrint(__FUNCTION__ ": Invalid thread\n");
return STATUS_INVALID_PARAMETER;
}
SetThreadCetKernelShadowStack(Thread, (uintptr_t)Context & 0xff);
return STATUS_SUCCESS;
}
void SetThreadKernelShadowStack(PKTHREAD Thread, void* ShadowStack)
{
if (Thread)
{
*(void**)((char*)Thread + KernelShadowStack_offset) = ShadowStack;
}
}
void SetThreadKernelShadowStackBase(PKTHREAD Thread, void* ShadowStackBase)
{
if (Thread)
{
*(void**)((char*)Thread + KernelShadowStackBase_offset) = ShadowStackBase;
}
}
void SetThreadKernelShadowStackInitial(
PKTHREAD Thread,
void* ShadowStackInitial)
{
if (Thread)
{
*(void**)((char*)Thread + KernelShadowStackInitial_offset) =
ShadowStackInitial;
}
}
void SetThreadKernelShadowStackLimit(PKTHREAD Thread, void* ShadowStackLimit)
{
if (Thread)
{
*(void**)((char*)Thread + KernelShadowStackLimit_offset) = ShadowStackLimit;
}
}
void SkipNextFrame()
{
uintptr_t module = 0;
uintptr_t* new_rsp = NULL;
DbgPrintEnter();
module = (uintptr_t)GetModuleBase((void*)SkipNextFrame);
new_rsp = (uintptr_t*)&new_rsp;
for (new_rsp += 2;; ++new_rsp)
{
if (MASK_KERNEL_ADDR(module) == MASK_KERNEL_ADDR(*new_rsp))
{
break;
}
}
setRsp(new_rsp);
DbgPrintLeave();
}
NTSTATUS ThreadWalker(ThreadCallback_t Callback, void* Context)
{
LIST_ENTRY* Entry = NULL;
LIST_ENTRY* Head = NULL;
NTSTATUS Status = STATUS_INVALID_PARAMETER;
PEPROCESS Process = NULL;
PKTHREAD Thread = NULL;
if (!Callback)
{
DbgPrint(__FUNCTION__ ": Invalid parameter\n");
goto EXIT;
}
Process = PsGetCurrentProcess();
Head = (LIST_ENTRY*)((char*)Process + ThreadListHead_offset);
for (Entry = Head->Flink; Entry != Head; Entry = Entry->Flink)
{
Thread = (PKTHREAD)((uintptr_t)Entry - ThreadListEntry_offset);
Status = Callback(Thread, Context);
if (NT_ERROR(Status))
{
DbgPrint(__FUNCTION__ ": Callback failed\n");
break;
}
}
EXIT:
DbgPrintLeave();
return Status;
}
+333
View File
@@ -0,0 +1,333 @@
#ifndef __DRIVER_UTILS_H__
#define __DRIVER_UTILS_H__
#include <stdint.h>
#include <wdm.h>
#include "common/utils.h"
#define DbgPrintEnter() DbgPrint("Entering " __FUNCTION__ "\n")
#define DbgPrintLeave() DbgPrint("Leaving " __FUNCTION__ "\n")
// ===========================================================================
// Callback definitions
// ===========================================================================
typedef NTSTATUS (*ThreadCallback_t)(PKTHREAD Thread, void* Context);
// ===========================================================================
// Function declarations
// ===========================================================================
/**
* \brief Creates a device with "\Device\ShadowStack" name and exposes it
* with "\DosDevices\ShadowStack" as symbolic link
*
* \param DriverObject Pointer to the driver object of the current driver
*
* \return STATUS_SUCCESS on success, otherwise error code
*/
NTSTATUS CreateExposedDevice(
DRIVER_OBJECT* DriverObject);
/**
* \brief Creates a device and expose it to the userland
*
* \param DriverObject Pointer to the driver object of the current driver
* \param DeviceName Pointer to the device name of the device to be created
* \param SymlinkName Pointer to the name that will be exposed to the userland
*
* \return STATUS_SUCCESS on success, otherwise error code
*/
NTSTATUS CreateExposedDeviceEx(
DRIVER_OBJECT* DriverObject,
wchar_t* DeviceName,
wchar_t* SymlinkName);
/**
* \brief Deletes the currently created device
*
* \param DriverObject Pointer to the driver object of the current driver
*/
void DeleteExposedDevice(
DRIVER_OBJECT* DriverObject);
/**
* \brief Deletes the device related to the given symbolic link
*
* \param DriverObject Pointer to the driver object of the current driver
* \param SymlinkName Pointer to the symbolic link name which has to be deleted
*/
void DeleteExposedDeviceEx(
DRIVER_OBJECT* DriverObject,
wchar_t* SymlinkName);
/**
* \brief Performs integer division
*
* \param Dividend Value to divide
* \param Divisor Value used to divide
*
* \return The quotient
*/
int32_t DivInteger(
int32_t Dividend,
int32_t Divisor);
/**
* \brief Increments the return address to the caller by 1
*/
void IncRetAddr();
/**
* \brief Retrieves the kernel shadow stack pointer of the current thread
*
* \return The kernel shadow stack pointer of the current thread
*/
void* GetCurrentThreadKernelShadowStack();
/**
* \brief Retrieves the kernel shadow stack base pointer of the current thread
*
* \return The kernel shadow stack base pointer of the current thread
*/
void* GetCurrentThreadKernelShadowStackBase();
/**
* \brief Retrieves the kernel shadow stack initial pointer of the current thread
*
* \return The kernel shadow stack initial pointer of the current thread
*/
void* GetCurrentThreadKernelShadowStackInitial();
/**
* \brief Retrieves the kernel shadow stack limit of the current thread
*
* \return The kernel shadow stack limit of the current thread
*/
void* GetCurrentThreadKernelShadowStackLimit();
/**
* \brief Retrieves the misc flags of the current thread
*
* \return Misc flags of the current thread
*/
MiscFlags_t GetCurrentThreadMiscFlags();
/**
* \brief Looks for the kernel base address
*
* \return The kernel base address
*/
void* GetKernelBase();
/**
* \brief Looks for the shadow PFN database
*
* \return The PFN database
*/
void* GetMmShadowPfnDatabase();
/**
* \brief Looks for the module base address related to the given address
*
* \param Address Address in the module from which the base address has to be
* retrieved
*
* \return The module base address
*/
void* GetModuleBase(
void* Address);
/**
* \brief Looks for the virtual shadow PTE address of the given address
*
* \param Address Address of which to get the virtual PTE address
*
* \return The virtual PTE address
*/
void* GetShadowPteAddress(
void* Address);
/**
* \brief Retrieves the misc flags of the given thread
*
* \param Thread Pointer to the thread from which the misc flags are retrieved
*
* \return Misc flags of the given thread
*/
MiscFlags_t GetThreadMiscFlags(
PKTHREAD Thread);
/**
* \brief Retrieves the kernel shadow stack pointer of the given thread
*
* \param Thread Pointer to the thread from which retrieve the kernel shadow
* stack pointer
*
* \return The kernel shadow stack pointer of the given thread
*/
void* GetThreadKernelShadowStack(
PKTHREAD Thread);
/**
* \brief Retrieves the kernel shadow stack base pointer of the given thread
*
* \param Thread Pointer to the thread from which retrieve the kernel shadow
* stack base pointer
*
* \return The kernel shadow stack base pointer of the given thread
*/
void* GetThreadKernelShadowStackBase(
PKTHREAD Thread);
/**
* \brief Retrieves the kernel shadow stack initial pointer of the given thread
*
* \param Thread Pointer to the thread from which retrieve the kernel shadow
* stack initial pointer
*
* \return The kernel shadow stack initial pointer of the given thread
*/
void* GetThreadKernelShadowStackInitial(
PKTHREAD Thread);
/**
* \brief Retrieves the kernel shadow stack limit pointer of the given thread
*
* \param Thread Pointer to the thread from which retrieve the kernel shadow
* stack limit pointer
*
* \return The kernel shadow stack limit pointer of the given thread
*/
void* GetThreadKernelShadowStackLimit(
PKTHREAD Thread);
/**
* \brief Prints the CetUserShadowStack and the CetKernelShadowStack flags of
* the given thread
*
* \param Thread Pointer to the thread from which the flags have to be read
*/
void PrintCetKernelShadowStack(
PKTHREAD Thread);
/**
* \brief Callback used to call PrintCetKernelShadowStack (act as a wrapper)
*
* \param Thread Pointer to the thread from which the flags have to be read
* \param Context Unused parameter
*
* \return STATUS_SUCCESS always
*/
NTSTATUS PrintCetKernelShadowStackCallback(
PKTHREAD Thread,
void* Context);
/**
* \brief Prints the process name of the given thread
*
* \param Thread Pointer to the thread from which the process then process name
* are retrieved
*/
void PrintThreadProcessName(
PKTHREAD Thread);
/**
* \brief Callback used to call PrintThreadProcessName (act as a wrapper)
*
* \param Thread Pointer to the thread from which the process then process name
* are retrieved
* \param Context Unused parameter
*
* \return STATUS_SUCCESS always
*/
NTSTATUS PrintThreadProcessNameCallback(
PKTHREAD Thread,
void* Context);
/**
* \brief Sets the CetKernelShadowStack of the given thread with given value
*
* \param Thread Pointer to the thread to which the CetKernelShadowStack flag
* as to be set
* \param Value Value to set
*/
void SetThreadCetKernelShadowStack(
PKTHREAD Thread,
uint8_t Value);
/**
* \brief Callback used to call SetThreadCetKernelShadowStack (act as a wrapper)
*
* \param Thread Pointer to the thread to which the CetKernelShadowStack flag
* as to be set
* \param Context Represent the value used to set CetKernelShadowStack in
* SetThreadCetKernelShadowStack function
*/
NTSTATUS SetThreadCetKernelShadowStackCallback(
PKTHREAD Thread,
void* Context);
/**
* \brief Sets the kernel shadow stack pointer of the given thread
*
* \param Thread Pointer to the thread to which set the kernel shadow stack
* pointer
* \param ShadowStack Pointer to the shadow stack to set
*/
void SetThreadKernelShadowStack(
PKTHREAD Thread,
void* ShadowStack);
/**
* \brief Sets the kernel shadow stack base pointer of the given thread
*
* \param Thread Pointer to the thread to which set the kernel shadow
* stack base pointer
* \param ShadowStackBase Pointer to the shadow stack base to set
*/
void SetThreadKernelShadowStackBase(
PKTHREAD Thread,
void* ShadowStackBase);
/**
* \brief Sets the kernel shadow stack initial pointer of the given thread
*
* \param Thread Pointer to the thread to which set the kernel
* shadow stack initial pointer
* \param ShadowStackInitial Pointer to the shadow stack initial to set
*/
void SetThreadKernelShadowStackInitial(
PKTHREAD Thread,
void* ShadowStackInitial);
/**
* \brief Sets the kernel shadow stack limit pointer of the given thread
*
* \param Thread Pointer to the thread to which set the kernel shadow
* stack limit pointer
* \param ShadowStackLimit Pointer to the shadow stack limit to set
*/
void SetThreadKernelShadowStackLimit(
PKTHREAD Thread,
void* ShadowStackLimit);
/**
* \brief Skips the next stack frame
*/
void SkipNextFrame();
/**
* \brief Walks through every thread of the current process
*
* \param Callback Pointer to the callback to call for each thread
* \param Context Pointer to the context to pass to each thread
*
* \return STATUS_SUCCESS on success, otherwise error code
*/
NTSTATUS ThreadWalker(
ThreadCallback_t Callback,
void* Context);
#endif // __DRIVER_UTILS_H__