├── libs ├── libMinHook.x64.lib └── libMinHook.x86.lib ├── winstructs.hpp ├── README.md ├── driverceptor ├── stdafx.hpp ├── driverceptor.inf ├── driver_hooks.hpp ├── helpers.hpp ├── driverceptor.vcxproj.filters ├── handles.hpp ├── tools.hpp ├── driverceptor.vcxproj ├── apc.txt ├── kernel.hpp └── driver.cpp ├── includes.hpp ├── testExe ├── testExe.vcxproj.filters ├── test.cpp └── testExe.vcxproj ├── intraceptor.vcxproj.filters ├── intraceptor.sln ├── main.cpp ├── .gitignore ├── MinHook.h ├── intraceptor.vcxproj ├── commands_id.hpp ├── commands.hpp └── hooks.hpp /libs/libMinHook.x64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crvvdev/intraceptor/HEAD/libs/libMinHook.x64.lib -------------------------------------------------------------------------------- /libs/libMinHook.x86.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crvvdev/intraceptor/HEAD/libs/libMinHook.x86.lib -------------------------------------------------------------------------------- /winstructs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef enum _MEMORY_INFORMATION_CLASS 4 | { 5 | MemoryBasicInformation 6 | } MEMORY_INFORMATION_CLASS; 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # intraceptor 2 | Intraceptor intercept Windows NT API calls and redirect them to a kernel driver to bypass process/threads handle protections. 3 | 4 | The current state of the project is semi-abandoned/not being worked ATM. 5 | -------------------------------------------------------------------------------- /driverceptor/stdafx.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "..\commands_id.hpp" 9 | #include "kernel.hpp" 10 | #include "tools.hpp" 11 | 12 | #ifdef _DEBUG 13 | #define DBGPRINT( s, ... ) DbgPrintEx( 0, 0, "[ Ceptor ] " s "\n", __VA_ARGS__ ); 14 | #else 15 | #define DBGPRINT( s, ... ) ( s ) 16 | #endif 17 | 18 | #include "helpers.hpp" 19 | #include "handles.hpp" -------------------------------------------------------------------------------- /includes.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #ifndef STATUS_SUCCESS 7 | #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) 8 | #endif 9 | 10 | #ifdef _WIN64 11 | #pragma comment( lib, "libMinHook.x64.lib" ) 12 | #else 13 | #pragma comment( lib, "libMinHook.x86.lib" ) 14 | #endif 15 | 16 | #pragma comment( lib, "ntdll" ) 17 | 18 | #include "winstructs.hpp" 19 | #include "commands.hpp" 20 | #include "hooks.hpp" 21 | 22 | #include "MinHook.h" -------------------------------------------------------------------------------- /driverceptor/driverceptor.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; driverceptor.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=System 8 | ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} 9 | Provider=%ManufacturerName% 10 | DriverVer= 11 | CatalogFile=driverceptor.cat 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | 16 | 17 | [SourceDisksNames] 18 | 1 = %DiskName%,,,"" 19 | 20 | [SourceDisksFiles] 21 | 22 | 23 | [Manufacturer] 24 | %ManufacturerName%=Standard,NT$ARCH$ 25 | 26 | [Standard.NT$ARCH$] 27 | 28 | 29 | [Strings] 30 | ManufacturerName="" ;TODO: Replace with your manufacturer name 31 | ClassName="" 32 | DiskName="driverceptor Source Disk" 33 | -------------------------------------------------------------------------------- /testExe/testExe.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /driverceptor/driver_hooks.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | f_NtCreateFile o_NtCreateFile = nullptr; 4 | f_NtOpenProcess o_NtOpenProcess = nullptr; 5 | f_NtQuerySystemInformation o_NtQuerySystemInformation = nullptr; 6 | f_NtQueryInformationProcess o_NtQueryInformationProcess = nullptr; 7 | f_NtLoadDriver o_NtLoadDriver = nullptr; 8 | f_NtGdiBitBlt o_NtGdiBitBlt = nullptr; 9 | f_NtUserFindWindowEx o_NtUserFindWindowEx = nullptr; 10 | f_NtUserBuildHwndList o_NtUserBuildHwndList = nullptr; 11 | f_NtUserGetForegroundWindow o_NtUserGetForegroundWindow = nullptr; 12 | f_NtUserGetThreadState o_NtUserGetThreadState = nullptr; 13 | f_NtUserSetWindowsHookEx o_NtUserSetWindowsHookEx = nullptr; 14 | f_NtUserSetWinEventHook o_NtUserSetWinEventHook = nullptr; 15 | f_NtUserGetClassName o_NtUserGetClassName = nullptr; 16 | f_NtUserInternalGetWindowText o_NtUserInternalGetWindowText = nullptr; 17 | f_NtUserInternalGetWindowIcon o_NtUserInternalGetWindowIcon = nullptr; 18 | 19 | //ZwRaiseException -------------------------------------------------------------------------------- /driverceptor/helpers.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | inline PVOID AllocateZeroPool( SIZE_T size ) 4 | { 5 | auto PoolPtr = ExAllocatePool( NonPagedPool, size ); 6 | 7 | if ( PoolPtr ) 8 | RtlZeroMemory( PoolPtr, size ); 9 | 10 | return PoolPtr; 11 | } 12 | 13 | inline VOID AdjustRelativePointers( std::uint8_t* buffer, std::uint8_t* target, SIZE_T size ) 14 | { 15 | if ( size < sizeof( PVOID ) ) { 16 | return; 17 | } 18 | 19 | for ( SIZE_T i = 0; i <= size - sizeof( PVOID ); i += sizeof( ULONG ) ) 20 | { 21 | PVOID* ptr = ( PVOID* )( buffer + i ); 22 | SIZE_T offset = ( std::uint8_t* ) * ptr - buffer; 23 | 24 | if ( offset < size ) { 25 | *ptr = target + offset; 26 | i += sizeof( ULONG ); 27 | } 28 | } 29 | } 30 | 31 | __forceinline bool AcquireProcessSync( PEPROCESS Process ) 32 | { 33 | return ( PsGetProcessExitProcessCalled( Process ) == FALSE && NT_SUCCESS( PsAcquireProcessExitSynchronization( Process ) ) ); 34 | } 35 | 36 | __forceinline void ReleaseProcessSync( PEPROCESS Process ) 37 | { 38 | PsReleaseProcessExitSynchronization( Process ); 39 | } 40 | 41 | __forceinline bool AcquireThreadSync( PETHREAD Thread ) 42 | { 43 | return ( PsIsThreadTerminating( Thread ) == FALSE && PsGetThreadExitStatus( Thread ) == STATUS_PENDING ); 44 | } -------------------------------------------------------------------------------- /intraceptor.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | -------------------------------------------------------------------------------- /driverceptor/driverceptor.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Driver Files 24 | 25 | 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Driver Files 49 | 50 | 51 | 52 | 53 | Header Files 54 | 55 | 56 | -------------------------------------------------------------------------------- /intraceptor.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30413.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "intraceptor", "intraceptor.vcxproj", "{003D6992-9564-480B-A507-E7E0B71AAB2E}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "driverceptor", "driverceptor\driverceptor.vcxproj", "{A958D6FF-0ABC-4655-B7D6-E641F276FCA7}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testExe", "testExe\testExe.vcxproj", "{E48713C6-7294-4CDA-B597-FBD9AADD7283}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|x64 = Debug|x64 15 | Release|x64 = Release|x64 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {003D6992-9564-480B-A507-E7E0B71AAB2E}.Debug|x64.ActiveCfg = Debug|x64 19 | {003D6992-9564-480B-A507-E7E0B71AAB2E}.Debug|x64.Build.0 = Debug|x64 20 | {003D6992-9564-480B-A507-E7E0B71AAB2E}.Release|x64.ActiveCfg = Release|x64 21 | {003D6992-9564-480B-A507-E7E0B71AAB2E}.Release|x64.Build.0 = Release|x64 22 | {A958D6FF-0ABC-4655-B7D6-E641F276FCA7}.Debug|x64.ActiveCfg = Debug|x64 23 | {A958D6FF-0ABC-4655-B7D6-E641F276FCA7}.Debug|x64.Build.0 = Debug|x64 24 | {A958D6FF-0ABC-4655-B7D6-E641F276FCA7}.Debug|x64.Deploy.0 = Debug|x64 25 | {A958D6FF-0ABC-4655-B7D6-E641F276FCA7}.Release|x64.ActiveCfg = Release|x64 26 | {A958D6FF-0ABC-4655-B7D6-E641F276FCA7}.Release|x64.Build.0 = Release|x64 27 | {A958D6FF-0ABC-4655-B7D6-E641F276FCA7}.Release|x64.Deploy.0 = Release|x64 28 | {E48713C6-7294-4CDA-B597-FBD9AADD7283}.Debug|x64.ActiveCfg = Debug|x64 29 | {E48713C6-7294-4CDA-B597-FBD9AADD7283}.Debug|x64.Build.0 = Debug|x64 30 | {E48713C6-7294-4CDA-B597-FBD9AADD7283}.Release|x64.ActiveCfg = Release|x64 31 | {E48713C6-7294-4CDA-B597-FBD9AADD7283}.Release|x64.Build.0 = Release|x64 32 | EndGlobalSection 33 | GlobalSection(SolutionProperties) = preSolution 34 | HideSolutionNode = FALSE 35 | EndGlobalSection 36 | GlobalSection(ExtensibilityGlobals) = postSolution 37 | SolutionGuid = {7BE9A443-4462-4181-9AF0-6447C38AD3DF} 38 | EndGlobalSection 39 | EndGlobal 40 | -------------------------------------------------------------------------------- /driverceptor/handles.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct _HANDLES_LIST_ENTRY 4 | { 5 | PETHREAD Thread; 6 | PEPROCESS Process; 7 | LIST_ENTRY Entry; 8 | HANDLE HandleValue; 9 | HANDLE ProcessId; 10 | BOOLEAN Wow64; 11 | 12 | } HANDLES_LIST_ENTRY, * PHANDLES_LIST_ENTRY; 13 | 14 | volatile LONG __HANDLES_VALUE = 0xF0F00000; 15 | PHANDLES_LIST_ENTRY __HANDLES_LIST_HEAD = nullptr; 16 | KSPIN_LOCK __HANDLES_LOCK; 17 | 18 | PHANDLES_LIST_ENTRY InitializeHandleList() 19 | { 20 | const auto List = PHANDLES_LIST_ENTRY( AllocateZeroPool( sizeof( HANDLES_LIST_ENTRY ) ) ); 21 | if ( !List ) 22 | return nullptr; 23 | 24 | DBGPRINT( "Initialized list head at 0x%p", List ); 25 | InitializeListHead( &List->Entry ); 26 | return List; 27 | } 28 | 29 | PHANDLES_LIST_ENTRY InsertHandleListEntry() 30 | { 31 | const auto Entry = PHANDLES_LIST_ENTRY( AllocateZeroPool( sizeof( HANDLES_LIST_ENTRY ) ) ); 32 | if ( !Entry ) 33 | return nullptr; 34 | 35 | KIRQL oldIrql; 36 | KeAcquireSpinLock( &__HANDLES_LOCK, &oldIrql ); 37 | Entry->HandleValue = ULongToHandle( InterlockedIncrement( &__HANDLES_VALUE ) ); 38 | InsertTailList( &__HANDLES_LIST_HEAD->Entry, &Entry->Entry ); 39 | KeReleaseSpinLock( &__HANDLES_LOCK, oldIrql ); 40 | 41 | return Entry; 42 | } 43 | 44 | void RemoveHandleListEntry( PHANDLES_LIST_ENTRY Entry ) 45 | { 46 | if ( !Entry ) 47 | return; 48 | 49 | KIRQL oldIrql; 50 | KeAcquireSpinLock( &__HANDLES_LOCK, &oldIrql ); 51 | RemoveEntryList( &Entry->Entry ); 52 | KeReleaseSpinLock( &__HANDLES_LOCK, oldIrql ); 53 | ExFreePool( Entry ); 54 | } 55 | 56 | PHANDLES_LIST_ENTRY FindHandleListEntry( HANDLE HandleValue ) 57 | { 58 | if ( IsListEmpty( &__HANDLES_LIST_HEAD->Entry ) ) 59 | return nullptr; 60 | 61 | PHANDLES_LIST_ENTRY Found = nullptr; 62 | PLIST_ENTRY ListEntry = nullptr; 63 | 64 | KIRQL oldIrql; 65 | KeAcquireSpinLock( &__HANDLES_LOCK, &oldIrql ); 66 | for 67 | ( 68 | ListEntry = __HANDLES_LIST_HEAD->Entry.Flink; 69 | ListEntry != &__HANDLES_LIST_HEAD->Entry; 70 | ListEntry = ListEntry->Flink 71 | ) 72 | { 73 | auto Data = CONTAINING_RECORD( ListEntry, HANDLES_LIST_ENTRY, Entry ); 74 | 75 | if ( Data->HandleValue == HandleValue ) 76 | Found = Data; 77 | 78 | if ( Found ) 79 | break; 80 | } 81 | KeReleaseSpinLock( &__HANDLES_LOCK, oldIrql ); 82 | return Found; 83 | } 84 | 85 | void ClearHandleList() 86 | { 87 | // TODO.. 88 | } -------------------------------------------------------------------------------- /driverceptor/tools.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | template 6 | inline T resolve_jxx( uint8_t* address ) 7 | { 8 | return reinterpret_cast< T >( address + *reinterpret_cast< int8_t* >( address + 1 ) + 2 ); 9 | } 10 | 11 | template 12 | inline T resolve_call( uint8_t* address ) 13 | { 14 | return reinterpret_cast< T >( address + *reinterpret_cast< int32_t* >( address + 1 ) + 5 ); 15 | } 16 | 17 | template 18 | inline T resolve_mov( uint8_t* address ) 19 | { 20 | return reinterpret_cast< T >( address + *reinterpret_cast< int32_t* >( address + 3 ) + 7 ); 21 | } 22 | 23 | inline BOOLEAN FindModuleByName( LPCSTR modname, SIZE_T* base = nullptr, SIZE_T* size = nullptr ) 24 | { 25 | if ( !modname ) 26 | return FALSE; 27 | 28 | ULONG bytes = 0; 29 | 30 | auto Status = ZwQuerySystemInformation( SystemModuleInformation, NULL, bytes, &bytes ); 31 | if ( !bytes ) 32 | return FALSE; 33 | 34 | const auto info = PRTL_PROCESS_MODULES( ExAllocatePool( NonPagedPool, bytes ) ); 35 | 36 | Status = ZwQuerySystemInformation( SystemModuleInformation, info, bytes, &bytes ); 37 | if ( !NT_SUCCESS( Status ) ) 38 | { 39 | ExFreePool( info ); 40 | return FALSE; 41 | } 42 | 43 | BOOLEAN bResult = FALSE; 44 | 45 | for ( ULONG i = 0; i < info->NumberOfModules; i++ ) 46 | { 47 | const auto pModule = &info->Modules[ i ]; 48 | 49 | if ( strstr( PCHAR( pModule->FullPathName ), modname ) ) 50 | { 51 | if ( base ) 52 | *base = SIZE_T( pModule->ImageBase ); 53 | 54 | if ( size ) 55 | *size = SIZE_T( pModule->ImageSize ); 56 | 57 | bResult = true; 58 | break; 59 | } 60 | } 61 | 62 | if ( info ) 63 | ExFreePool( info ); 64 | 65 | return bResult; 66 | } 67 | 68 | inline BOOLEAN bDataCompare( const UCHAR* pData, const UCHAR* bMask, const char* szMask ) 69 | { 70 | for ( ; *szMask; ++szMask, ++pData, ++bMask ) 71 | if ( *szMask == 'x' && *pData != *bMask ) 72 | return 0; 73 | 74 | return ( *szMask ) == 0; 75 | } 76 | 77 | inline PUCHAR FindPattern( LPCSTR modname, LPCSTR secname, UCHAR* bMask, const char* szMask ) 78 | { 79 | SIZE_T base = NULL; 80 | 81 | if ( !modname || !secname || !bMask || !szMask ) 82 | return nullptr; 83 | 84 | if ( !FindModuleByName( modname, &base ) ) 85 | return nullptr; 86 | 87 | if ( !base ) 88 | return nullptr; 89 | 90 | auto nth = RtlImageNtHeader( PVOID( base ) ); 91 | if ( !nth ) 92 | return nullptr; 93 | 94 | PIMAGE_SECTION_HEADER pSection = nullptr; 95 | 96 | auto sec = IMAGE_FIRST_SECTION( nth ); 97 | for ( auto i = 0; i < nth->FileHeader.NumberOfSections; i++, sec++ ) 98 | { 99 | if ( !_strnicmp( reinterpret_cast< char* >( sec->Name ), secname, IMAGE_SIZEOF_SHORT_NAME ) ) 100 | { 101 | pSection = sec; 102 | break; 103 | } 104 | } 105 | 106 | if ( pSection ) 107 | { 108 | auto dwAddress = ( SIZE_T )( base + pSection->VirtualAddress ); 109 | 110 | for ( auto i = 0ul; i < pSection->Misc.VirtualSize; ++i ) 111 | { 112 | if ( bDataCompare( ( UCHAR* )( dwAddress + i ), bMask, szMask ) ) 113 | return PUCHAR( dwAddress + i ); 114 | } 115 | } 116 | return nullptr; 117 | } -------------------------------------------------------------------------------- /driverceptor/driverceptor.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {A958D6FF-0ABC-4655-B7D6-E641F276FCA7} 15 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 16 | v4.5 17 | 12.0 18 | Debug 19 | Win32 20 | driverceptor 21 | 22 | 23 | 24 | Windows10 25 | true 26 | WindowsKernelModeDriver10.0 27 | Driver 28 | WDM 29 | 30 | 31 | Windows10 32 | false 33 | WindowsKernelModeDriver10.0 34 | Driver 35 | WDM 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | DbgengKernelDebugger 47 | $(VC_IncludePath);$(CRT_IncludePath);$(KM_IncludePath);$(KIT_SHARED_IncludePath) 48 | 49 | 50 | DbgengKernelDebugger 51 | $(VC_IncludePath);$(VC_IncludePath);$(IncludePath) 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /testExe/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #pragma comment( lib, "ntdll" ) 8 | 9 | #define CEPTOR_VALID_HANDLE( h ) ( ( ( ( std::uint64_t )h >> 20 ) & 0xFFF ) == 0xF0F ) 10 | 11 | DWORD FindProcess( const wchar_t* szName ) 12 | { 13 | HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); 14 | if ( !hSnap ) 15 | return 0; 16 | 17 | DWORD ProcessId = NULL; 18 | 19 | PROCESSENTRY32 pe32{ }; 20 | pe32.dwSize = sizeof( pe32 ); 21 | 22 | Process32First( hSnap, &pe32 ); 23 | do 24 | { 25 | if ( !wcscmp( pe32.szExeFile, szName ) ) 26 | { 27 | ProcessId = pe32.th32ProcessID; 28 | break; 29 | } 30 | } while ( Process32Next( hSnap, &pe32 ) ); 31 | 32 | return ProcessId; 33 | } 34 | 35 | DWORD WINAPI Worker( PVOID ) 36 | { 37 | while ( true ) 38 | { 39 | Sleep( 60 * 1000 ); 40 | printf( "Thread finished\n" ); 41 | ExitThread( 0 ); 42 | } 43 | return 0; 44 | } 45 | 46 | int main() 47 | { 48 | auto hModule = LoadLibraryA( "intraceptor.dll" ); 49 | if ( !hModule ) 50 | { 51 | printf( "LoadLibrary returned %d\n", GetLastError() ); 52 | getchar(); 53 | return 1; 54 | } 55 | 56 | Sleep( 2500 ); 57 | 58 | printf( "Trying to attach into explorer.exe\n" ); 59 | ULONG ExplorerPID = FindProcess( L"explorer.exe" ); 60 | printf( "Explorer PID: 0x%X\n", ExplorerPID ); 61 | 62 | HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, ExplorerPID ); 63 | if ( hProcess ) 64 | { 65 | printf( "Process Handle: 0x%p\n", hProcess ); 66 | 67 | // 68 | // NtQueryInformationProcess 69 | // 70 | PROCESS_BASIC_INFORMATION pbi{ }; 71 | DWORD pbiLen = 0; 72 | NtQueryInformationProcess( hProcess, PROCESSINFOCLASS::ProcessBasicInformation, &pbi, sizeof( pbi ), &pbiLen ); 73 | 74 | printf( "PEB: 0x%p\n", pbi.PebBaseAddress ); 75 | 76 | // 77 | // VirtualAllocEx 78 | // 79 | auto Addr = VirtualAllocEx( hProcess, nullptr, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ); 80 | printf( "Addr: 0x%p\n", Addr ); 81 | 82 | // 83 | // RPM 84 | // 85 | ULONG AddrVal = 10; 86 | ReadProcessMemory( hProcess, Addr, &AddrVal, sizeof( AddrVal ), nullptr ); 87 | 88 | printf( "Addr: 0x%X\n", AddrVal ); 89 | 90 | // 91 | // WPM 92 | // 93 | if ( WriteProcessMemory( hProcess, Addr, "\xAD\xED\xEF", 4, nullptr ) ) 94 | printf( "Write success!\n" ); 95 | 96 | // 97 | // RPM 2 98 | // 99 | ReadProcessMemory( hProcess, Addr, &AddrVal, sizeof( AddrVal ), nullptr ); 100 | 101 | printf( "Addr: 0x%X\n", AddrVal ); 102 | 103 | // 104 | // VirtualProtectEx 105 | // 106 | DWORD dwOld = 0; 107 | VirtualProtectEx( hProcess, Addr, 0x1000, PAGE_EXECUTE_READWRITE, &dwOld ); 108 | 109 | // 110 | // VirtualQueryEx 111 | // 112 | MEMORY_BASIC_INFORMATION mbi{ }; 113 | if ( VirtualQueryEx( hProcess, Addr, &mbi, sizeof( mbi ) ) ) 114 | printf( "AllocationBase: 0x%p\n", mbi.AllocationBase ); 115 | 116 | // 117 | // VirtualFreeEx 118 | // 119 | VirtualFreeEx( hProcess, Addr, 0, MEM_RELEASE ); 120 | 121 | // 122 | // CreateThread 123 | // 124 | DWORD ThreadId = 0; 125 | CreateThread( nullptr, NULL, Worker, nullptr, NULL, &ThreadId ); 126 | printf( "ThreadId: %d\n", ThreadId ); 127 | 128 | // 129 | // OpenThread 130 | // 131 | HANDLE hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, ThreadId ); 132 | if ( hThread ) 133 | { 134 | printf( "Thread Handle: 0x%p\n", hThread ); 135 | 136 | CONTEXT ctx{ }; 137 | ctx.ContextFlags = CONTEXT_ALL; 138 | 139 | SuspendThread( hThread ); 140 | GetThreadContext( hThread, &ctx ); 141 | printf( "Rip = 0x%llX\n", ctx.Rip ); 142 | SetThreadContext( hThread, &ctx ); 143 | ResumeThread( hThread ); 144 | 145 | auto Res = WaitForSingleObject( hThread, INFINITE ); 146 | printf( "WaitForSingleObject res: %d\n", Res ); 147 | 148 | CloseHandle( hThread ); 149 | } 150 | 151 | CloseHandle( hProcess ); 152 | } 153 | 154 | Sleep( INFINITE ); 155 | return 0; 156 | } -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "includes.hpp" 2 | 3 | std::unique_ptr< CCommand > g_cmdDriver = nullptr; 4 | 5 | DWORD WINAPI StartThread( PVOID ) 6 | { 7 | while ( !GetModuleHandleA( "ntdll.dll" ) ) 8 | Sleep( 150 ); 9 | 10 | MH_Initialize(); 11 | 12 | g_cmdDriver = std::make_unique< CCommand >(); 13 | 14 | if ( AttachConsole( GetCurrentProcessId() ) != ERROR_ACCESS_DENIED ) 15 | { 16 | AllocConsole(); 17 | FILE* f = nullptr; 18 | freopen_s( &f, "CONIN$", "r", stdin ); 19 | freopen_s( &f, "CONOUT$", "w", stderr ); 20 | freopen_s( &f, "CONOUT$", "w", stdout ); 21 | } 22 | 23 | printf( "g_cmdDriver->Status: %d\n", g_cmdDriver->Status() ); 24 | 25 | HMODULE ntdll = LoadLibraryA( "ntdll.dll" ); 26 | 27 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtClose" ) ), &hk_NtClose, reinterpret_cast< PVOID* >( &oNtClose ) );// 28 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtWaitForSingleObject" ) ), &hk_NtWaitForSingleObject, reinterpret_cast< PVOID* >( &oNtWaitForSingleObject ) );// 29 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtOpenProcess" ) ), &hk_NtOpenProcess, reinterpret_cast< PVOID* >( &oNtOpenProcess ) );// 30 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtReadVirtualMemory" ) ), &hk_NtReadVirtualMemory, reinterpret_cast< PVOID* >( &oNtReadVirtualMemory ) );// 31 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtWriteVirtualMemory" ) ), &hk_NtWriteVirtualMemory, reinterpret_cast< PVOID* >( &oNtWriteVirtualMemory ) );// 32 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtQueryVirtualMemory" ) ), &hk_NtQueryVirtualMemory, reinterpret_cast< PVOID* >( &oNtQueryVirtualMemory ) );// 33 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtAllocateVirtualMemory" ) ), &hk_NtAllocateVirtualMemory, reinterpret_cast< PVOID* >( &oNtAllocateVirtualMemory ) );// 34 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtFreeVirtualMemory" ) ), &hk_NtFreeVirtualMemory, reinterpret_cast< PVOID* >( &oNtFreeVirtualMemory ) );// 35 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtProtectVirtualMemory" ) ), &hk_NtProtectVirtualMemory, reinterpret_cast< PVOID* >( &oNtProtectVirtualMemory ) );// 36 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtQueryInformationProcess" ) ), &hk_NtQueryInformationProcess, reinterpret_cast< PVOID* >( &oNtQueryInformationProcess ) );// 37 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtSuspendProcess" ) ), &hk_NtSuspendProcess, reinterpret_cast< PVOID* >( &oNtSuspendProcess ) );// 38 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtResumeProcess" ) ), &hk_NtResumeProcess, reinterpret_cast< PVOID* >( &oNtResumeProcess ) );// 39 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtQuerySystemInformationEx" ) ), &hk_NtQuerySystemInformationEx, reinterpret_cast< PVOID* >( &oNtQuerySystemInformationEx ) );// 40 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtSetInformationProcess" ) ), &hk_NtSetInformationProcess, reinterpret_cast< PVOID* >( &oNtSetInformationProcess ) );// 41 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtFlushInstructionCache" ) ), &hk_NtFlushInstructionCache, reinterpret_cast< PVOID* >( &oNtFlushInstructionCache ) );// 42 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtFlushVirtualMemory" ) ), &hk_NtFlushVirtualMemory, reinterpret_cast< PVOID* >( &oNtFlushVirtualMemory ) );// 43 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtLockVirtualMemory" ) ), &hk_NtLockVirtualMemory, reinterpret_cast< PVOID* >( &oNtLockVirtualMemory ) );// 44 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtUnlockVirtualMemory" ) ), &hk_NtUnlockVirtualMemory, reinterpret_cast< PVOID* >( &oNtUnlockVirtualMemory ) );// 45 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtOpenThread" ) ), &hk_NtOpenThread, reinterpret_cast< PVOID* >( &oNtOpenThread ) );// 46 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtQueryInformationThread" ) ), &hk_NtQueryInformationThread, reinterpret_cast< PVOID* >( &oNtQueryInformationThread ) );// 47 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtSetInformationThread" ) ), &hk_NtSetInformationThread, reinterpret_cast< PVOID* >( &oNtSetInformationThread ) );// 48 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtGetContextThread" ) ), &hk_NtGetContextThread, reinterpret_cast< PVOID* >( &oNtGetContextThread ) );// 49 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtSetContextThread" ) ), &hk_NtSetContextThread, reinterpret_cast< PVOID* >( &oNtSetContextThread ) );// 50 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtSuspendThread" ) ), &hk_NtSuspendThread, reinterpret_cast< PVOID* >( &oNtSuspendThread ) );// 51 | MH_CreateHook( PVOID( GetProcAddress( ntdll, "NtResumeThread" ) ), &hk_NtResumeThread, reinterpret_cast< PVOID* >( &oNtResumeThread ) );// 52 | 53 | MH_EnableHook( MH_ALL_HOOKS ); 54 | 55 | return EXIT_SUCCESS; 56 | } 57 | 58 | EXTERN_C __declspec( dllexport ) BOOL WINAPI DllMain( HMODULE hDll, DWORD dwReason, PVOID ) 59 | { 60 | if ( dwReason == DLL_PROCESS_ATTACH ) 61 | { 62 | CreateThread( nullptr, NULL, StartThread, nullptr, NULL, nullptr ); 63 | } 64 | return TRUE; 65 | } -------------------------------------------------------------------------------- /driverceptor/apc.txt: -------------------------------------------------------------------------------- 1 | typedef struct _THREAD_CONTEXT_ARGS 2 | { 3 | BOOLEAN Query; 4 | THREADINFOCLASS InfoClass; 5 | PVOID ThreadInfo; 6 | ULONG ThreadInfoLenght; 7 | PULONG ReturnLenght; 8 | NTSTATUS Status; 9 | } THREAD_CONTEXT_ARGS, * PTHREAD_CONTEXT_ARGS; 10 | 11 | VOID NTAPI ApcExcInThreadCtx( PVOID Arg1, PVOID Arg2, PVOID Arg3 ) 12 | { 13 | UNREFERENCED_PARAMETER( Arg3 ); 14 | 15 | HANDLE Event = HANDLE( Arg1 ); 16 | PTHREAD_CONTEXT_ARGS Args = PTHREAD_CONTEXT_ARGS( Arg2 ); 17 | 18 | DBGPRINT( "%s %d : ApcExcInThreadCtx - Event: 0x%p - Args: 0x%p", __FUNCTION__, __LINE__, Event, Args ); 19 | 20 | if ( Args ) 21 | { 22 | if ( Args->Query == TRUE ) 23 | { 24 | Args->Status = ZwQueryInformationThread( 25 | NtCurrentThread(), 26 | Args->InfoClass, 27 | Args->ThreadInfo, 28 | Args->ThreadInfoLenght, 29 | Args->ReturnLenght ); 30 | } 31 | else 32 | { 33 | Args->Status = ZwSetInformationThread( 34 | NtCurrentThread(), 35 | Args->InfoClass, 36 | Args->ThreadInfo, 37 | Args->ThreadInfoLenght ); 38 | } 39 | 40 | DBGPRINT( "%s %d : ApcExcInThreadCtx - Status: 0x%X", __FUNCTION__, __LINE__, Args->Status ); 41 | } 42 | 43 | auto Status = ZwSetEvent( Event, nullptr ); 44 | DBGPRINT( "%s %d : ApcExcInThreadCtx - ZwSetEvent = 0x%X.", __FUNCTION__, __LINE__, Status ); 45 | } 46 | 47 | VOID KernelApcInjectCallback( 48 | PKAPC Apc, 49 | PKNORMAL_ROUTINE* NormalRoutine, 50 | PVOID* NormalContext, 51 | PVOID* SystemArgument1, 52 | PVOID* SystemArgument2 53 | ) 54 | { 55 | UNREFERENCED_PARAMETER( SystemArgument1 ); 56 | UNREFERENCED_PARAMETER( SystemArgument2 ); 57 | UNREFERENCED_PARAMETER( Apc ); 58 | UNREFERENCED_PARAMETER( NormalContext ); 59 | 60 | //DPRINT( "BlackBone: %s: Called. NormalRoutine = 0x%p\n", __FUNCTION__, *NormalRoutine ); 61 | 62 | // Skip execution 63 | if ( PsIsThreadTerminating( PsGetCurrentThread() ) ) 64 | *NormalRoutine = NULL; 65 | 66 | DBGPRINT( "%s %d : KernelApcInjectCallback called - NormalRoutine = 0x%p", __FUNCTION__, __LINE__, *NormalRoutine ); 67 | 68 | // Fix Wow64 APC 69 | //if ( PsGetCurrentProcessWow64Process() != NULL ) 70 | // PsWrapApcWow64Thread( NormalContext, ( PVOID* )NormalRoutine ); 71 | //ExFreePoolWithTag( Apc, BB_POOL_TAG ); 72 | } 73 | 74 | VOID KernelApcPrepareCallback( 75 | PKAPC Apc, 76 | PKNORMAL_ROUTINE* NormalRoutine, 77 | PVOID* NormalContext, 78 | PVOID* SystemArgument1, 79 | PVOID* SystemArgument2 80 | ) 81 | { 82 | UNREFERENCED_PARAMETER( Apc ); 83 | UNREFERENCED_PARAMETER( NormalRoutine ); 84 | UNREFERENCED_PARAMETER( NormalContext ); 85 | UNREFERENCED_PARAMETER( SystemArgument1 ); 86 | UNREFERENCED_PARAMETER( SystemArgument2 ); 87 | 88 | DBGPRINT( "%s %d : KernelApcPrepareCallback called", __FUNCTION__, __LINE__ ); 89 | 90 | // Alert current thread 91 | KeTestAlertThread( UserMode ); 92 | } 93 | 94 | /*HANDLE hSyncEvent{ }; 95 | 96 | Status = ZwCreateEvent( &hSyncEvent, GENERIC_READ, nullptr, NotificationEvent, FALSE ); 97 | if ( NT_SUCCESS( Status ) ) 98 | { 99 | ExAcquireFastMutex( &ExpThreadContextQueryMutex ); 100 | 101 | DBGPRINT( "%s %d : IOCTL_QUERY_THREAD_INFO - KTHREAD: 0x%p", __FUNCTION__, __LINE__, Entry->Thread ); 102 | 103 | BOOLEAN bSkip = IsSkippabbleThread( Entry->Thread, Entry->Wow64 ); 104 | DBGPRINT( "%s %d : IOCTL_QUERY_THREAD_INFO - Should Skip? %d", __FUNCTION__, __LINE__, bSkip ); 105 | 106 | if ( bSkip == FALSE ) 107 | { 108 | auto Apc = PKAPC( AllocateZeroPool( sizeof( KAPC ) ) ); 109 | KeInitializeApc( 110 | Apc, 111 | Entry->Thread, 112 | OriginalApcEnvironment, 113 | &KernelApcInjectCallback, 114 | nullptr, 115 | ApcExcInThreadCtx, 116 | UserMode, 117 | hSyncEvent ); 118 | 119 | auto PrepareApc = PKAPC( AllocateZeroPool( sizeof( KAPC ) ) ); 120 | KeInitializeApc( 121 | PrepareApc, Entry->Thread, 122 | OriginalApcEnvironment, &KernelApcPrepareCallback, 123 | NULL, NULL, KernelMode, NULL 124 | ); 125 | 126 | const auto ApcBuffer = PTHREAD_CONTEXT_ARGS( AllocateZeroPool( sizeof( THREAD_CONTEXT_ARGS ) ) ); 127 | if ( ApcBuffer ) 128 | { 129 | ULONG ResultLen = NULL; 130 | 131 | ApcBuffer->Query = TRUE; 132 | ApcBuffer->Status = STATUS_TIMEOUT; 133 | ApcBuffer->InfoClass = THREADINFOCLASS( Buffer->InformationClass ); 134 | ApcBuffer->ThreadInfo = Buffer->ThreadInfo; 135 | ApcBuffer->ThreadInfoLenght = Buffer->ThreadInfoLenght; 136 | ApcBuffer->ReturnLenght = &ResultLen; 137 | 138 | if ( KeInsertQueueApc( Apc, ApcBuffer, nullptr, 0 ) ) 139 | { 140 | KeInsertQueueApc( PrepareApc, NULL, NULL, 0 ); 141 | 142 | DBGPRINT( "%s %d : IOCTL_QUERY_THREAD_INFO inserted APC.", __FUNCTION__, __LINE__ ); 143 | Status = ZwWaitForSingleObject( hSyncEvent, FALSE, nullptr ); 144 | ZwClose( hSyncEvent ); 145 | } 146 | else 147 | DBGPRINT( "%s %d : IOCTL_QUERY_THREAD_INFO failed to insert APC.", __FUNCTION__, __LINE__ ); 148 | 149 | if ( NT_SUCCESS( Status ) ) 150 | { 151 | if ( Buffer->ResultLenght ) 152 | *Buffer->ResultLenght = ResultLen; 153 | 154 | Status = ApcBuffer->Status; 155 | } 156 | 157 | ExFreePool( Buffer ); 158 | } 159 | } 160 | 161 | ExReleaseFastMutex( &ExpThreadContextQueryMutex ); 162 | }*/ -------------------------------------------------------------------------------- /testExe/testExe.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {e48713c6-7294-4cda-b597-fbd9aadd7283} 25 | testExe 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | MultiThreadedDebug 120 | 121 | 122 | Console 123 | true 124 | 125 | 126 | 127 | 128 | Level3 129 | true 130 | true 131 | true 132 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 133 | true 134 | 135 | 136 | Console 137 | true 138 | true 139 | true 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /MinHook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) 32 | #error MinHook supports only x86 and x64 systems. 33 | #endif 34 | 35 | #include 36 | 37 | // MinHook Error Codes. 38 | typedef enum MH_STATUS 39 | { 40 | // Unknown error. Should not be returned. 41 | MH_UNKNOWN = -1, 42 | 43 | // Successful. 44 | MH_OK = 0, 45 | 46 | // MinHook is already initialized. 47 | MH_ERROR_ALREADY_INITIALIZED, 48 | 49 | // MinHook is not initialized yet, or already uninitialized. 50 | MH_ERROR_NOT_INITIALIZED, 51 | 52 | // The hook for the specified target function is already created. 53 | MH_ERROR_ALREADY_CREATED, 54 | 55 | // The hook for the specified target function is not created yet. 56 | MH_ERROR_NOT_CREATED, 57 | 58 | // The hook for the specified target function is already enabled. 59 | MH_ERROR_ENABLED, 60 | 61 | // The hook for the specified target function is not enabled yet, or already 62 | // disabled. 63 | MH_ERROR_DISABLED, 64 | 65 | // The specified pointer is invalid. It points the address of non-allocated 66 | // and/or non-executable region. 67 | MH_ERROR_NOT_EXECUTABLE, 68 | 69 | // The specified target function cannot be hooked. 70 | MH_ERROR_UNSUPPORTED_FUNCTION, 71 | 72 | // Failed to allocate memory. 73 | MH_ERROR_MEMORY_ALLOC, 74 | 75 | // Failed to change the memory protection. 76 | MH_ERROR_MEMORY_PROTECT, 77 | 78 | // The specified module is not loaded. 79 | MH_ERROR_MODULE_NOT_FOUND, 80 | 81 | // The specified function is not found. 82 | MH_ERROR_FUNCTION_NOT_FOUND 83 | } 84 | MH_STATUS; 85 | 86 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook, 87 | // MH_QueueEnableHook or MH_QueueDisableHook. 88 | #define MH_ALL_HOOKS NULL 89 | 90 | #ifdef __cplusplus 91 | extern "C" { 92 | #endif 93 | 94 | // Initialize the MinHook library. You must call this function EXACTLY ONCE 95 | // at the beginning of your program. 96 | MH_STATUS WINAPI MH_Initialize(VOID); 97 | 98 | // Uninitialize the MinHook library. You must call this function EXACTLY 99 | // ONCE at the end of your program. 100 | MH_STATUS WINAPI MH_Uninitialize(VOID); 101 | 102 | // Creates a Hook for the specified target function, in disabled state. 103 | // Parameters: 104 | // pTarget [in] A pointer to the target function, which will be 105 | // overridden by the detour function. 106 | // pDetour [in] A pointer to the detour function, which will override 107 | // the target function. 108 | // ppOriginal [out] A pointer to the trampoline function, which will be 109 | // used to call the original target function. 110 | // This parameter can be NULL. 111 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); 112 | 113 | // Creates a Hook for the specified API function, in disabled state. 114 | // Parameters: 115 | // pszModule [in] A pointer to the loaded module name which contains the 116 | // target function. 117 | // pszTarget [in] A pointer to the target function name, which will be 118 | // overridden by the detour function. 119 | // pDetour [in] A pointer to the detour function, which will override 120 | // the target function. 121 | // ppOriginal [out] A pointer to the trampoline function, which will be 122 | // used to call the original target function. 123 | // This parameter can be NULL. 124 | MH_STATUS WINAPI MH_CreateHookApi( 125 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); 126 | 127 | // Creates a Hook for the specified API function, in disabled state. 128 | // Parameters: 129 | // pszModule [in] A pointer to the loaded module name which contains the 130 | // target function. 131 | // pszTarget [in] A pointer to the target function name, which will be 132 | // overridden by the detour function. 133 | // pDetour [in] A pointer to the detour function, which will override 134 | // the target function. 135 | // ppOriginal [out] A pointer to the trampoline function, which will be 136 | // used to call the original target function. 137 | // This parameter can be NULL. 138 | // ppTarget [out] A pointer to the target function, which will be used 139 | // with other functions. 140 | // This parameter can be NULL. 141 | MH_STATUS WINAPI MH_CreateHookApiEx( 142 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); 143 | 144 | // Removes an already created hook. 145 | // Parameters: 146 | // pTarget [in] A pointer to the target function. 147 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); 148 | 149 | // Enables an already created hook. 150 | // Parameters: 151 | // pTarget [in] A pointer to the target function. 152 | // If this parameter is MH_ALL_HOOKS, all created hooks are 153 | // enabled in one go. 154 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); 155 | 156 | // Disables an already created hook. 157 | // Parameters: 158 | // pTarget [in] A pointer to the target function. 159 | // If this parameter is MH_ALL_HOOKS, all created hooks are 160 | // disabled in one go. 161 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); 162 | 163 | // Queues to enable an already created hook. 164 | // Parameters: 165 | // pTarget [in] A pointer to the target function. 166 | // If this parameter is MH_ALL_HOOKS, all created hooks are 167 | // queued to be enabled. 168 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); 169 | 170 | // Queues to disable an already created hook. 171 | // Parameters: 172 | // pTarget [in] A pointer to the target function. 173 | // If this parameter is MH_ALL_HOOKS, all created hooks are 174 | // queued to be disabled. 175 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); 176 | 177 | // Applies all queued changes in one go. 178 | MH_STATUS WINAPI MH_ApplyQueued(VOID); 179 | 180 | // Translates the MH_STATUS to its name as a string. 181 | const char * WINAPI MH_StatusToString(MH_STATUS status); 182 | 183 | #ifdef __cplusplus 184 | } 185 | #endif 186 | 187 | -------------------------------------------------------------------------------- /intraceptor.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {003d6992-9564-480b-a507-e7e0b71aab2e} 25 | intraceptor 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | .\libs;$(LibraryPath) 76 | 77 | 78 | false 79 | .\libs;$(LibraryPath) 80 | 81 | 82 | true 83 | .\libs;$(LibraryPath) 84 | 85 | 86 | false 87 | .\libs;$(LibraryPath) 88 | 89 | 90 | 91 | Level3 92 | true 93 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 94 | true 95 | 96 | 97 | Windows 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | true 106 | true 107 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 108 | true 109 | MultiThreaded 110 | 111 | 112 | Windows 113 | true 114 | true 115 | true 116 | 117 | 118 | 119 | 120 | Level3 121 | true 122 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 123 | true 124 | MultiThreadedDebug 125 | 126 | 127 | Windows 128 | true 129 | 130 | 131 | 132 | 133 | Level3 134 | true 135 | true 136 | true 137 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 138 | true 139 | MultiThreaded 140 | 141 | 142 | Windows 143 | true 144 | true 145 | true 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /commands_id.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define CEPTOR_VALID_HANDLE( h ) ( ( ( ( std::uint64_t )h >> 20 ) & 0xFFF ) == 0xF0F ) 6 | 7 | enum IoControlCodes : std::uint32_t 8 | { 9 | IOCTL_ATTACH_TO_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0000, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), //- 10 | IOCTL_READ_MEMORY_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0001, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), //- 11 | IOCTL_WRITE_MEMORY_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0002, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), //- 12 | IOCTL_QUERY_MEMORY_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0003, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), //- 13 | IOCTL_QUERY_INFO_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0004, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), //- 14 | IOCTL_QUERY_SYSTEM_INFO_EX = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0005, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), // 15 | IOCTL_SET_INFORMATION_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0006, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), // 16 | IOCTL_FLUSH_INSTRUCTION_CACHE = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0007, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), // 17 | IOCTL_FLUSH_MEMORY_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0008, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), // 18 | IOCTL_ALLOCATE_MEMORY_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0009, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), //- 19 | IOCTL_FREE_MEMORY_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0010, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), //- 20 | IOCTL_LOCK_MEMORY_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0011, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), // 21 | IOCTL_UNLOCK_MEMORY_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0012, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), // 22 | IOCTL_PROTECT_MEMORY_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0013, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), //- 23 | IOCTL_OPEN_THREAD = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0014, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), // 24 | IOCTL_QUERY_THREAD_INFO = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0015, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), // 25 | IOCTL_SET_THREAD_INFO = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0016, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), // 26 | IOCTL_GET_CONTEXT_THREAD = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0017, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), // 27 | IOCTL_SET_CONTEXT_THREAD = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0018, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), // 28 | IOCTL_RESUME_THREAD = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0019, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), // 29 | IOCTL_SUSPEND_THREAD = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0020, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), // 30 | IOCTL_WAIT_FOR_OBJECT = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0021, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), // 31 | IOCTL_SUSPEND_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0022, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), 32 | IOCTL_RESUME_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0023, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ), 33 | IOCTL_DETACH_FROM_PROCESS = CTL_CODE( FILE_DEVICE_UNKNOWN, 0x0024, METHOD_BUFFERED, FILE_SPECIAL_ACCESS ) //- 34 | }; 35 | 36 | typedef struct _ATTACH_PROCESS 37 | { 38 | std::uint64_t ProcessId; 39 | std::uint64_t ThreadId; 40 | std::uint64_t OutProcessHandle; 41 | 42 | } ATTACH_PROCESS, * PATTACH_PROCESS; 43 | 44 | typedef struct _DETACH_PROCESS 45 | { 46 | std::uint64_t ProcessHandle; 47 | 48 | } DETACH_PROCESS, * PDETACH_PROCESS; 49 | 50 | typedef struct _ALLOCMEMORY_PROCESS 51 | { 52 | std::uint64_t ProcessHandle; 53 | std::uint64_t BaseAddress; 54 | std::uint64_t Lenght; 55 | std::uint32_t Type; 56 | std::uint32_t Protect; 57 | 58 | } ALLOCMEMORY_PROCESS, * PALLOCMEMORY_PROCESS; 59 | 60 | typedef struct _FREEMEMORY_PROCESS 61 | { 62 | std::uint64_t ProcessHandle; 63 | std::uint64_t* BaseAddress; 64 | std::uint64_t Lenght; 65 | std::uint32_t Type; 66 | 67 | } FREEMEMORY_PROCESS, * PFREEMEMORY_PROCESS; 68 | 69 | typedef struct _LOCKMEMORY_PROCESS 70 | { 71 | std::uint64_t ProcessHandle; 72 | std::uint64_t* BaseAddress; 73 | std::uint64_t Lenght; 74 | std::uint32_t Option; 75 | 76 | } LOCKMEMORY_PROCESS, * PLOCKMEMORY_PROCESS; 77 | 78 | typedef struct _UNLOCKMEMORY_PROCESS 79 | { 80 | std::uint64_t ProcessHandle; 81 | std::uint64_t* BaseAddress; 82 | std::uint64_t Lenght; 83 | std::uint32_t Option; 84 | 85 | } UNLOCKMEMORY_PROCESS, * PUNLOCKMEMORY_PROCESS; 86 | 87 | typedef struct _READMEMORY_PROCESS 88 | { 89 | std::uint64_t ProcessHandle; 90 | std::uint64_t* BaseAddress; 91 | std::uint64_t* Buffer; 92 | std::uint64_t Lenght; 93 | std::uint64_t* BytesRead; 94 | 95 | } READMEMORY_PROCESS, * PREADMEMORY_PROCESS; 96 | 97 | typedef struct _WRITEMEMORY_PROCESS 98 | { 99 | std::uint64_t ProcessHandle; 100 | std::uint64_t* BaseAddress; 101 | std::uint64_t* Buffer; 102 | std::uint64_t Lenght; 103 | std::uint64_t* BytesWritten; 104 | 105 | } WRITEMEMORY_PROCESS, * PWRITEMEMORY_PROCESS; 106 | 107 | typedef struct _FLUSHCACHE_MEMORY_PROCESS 108 | { 109 | std::uint64_t ProcessHandle; 110 | std::uint64_t* BaseAddress; 111 | std::uint32_t Lenght; 112 | 113 | } FLUSHCACHE_MEMORY_PROCESS, * PFLUSHCACHE_MEMORY_PROCESS; 114 | 115 | typedef struct _FLUSHVIRTUAL_MEMORY_PROCESS 116 | { 117 | std::uint64_t ProcessHandle; 118 | std::uint64_t* BaseAddress; 119 | std::uint64_t Lenght; 120 | PIO_STATUS_BLOCK IoStatus; 121 | 122 | } FLUSHVIRTUAL_MEMORY_PROCESS, * PFLUSHVIRTUAL_MEMORY_PROCESS; 123 | 124 | typedef struct _PROTECTMEMORY_PROCESS 125 | { 126 | std::uint64_t ProcessHandle; 127 | std::uint64_t* BaseAddress; 128 | std::uint64_t Lenght; 129 | std::uint32_t NewAccess; 130 | std::uint32_t* OldAccess; 131 | 132 | } PROTECTMEMORY_PROCESS, * PPROTECTMEMORY_PROCESS; 133 | 134 | typedef struct _QUERYMEMORY_PROCESS 135 | { 136 | std::uint64_t ProcessHandle; 137 | std::uint64_t* BaseAddress; 138 | std::uint32_t InformationClass; 139 | std::uint64_t* Buffer; 140 | std::uint64_t Lenght; 141 | std::uint32_t* ResultLength; 142 | 143 | } QUERYMEMORY_PROCESS, * PQUERYMEMORY_PROCESS; 144 | 145 | typedef struct _QUERYINFO_PROCESS 146 | { 147 | std::uint64_t ProcessHandle; 148 | std::uint32_t InformationClass; 149 | std::uint64_t* Buffer; 150 | std::uint32_t Lenght; 151 | std::uint32_t* ResultLength; 152 | 153 | } QUERYINFO_PROCESS, * PQUERYINFO_PROCESS; 154 | 155 | typedef struct _SETINFO_PROCESS 156 | { 157 | std::uint64_t ProcessHandle; 158 | std::uint32_t InformationClass; 159 | std::uint64_t* Buffer; 160 | std::uint32_t Lenght; 161 | 162 | } SETINFO_PROCESS, * PSETINFO_PROCESS; 163 | 164 | typedef struct _QUERY_SYSTEMINFOEX 165 | { 166 | std::uint32_t InformationClass; 167 | std::uint64_t* InputBuffer; 168 | std::uint32_t InputBufferLenght; 169 | std::uint64_t* SystemInfo; 170 | std::uint32_t SystemInfoLenght; 171 | std::uint32_t* ResultLength; 172 | 173 | } QUERY_SYSTEMINFOEX, * PQUERY_SYSTEMINFOEX; 174 | 175 | typedef struct _OPEN_THREAD_PROCESS 176 | { 177 | std::uint64_t ProcessId; 178 | std::uint64_t ThreadId; 179 | std::uint64_t OutThreadHandle; 180 | 181 | } OPEN_THREAD_PROCESS, * POPEN_THREAD_PROCESS; 182 | 183 | typedef struct _SET_CONTEXT_THREAD_PROCESS 184 | { 185 | std::uint64_t ThreadHandleValue; 186 | PCONTEXT Context; 187 | PCONTEXT Wow64Context; 188 | 189 | } SET_CONTEXT_THREAD_PROCESS, * PSET_CONTEXT_THREAD_PROCESS; 190 | 191 | typedef struct _GET_CONTEXT_THREAD_PROCESS 192 | { 193 | std::uint64_t ThreadHandleValue; 194 | PCONTEXT Context; 195 | PCONTEXT Wow64Context; 196 | 197 | } GET_CONTEXT_THREAD_PROCESS, * PGET_CONTEXT_THREAD_PROCESS; 198 | 199 | typedef struct _SUSPEND_THREAD_PROCESS 200 | { 201 | std::uint64_t ThreadHandleValue; 202 | std::uint32_t* Count; 203 | 204 | } SUSPEND_THREAD_PROCESS, * PSUSPEND_THREAD_PROCESS; 205 | 206 | typedef struct _RESUME_THREAD_PROCESS 207 | { 208 | std::uint64_t ThreadHandleValue; 209 | std::uint32_t* Count; 210 | 211 | } RESUME_THREAD_PROCESS, * PRESUME_THREAD_PROCESS; 212 | 213 | typedef struct _QUERYINFO_THREAD_PROCESS 214 | { 215 | std::uint64_t ThreadHandleValue; 216 | std::uint32_t InformationClass; 217 | std::uint64_t* ThreadInfo; 218 | std::uint32_t ThreadInfoLenght; 219 | std::uint32_t* ResultLenght; 220 | 221 | } QUERYINFO_THREAD_PROCESS, * PQUERYINFO_THREAD_PROCESS; 222 | 223 | typedef struct _SETINFO_THREAD_PROCESS 224 | { 225 | std::uint64_t ThreadHandleValue; 226 | std::uint32_t InformationClass; 227 | std::uint64_t* ThreadInfo; 228 | std::uint32_t ThreadInfoLenght; 229 | 230 | } SETINFO_THREAD_PROCESS, * PSETINFO_THREAD_PROCESS; 231 | 232 | typedef struct _WAIT_OBJECT_PROCESS 233 | { 234 | std::uint64_t ObjectValue; 235 | BOOLEAN Alertable; 236 | PLARGE_INTEGER Timeout; 237 | 238 | } WAIT_OBJECT_PROCESS, * PWAIT_OBJECT_PROCESS; 239 | 240 | typedef struct _PROCESS_MISC 241 | { 242 | std::uint64_t ProcessHandle; 243 | BOOLEAN Suspend; 244 | 245 | } PROCESS_MISC, * PPROCESS_MISC; -------------------------------------------------------------------------------- /commands.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "commands_id.hpp" 5 | 6 | class CCommand 7 | { 8 | private: 9 | HANDLE hDriver = INVALID_HANDLE_VALUE; 10 | bool bInitialized = false; 11 | NTSTATUS LastStatus = STATUS_SUCCESS; 12 | 13 | bool SendCmd( std::uint32_t dwIOCTL, std::uint64_t* Buffer, std::uint32_t Lenght ) 14 | { 15 | IO_STATUS_BLOCK io{ }; 16 | 17 | LastStatus = NtDeviceIoControlFile( 18 | hDriver, nullptr, nullptr, nullptr, &io, 19 | dwIOCTL, Buffer, Lenght, Buffer, Lenght ); 20 | 21 | return NT_SUCCESS( LastStatus ); 22 | } 23 | 24 | public: 25 | CCommand() 26 | { 27 | UNICODE_STRING us{ }; 28 | RtlInitUnicodeString( &us, ( L"\\DosDevices\\Global\\KlhkCtrl" ) ); 29 | 30 | OBJECT_ATTRIBUTES oa{ }; 31 | InitializeObjectAttributes( &oa, &us, OBJ_CASE_INSENSITIVE, NULL, NULL ); 32 | 33 | IO_STATUS_BLOCK io{ }; 34 | const auto res = NtOpenFile( &hDriver, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &oa, &io, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE ); 35 | if ( !NT_SUCCESS( res ) ) 36 | { 37 | printf( "NtOpenFile failed 0x%X\n", res ); 38 | getchar(); 39 | return; 40 | } 41 | 42 | if ( hDriver == INVALID_HANDLE_VALUE || !hDriver ) 43 | { 44 | MessageBoxA( GetActiveWindow(), "Driver not found or loaded!", NULL, MB_ICONSTOP ); 45 | } 46 | else 47 | bInitialized = true; 48 | } 49 | 50 | ~CCommand() 51 | { 52 | if ( bInitialized ) 53 | CloseHandle( hDriver ); 54 | } 55 | 56 | bool Status() const 57 | { 58 | return bInitialized; 59 | } 60 | 61 | NTSTATUS GetLastNtError() const 62 | { 63 | return LastStatus; 64 | } 65 | 66 | bool AttachProcess( std::uint64_t ProcessId, std::uint64_t ThreadId, std::uint64_t* hProcess ) 67 | { 68 | ATTACH_PROCESS cmd{ }; 69 | cmd.ProcessId = ProcessId; 70 | cmd.ThreadId = ThreadId; 71 | 72 | const auto res = SendCmd( IOCTL_ATTACH_TO_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 73 | if ( res ) 74 | { 75 | if ( hProcess ) 76 | *hProcess = cmd.OutProcessHandle; 77 | } 78 | return res; 79 | } 80 | 81 | bool DetachProcess( std::uint64_t ProcessHandle ) 82 | { 83 | DETACH_PROCESS cmd{ }; 84 | cmd.ProcessHandle = ProcessHandle; 85 | 86 | return SendCmd( IOCTL_DETACH_FROM_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 87 | } 88 | 89 | bool SuspendProcess( std::uint64_t ProcessHandle ) 90 | { 91 | PROCESS_MISC cmd{ }; 92 | cmd.ProcessHandle = ProcessHandle; 93 | cmd.Suspend = TRUE; 94 | 95 | return SendCmd( IOCTL_SUSPEND_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 96 | } 97 | 98 | bool ResumeProcess( std::uint64_t ProcessHandle ) 99 | { 100 | PROCESS_MISC cmd{ }; 101 | cmd.ProcessHandle = ProcessHandle; 102 | cmd.Suspend = FALSE; 103 | 104 | return SendCmd( IOCTL_RESUME_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 105 | } 106 | 107 | bool FlushInstructionCache( std::uint64_t ProcessHandle, std::uint64_t* BaseAddress, std::uint32_t Length ) 108 | { 109 | FLUSHCACHE_MEMORY_PROCESS cmd{ }; 110 | cmd.ProcessHandle = ProcessHandle; 111 | cmd.BaseAddress = BaseAddress; 112 | cmd.Lenght = Length; 113 | 114 | return SendCmd( IOCTL_FLUSH_INSTRUCTION_CACHE, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 115 | } 116 | 117 | bool SetInformationProcess( std::uint64_t ProcessHandle, std::uint32_t InfoClass, std::uint64_t* ProcessInfo, std::uint32_t ProcessInfoLenght ) 118 | { 119 | SETINFO_PROCESS cmd{ }; 120 | cmd.ProcessHandle = ProcessHandle; 121 | cmd.InformationClass = InfoClass; 122 | cmd.Buffer = ProcessInfo; 123 | cmd.Lenght = ProcessInfoLenght; 124 | 125 | return SendCmd( IOCTL_SET_INFORMATION_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 126 | } 127 | 128 | bool ReadProcessMemory( std::uint64_t ProcessHandle, std::uint64_t* BaseAddress, std::uint64_t* Buffer, std::uint64_t Lenght, std::uint64_t* BytesReaded ) 129 | { 130 | READMEMORY_PROCESS cmd{ }; 131 | cmd.ProcessHandle = ProcessHandle; 132 | cmd.BaseAddress = BaseAddress; 133 | cmd.Buffer = Buffer; 134 | cmd.Lenght = Lenght; 135 | cmd.BytesRead = BytesReaded; 136 | 137 | return SendCmd( IOCTL_READ_MEMORY_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 138 | } 139 | 140 | bool WriteProcessMemory( std::uint64_t ProcessHandle, std::uint64_t* BaseAddress, std::uint64_t* Buffer, std::uint64_t Lenght, std::uint64_t* BytesWritten ) 141 | { 142 | WRITEMEMORY_PROCESS cmd{ }; 143 | cmd.ProcessHandle = ProcessHandle; 144 | cmd.BaseAddress = BaseAddress; 145 | cmd.Buffer = Buffer; 146 | cmd.Lenght = Lenght; 147 | cmd.BytesWritten = BytesWritten; 148 | 149 | return SendCmd( IOCTL_WRITE_MEMORY_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 150 | } 151 | 152 | std::uint64_t VirtualAllocEx( std::uint64_t ProcessHandle, std::uint64_t BaseAddress, std::uint64_t Lenght, std::uint32_t Type, std::uint32_t Protect ) 153 | { 154 | ALLOCMEMORY_PROCESS cmd{ }; 155 | cmd.ProcessHandle = ProcessHandle; 156 | cmd.BaseAddress = BaseAddress; 157 | cmd.Lenght = Lenght; 158 | cmd.Type = Type; 159 | cmd.Protect = Protect; 160 | 161 | if ( SendCmd( IOCTL_ALLOCATE_MEMORY_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ) ) 162 | return cmd.BaseAddress; 163 | 164 | return NULL; 165 | } 166 | 167 | bool FlushMemory( std::uint64_t ProcessHandle, std::uint64_t* BaseAddress, std::uint64_t Lenght, PIO_STATUS_BLOCK IoStatus ) 168 | { 169 | FLUSHVIRTUAL_MEMORY_PROCESS cmd{ }; 170 | cmd.ProcessHandle = ProcessHandle; 171 | cmd.BaseAddress = BaseAddress; 172 | cmd.Lenght = Lenght; 173 | cmd.IoStatus = IoStatus; 174 | 175 | return SendCmd( IOCTL_FLUSH_MEMORY_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 176 | } 177 | 178 | bool VirtualLockEx( std::uint64_t ProcessHandle, std::uint64_t* BaseAddress, std::uint64_t Lenght, std::uint32_t LockOption ) 179 | { 180 | LOCKMEMORY_PROCESS cmd{ }; 181 | cmd.ProcessHandle = ProcessHandle; 182 | cmd.BaseAddress = BaseAddress; 183 | cmd.Lenght = Lenght; 184 | cmd.Option = LockOption; 185 | 186 | return SendCmd( IOCTL_LOCK_MEMORY_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 187 | } 188 | 189 | bool VirtualUnlockEx( std::uint64_t ProcessHandle, std::uint64_t* BaseAddress, std::uint64_t Lenght, std::uint32_t LockOption ) 190 | { 191 | UNLOCKMEMORY_PROCESS cmd{ }; 192 | cmd.ProcessHandle = ProcessHandle; 193 | cmd.BaseAddress = BaseAddress; 194 | cmd.Lenght = Lenght; 195 | cmd.Option = LockOption; 196 | 197 | return SendCmd( IOCTL_UNLOCK_MEMORY_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 198 | } 199 | 200 | bool VirtualFreeEx( std::uint64_t ProcessHandle, std::uint64_t* BaseAddress, std::uint64_t Lenght, std::uint32_t Type ) 201 | { 202 | FREEMEMORY_PROCESS cmd{ }; 203 | cmd.ProcessHandle = ProcessHandle; 204 | cmd.BaseAddress = BaseAddress; 205 | cmd.Lenght = Lenght; 206 | cmd.Type = Type; 207 | 208 | return SendCmd( IOCTL_FREE_MEMORY_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 209 | } 210 | 211 | bool VirtualProtectEx( std::uint64_t ProcessHandle, std::uint64_t* BaseAddress, std::uint64_t Lenght, std::uint32_t NewAccess, std::uint32_t* OldAccess ) 212 | { 213 | PROTECTMEMORY_PROCESS cmd{ }; 214 | cmd.ProcessHandle = ProcessHandle; 215 | cmd.BaseAddress = BaseAddress; 216 | cmd.Lenght = Lenght; 217 | cmd.NewAccess = NewAccess; 218 | cmd.OldAccess = OldAccess; 219 | 220 | return SendCmd( IOCTL_PROTECT_MEMORY_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 221 | } 222 | 223 | bool VirtualQueryEx( std::uint64_t ProcessHandle, std::uint64_t* BaseAddress, std::uint32_t InformationClass, std::uint64_t* Buffer, std::uint64_t Length, std::uint32_t* ResultLength ) 224 | { 225 | QUERYMEMORY_PROCESS cmd{ }; 226 | cmd.ProcessHandle = ProcessHandle; 227 | cmd.BaseAddress = BaseAddress; 228 | cmd.InformationClass = InformationClass; 229 | cmd.Buffer = Buffer; 230 | cmd.Lenght = Length; 231 | cmd.ResultLength = ResultLength; 232 | 233 | return SendCmd( IOCTL_QUERY_MEMORY_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 234 | } 235 | 236 | bool QueryInformationProcess( std::uint64_t ProcessHandle, std::uint32_t InformationClass, std::uint64_t* Buffer, std::uint32_t Length, std::uint32_t* ResultLength ) 237 | { 238 | QUERYINFO_PROCESS cmd{ }; 239 | cmd.ProcessHandle = ProcessHandle; 240 | cmd.InformationClass = InformationClass; 241 | cmd.Buffer = Buffer; 242 | cmd.Lenght = Length; 243 | cmd.ResultLength = ResultLength; 244 | 245 | return SendCmd( IOCTL_QUERY_INFO_PROCESS, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 246 | } 247 | 248 | bool QuerySystemInformationEx( std::uint32_t InformationClass, std::uint64_t* InputBuffer, std::uint32_t InputBufferLenght, std::uint64_t* SystemInfo, std::uint32_t SystemInfoLenght, std::uint32_t* ResultLength ) 249 | { 250 | QUERY_SYSTEMINFOEX cmd{ }; 251 | cmd.InformationClass = InformationClass; 252 | cmd.InputBuffer = InputBuffer; 253 | cmd.InputBufferLenght = InputBufferLenght; 254 | cmd.SystemInfo = SystemInfo; 255 | cmd.SystemInfoLenght = SystemInfoLenght; 256 | cmd.ResultLength = ResultLength; 257 | 258 | return SendCmd( IOCTL_QUERY_SYSTEM_INFO_EX, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 259 | } 260 | 261 | bool OpenThread( std::uint64_t ThreadId, std::uint64_t ProcessId, std::uint64_t* hThreadHandle ) 262 | { 263 | OPEN_THREAD_PROCESS cmd{ }; 264 | cmd.ProcessId = ProcessId; 265 | cmd.ThreadId = ThreadId; 266 | 267 | const auto res = SendCmd( IOCTL_OPEN_THREAD, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 268 | if ( res ) 269 | { 270 | if ( hThreadHandle ) 271 | *hThreadHandle = cmd.OutThreadHandle; 272 | } 273 | return res; 274 | } 275 | 276 | bool GetThreadContext( std::uint64_t ThreadHandle, PCONTEXT pCtx ) 277 | { 278 | GET_CONTEXT_THREAD_PROCESS cmd{ }; 279 | cmd.ThreadHandleValue = ThreadHandle; 280 | cmd.Context = pCtx; 281 | 282 | return SendCmd( IOCTL_GET_CONTEXT_THREAD, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 283 | } 284 | 285 | bool SetThreadContext( std::uint64_t ThreadHandle, PCONTEXT pCtx ) 286 | { 287 | SET_CONTEXT_THREAD_PROCESS cmd{ }; 288 | cmd.ThreadHandleValue = ThreadHandle; 289 | cmd.Context = pCtx; 290 | 291 | return SendCmd( IOCTL_SET_CONTEXT_THREAD, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 292 | } 293 | 294 | bool ResumeThread( std::uint64_t ThreadHandle, std::uint32_t* ResumeCount ) 295 | { 296 | RESUME_THREAD_PROCESS cmd{ }; 297 | cmd.ThreadHandleValue = ThreadHandle; 298 | cmd.Count = ResumeCount; 299 | 300 | return SendCmd( IOCTL_RESUME_THREAD, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 301 | } 302 | 303 | bool SuspendThread( std::uint64_t ThreadHandle, std::uint32_t* SuspendCount ) 304 | { 305 | SUSPEND_THREAD_PROCESS cmd{ }; 306 | cmd.ThreadHandleValue = ThreadHandle; 307 | cmd.Count = SuspendCount; 308 | 309 | return SendCmd( IOCTL_SUSPEND_THREAD, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 310 | } 311 | 312 | bool QueryThreadInformation( std::uint64_t ThreadHandle, std::uint32_t InfoClass, std::uint64_t* ThreadInfo, std::uint32_t ThreadInfoLenght, std::uint32_t* ResultLenght ) 313 | { 314 | QUERYINFO_THREAD_PROCESS cmd{ }; 315 | cmd.ThreadHandleValue = ThreadHandle; 316 | cmd.ThreadInfo = ThreadInfo; 317 | cmd.ThreadInfoLenght = ThreadInfoLenght; 318 | cmd.ResultLenght = ResultLenght; 319 | cmd.InformationClass = InfoClass; 320 | 321 | return SendCmd( IOCTL_QUERY_THREAD_INFO, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 322 | } 323 | 324 | bool SetThreadInformation( std::uint64_t ThreadHandle, std::uint32_t InfoClass, std::uint64_t* ThreadInfo, std::uint32_t ThreadInfoLenght ) 325 | { 326 | SETINFO_THREAD_PROCESS cmd{ }; 327 | cmd.ThreadHandleValue = ThreadHandle; 328 | cmd.ThreadInfo = ThreadInfo; 329 | cmd.ThreadInfoLenght = ThreadInfoLenght; 330 | cmd.InformationClass = InfoClass; 331 | 332 | return SendCmd( IOCTL_SET_THREAD_INFO, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 333 | } 334 | 335 | void WaitForSingleObject( std::uint64_t ObjectId, BOOL Alertable, PLARGE_INTEGER Timeout ) 336 | { 337 | WAIT_OBJECT_PROCESS cmd{ }; 338 | cmd.ObjectValue = ObjectId; 339 | cmd.Alertable = Alertable; 340 | cmd.Timeout = Timeout; 341 | 342 | SendCmd( IOCTL_WAIT_FOR_OBJECT, reinterpret_cast< std::uint64_t* >( &cmd ), sizeof( cmd ) ); 343 | } 344 | }; 345 | 346 | extern std::unique_ptr< CCommand > g_cmdDriver; -------------------------------------------------------------------------------- /driverceptor/kernel.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef enum _KAPC_ENVIRONMENT 4 | { 5 | OriginalApcEnvironment, 6 | AttachedApcEnvironment, 7 | CurrentApcEnvironment, 8 | InsertApcEnvironment 9 | } KAPC_ENVIRONMENT, * PKAPC_ENVIRONMENT; 10 | 11 | typedef enum _SYSTEM_INFORMATION_CLASS 12 | { 13 | SystemBasicInformation = 0x0, 14 | SystemProcessorInformation = 0x1, 15 | SystemPerformanceInformation = 0x2, 16 | SystemTimeOfDayInformation = 0x3, 17 | SystemPathInformation = 0x4, 18 | SystemProcessInformation = 0x5, 19 | SystemCallCountInformation = 0x6, 20 | SystemDeviceInformation = 0x7, 21 | SystemProcessorPerformanceInformation = 0x8, 22 | SystemFlagsInformation = 0x9, 23 | SystemCallTimeInformation = 0xa, 24 | SystemModuleInformation = 0xb, 25 | SystemLocksInformation = 0xc, 26 | SystemStackTraceInformation = 0xd, 27 | SystemPagedPoolInformation = 0xe, 28 | SystemNonPagedPoolInformation = 0xf, 29 | SystemHandleInformation = 0x10, 30 | SystemObjectInformation = 0x11, 31 | SystemPageFileInformation = 0x12, 32 | SystemVdmInstemulInformation = 0x13, 33 | SystemVdmBopInformation = 0x14, 34 | SystemFileCacheInformation = 0x15, 35 | SystemPoolTagInformation = 0x16, 36 | SystemInterruptInformation = 0x17, 37 | SystemDpcBehaviorInformation = 0x18, 38 | SystemFullMemoryInformation = 0x19, 39 | SystemLoadGdiDriverInformation = 0x1a, 40 | SystemUnloadGdiDriverInformation = 0x1b, 41 | SystemTimeAdjustmentInformation = 0x1c, 42 | SystemSummaryMemoryInformation = 0x1d, 43 | SystemMirrorMemoryInformation = 0x1e, 44 | SystemPerformanceTraceInformation = 0x1f, 45 | SystemObsolete0 = 0x20, 46 | SystemExceptionInformation = 0x21, 47 | SystemCrashDumpStateInformation = 0x22, 48 | SystemKernelDebuggerInformation = 0x23, 49 | SystemContextSwitchInformation = 0x24, 50 | SystemRegistryQuotaInformation = 0x25, 51 | SystemExtendServiceTableInformation = 0x26, 52 | SystemPrioritySeperation = 0x27, 53 | SystemVerifierAddDriverInformation = 0x28, 54 | SystemVerifierRemoveDriverInformation = 0x29, 55 | SystemProcessorIdleInformation = 0x2a, 56 | SystemLegacyDriverInformation = 0x2b, 57 | SystemCurrentTimeZoneInformation = 0x2c, 58 | SystemLookasideInformation = 0x2d, 59 | SystemTimeSlipNotification = 0x2e, 60 | SystemSessionCreate = 0x2f, 61 | SystemSessionDetach = 0x30, 62 | SystemSessionInformation = 0x31, 63 | SystemRangeStartInformation = 0x32, 64 | SystemVerifierInformation = 0x33, 65 | SystemVerifierThunkExtend = 0x34, 66 | SystemSessionProcessInformation = 0x35, 67 | SystemLoadGdiDriverInSystemSpace = 0x36, 68 | SystemNumaProcessorMap = 0x37, 69 | SystemPrefetcherInformation = 0x38, 70 | SystemExtendedProcessInformation = 0x39, 71 | SystemRecommendedSharedDataAlignment = 0x3a, 72 | SystemComPlusPackage = 0x3b, 73 | SystemNumaAvailableMemory = 0x3c, 74 | SystemProcessorPowerInformation = 0x3d, 75 | SystemEmulationBasicInformation = 0x3e, 76 | SystemEmulationProcessorInformation = 0x3f, 77 | SystemExtendedHandleInformation = 0x40, 78 | SystemLostDelayedWriteInformation = 0x41, 79 | SystemBigPoolInformation = 0x42, 80 | SystemSessionPoolTagInformation = 0x43, 81 | SystemSessionMappedViewInformation = 0x44, 82 | SystemHotpatchInformation = 0x45, 83 | SystemObjectSecurityMode = 0x46, 84 | SystemWatchdogTimerHandler = 0x47, 85 | SystemWatchdogTimerInformation = 0x48, 86 | SystemLogicalProcessorInformation = 0x49, 87 | SystemWow64SharedInformationObsolete = 0x4a, 88 | SystemRegisterFirmwareTableInformationHandler = 0x4b, 89 | SystemFirmwareTableInformation = 0x4c, 90 | SystemModuleInformationEx = 0x4d, 91 | SystemVerifierTriageInformation = 0x4e, 92 | SystemSuperfetchInformation = 0x4f, 93 | SystemMemoryListInformation = 0x50, 94 | SystemFileCacheInformationEx = 0x51, 95 | SystemThreadPriorityClientIdInformation = 0x52, 96 | SystemProcessorIdleCycleTimeInformation = 0x53, 97 | SystemVerifierCancellationInformation = 0x54, 98 | SystemProcessorPowerInformationEx = 0x55, 99 | SystemRefTraceInformation = 0x56, 100 | SystemSpecialPoolInformation = 0x57, 101 | SystemProcessIdInformation = 0x58, 102 | SystemErrorPortInformation = 0x59, 103 | SystemBootEnvironmentInformation = 0x5a, 104 | SystemHypervisorInformation = 0x5b, 105 | SystemVerifierInformationEx = 0x5c, 106 | SystemTimeZoneInformation = 0x5d, 107 | SystemImageFileExecutionOptionsInformation = 0x5e, 108 | SystemCoverageInformation = 0x5f, 109 | SystemPrefetchPatchInformation = 0x60, 110 | SystemVerifierFaultsInformation = 0x61, 111 | SystemSystemPartitionInformation = 0x62, 112 | SystemSystemDiskInformation = 0x63, 113 | SystemProcessorPerformanceDistribution = 0x64, 114 | SystemNumaProximityNodeInformation = 0x65, 115 | SystemDynamicTimeZoneInformation = 0x66, 116 | SystemCodeIntegrityInformation = 0x67, 117 | SystemProcessorMicrocodeUpdateInformation = 0x68, 118 | SystemProcessorBrandString = 0x69, 119 | SystemVirtualAddressInformation = 0x6a, 120 | SystemLogicalProcessorAndGroupInformation = 0x6b, 121 | SystemProcessorCycleTimeInformation = 0x6c, 122 | SystemStoreInformation = 0x6d, 123 | SystemRegistryAppendString = 0x6e, 124 | SystemAitSamplingValue = 0x6f, 125 | SystemVhdBootInformation = 0x70, 126 | SystemCpuQuotaInformation = 0x71, 127 | SystemNativeBasicInformation = 0x72, 128 | SystemErrorPortTimeouts = 0x73, 129 | SystemLowPriorityIoInformation = 0x74, 130 | SystemBootEntropyInformation = 0x75, 131 | SystemVerifierCountersInformation = 0x76, 132 | SystemPagedPoolInformationEx = 0x77, 133 | SystemSystemPtesInformationEx = 0x78, 134 | SystemNodeDistanceInformation = 0x79, 135 | SystemAcpiAuditInformation = 0x7a, 136 | SystemBasicPerformanceInformation = 0x7b, 137 | SystemQueryPerformanceCounterInformation = 0x7c, 138 | SystemSessionBigPoolInformation = 0x7d, 139 | SystemBootGraphicsInformation = 0x7e, 140 | SystemScrubPhysicalMemoryInformation = 0x7f, 141 | SystemBadPageInformation = 0x80, 142 | SystemProcessorProfileControlArea = 0x81, 143 | SystemCombinePhysicalMemoryInformation = 0x82, 144 | SystemEntropyInterruptTimingInformation = 0x83, 145 | SystemConsoleInformation = 0x84, 146 | SystemPlatformBinaryInformation = 0x85, 147 | SystemThrottleNotificationInformation = 0x86, 148 | SystemHypervisorProcessorCountInformation = 0x87, 149 | SystemDeviceDataInformation = 0x88, 150 | SystemDeviceDataEnumerationInformation = 0x89, 151 | SystemMemoryTopologyInformation = 0x8a, 152 | SystemMemoryChannelInformation = 0x8b, 153 | SystemBootLogoInformation = 0x8c, 154 | SystemProcessorPerformanceInformationEx = 0x8d, 155 | SystemSpare0 = 0x8e, 156 | SystemSecureBootPolicyInformation = 0x8f, 157 | SystemPageFileInformationEx = 0x90, 158 | SystemSecureBootInformation = 0x91, 159 | SystemEntropyInterruptTimingRawInformation = 0x92, 160 | SystemPortableWorkspaceEfiLauncherInformation = 0x93, 161 | SystemFullProcessInformation = 0x94, 162 | SystemKernelDebuggerInformationEx = 0x95, 163 | SystemBootMetadataInformation = 0x96, 164 | SystemSoftRebootInformation = 0x97, 165 | SystemElamCertificateInformation = 0x98, 166 | SystemOfflineDumpConfigInformation = 0x99, 167 | SystemProcessorFeaturesInformation = 0x9a, 168 | SystemRegistryReconciliationInformation = 0x9b, 169 | SystemSupportedProcessArchitectures = 0xb5, 170 | } SYSTEM_INFORMATION_CLASS; 171 | 172 | typedef struct _THREAD_BASIC_INFORMATION 173 | { 174 | NTSTATUS ExitStatus; 175 | PVOID TebBaseAddress; 176 | CLIENT_ID ClientId; 177 | KAFFINITY AffinityMask; 178 | KPRIORITY Priority; 179 | KPRIORITY BasePriority; 180 | } THREAD_BASIC_INFORMATION, * PTHREAD_BASIC_INFORMATION; 181 | 182 | typedef struct _RTL_PROCESS_MODULE_INFORMATION 183 | { 184 | HANDLE Section; 185 | PVOID MappedBase; 186 | PVOID ImageBase; 187 | ULONG ImageSize; 188 | ULONG Flags; 189 | USHORT LoadOrderIndex; 190 | USHORT InitOrderIndex; 191 | USHORT LoadCount; 192 | USHORT OffsetToFileName; 193 | UCHAR FullPathName[ 256 ]; 194 | } RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; 195 | 196 | typedef struct _RTL_PROCESS_MODULES 197 | { 198 | ULONG NumberOfModules; 199 | RTL_PROCESS_MODULE_INFORMATION Modules[ 1 ]; 200 | } RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; 201 | 202 | typedef VOID( NTAPI* PKNORMAL_ROUTINE )( 203 | PVOID NormalContext, 204 | PVOID SystemArgument1, 205 | PVOID SystemArgument2 206 | ); 207 | 208 | typedef VOID( NTAPI* PKKERNEL_ROUTINE )( 209 | PRKAPC Apc, 210 | PKNORMAL_ROUTINE* NormalRoutine, 211 | PVOID* NormalContext, 212 | PVOID* SystemArgument1, 213 | PVOID* SystemArgument2 214 | ); 215 | 216 | typedef VOID( NTAPI* PKRUNDOWN_ROUTINE )( PRKAPC Apc ); 217 | 218 | EXTERN_C 219 | { 220 | NTSYSCALLAPI POBJECT_TYPE * IoDriverObjectType; 221 | 222 | NTSYSCALLAPI BOOLEAN NTAPI 223 | KeInsertQueueApc( 224 | IN PRKAPC Apc, 225 | IN PVOID SystemArgument1, 226 | IN PVOID SystemArgument2, 227 | IN KPRIORITY Increment 228 | ); 229 | 230 | NTSYSCALLAPI VOID NTAPI 231 | KeInitializeApc( 232 | IN PRKAPC Apc, 233 | IN PRKTHREAD Thread, 234 | IN KAPC_ENVIRONMENT Environment, 235 | IN PKKERNEL_ROUTINE KernelRoutine, 236 | IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL, 237 | IN PKNORMAL_ROUTINE NormalRoutine OPTIONAL, 238 | IN KPROCESSOR_MODE ApcMode OPTIONAL, 239 | IN PVOID NormalContext OPTIONAL 240 | ); 241 | 242 | NTSYSCALLAPI NTSTATUS NTAPI ZwQueryInformationThread( 243 | _In_ HANDLE ThreadHandle, 244 | _In_ THREADINFOCLASS ThreadInformationClass, 245 | _In_ PVOID ThreadInformation, 246 | _In_ ULONG ThreadInformationLength, 247 | _Out_opt_ PULONG ReturnLength 248 | ); 249 | 250 | NTSYSCALLAPI NTSTATUS NTAPI 251 | PsGetContextThread( 252 | __in PETHREAD Thread, 253 | __inout PCONTEXT ThreadContext, 254 | __in KPROCESSOR_MODE Mode 255 | ); 256 | 257 | NTSYSCALLAPI NTSTATUS NTAPI 258 | PsSetContextThread( 259 | __in PETHREAD Thread, 260 | __in PCONTEXT ThreadContext, 261 | __in KPROCESSOR_MODE Mode 262 | ); 263 | 264 | NTKERNELAPI NTSTATUS NTAPI PsLookupProcessThreadByCid( PCLIENT_ID ClientId, PEPROCESS* Process, PETHREAD* Thread ); 265 | 266 | NTKERNELAPI PPEB NTAPI PsGetProcessPeb( IN PEPROCESS Process ); 267 | NTKERNELAPI PVOID NTAPI PsGetProcessWow64Process( IN PEPROCESS Process ); 268 | 269 | NTKERNELAPI 270 | PIMAGE_NT_HEADERS 271 | NTAPI 272 | RtlImageNtHeader( PVOID Base ); 273 | 274 | NTKERNELAPI 275 | NTSTATUS 276 | NTAPI 277 | 278 | 279 | ZwFlushInstructionCache( 280 | 281 | 282 | 283 | IN HANDLE ProcessHandle, 284 | IN PVOID BaseAddress, 285 | IN ULONG NumberOfBytesToFlush ); 286 | 287 | NTSYSAPI 288 | NTSTATUS 289 | NTAPI 290 | ZwProtectVirtualMemory( 291 | 292 | 293 | IN HANDLE ProcessHandle, 294 | IN OUT PVOID* BaseAddress, 295 | IN OUT PSIZE_T NumberOfBytesToProtect, 296 | IN ULONG NewAccessProtection, 297 | OUT PULONG OldAccessProtection ); 298 | 299 | 300 | NTSYSAPI 301 | NTSTATUS 302 | NTAPI 303 | ZwUnlockVirtualMemory( 304 | 305 | 306 | IN HANDLE ProcessHandle, 307 | IN PVOID* BaseAddress, 308 | IN OUT PSIZE_T NumberOfBytesToUnlock, 309 | IN ULONG LockType ); 310 | 311 | NTSYSAPI 312 | NTSTATUS 313 | NTAPI 314 | ZwLockVirtualMemory( 315 | IN HANDLE ProcessHandle, 316 | IN PVOID* BaseAddress, 317 | IN OUT PSIZE_T NumberOfBytesToLock, 318 | IN ULONG LockOption ); 319 | 320 | NTSYSCALLAPI NTSTATUS NTAPI MmCopyVirtualMemory( PEPROCESS SourceProcess, PVOID SourceAddress, PEPROCESS TargetProcess, PVOID TargetAddress, SIZE_T BufferSize, KPROCESSOR_MODE PreviousMode, PSIZE_T ReturnSize ); 321 | NTSYSCALLAPI NTSTATUS NTAPI ObReferenceObjectByName( PUNICODE_STRING ObjectName, ULONG Attributes, PACCESS_STATE AccessState, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, PVOID ParseContext OPTIONAL, PVOID* Object ); 322 | NTSYSCALLAPI NTSTATUS NTAPI ZwQueryInformationProcess( 323 | _In_ HANDLE ProcessHandle, 324 | _In_ PROCESSINFOCLASS ProcessInformationClass, 325 | _Out_ PVOID ProcessInformation, 326 | _In_ ULONG ProcessInformationLength, 327 | _Out_opt_ PULONG ReturnLength 328 | ); 329 | 330 | NTSYSCALLAPI NTSTATUS NTAPI ZwSetInformationProcess( __in HANDLE ProcessHandle, 331 | __in PROCESSINFOCLASS ProcessInformationClass, 332 | __in_bcount( ProcessInformationLength ) PVOID ProcessInformation, 333 | __in ULONG ProcessInformationLength 334 | ); 335 | 336 | NTSYSCALLAPI NTSTATUS 337 | ZwQuerySystemInformationEx( 338 | SYSTEM_INFORMATION_CLASS SystemInformationClass, 339 | PVOID InputBuffer, 340 | ULONG InputBufferLength, 341 | PVOID SystemInformation, 342 | ULONG SystemInformationLength, 343 | ULONG* ReturnLength ); 344 | 345 | NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation( SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG ); 346 | 347 | NTKERNELAPI PVOID NTAPI PsGetThreadTeb( PETHREAD Thread ); 348 | 349 | NTKERNELAPI BOOLEAN NTAPI PsGetProcessExitProcessCalled( PEPROCESS Process ); 350 | 351 | EXTERN_C 352 | NTSTATUS 353 | NTAPI 354 | PsAcquireProcessExitSynchronization( 355 | _In_ PEPROCESS Process 356 | ); 357 | 358 | EXTERN_C 359 | VOID 360 | NTAPI 361 | PsReleaseProcessExitSynchronization( 362 | _In_ PEPROCESS Process 363 | ); 364 | }; 365 | 366 | NTSTATUS( NTAPI* PsResumeThread ) ( IN PETHREAD pEThread, OUT PULONG PreviousCount ) = nullptr; 367 | NTSTATUS( NTAPI* PsSuspendThread )( IN PETHREAD pEThread, OUT PULONG PreviousSuspendCount ) = nullptr; 368 | BOOLEAN( NTAPI* KeTestAlertThread)( IN KPROCESSOR_MODE AlertMode ) = nullptr; 369 | 370 | #define THREAD_INFO_SIZE (0x6E4) 371 | static ULONG THREAD_INFO_SECTIONS[] = { 0x78, 0x7C, 0xC3, 0xC5, 0x220, 0x228, 0x233, 0x234, 0x240, 0x250, 0x28C, 0x290, 0x2DC, 0x2E0, 0x5D8, 0x618, 0x680, 0x6A8, 0x6BC, THREAD_INFO_SIZE }; 372 | -------------------------------------------------------------------------------- /hooks.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // 4 | // CloseHandle 5 | // 6 | NTSTATUS( NTAPI* oNtClose )( HANDLE ); 7 | 8 | NTSTATUS NTAPI hk_NtClose( HANDLE Handle ) 9 | { 10 | if ( CEPTOR_VALID_HANDLE( Handle ) && g_cmdDriver->DetachProcess( uint64_t( Handle ) ) ) 11 | { 12 | printf( "[ ! ] NtClose - closed handle = 0x%llX\n", uint64_t( Handle ) ); 13 | return STATUS_SUCCESS; 14 | } 15 | 16 | return oNtClose( Handle ); 17 | } 18 | 19 | // 20 | // OpenProcess 21 | // 22 | NTSTATUS( NTAPI* oNtOpenProcess )( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, CLIENT_ID* ); 23 | 24 | NTSTATUS NTAPI hk_NtOpenProcess( PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, CLIENT_ID* ClientId ) 25 | { 26 | if ( ProcessHandle && ClientId && ClientId->UniqueProcess != ULongToHandle( GetCurrentProcessId() ) ) 27 | { 28 | uint64_t Handle = NULL; 29 | if ( g_cmdDriver->AttachProcess( uint64_t( ClientId->UniqueProcess ), uint64_t( ClientId->UniqueThread ), &Handle ) ) 30 | { 31 | *ProcessHandle = PHANDLE( Handle ); 32 | printf( "[ ! ] NtOpenProcess on TID: 0x%p, PID: 0x%p - opened handle = 0x%p\n", ClientId->UniqueThread, ClientId->UniqueProcess, *ProcessHandle ); 33 | return STATUS_SUCCESS; 34 | } 35 | else 36 | { 37 | printf( "[ ! ] NtOpenProcess - TID: 0x%p, PID: 0x%p - returned 0x%X\n", ClientId->UniqueThread, ClientId->UniqueProcess, g_cmdDriver->GetLastNtError() ); 38 | return g_cmdDriver->GetLastNtError(); 39 | } 40 | } 41 | return oNtOpenProcess( ProcessHandle, DesiredAccess, ObjectAttributes, ClientId ); 42 | } 43 | 44 | // 45 | // ReadProcessMemory 46 | // 47 | NTSTATUS( NTAPI* oNtReadVirtualMemory )( HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T ); 48 | 49 | NTSTATUS NTAPI hk_NtReadVirtualMemory( HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, SIZE_T NumberOfBytesToRead, PSIZE_T NumberOfBytesReaded ) 50 | { 51 | if ( ProcessHandle != GetCurrentProcess() && CEPTOR_VALID_HANDLE( ProcessHandle ) ) 52 | { 53 | if ( g_cmdDriver->ReadProcessMemory( 54 | uint64_t( ProcessHandle ), 55 | reinterpret_cast< uint64_t* >( BaseAddress ), 56 | reinterpret_cast< uint64_t* >( Buffer ), 57 | NumberOfBytesToRead, 58 | NumberOfBytesReaded ) 59 | ) 60 | { 61 | // printf( "[ ! ] NtReadVirtualMemory - success!\n" ); 62 | return STATUS_SUCCESS; 63 | } 64 | else 65 | { 66 | printf( "[ ! ] NtReadVirtualMemory returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 67 | return g_cmdDriver->GetLastNtError(); 68 | } 69 | } 70 | return oNtReadVirtualMemory( ProcessHandle, BaseAddress, Buffer, NumberOfBytesToRead, NumberOfBytesReaded ); 71 | } 72 | 73 | // 74 | // WriteProcessMemory 75 | // 76 | NTSTATUS( NTAPI* oNtWriteVirtualMemory )( HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T ); 77 | 78 | NTSTATUS NTAPI hk_NtWriteVirtualMemory( HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, SIZE_T NumberOfBytesToWrite, PSIZE_T NumberOfBytesWritten ) 79 | { 80 | if ( ProcessHandle != GetCurrentProcess() && CEPTOR_VALID_HANDLE( ProcessHandle ) ) 81 | { 82 | if ( g_cmdDriver->WriteProcessMemory( 83 | uint64_t( ProcessHandle ), 84 | reinterpret_cast< uint64_t* >( BaseAddress ), 85 | reinterpret_cast< uint64_t* >( Buffer ), 86 | NumberOfBytesToWrite, 87 | NumberOfBytesWritten ) 88 | ) 89 | { 90 | // printf( "[ ! ] NtWriteVirtualMemory - success!\n" ); 91 | return STATUS_SUCCESS; 92 | } 93 | else 94 | { 95 | printf( "[ ! ] NtWriteVirtualMemory returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 96 | return g_cmdDriver->GetLastNtError(); 97 | } 98 | } 99 | return oNtWriteVirtualMemory( ProcessHandle, BaseAddress, Buffer, NumberOfBytesToWrite, NumberOfBytesWritten ); 100 | } 101 | 102 | // 103 | // VirtualQueryEx 104 | // 105 | NTSTATUS( NTAPI* oNtQueryVirtualMemory )( HANDLE, PVOID, MEMORY_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T ); 106 | 107 | NTSTATUS NTAPI hk_NtQueryVirtualMemory( HANDLE ProcessHandle, PVOID BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID Buffer, SIZE_T Length, PSIZE_T ResultLength ) 108 | { 109 | if ( ProcessHandle != GetCurrentProcess() && CEPTOR_VALID_HANDLE( ProcessHandle ) ) 110 | { 111 | if ( g_cmdDriver->VirtualQueryEx( 112 | uint64_t( ProcessHandle ), 113 | reinterpret_cast< uint64_t* >( BaseAddress ), 114 | MemoryInformationClass, 115 | reinterpret_cast< uint64_t* >( Buffer ), 116 | Length, 117 | reinterpret_cast< uint32_t* >( ResultLength ) ) 118 | ) 119 | { 120 | // printf( "[ ! ] NtQueryVirtualMemory - success!\n" ); 121 | return STATUS_SUCCESS; 122 | } 123 | else 124 | { 125 | printf( "[ ! ] NtQueryVirtualMemory returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 126 | return g_cmdDriver->GetLastNtError(); 127 | } 128 | } 129 | return oNtQueryVirtualMemory( ProcessHandle, BaseAddress, MemoryInformationClass, Buffer, Length, ResultLength ); 130 | } 131 | 132 | // 133 | // VirtualAllocEx 134 | // 135 | NTSTATUS( NTAPI* oNtAllocateVirtualMemory )( HANDLE, PVOID*, ULONG, PSIZE_T, ULONG, ULONG ); 136 | 137 | NTSTATUS NTAPI hk_NtAllocateVirtualMemory( HANDLE ProcessHandle, PVOID* BaseAddress, ULONG ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect ) 138 | { 139 | if ( ProcessHandle != GetCurrentProcess() && CEPTOR_VALID_HANDLE( ProcessHandle ) && BaseAddress && RegionSize ) 140 | { 141 | std::uint64_t AllocBase = g_cmdDriver->VirtualAllocEx( 142 | uint64_t( ProcessHandle ), 143 | std::uint64_t( *BaseAddress ), 144 | *RegionSize, 145 | AllocationType, 146 | Protect 147 | ); 148 | 149 | if ( AllocBase ) 150 | { 151 | *BaseAddress = PVOID( AllocBase ); 152 | // printf( "[ ! ] NtAllocateVirtualMemory - success!\n" ); 153 | return STATUS_SUCCESS; 154 | } 155 | else 156 | { 157 | printf( "[ ! ] NtAllocateVirtualMemory returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 158 | return g_cmdDriver->GetLastNtError(); 159 | } 160 | } 161 | return oNtAllocateVirtualMemory( ProcessHandle, BaseAddress, ZeroBits, RegionSize, AllocationType, Protect ); 162 | } 163 | 164 | // 165 | // VirtualFreeEx 166 | // 167 | NTSTATUS( NTAPI* oNtFreeVirtualMemory )( HANDLE, PVOID*, PSIZE_T, ULONG ); 168 | 169 | NTSTATUS NTAPI hk_NtFreeVirtualMemory( HANDLE ProcessHandle, PVOID* BaseAddress, PSIZE_T RegionSize, ULONG FreeType ) 170 | { 171 | if ( ProcessHandle != GetCurrentProcess() && CEPTOR_VALID_HANDLE( ProcessHandle ) && BaseAddress && RegionSize ) 172 | { 173 | if ( g_cmdDriver->VirtualFreeEx( 174 | uint64_t( ProcessHandle ), 175 | reinterpret_cast< std::uint64_t* >( *BaseAddress ), 176 | *RegionSize, 177 | FreeType ) 178 | ) 179 | { 180 | // printf( "[ ! ] NtFreeVirtualMemory - success!\n" ); 181 | return STATUS_SUCCESS; 182 | } 183 | else 184 | { 185 | printf( "[ ! ] NtFreeVirtualMemory returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 186 | return g_cmdDriver->GetLastNtError(); 187 | } 188 | } 189 | return oNtFreeVirtualMemory( ProcessHandle, BaseAddress, RegionSize, FreeType ); 190 | } 191 | 192 | // 193 | // VirtualProtectEx 194 | // 195 | NTSTATUS( NTAPI* oNtProtectVirtualMemory )( HANDLE, PVOID*, PSIZE_T, ULONG, PULONG ); 196 | 197 | NTSTATUS NTAPI hk_NtProtectVirtualMemory( HANDLE ProcessHandle, PVOID* BaseAddress, PSIZE_T NumberOfBytesToProtect, ULONG NewAccessProtection, PULONG OldAccessProtection ) 198 | { 199 | if ( ProcessHandle != GetCurrentProcess() && CEPTOR_VALID_HANDLE( ProcessHandle ) && BaseAddress && NumberOfBytesToProtect ) 200 | { 201 | std::uint32_t OldAccess{ }; 202 | 203 | if ( g_cmdDriver->VirtualProtectEx( 204 | uint64_t( ProcessHandle ), 205 | reinterpret_cast< std::uint64_t* >( *BaseAddress ), 206 | *NumberOfBytesToProtect, 207 | NewAccessProtection, 208 | &OldAccess ) 209 | ) 210 | { 211 | if ( OldAccessProtection ) 212 | *OldAccessProtection = OldAccess; 213 | 214 | // printf( "[ ! ] NtProtectVirtualMemory - success!\n" ); 215 | return STATUS_SUCCESS; 216 | } 217 | else 218 | { 219 | printf( "[ ! ] NtProtectVirtualMemory returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 220 | return g_cmdDriver->GetLastNtError(); 221 | } 222 | } 223 | return oNtProtectVirtualMemory( ProcessHandle, BaseAddress, NumberOfBytesToProtect, NewAccessProtection, OldAccessProtection ); 224 | } 225 | 226 | // 227 | // VirtualLockEx 228 | // 229 | NTSTATUS( NTAPI* oNtLockVirtualMemory )( HANDLE, PVOID*, PSIZE_T, ULONG ); 230 | 231 | NTSTATUS NTAPI hk_NtLockVirtualMemory( HANDLE ProcessHandle, PVOID* BaseAddress, PSIZE_T RegionSize, ULONG LockOption ) 232 | { 233 | if ( ProcessHandle != GetCurrentProcess() && CEPTOR_VALID_HANDLE( ProcessHandle ) && BaseAddress && RegionSize ) 234 | { 235 | if ( g_cmdDriver->VirtualLockEx( 236 | uint64_t( ProcessHandle ), 237 | reinterpret_cast< std::uint64_t* >( *BaseAddress ), 238 | *RegionSize, 239 | LockOption ) 240 | ) 241 | { 242 | // printf( "[ ! ] NtLockVirtualMemory - success!\n" ); 243 | return STATUS_SUCCESS; 244 | } 245 | else 246 | { 247 | printf( "[ ! ] NtLockVirtualMemory returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 248 | return g_cmdDriver->GetLastNtError(); 249 | } 250 | } 251 | return oNtLockVirtualMemory( ProcessHandle, BaseAddress, RegionSize, LockOption ); 252 | } 253 | 254 | // 255 | // VirtualUnlockEx 256 | // 257 | NTSTATUS( NTAPI* oNtUnlockVirtualMemory )( HANDLE, PVOID*, PSIZE_T, ULONG ); 258 | 259 | NTSTATUS NTAPI hk_NtUnlockVirtualMemory( HANDLE ProcessHandle, PVOID* BaseAddress, PSIZE_T RegionSize, ULONG LockOption ) 260 | { 261 | if ( ProcessHandle != GetCurrentProcess() && CEPTOR_VALID_HANDLE( ProcessHandle ) && BaseAddress && RegionSize ) 262 | { 263 | if ( g_cmdDriver->VirtualUnlockEx( 264 | uint64_t( ProcessHandle ), 265 | reinterpret_cast< std::uint64_t* >( *BaseAddress ), 266 | *RegionSize, 267 | LockOption ) 268 | ) 269 | { 270 | // printf( "[ ! ] NtUnlockVirtualMemory - success!\n" ); 271 | return STATUS_SUCCESS; 272 | } 273 | else 274 | { 275 | printf( "[ ! ] NtUnlockVirtualMemory returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 276 | return g_cmdDriver->GetLastNtError(); 277 | } 278 | } 279 | return oNtUnlockVirtualMemory( ProcessHandle, BaseAddress, RegionSize, LockOption ); 280 | } 281 | 282 | // 283 | // FlushInstructionCache 284 | // 285 | NTSTATUS( NTAPI* oNtFlushInstructionCache )( HANDLE, PVOID, ULONG ); 286 | 287 | NTSTATUS NTAPI hk_NtFlushInstructionCache( HANDLE processHandle, PVOID baseAddress, ULONG numberOfBytesToFlush ) 288 | { 289 | if ( processHandle != GetCurrentProcess() && CEPTOR_VALID_HANDLE( processHandle ) && baseAddress ) 290 | { 291 | if ( g_cmdDriver->FlushInstructionCache( 292 | uint64_t( processHandle ), 293 | reinterpret_cast< std::uint64_t* >( baseAddress ), 294 | numberOfBytesToFlush ) 295 | ) 296 | { 297 | // printf( "[ ! ] NtFlushInstructionCache - success!\n" ); 298 | return STATUS_SUCCESS; 299 | } 300 | else 301 | { 302 | printf( "[ ! ] NtFlushInstructionCache returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 303 | return g_cmdDriver->GetLastNtError(); 304 | } 305 | } 306 | return oNtFlushInstructionCache( processHandle, baseAddress, numberOfBytesToFlush ); 307 | } 308 | 309 | // 310 | // NtSetInformationProcess 311 | // 312 | NTSTATUS( NTAPI* oNtSetInformationProcess )( HANDLE, PROCESSINFOCLASS, PVOID, ULONG ); 313 | 314 | NTSTATUS NTAPI hk_NtSetInformationProcess( HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength ) 315 | { 316 | if ( ProcessHandle != GetCurrentProcess() && CEPTOR_VALID_HANDLE( ProcessHandle ) && ProcessInformation && ProcessInformationLength > 0 ) 317 | { 318 | if ( g_cmdDriver->SetInformationProcess( 319 | uint64_t( ProcessHandle ), 320 | ProcessInformationClass, 321 | reinterpret_cast< std::uint64_t* >( ProcessInformation ), 322 | ProcessInformationLength ) 323 | ) 324 | { 325 | // printf( "[ ! ] NtSetInformationProcess - success!\n" ); 326 | return STATUS_SUCCESS; 327 | } 328 | else 329 | { 330 | printf( "[ ! ] NtSetInformationProcess returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 331 | return g_cmdDriver->GetLastNtError(); 332 | } 333 | } 334 | return oNtSetInformationProcess( ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength ); 335 | } 336 | 337 | // 338 | // NtFlushVirtualMemory 339 | // 340 | NTSTATUS( NTAPI* oNtFlushVirtualMemory )( HANDLE, PVOID*, PSIZE_T, PIO_STATUS_BLOCK ); 341 | 342 | NTSTATUS NTAPI hk_NtFlushVirtualMemory( HANDLE ProcessHandle, PVOID* BaseAddress, PSIZE_T RegionSize, PIO_STATUS_BLOCK ioStatus ) 343 | { 344 | if ( ProcessHandle != GetCurrentProcess() && CEPTOR_VALID_HANDLE( ProcessHandle ) && BaseAddress && RegionSize && ioStatus ) 345 | { 346 | if ( g_cmdDriver->FlushMemory( 347 | uint64_t( ProcessHandle ), 348 | reinterpret_cast< std::uint64_t* >( *BaseAddress ), 349 | *RegionSize, 350 | ioStatus ) 351 | ) 352 | { 353 | // printf( "[ ! ] NtFlushVirtualMemory - success!\n" ); 354 | return STATUS_SUCCESS; 355 | } 356 | else 357 | { 358 | printf( "[ ! ] NtFlushVirtualMemory returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 359 | return g_cmdDriver->GetLastNtError(); 360 | } 361 | } 362 | return oNtFlushVirtualMemory( ProcessHandle, BaseAddress, RegionSize, ioStatus ); 363 | } 364 | 365 | // 366 | // SuspendProcess 367 | // 368 | NTSTATUS( NTAPI* oNtSuspendProcess )( HANDLE ); 369 | 370 | NTSTATUS NTAPI hk_NtSuspendProcess( HANDLE ProcessHandle ) 371 | { 372 | if ( ProcessHandle != GetCurrentProcess() && CEPTOR_VALID_HANDLE( ProcessHandle ) ) 373 | { 374 | if ( g_cmdDriver->SuspendProcess( uint64_t( ProcessHandle ) ) ) 375 | { 376 | //printf( "[ ! ] NtSuspendProcess - success!\n" ); 377 | return STATUS_SUCCESS; 378 | } 379 | else 380 | { 381 | printf( "[ ! ] NtSuspendProcess returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 382 | return g_cmdDriver->GetLastNtError(); 383 | } 384 | } 385 | return oNtSuspendProcess( ProcessHandle ); 386 | } 387 | 388 | // 389 | // ResumeProcess 390 | // 391 | NTSTATUS( NTAPI* oNtResumeProcess )( HANDLE ); 392 | 393 | NTSTATUS NTAPI hk_NtResumeProcess( HANDLE ProcessHandle ) 394 | { 395 | if ( ProcessHandle != GetCurrentProcess() && CEPTOR_VALID_HANDLE( ProcessHandle ) ) 396 | { 397 | if ( g_cmdDriver->ResumeProcess( uint64_t( ProcessHandle ) ) ) 398 | { 399 | // printf( "[ ! ] NtResumeProcess - success!\n" ); 400 | return STATUS_SUCCESS; 401 | } 402 | else 403 | { 404 | printf( "[ ! ] NtResumeProcess returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 405 | return g_cmdDriver->GetLastNtError(); 406 | } 407 | } 408 | return oNtResumeProcess( ProcessHandle ); 409 | } 410 | 411 | NTSTATUS( NTAPI* oNtOpenThread )( PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, CLIENT_ID* ); 412 | 413 | NTSTATUS NTAPI hk_NtOpenThread( PHANDLE threadHandle, ACCESS_MASK accessMask, POBJECT_ATTRIBUTES objectAttributes, CLIENT_ID* clientId ) 414 | { 415 | if ( threadHandle && 416 | clientId && 417 | clientId->UniqueThread != ULongToHandle( GetCurrentThreadId() ) && 418 | clientId->UniqueProcess != GetCurrentProcess() ) 419 | { 420 | std::uint64_t OutThreadHandle{ }; 421 | 422 | if ( g_cmdDriver->OpenThread( 423 | uint64_t( clientId->UniqueThread ), 424 | uint64_t( clientId->UniqueProcess ), 425 | &OutThreadHandle ) 426 | ) 427 | { 428 | *threadHandle = PHANDLE( OutThreadHandle ); 429 | printf( "[ ! ] NtOpenThread on TID: 0x%p - opened handle = 0x%p\n", clientId->UniqueThread, *threadHandle ); 430 | return STATUS_SUCCESS; 431 | } 432 | else 433 | { 434 | printf( "[ ! ] NtOpenThread ( Thread = 0x%p, Process = 0x%p ) returned 0x%X\n", clientId->UniqueThread, clientId->UniqueProcess, g_cmdDriver->GetLastNtError() ); 435 | return g_cmdDriver->GetLastNtError(); 436 | } 437 | } 438 | return oNtOpenThread( threadHandle, accessMask, objectAttributes, clientId ); 439 | } 440 | 441 | NTSTATUS( NTAPI* oNtQueryInformationThread )( HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG ); 442 | 443 | NTSTATUS NTAPI hk_NtQueryInformationThread( HANDLE threadHandle, THREADINFOCLASS threadInformationClass, PVOID threadInformation, ULONG threadInformationLength, PULONG returnLength ) 444 | { 445 | if ( threadHandle != GetCurrentThread() && CEPTOR_VALID_HANDLE( threadHandle ) ) 446 | { 447 | std::uint32_t ReturnLen = NULL; 448 | 449 | if ( g_cmdDriver->QueryThreadInformation( 450 | uint64_t( threadHandle ), 451 | threadInformationClass, 452 | reinterpret_cast< std::uint64_t* >( threadInformation ), 453 | threadInformationLength, 454 | &ReturnLen ) 455 | ) 456 | { 457 | if ( returnLength ) 458 | *returnLength = ReturnLen; 459 | 460 | // printf( "[ ! ] NtQueryInformationThread - success!\n" ); 461 | return STATUS_SUCCESS; 462 | } 463 | else 464 | { 465 | printf( "[ ! ] NtQueryInformationThread returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 466 | return g_cmdDriver->GetLastNtError(); 467 | } 468 | } 469 | return oNtQueryInformationThread( threadHandle, threadInformationClass, threadInformation, threadInformationLength, returnLength ); 470 | } 471 | 472 | NTSTATUS( NTAPI* oNtSetInformationThread )( HANDLE, THREADINFOCLASS, PVOID, ULONG ); 473 | 474 | NTSTATUS NTAPI hk_NtSetInformationThread( HANDLE threadHandle, THREADINFOCLASS threadInformationClass, PVOID threadInformation, ULONG threadInformationLength ) 475 | { 476 | if ( threadHandle != GetCurrentThread() && CEPTOR_VALID_HANDLE( threadHandle ) ) 477 | { 478 | if ( g_cmdDriver->SetThreadInformation( 479 | uint64_t( threadHandle ), 480 | threadInformationClass, 481 | reinterpret_cast< std::uint64_t* >( threadInformation ), 482 | threadInformationLength ) 483 | ) 484 | { 485 | //printf( "[ ! ] NtSetInformationThread - success!\n" ); 486 | return STATUS_SUCCESS; 487 | } 488 | else 489 | { 490 | printf( "[ ! ] NtSetInformationThread returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 491 | return g_cmdDriver->GetLastNtError(); 492 | } 493 | } 494 | return oNtSetInformationThread( threadHandle, threadInformationClass, threadInformation, threadInformationLength ); 495 | } 496 | 497 | NTSTATUS( NTAPI* oNtGetContextThread )( HANDLE, PCONTEXT ); 498 | 499 | NTSTATUS NTAPI hk_NtGetContextThread( HANDLE threadHandle, PCONTEXT context ) 500 | { 501 | if ( threadHandle != GetCurrentThread() && CEPTOR_VALID_HANDLE( threadHandle ) ) 502 | { 503 | if ( g_cmdDriver->GetThreadContext( 504 | uint64_t( threadHandle ), 505 | context ) 506 | ) 507 | { 508 | //printf( "[ ! ] NtGetContextThread - success!\n" ); 509 | return STATUS_SUCCESS; 510 | } 511 | else 512 | { 513 | printf( "[ ! ] NtGetContextThread returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 514 | return g_cmdDriver->GetLastNtError(); 515 | } 516 | } 517 | return oNtGetContextThread( threadHandle, context ); 518 | } 519 | 520 | NTSTATUS( NTAPI* oNtSetContextThread )( HANDLE, PCONTEXT ); 521 | 522 | NTSTATUS NTAPI hk_NtSetContextThread( HANDLE threadHandle, PCONTEXT context ) 523 | { 524 | if ( threadHandle != GetCurrentThread() && CEPTOR_VALID_HANDLE( threadHandle ) ) 525 | { 526 | if ( g_cmdDriver->SetThreadContext( 527 | uint64_t( threadHandle ), 528 | context ) 529 | ) 530 | { 531 | //printf( "[ ! ] NtSetContextThread - success!\n" ); 532 | return STATUS_SUCCESS; 533 | } 534 | else 535 | { 536 | printf( "[ ! ] NtSetContextThread returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 537 | return g_cmdDriver->GetLastNtError(); 538 | } 539 | } 540 | return oNtSetContextThread( threadHandle, context ); 541 | } 542 | 543 | NTSTATUS( NTAPI* oNtResumeThread )( HANDLE, PULONG ); 544 | 545 | NTSTATUS NTAPI hk_NtResumeThread( HANDLE threadHandle, PULONG suspendCount ) 546 | { 547 | if ( threadHandle != GetCurrentThread() && CEPTOR_VALID_HANDLE( threadHandle ) ) 548 | { 549 | std::uint32_t Count = NULL; 550 | if ( g_cmdDriver->ResumeThread( 551 | uint64_t( threadHandle ), 552 | &Count ) 553 | ) 554 | { 555 | if ( suspendCount ) 556 | *suspendCount = Count; 557 | 558 | //printf( "[ ! ] NtResumeThread - success!\n" ); 559 | return STATUS_SUCCESS; 560 | } 561 | else 562 | { 563 | printf( "[ ! ] NtResumeThread returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 564 | return g_cmdDriver->GetLastNtError(); 565 | } 566 | } 567 | return oNtResumeThread( threadHandle, suspendCount ); 568 | } 569 | 570 | NTSTATUS( NTAPI* oNtSuspendThread )( HANDLE, PULONG ); 571 | 572 | NTSTATUS NTAPI hk_NtSuspendThread( HANDLE threadHandle, PULONG previousSuspendCount ) 573 | { 574 | if ( threadHandle != GetCurrentThread() && CEPTOR_VALID_HANDLE( threadHandle ) ) 575 | { 576 | std::uint32_t Count = NULL; 577 | if ( g_cmdDriver->SuspendThread( 578 | uint64_t( threadHandle ), 579 | &Count ) 580 | ) 581 | { 582 | if ( previousSuspendCount ) 583 | *previousSuspendCount = Count; 584 | 585 | //printf( "[ ! ] NtSuspendThread - success!\n" ); 586 | return STATUS_SUCCESS; 587 | } 588 | else 589 | { 590 | printf( "[ ! ] NtSuspendThread returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 591 | return g_cmdDriver->GetLastNtError(); 592 | } 593 | } 594 | return oNtSuspendThread( threadHandle, previousSuspendCount ); 595 | } 596 | 597 | // 598 | // Query Information Process 599 | // 600 | NTSTATUS( NTAPI* oNtQueryInformationProcess )( HANDLE, PROCESS_INFORMATION_CLASS, PVOID, ULONG, PULONG ); 601 | 602 | NTSTATUS NTAPI hk_NtQueryInformationProcess( HANDLE ProcessHandle, PROCESS_INFORMATION_CLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength ) 603 | { 604 | if ( ProcessHandle != GetCurrentProcess() && CEPTOR_VALID_HANDLE( ProcessHandle ) ) 605 | { 606 | if ( g_cmdDriver->QueryInformationProcess( 607 | uint64_t( ProcessHandle ), 608 | ProcessInformationClass, 609 | reinterpret_cast< uint64_t* >( ProcessInformation ), 610 | ProcessInformationLength, 611 | reinterpret_cast< uint32_t* >( ReturnLength ) ) 612 | ) 613 | { 614 | //printf( "[ ! ] NtQueryInformationProcess - success!\n" ); 615 | return STATUS_SUCCESS; 616 | } 617 | else 618 | { 619 | printf( "[ ! ] NtQueryInformationProcess returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 620 | return g_cmdDriver->GetLastNtError(); 621 | } 622 | } 623 | return oNtQueryInformationProcess( ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength ); 624 | } 625 | 626 | NTSTATUS( NTAPI* oNtQuerySystemInformationEx )( SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PVOID, ULONG, PULONG ); 627 | 628 | NTSTATUS NTAPI hk_NtQuerySystemInformationEx( SYSTEM_INFORMATION_CLASS systemInformationClass, PVOID inputBuffer, ULONG inputBufferLength, PVOID systemInformation, ULONG systemInformationLength, PULONG returnLength ) 629 | { 630 | switch ( systemInformationClass ) 631 | { 632 | case 0xb5: //SystemSupportedProcessArchitectures 633 | if ( inputBuffer && inputBufferLength >= sizeof( HANDLE ) && CEPTOR_VALID_HANDLE( inputBuffer ) ) 634 | { 635 | std::uint32_t ResLength = NULL; 636 | 637 | if ( g_cmdDriver->QuerySystemInformationEx( 638 | systemInformationClass, 639 | reinterpret_cast< uint64_t* >( inputBuffer ), 640 | inputBufferLength, 641 | reinterpret_cast< uint64_t* >( systemInformation ), 642 | systemInformationLength, 643 | &ResLength ) 644 | ) 645 | { 646 | if ( returnLength ) 647 | *returnLength = ResLength; 648 | 649 | //printf( "[ ! ] NtQuerySystemInformationEx - success!\n" ); 650 | return STATUS_SUCCESS; 651 | } 652 | else 653 | { 654 | printf( "[ ! ] NtQuerySystemInformationEx returned 0x%X\n", g_cmdDriver->GetLastNtError() ); 655 | return g_cmdDriver->GetLastNtError(); 656 | } 657 | } 658 | break; 659 | } 660 | return oNtQuerySystemInformationEx( systemInformationClass, inputBuffer, inputBufferLength, systemInformation, systemInformationLength, returnLength ); 661 | } 662 | 663 | // 664 | // WaitForSingleObject 665 | // 666 | NTSTATUS( NTAPI* oNtWaitForSingleObject )( HANDLE, BOOLEAN, PLARGE_INTEGER ); 667 | 668 | NTSTATUS NTAPI hk_NtWaitForSingleObject( HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout ) 669 | { 670 | auto Status = oNtWaitForSingleObject( Handle, Alertable, Timeout ); 671 | if ( !NT_SUCCESS( Status ) ) 672 | printf( "[ ! ] NtWaitForSingleObject - Handle: 0x%p, Status: 0x%X!\n", Handle, Status ); 673 | 674 | return Status; 675 | /*if ( NT_SUCCESS( Status ) ) 676 | return Status; 677 | 678 | if ( CEPTOR_VALID_HANDLE( Handle ) ) 679 | { 680 | printf( "[ ! ] NtWaitForSingleObject - 0x%p!\n", Handle ); 681 | 682 | g_cmdDriver->WaitForSingleObject( 683 | uint64_t( Handle ), 684 | Alertable, 685 | Timeout 686 | ); 687 | 688 | return g_cmdDriver->GetLastNtError(); 689 | } 690 | else 691 | { 692 | auto HandleId = GetThreadId( Handle ); 693 | 694 | if ( HandleId ) 695 | printf( "[ ! ] NtWaitForSingleObject - ThreadId: %d!\n", HandleId ); 696 | else 697 | HandleId = GetProcessId( Handle ); 698 | 699 | if ( HandleId ) 700 | { 701 | printf( "[ ! ] NtWaitForSingleObject - ProcessId: %d!\n", HandleId ); 702 | 703 | g_cmdDriver->WaitForSingleObject( 704 | uint64_t( HandleId ), 705 | Alertable, 706 | Timeout 707 | ); 708 | 709 | return g_cmdDriver->GetLastNtError(); 710 | } 711 | else 712 | printf( "[ ! ] NtWaitForSingleObject - Unknown: 0x%p!\n", Handle ); 713 | } 714 | 715 | return oNtWaitForSingleObject( Handle, Alertable, Timeout );*/ 716 | } -------------------------------------------------------------------------------- /driverceptor/driver.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.hpp" 2 | 3 | PDRIVER_DISPATCH g_originalDispatcher = nullptr; 4 | PDRIVER_OBJECT g_driverObject = nullptr; 5 | 6 | NTSTATUS IoControl( PDEVICE_OBJECT DeviceObject, PIRP Irp ) 7 | { 8 | UNREFERENCED_PARAMETER( DeviceObject ); 9 | 10 | NTSTATUS Status = 1337; 11 | ULONG OutputLenght = 0; 12 | 13 | PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation( Irp ); 14 | const ULONG InputLenght = stack->Parameters.DeviceIoControl.InputBufferLength; 15 | 16 | // DBGPRINT( "%s %d : Recieved Ioctl 0x%X", __FUNCTION__, __LINE__, stack->Parameters.DeviceIoControl.IoControlCode ); 17 | 18 | switch ( stack->Parameters.DeviceIoControl.IoControlCode ) 19 | { 20 | 21 | case IOCTL_ATTACH_TO_PROCESS: 22 | { 23 | const auto Buffer = PATTACH_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 24 | if ( Buffer && InputLenght >= sizeof( ATTACH_PROCESS ) ) 25 | { 26 | auto TargetPid = HANDLE( Buffer->ProcessId ); 27 | auto TargetTid = HANDLE( Buffer->ThreadId ); 28 | 29 | if ( TargetPid && CEPTOR_VALID_HANDLE( TargetPid ) ) 30 | { 31 | Status = STATUS_INVALID_HANDLE; 32 | goto exit; 33 | } 34 | 35 | if ( TargetPid || TargetTid ) 36 | { 37 | auto List = InsertHandleListEntry( ); 38 | if ( List ) 39 | { 40 | Status = PsLookupProcessByProcessId( TargetPid, &List->Process ); 41 | 42 | if ( NT_SUCCESS( Status ) ) 43 | { 44 | Status = STATUS_PROCESS_IS_TERMINATING; 45 | 46 | if ( AcquireProcessSync( List->Process ) ) 47 | { 48 | Buffer->OutProcessHandle = std::uint64_t( List->HandleValue ); 49 | 50 | List->ProcessId = TargetPid; 51 | 52 | if ( List->Process ) 53 | List->Wow64 = ( PsGetProcessWow64Process( List->Process ) != NULL ); 54 | 55 | //DBGPRINT( "%s %d : IOCTL_ATTACH_TO_PROCESS - ProcessHandle: 0x%llX - returned 0x%X", __FUNCTION__, __LINE__, Buffer->OutProcessHandle, Status ); 56 | Status = STATUS_SUCCESS; 57 | ReleaseProcessSync( List->Process ); 58 | } 59 | else 60 | { 61 | ObDereferenceObject( List->Process ); 62 | RemoveHandleListEntry( List ); 63 | } 64 | } 65 | else 66 | RemoveHandleListEntry( List ); 67 | } 68 | } 69 | 70 | exit: 71 | if ( !NT_SUCCESS( Status ) ) 72 | DBGPRINT( "%s %d : IOCTL_ATTACH_TO_PROCESS PID = 0x%p, TID = 0x%p, status: 0x%X", __FUNCTION__, __LINE__, TargetPid, TargetTid, Status ); 73 | 74 | OutputLenght = sizeof( ATTACH_PROCESS ); 75 | } 76 | break; 77 | } 78 | 79 | case IOCTL_DETACH_FROM_PROCESS: 80 | { 81 | const auto Buffer = PDETACH_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 82 | if ( Buffer && InputLenght >= sizeof( DETACH_PROCESS ) ) 83 | { 84 | auto HandleValue = HANDLE( Buffer->ProcessHandle ); 85 | 86 | if ( HandleValue ) 87 | { 88 | auto Entry = FindHandleListEntry( HandleValue ); 89 | if ( Entry ) 90 | { 91 | if ( Entry->Process ) 92 | { 93 | ObDereferenceObject( Entry->Process ); 94 | Entry->Process = nullptr; 95 | } 96 | 97 | if ( Entry->Thread ) 98 | { 99 | ObDereferenceObject( Entry->Thread ); 100 | Entry->Thread = nullptr; 101 | } 102 | 103 | RemoveHandleListEntry( Entry ); 104 | Status = STATUS_SUCCESS; 105 | } 106 | else 107 | Status = STATUS_NOT_FOUND; 108 | } 109 | 110 | if ( !NT_SUCCESS( Status ) ) 111 | DBGPRINT( "%s %d : IOCTL_DETACH_FROM_PROCESS - ProcessHandle: 0x%llX - returned 0x%X", __FUNCTION__, __LINE__, Buffer->ProcessHandle, Status ); 112 | 113 | OutputLenght = sizeof( DETACH_PROCESS ); 114 | } 115 | break; 116 | } 117 | 118 | case IOCTL_READ_MEMORY_PROCESS: 119 | { 120 | const auto Buffer = PREADMEMORY_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 121 | if ( Buffer && InputLenght >= sizeof( READMEMORY_PROCESS ) ) 122 | { 123 | auto HandleValue = HANDLE( Buffer->ProcessHandle ); 124 | 125 | if ( HandleValue ) 126 | { 127 | auto Entry = FindHandleListEntry( HandleValue ); 128 | if ( Entry ) 129 | { 130 | SIZE_T SizeBuf = Buffer->Lenght; 131 | PVOID Address = Buffer->BaseAddress; 132 | PVOID Buf = Buffer->Buffer; 133 | 134 | if ( SizeBuf > 0 ) 135 | { 136 | SIZE_T numberOfBytesRead = 0; 137 | 138 | Status = MmCopyVirtualMemory( 139 | Entry->Process, Address, 140 | PsGetCurrentProcess(), 141 | Buf, 142 | SizeBuf, 143 | ExGetPreviousMode(), 144 | &numberOfBytesRead 145 | ); 146 | 147 | if ( numberOfBytesRead ) 148 | { 149 | if ( Buffer->BytesRead ) 150 | *Buffer->BytesRead = numberOfBytesRead; 151 | } 152 | } 153 | } 154 | else 155 | Status = STATUS_NOT_FOUND; 156 | } 157 | 158 | if ( !NT_SUCCESS( Status ) ) 159 | DBGPRINT( "%s %d : IOCTL_READ_MEMORY_PROCESS PID = 0x%p, ( Base = 0x%p, Buffer = 0x%p, Lenght = 0x%llX ) returned 0x%X", __FUNCTION__, __LINE__, HandleValue , Buffer->BaseAddress, Buffer->Buffer, Buffer->Lenght, Status ); 160 | 161 | OutputLenght = sizeof( READMEMORY_PROCESS ); 162 | } 163 | break; 164 | } 165 | 166 | case IOCTL_WRITE_MEMORY_PROCESS: 167 | { 168 | const auto Buffer = PWRITEMEMORY_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 169 | if ( Buffer && InputLenght >= sizeof( WRITEMEMORY_PROCESS ) ) 170 | { 171 | auto HandleValue = HANDLE( Buffer->ProcessHandle ); 172 | 173 | if ( HandleValue ) 174 | { 175 | auto Entry = FindHandleListEntry( HandleValue ); 176 | if ( Entry ) 177 | { 178 | SIZE_T Lenght = SIZE_T( Buffer->Lenght ); 179 | SIZE_T BytesWritten = NULL; 180 | Status = MmCopyVirtualMemory( PsGetCurrentProcess(), Buffer->Buffer, Entry->Process, Buffer->BaseAddress, Lenght, ExGetPreviousMode(), &BytesWritten ); 181 | 182 | if ( BytesWritten ) 183 | { 184 | if ( Buffer->BytesWritten ) 185 | *Buffer->BytesWritten = BytesWritten; 186 | } 187 | } 188 | else 189 | Status = STATUS_NOT_FOUND; 190 | } 191 | 192 | if ( !NT_SUCCESS( Status ) ) 193 | DBGPRINT( "%s %d : IOCTL_WRITE_MEMORY_PROCESS returned 0x%X", __FUNCTION__, __LINE__, Status ); 194 | 195 | OutputLenght = sizeof( WRITEMEMORY_PROCESS ); 196 | } 197 | break; 198 | } 199 | 200 | case IOCTL_QUERY_MEMORY_PROCESS: 201 | { 202 | const auto Buffer = PQUERYMEMORY_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 203 | if ( Buffer && InputLenght >= sizeof( QUERYMEMORY_PROCESS ) ) 204 | { 205 | auto HandleValue = HANDLE( Buffer->ProcessHandle ); 206 | 207 | if ( HandleValue ) 208 | { 209 | auto Entry = FindHandleListEntry( HandleValue ); 210 | if ( Entry ) 211 | { 212 | PVOID BaseAddress = PVOID( Buffer->BaseAddress ); 213 | ULONG InformationClass = ULONG( Buffer->InformationClass ); 214 | SIZE_T Lenght = SIZE_T( Buffer->Lenght ); 215 | SIZE_T RetLenght = NULL; 216 | 217 | auto MemoryInformation = PVOID( AllocateZeroPool( Lenght ) ); 218 | if ( MemoryInformation ) 219 | { 220 | if ( AcquireProcessSync( Entry->Process ) ) 221 | { 222 | KAPC_STATE apc{ }; 223 | KeStackAttachProcess( Entry->Process, &apc ); 224 | Status = ZwQueryVirtualMemory( 225 | NtCurrentProcess(), 226 | BaseAddress, 227 | MEMORY_INFORMATION_CLASS( InformationClass ), 228 | MemoryInformation, 229 | Lenght, 230 | &RetLenght ); 231 | KeUnstackDetachProcess( &apc ); 232 | 233 | ReleaseProcessSync( Entry->Process ); 234 | } 235 | 236 | if ( NT_SUCCESS( Status ) && RetLenght ) 237 | { 238 | if( InformationClass == 2 /*MemoryMappedFilenameInformation*/ ) 239 | AdjustRelativePointers( ( std::uint8_t *)MemoryInformation, ( std::uint8_t* )Buffer->Buffer, RetLenght ); 240 | 241 | RtlCopyMemory( PVOID( Buffer->Buffer ), MemoryInformation, RetLenght ); 242 | } 243 | 244 | ExFreePool( MemoryInformation ); 245 | } 246 | 247 | if ( Buffer->ResultLength ) 248 | *Buffer->ResultLength = RetLenght & 0xFFFFFFFF; 249 | } 250 | else 251 | Status = STATUS_NOT_FOUND; 252 | } 253 | 254 | if ( !NT_SUCCESS( Status ) ) 255 | DBGPRINT( "%s %d : IOCTL_QUERY_MEMORY_PROCESS returned 0x%X", __FUNCTION__, __LINE__, Status ); 256 | 257 | OutputLenght = sizeof( QUERYMEMORY_PROCESS ); 258 | } 259 | break; 260 | } 261 | 262 | case IOCTL_QUERY_INFO_PROCESS: 263 | { 264 | const auto Buffer = PQUERYINFO_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 265 | if ( Buffer && InputLenght >= sizeof( QUERYINFO_PROCESS ) ) 266 | { 267 | auto HandleValue = HANDLE( Buffer->ProcessHandle ); 268 | 269 | if ( HandleValue ) 270 | { 271 | auto Entry = FindHandleListEntry( HandleValue ); 272 | if ( Entry ) 273 | { 274 | ULONG InformationClass = ULONG( Buffer->InformationClass ); 275 | ULONG Lenght = Buffer->Lenght; 276 | ULONG RetLenght = NULL; 277 | 278 | auto ProcessInformation = PVOID( AllocateZeroPool( Lenght ) ); 279 | if ( ProcessInformation ) 280 | { 281 | if ( AcquireProcessSync( Entry->Process ) ) 282 | { 283 | KAPC_STATE apc{ }; 284 | KeStackAttachProcess( Entry->Process, &apc ); 285 | 286 | Status = ZwQueryInformationProcess( 287 | NtCurrentProcess(), 288 | PROCESSINFOCLASS( InformationClass ), 289 | ProcessInformation, 290 | Lenght, 291 | &RetLenght ); 292 | 293 | KeUnstackDetachProcess( &apc ); 294 | 295 | if ( Buffer->ResultLength ) 296 | *Buffer->ResultLength = RetLenght; 297 | 298 | ReleaseProcessSync( Entry->Process ); 299 | } 300 | 301 | if ( NT_SUCCESS( Status ) ) 302 | { 303 | AdjustRelativePointers( reinterpret_cast< std::uint8_t* >( ProcessInformation ), reinterpret_cast< std::uint8_t* >( Buffer->Buffer ), Lenght ); 304 | RtlCopyMemory( PVOID( Buffer->Buffer ), ProcessInformation, Lenght ); 305 | } 306 | 307 | ExFreePool( ProcessInformation ); 308 | // DBGPRINT( "%s %d : IOCTL_QUERY_INFO_PROCESS - InfoClass: %d, ProcessInfo = 0x%p, Lenght = 0x%X", __FUNCTION__, __LINE__, InformationClass, Buffer->Buffer, Lenght ); 309 | } 310 | } 311 | else 312 | Status = STATUS_NOT_FOUND; 313 | } 314 | 315 | if ( !NT_SUCCESS( Status ) ) 316 | DBGPRINT( "%s %d : IOCTL_QUERY_INFO_PROCESS returned 0x%X", __FUNCTION__, __LINE__, Status ); 317 | 318 | OutputLenght = sizeof( QUERYINFO_PROCESS ); 319 | } 320 | break; 321 | } 322 | 323 | case IOCTL_QUERY_SYSTEM_INFO_EX: 324 | { 325 | const auto Buffer = PQUERY_SYSTEMINFOEX( Irp->AssociatedIrp.SystemBuffer ); 326 | if ( Buffer && InputLenght >= sizeof( QUERY_SYSTEMINFOEX ) ) 327 | { 328 | ULONG RetLenght = NULL; 329 | SYSTEM_INFORMATION_CLASS InfoClass = SYSTEM_INFORMATION_CLASS( Buffer->InformationClass ); 330 | 331 | ULONG InputBuffLen = Buffer->InputBufferLenght; 332 | ULONG SysInfoLen = Buffer->SystemInfoLenght; 333 | 334 | auto SystemInfo = PVOID( AllocateZeroPool( SysInfoLen ) ); 335 | if ( SystemInfo ) 336 | { 337 | switch ( InfoClass ) 338 | { 339 | case SystemSupportedProcessArchitectures: 340 | { 341 | if ( CEPTOR_VALID_HANDLE( Buffer->InputBuffer ) ) 342 | { 343 | auto HandleValue = HANDLE( Buffer->InputBuffer ); 344 | 345 | if ( HandleValue ) 346 | { 347 | auto Entry = FindHandleListEntry( HandleValue ); 348 | if ( Entry ) 349 | { 350 | auto processHandle = NtCurrentProcess(); 351 | 352 | if ( AcquireProcessSync( Entry->Process ) ) 353 | { 354 | KAPC_STATE apc{ }; 355 | KeStackAttachProcess( Entry->Process, &apc ); 356 | 357 | Status = 358 | ZwQuerySystemInformationEx( 359 | InfoClass, 360 | &processHandle, 361 | InputBuffLen, 362 | SystemInfo, 363 | SysInfoLen, 364 | &RetLenght ); 365 | 366 | KeUnstackDetachProcess( &apc ); 367 | 368 | if ( Buffer->ResultLength ) 369 | *Buffer->ResultLength = RetLenght; 370 | 371 | ReleaseProcessSync( Entry->Process ); 372 | } 373 | 374 | if ( NT_SUCCESS( Status ) ) 375 | RtlCopyMemory( PVOID( Buffer->SystemInfo ), SystemInfo, SysInfoLen ); 376 | } 377 | } 378 | 379 | // DBGPRINT( "%s %d : IOCTL_QUERY_SYSTEM_INFO_EX - Special - returned 0x%X", __FUNCTION__, __LINE__, Status ); 380 | } 381 | //else 382 | // DBGPRINT( "%s %d : IOCTL_QUERY_SYSTEM_INFO_EX - SystemSupportedProcessArchitectures - Ptr: 0x%p", __FUNCTION__, __LINE__, Buffer->InputBuffer ); 383 | 384 | break; 385 | } 386 | 387 | default: 388 | { 389 | Status = ZwQuerySystemInformationEx( 390 | InfoClass, 391 | Buffer->InputBuffer, 392 | Buffer->InputBufferLenght, 393 | SystemInfo, 394 | SysInfoLen, 395 | &RetLenght ); 396 | 397 | if ( Buffer->ResultLength ) 398 | *Buffer->ResultLength = RetLenght; 399 | 400 | if ( NT_SUCCESS( Status ) ) 401 | RtlCopyMemory( PVOID( Buffer->SystemInfo ), SystemInfo, SysInfoLen ); 402 | 403 | break; 404 | } 405 | } 406 | 407 | ExFreePool( SystemInfo ); 408 | } 409 | 410 | if ( !NT_SUCCESS( Status ) ) 411 | DBGPRINT( "%s %d : IOCTL_QUERY_SYSTEM_INFO_EX returned 0x%X", __FUNCTION__, __LINE__, Status ); 412 | 413 | OutputLenght = sizeof( QUERY_SYSTEMINFOEX ); 414 | } 415 | break; 416 | } 417 | 418 | case IOCTL_SET_INFORMATION_PROCESS: 419 | { 420 | const auto Buffer = PSETINFO_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 421 | if ( Buffer && InputLenght >= sizeof( SETINFO_PROCESS ) ) 422 | { 423 | auto HandleValue = HANDLE( Buffer->ProcessHandle ); 424 | 425 | if ( HandleValue ) 426 | { 427 | auto Entry = FindHandleListEntry( HandleValue ); 428 | if ( Entry ) 429 | { 430 | ULONG InformationClass = ULONG( Buffer->InformationClass ); 431 | ULONG Lenght = Buffer->Lenght; 432 | 433 | auto ProcessInfo = PVOID( AllocateZeroPool( Lenght ) ); 434 | if ( ProcessInfo ) 435 | { 436 | RtlCopyMemory( ProcessInfo, PVOID( Buffer->Buffer ), Lenght ); 437 | 438 | if ( AcquireProcessSync( Entry->Process ) ) 439 | { 440 | KAPC_STATE apc{ }; 441 | KeStackAttachProcess( Entry->Process, &apc ); 442 | Status = ZwSetInformationProcess( NtCurrentProcess(), PROCESSINFOCLASS( InformationClass ), ProcessInfo, Lenght ); 443 | KeUnstackDetachProcess( &apc ); 444 | 445 | ReleaseProcessSync( Entry->Process ); 446 | } 447 | 448 | ExFreePool( ProcessInfo ); 449 | } 450 | } 451 | else 452 | Status = STATUS_NOT_FOUND; 453 | } 454 | 455 | if ( !NT_SUCCESS( Status ) ) 456 | DBGPRINT( "%s %d : IOCTL_SET_INFORMATION_PROCESS returned 0x%X", __FUNCTION__, __LINE__, Status ); 457 | 458 | OutputLenght = sizeof( SETINFO_PROCESS ); 459 | } 460 | break; 461 | } 462 | 463 | case IOCTL_FLUSH_INSTRUCTION_CACHE: 464 | { 465 | const auto Buffer = PFLUSHCACHE_MEMORY_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 466 | if ( Buffer && InputLenght >= sizeof( FLUSHCACHE_MEMORY_PROCESS ) ) 467 | { 468 | auto HandleValue = HANDLE( Buffer->ProcessHandle ); 469 | 470 | if ( HandleValue ) 471 | { 472 | auto Entry = FindHandleListEntry( HandleValue ); 473 | if ( Entry ) 474 | { 475 | if ( AcquireProcessSync( Entry->Process ) ) 476 | { 477 | PVOID BaseAddress = PVOID( Buffer->BaseAddress ); 478 | ULONG Lenght = ULONG( Buffer->Lenght ); 479 | 480 | KAPC_STATE apc{ }; 481 | KeStackAttachProcess( Entry->Process, &apc ); 482 | Status = ZwFlushInstructionCache( NtCurrentProcess(), &BaseAddress, Lenght ); 483 | KeUnstackDetachProcess( &apc ); 484 | 485 | ReleaseProcessSync( Entry->Process ); 486 | } 487 | } 488 | else 489 | Status = STATUS_NOT_FOUND; 490 | } 491 | 492 | if ( !NT_SUCCESS( Status ) ) 493 | DBGPRINT( "%s %d : IOCTL_FLUSH_INSTRUCTION_CACHE returned 0x%X", __FUNCTION__, __LINE__, Status ); 494 | 495 | OutputLenght = sizeof( FLUSHCACHE_MEMORY_PROCESS ); 496 | } 497 | break; 498 | } 499 | 500 | case IOCTL_FLUSH_MEMORY_PROCESS: 501 | { 502 | const auto Buffer = PFLUSHVIRTUAL_MEMORY_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 503 | if ( Buffer && InputLenght >= sizeof( FLUSHVIRTUAL_MEMORY_PROCESS ) ) 504 | { 505 | auto HandleValue = HANDLE( Buffer->ProcessHandle ); 506 | 507 | if ( HandleValue ) 508 | { 509 | auto Entry = FindHandleListEntry( HandleValue ); 510 | if ( Entry ) 511 | { 512 | PVOID BaseAddress = PVOID( Buffer->BaseAddress ); 513 | SIZE_T RegionSize = SIZE_T( Buffer->Lenght ); 514 | 515 | auto IoStatus = PIO_STATUS_BLOCK( AllocateZeroPool( sizeof( IO_STATUS_BLOCK ) ) ); 516 | if ( IoStatus ) 517 | { 518 | if ( AcquireProcessSync( Entry->Process ) ) 519 | { 520 | KAPC_STATE apc{ }; 521 | KeStackAttachProcess( Entry->Process, &apc ); 522 | Status = ZwFlushVirtualMemory( NtCurrentProcess(), &BaseAddress, &RegionSize, IoStatus ); 523 | KeUnstackDetachProcess( &apc ); 524 | 525 | ReleaseProcessSync( Entry->Process ); 526 | } 527 | 528 | if ( NT_SUCCESS( Status ) && Buffer->IoStatus && MmIsAddressValid( Buffer->IoStatus ) ) 529 | RtlCopyMemory( Buffer->IoStatus, IoStatus, sizeof( IO_STATUS_BLOCK ) ); 530 | 531 | ExFreePool( IoStatus ); 532 | } 533 | } 534 | else 535 | Status = STATUS_NOT_FOUND; 536 | } 537 | 538 | if ( !NT_SUCCESS( Status ) ) 539 | DBGPRINT( "%s %d : IOCTL_FLUSH_MEMORY_PROCESS returned 0x%X", __FUNCTION__, __LINE__, Status ); 540 | 541 | OutputLenght = sizeof( FLUSHVIRTUAL_MEMORY_PROCESS ); 542 | } 543 | break; 544 | } 545 | 546 | case IOCTL_ALLOCATE_MEMORY_PROCESS: 547 | { 548 | auto Buffer = PALLOCMEMORY_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 549 | if ( Buffer && InputLenght >= sizeof( ALLOCMEMORY_PROCESS ) ) 550 | { 551 | auto HandleValue = HANDLE( Buffer->ProcessHandle ); 552 | 553 | if ( HandleValue ) 554 | { 555 | auto Entry = FindHandleListEntry( HandleValue ); 556 | if ( Entry ) 557 | { 558 | PVOID BaseAddress = PVOID( Buffer->BaseAddress ); 559 | SIZE_T RegionSize = SIZE_T( Buffer->Lenght ); 560 | ULONG Type = Buffer->Type; 561 | ULONG Protect = Buffer->Protect; 562 | 563 | if ( AcquireProcessSync( Entry->Process ) ) 564 | { 565 | KAPC_STATE apc{ }; 566 | KeStackAttachProcess( Entry->Process, &apc ); 567 | Status = ZwAllocateVirtualMemory( NtCurrentProcess(), &BaseAddress, NULL, &RegionSize, Type, Protect ); 568 | KeUnstackDetachProcess( &apc ); 569 | 570 | ReleaseProcessSync( Entry->Process ); 571 | } 572 | 573 | if ( NT_SUCCESS( Status ) ) 574 | Buffer->BaseAddress = std::uint64_t( BaseAddress ); 575 | } 576 | else 577 | Status = STATUS_NOT_FOUND; 578 | } 579 | 580 | if ( !NT_SUCCESS( Status ) ) 581 | DBGPRINT( "%s %d : IOCTL_ALLOCATE_MEMORY_PROCESS - Base: 0x%llX - returned 0x%X", __FUNCTION__, __LINE__, Buffer->BaseAddress, Status ); 582 | 583 | OutputLenght = sizeof( ALLOCMEMORY_PROCESS ); 584 | } 585 | break; 586 | } 587 | 588 | case IOCTL_FREE_MEMORY_PROCESS: 589 | { 590 | const auto Buffer = PFREEMEMORY_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 591 | if ( Buffer && InputLenght >= sizeof( FREEMEMORY_PROCESS ) ) 592 | { 593 | auto HandleValue = HANDLE( Buffer->ProcessHandle ); 594 | 595 | if ( HandleValue ) 596 | { 597 | auto Entry = FindHandleListEntry( HandleValue ); 598 | if ( Entry ) 599 | { 600 | PVOID BaseAddress = PVOID( Buffer->BaseAddress ); 601 | SIZE_T RegionSize = SIZE_T( Buffer->Lenght ); 602 | ULONG Type = Buffer->Type; 603 | 604 | if ( AcquireProcessSync( Entry->Process ) ) 605 | { 606 | KAPC_STATE apc{ }; 607 | KeStackAttachProcess( Entry->Process, &apc ); 608 | Status = ZwFreeVirtualMemory( NtCurrentProcess(), &BaseAddress, &RegionSize, Type ); 609 | KeUnstackDetachProcess( &apc ); 610 | 611 | ReleaseProcessSync( Entry->Process ); 612 | } 613 | } 614 | else 615 | Status = STATUS_NOT_FOUND; 616 | } 617 | 618 | if ( !NT_SUCCESS( Status ) ) 619 | DBGPRINT( "%s %d : IOCTL_FREE_MEMORY_PROCESS returned 0x%X", __FUNCTION__, __LINE__, Status ); 620 | 621 | OutputLenght = sizeof( FREEMEMORY_PROCESS ); 622 | } 623 | break; 624 | } 625 | 626 | case IOCTL_LOCK_MEMORY_PROCESS: 627 | { 628 | const auto Buffer = PLOCKMEMORY_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 629 | if ( Buffer && InputLenght >= sizeof( LOCKMEMORY_PROCESS ) ) 630 | { 631 | auto HandleValue = HANDLE( Buffer->ProcessHandle ); 632 | 633 | if ( HandleValue ) 634 | { 635 | auto Entry = FindHandleListEntry( HandleValue ); 636 | if ( Entry ) 637 | { 638 | PVOID BaseAddress = PVOID( Buffer->BaseAddress ); 639 | SIZE_T RegionSize = SIZE_T( Buffer->Lenght ); 640 | ULONG Option = ULONG( Buffer->Option ); 641 | 642 | if ( AcquireProcessSync( Entry->Process ) ) 643 | { 644 | KAPC_STATE apc{ }; 645 | KeStackAttachProcess( Entry->Process, &apc ); 646 | Status = ZwLockVirtualMemory( NtCurrentProcess(), &BaseAddress, &RegionSize, Option ); 647 | KeUnstackDetachProcess( &apc ); 648 | 649 | ReleaseProcessSync( Entry->Process ); 650 | } 651 | } 652 | else 653 | Status = STATUS_NOT_FOUND; 654 | } 655 | 656 | if ( !NT_SUCCESS( Status ) ) 657 | DBGPRINT( "%s %d : IOCTL_LOCK_MEMORY_PROCESS returned 0x%X", __FUNCTION__, __LINE__, Status ); 658 | 659 | OutputLenght = sizeof( LOCKMEMORY_PROCESS ); 660 | } 661 | break; 662 | } 663 | 664 | case IOCTL_UNLOCK_MEMORY_PROCESS: 665 | { 666 | const auto Buffer = PUNLOCKMEMORY_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 667 | if ( Buffer && InputLenght >= sizeof( UNLOCKMEMORY_PROCESS ) ) 668 | { 669 | auto HandleValue = HANDLE( Buffer->ProcessHandle ); 670 | 671 | if ( HandleValue ) 672 | { 673 | auto Entry = FindHandleListEntry( HandleValue ); 674 | if ( Entry ) 675 | { 676 | PVOID BaseAddress = PVOID( Buffer->BaseAddress ); 677 | SIZE_T RegionSize = SIZE_T( Buffer->Lenght ); 678 | ULONG Option = ULONG( Buffer->Option ); 679 | 680 | if ( AcquireProcessSync( Entry->Process ) ) 681 | { 682 | KAPC_STATE apc{ }; 683 | KeStackAttachProcess( Entry->Process, &apc ); 684 | Status = ZwUnlockVirtualMemory( NtCurrentProcess(), &BaseAddress, &RegionSize, Option ); 685 | KeUnstackDetachProcess( &apc ); 686 | 687 | ReleaseProcessSync( Entry->Process ); 688 | } 689 | } 690 | else 691 | Status = STATUS_NOT_FOUND; 692 | } 693 | 694 | if ( !NT_SUCCESS( Status ) ) 695 | DBGPRINT( "%s %d : IOCTL_UNLOCK_MEMORY_PROCESS returned 0x%X", __FUNCTION__, __LINE__, Status ); 696 | 697 | OutputLenght = sizeof( UNLOCKMEMORY_PROCESS ); 698 | } 699 | break; 700 | } 701 | 702 | case IOCTL_PROTECT_MEMORY_PROCESS: 703 | { 704 | const auto Buffer = PPROTECTMEMORY_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 705 | if ( Buffer && InputLenght >= sizeof( PROTECTMEMORY_PROCESS ) ) 706 | { 707 | auto HandleValue = HANDLE( Buffer->ProcessHandle ); 708 | 709 | if ( HandleValue ) 710 | { 711 | auto Entry = FindHandleListEntry( HandleValue ); 712 | if ( Entry ) 713 | { 714 | PVOID BaseAddress = PVOID( Buffer->BaseAddress ); 715 | SIZE_T RegionSize = SIZE_T( Buffer->Lenght ); 716 | ULONG NewAccess = ULONG( Buffer->NewAccess ); 717 | ULONG OldAccess = NULL; 718 | 719 | if ( AcquireProcessSync( Entry->Process ) ) 720 | { 721 | KAPC_STATE apc{ }; 722 | KeStackAttachProcess( Entry->Process, &apc ); 723 | Status = ZwProtectVirtualMemory( NtCurrentProcess(), &BaseAddress, &RegionSize, NewAccess, &OldAccess ); 724 | KeUnstackDetachProcess( &apc ); 725 | 726 | ReleaseProcessSync( Entry->Process ); 727 | } 728 | 729 | if ( Buffer->OldAccess ) 730 | *Buffer->OldAccess = OldAccess; 731 | } 732 | else 733 | Status = STATUS_NOT_FOUND; 734 | } 735 | 736 | if ( !NT_SUCCESS( Status ) ) 737 | DBGPRINT( "%s %d : IOCTL_PROTECT_MEMORY_PROCESS returned 0x%X", __FUNCTION__, __LINE__, Status ); 738 | 739 | OutputLenght = sizeof( PROTECTMEMORY_PROCESS ); 740 | } 741 | break; 742 | } 743 | 744 | case IOCTL_OPEN_THREAD: 745 | { 746 | const auto Buffer = POPEN_THREAD_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 747 | if ( Buffer && InputLenght >= sizeof( OPEN_THREAD_PROCESS ) ) 748 | { 749 | auto TargetProcessId = HANDLE( Buffer->ProcessId ); 750 | auto TargetThreadId = HANDLE( Buffer->ThreadId ); 751 | 752 | auto List = InsertHandleListEntry( ); 753 | if ( List ) 754 | { 755 | if ( TargetThreadId && TargetProcessId ) 756 | { 757 | CLIENT_ID cid{ }; 758 | cid.UniqueProcess = TargetProcessId; 759 | cid.UniqueThread = TargetThreadId; 760 | 761 | Status = PsLookupProcessThreadByCid( &cid, &List->Process, &List->Thread ); 762 | if ( NT_SUCCESS( Status ) ) 763 | { 764 | Status = STATUS_THREAD_IS_TERMINATING; 765 | 766 | if ( AcquireThreadSync( List->Thread ) ) 767 | { 768 | List->ProcessId = TargetProcessId; 769 | List->Wow64 = ( PsGetProcessWow64Process( List->Process ) != NULL ); 770 | Buffer->OutThreadHandle = std::uint64_t( List->HandleValue ); 771 | } 772 | else 773 | { 774 | ObDereferenceObject( List->Process ); 775 | ObDereferenceObject( List->Thread ); 776 | RemoveHandleListEntry( List ); 777 | } 778 | } 779 | else 780 | RemoveHandleListEntry( List ); 781 | } 782 | else if ( TargetThreadId && !TargetProcessId ) 783 | { 784 | Status = PsLookupThreadByThreadId( TargetThreadId, &List->Thread ); 785 | if ( NT_SUCCESS( Status ) ) 786 | { 787 | Status = STATUS_THREAD_IS_TERMINATING; 788 | 789 | if ( AcquireThreadSync( List->Thread ) ) 790 | { 791 | List->Process = PsGetThreadProcess( List->Thread ); 792 | List->ProcessId = TargetProcessId; 793 | List->Wow64 = ( PsGetProcessWow64Process( List->Process ) != NULL ); 794 | Buffer->OutThreadHandle = std::uint64_t( List->HandleValue ); 795 | } 796 | else 797 | { 798 | ObDereferenceObject( List->Thread ); 799 | RemoveHandleListEntry( List ); 800 | } 801 | } 802 | else 803 | RemoveHandleListEntry( List ); 804 | } 805 | else 806 | Status = STATUS_INVALID_PARAMETER; 807 | } 808 | 809 | if ( !NT_SUCCESS( Status ) ) 810 | DBGPRINT( "%s %d : IOCTL_OPEN_THREAD - returned 0x%X", __FUNCTION__, __LINE__, Status ); 811 | 812 | OutputLenght = sizeof( OPEN_THREAD_PROCESS ); 813 | } 814 | break; 815 | } 816 | 817 | case IOCTL_SET_CONTEXT_THREAD: 818 | { 819 | const auto Buffer = PSET_CONTEXT_THREAD_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 820 | if ( Buffer && InputLenght >= sizeof( SET_CONTEXT_THREAD_PROCESS ) ) 821 | { 822 | auto HandleValue = HANDLE( Buffer->ThreadHandleValue ); 823 | 824 | if ( HandleValue ) 825 | { 826 | auto Entry = FindHandleListEntry( HandleValue ); 827 | if ( Entry ) 828 | { 829 | if ( AcquireThreadSync( Entry->Thread ) ) 830 | { 831 | if ( !Entry->Wow64 ) 832 | Status = PsSetContextThread( Entry->Thread, Buffer->Context, UserMode ); 833 | } 834 | } 835 | else 836 | Status = STATUS_NOT_FOUND; 837 | } 838 | 839 | if ( !NT_SUCCESS( Status ) ) 840 | DBGPRINT( "%s %d : IOCTL_SET_CONTEXT_THREAD returned 0x%X", __FUNCTION__, __LINE__, Status ); 841 | 842 | OutputLenght = sizeof( SET_CONTEXT_THREAD_PROCESS ); 843 | } 844 | break; 845 | } 846 | 847 | case IOCTL_GET_CONTEXT_THREAD: 848 | { 849 | const auto Buffer = PGET_CONTEXT_THREAD_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 850 | if ( Buffer && InputLenght >= sizeof( GET_CONTEXT_THREAD_PROCESS ) ) 851 | { 852 | auto HandleValue = HANDLE( Buffer->ThreadHandleValue ); 853 | 854 | if ( HandleValue ) 855 | { 856 | auto Entry = FindHandleListEntry( HandleValue ); 857 | if ( Entry ) 858 | { 859 | if ( AcquireThreadSync( Entry->Thread ) ) 860 | { 861 | if ( !Entry->Wow64 ) 862 | Status = PsGetContextThread( Entry->Thread, Buffer->Context, UserMode ); 863 | } 864 | } 865 | else 866 | Status = STATUS_NOT_FOUND; 867 | } 868 | 869 | if ( !NT_SUCCESS( Status ) ) 870 | DBGPRINT( "%s %d : IOCTL_GET_CONTEXT_THREAD returned 0x%X", __FUNCTION__, __LINE__, Status ); 871 | 872 | OutputLenght = sizeof( GET_CONTEXT_THREAD_PROCESS ); 873 | } 874 | break; 875 | } 876 | 877 | case IOCTL_SUSPEND_THREAD: 878 | { 879 | const auto Buffer = PSUSPEND_THREAD_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 880 | if ( Buffer && InputLenght >= sizeof( SUSPEND_THREAD_PROCESS ) ) 881 | { 882 | auto HandleValue = HANDLE( Buffer->ThreadHandleValue ); 883 | 884 | if ( HandleValue ) 885 | { 886 | auto Entry = FindHandleListEntry( HandleValue ); 887 | if ( Entry ) 888 | { 889 | ULONG Count = NULL; 890 | 891 | if ( AcquireThreadSync( Entry->Thread ) ) 892 | { 893 | if ( !Entry->Wow64 ) 894 | Status = PsSuspendThread( Entry->Thread, &Count ); 895 | 896 | if ( Buffer->Count ) 897 | *Buffer->Count = Count; 898 | } 899 | } 900 | else 901 | Status = STATUS_NOT_FOUND; 902 | } 903 | 904 | if ( !NT_SUCCESS( Status ) ) 905 | DBGPRINT( "%s %d : IOCTL_SUSPEND_THREAD returned 0x%X", __FUNCTION__, __LINE__, Status ); 906 | 907 | OutputLenght = sizeof( SUSPEND_THREAD_PROCESS ); 908 | } 909 | break; 910 | } 911 | 912 | case IOCTL_RESUME_THREAD: 913 | { 914 | const auto Buffer = PRESUME_THREAD_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 915 | if ( Buffer && InputLenght >= sizeof( RESUME_THREAD_PROCESS ) ) 916 | { 917 | auto HandleValue = HANDLE( Buffer->ThreadHandleValue ); 918 | 919 | if ( HandleValue ) 920 | { 921 | auto Entry = FindHandleListEntry( HandleValue ); 922 | if ( Entry ) 923 | { 924 | ULONG Count = NULL; 925 | 926 | if ( AcquireThreadSync( Entry->Thread ) ) 927 | { 928 | if ( !Entry->Wow64 ) 929 | Status = PsResumeThread( Entry->Thread, &Count ); 930 | 931 | if ( Buffer->Count ) 932 | *Buffer->Count = Count; 933 | } 934 | } 935 | else 936 | Status = STATUS_NOT_FOUND; 937 | } 938 | 939 | if ( !NT_SUCCESS( Status ) ) 940 | DBGPRINT( "%s %d : IOCTL_RESUME_THREAD returned 0x%X", __FUNCTION__, __LINE__, Status ); 941 | 942 | OutputLenght = sizeof( RESUME_THREAD_PROCESS ); 943 | } 944 | break; 945 | } 946 | 947 | case IOCTL_QUERY_THREAD_INFO: 948 | { 949 | const auto Buffer = PQUERYINFO_THREAD_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 950 | if ( Buffer && InputLenght >= sizeof( QUERYINFO_THREAD_PROCESS ) ) 951 | { 952 | auto HandleValue = HANDLE( Buffer->ThreadHandleValue ); 953 | 954 | if ( HandleValue ) 955 | { 956 | auto Entry = FindHandleListEntry( HandleValue ); 957 | if ( Entry ) 958 | { 959 | if ( AcquireThreadSync( Entry->Thread ) ) 960 | { 961 | PUCHAR tebBaseAddress = PUCHAR( PsGetThreadTeb( Entry->Thread ) ); 962 | 963 | if ( Entry->Wow64 ) 964 | tebBaseAddress += 0x2000; 965 | 966 | KeEnterGuardedRegion(); 967 | 968 | std::uint8_t info[ THREAD_INFO_SIZE ] = { 0 }; 969 | memcpy( info, PsGetCurrentThread(), THREAD_INFO_SIZE ); 970 | 971 | for ( ULONG i = 0; i < ARRAYSIZE( THREAD_INFO_SECTIONS ); i += 2 ) 972 | { 973 | ULONG start = THREAD_INFO_SECTIONS[ i ]; 974 | ULONG end = THREAD_INFO_SECTIONS[ i + 1 ]; 975 | memcpy( ( std::uint8_t* )PsGetCurrentThread() + start, ( std::uint8_t* )Entry->Thread + start, end - start ); 976 | } 977 | 978 | ULONG ResultLen = NULL; 979 | 980 | Status = ZwQueryInformationThread( 981 | NtCurrentThread(), 982 | THREADINFOCLASS( Buffer->InformationClass ), 983 | Buffer->ThreadInfo, 984 | Buffer->ThreadInfoLenght, 985 | &ResultLen 986 | ); 987 | 988 | if ( Buffer->ResultLenght ) 989 | *Buffer->ResultLenght = ResultLen; 990 | 991 | if ( 992 | NT_SUCCESS( Status ) && 993 | Buffer->InformationClass == ThreadBasicInformation && 994 | Buffer->ThreadInfo && 995 | Buffer->ThreadInfoLenght >= sizeof( PTHREAD_BASIC_INFORMATION ) ) 996 | { 997 | auto tbi = PTHREAD_BASIC_INFORMATION( Buffer->ThreadInfo ); 998 | tbi->TebBaseAddress = tebBaseAddress; 999 | 1000 | // DBGPRINT( "%s %d : IOCTL_QUERY_THREAD_INFO - Copy TEB = 0x%p 0x%p", __FUNCTION__, __LINE__, tbi->TebBaseAddress, tebBaseAddress ); 1001 | } 1002 | else 1003 | Status = STATUS_INVALID_PARAMETER; 1004 | 1005 | for ( ULONG i = 0; i < ARRAYSIZE( THREAD_INFO_SECTIONS ); i += 2 ) 1006 | { 1007 | ULONG start = THREAD_INFO_SECTIONS[ i ]; 1008 | ULONG end = THREAD_INFO_SECTIONS[ i + 1 ]; 1009 | ULONG len = end - start; 1010 | 1011 | memcpy( ( std::uint8_t* )Entry->Thread + start, ( std::uint8_t* )PsGetCurrentThread() + start, len ); 1012 | memcpy( ( std::uint8_t* )PsGetCurrentThread() + start, ( std::uint8_t* )info + start, len ); 1013 | } 1014 | 1015 | KeLeaveGuardedRegion(); 1016 | } 1017 | } 1018 | else 1019 | Status = STATUS_NOT_FOUND; 1020 | } 1021 | 1022 | if ( !NT_SUCCESS( Status ) ) 1023 | DBGPRINT( "%s %d : IOCTL_QUERY_THREAD_INFO returned 0x%X", __FUNCTION__, __LINE__, Status ); 1024 | 1025 | OutputLenght = sizeof( QUERYINFO_THREAD_PROCESS ); 1026 | } 1027 | break; 1028 | } 1029 | 1030 | case IOCTL_SET_THREAD_INFO: 1031 | { 1032 | const auto Buffer = PSETINFO_THREAD_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 1033 | if ( Buffer && InputLenght >= sizeof( SETINFO_THREAD_PROCESS ) ) 1034 | { 1035 | auto HandleValue = HANDLE( Buffer->ThreadHandleValue ); 1036 | 1037 | if ( HandleValue ) 1038 | { 1039 | auto Entry = FindHandleListEntry( HandleValue ); 1040 | if ( Entry ) 1041 | { 1042 | if ( AcquireThreadSync( Entry->Thread ) ) 1043 | { 1044 | KeEnterGuardedRegion(); 1045 | 1046 | switch ( Buffer->InformationClass ) 1047 | { 1048 | 1049 | case ThreadZeroTlsCell: 1050 | Status = STATUS_NOT_IMPLEMENTED; 1051 | break; 1052 | 1053 | case ThreadIdealProcessor: 1054 | { 1055 | if ( !Buffer->ThreadInfo ) 1056 | { 1057 | Status = STATUS_INVALID_PARAMETER; 1058 | break; 1059 | } 1060 | 1061 | if ( Buffer->ThreadInfoLenght != sizeof( ULONG ) ) 1062 | { 1063 | Status = STATUS_INFO_LENGTH_MISMATCH; 1064 | break; 1065 | } 1066 | 1067 | ULONG idealProcessor = 0; 1068 | RtlCopyMemory( PVOID( Buffer->ThreadInfo ), &idealProcessor, sizeof( idealProcessor ) ); 1069 | 1070 | Status = KeSetIdealProcessorThread( Entry->Thread, ( UCHAR )idealProcessor ); 1071 | break; 1072 | } 1073 | 1074 | default: 1075 | if ( NT_SUCCESS( Status = PsSuspendThread( Entry->Thread, 0 ) ) ) 1076 | { 1077 | std::uint8_t info[ THREAD_INFO_SIZE ] = { 0 }; 1078 | memcpy( info, PsGetCurrentThread(), THREAD_INFO_SIZE ); 1079 | 1080 | for ( ULONG i = 0; i < ARRAYSIZE( THREAD_INFO_SECTIONS ); i += 2 ) 1081 | { 1082 | ULONG start = THREAD_INFO_SECTIONS[ i ]; 1083 | ULONG end = THREAD_INFO_SECTIONS[ i + 1 ]; 1084 | memcpy( ( std::uint8_t* )PsGetCurrentThread() + start, ( std::uint8_t* )Entry->Thread + start, end - start ); 1085 | } 1086 | 1087 | Status = ZwSetInformationThread( 1088 | NtCurrentThread(), 1089 | THREADINFOCLASS( Buffer->InformationClass ), 1090 | Buffer->ThreadInfo, 1091 | Buffer->ThreadInfoLenght ); 1092 | 1093 | for ( ULONG i = 0; i < ARRAYSIZE( THREAD_INFO_SECTIONS ); i += 2 ) 1094 | { 1095 | ULONG start = THREAD_INFO_SECTIONS[ i ]; 1096 | ULONG end = THREAD_INFO_SECTIONS[ i + 1 ]; 1097 | ULONG len = end - start; 1098 | 1099 | memcpy( ( std::uint8_t* )Entry->Thread + start, ( std::uint8_t* )PsGetCurrentThread() + start, len ); 1100 | memcpy( ( std::uint8_t* )PsGetCurrentThread() + start, ( std::uint8_t* )info + start, len ); 1101 | } 1102 | 1103 | PsResumeThread( Entry->Thread, 0 ); 1104 | } 1105 | 1106 | break; 1107 | } 1108 | 1109 | KeLeaveGuardedRegion(); 1110 | } 1111 | } 1112 | else 1113 | Status = STATUS_NOT_FOUND; 1114 | } 1115 | 1116 | if ( !NT_SUCCESS( Status ) ) 1117 | DBGPRINT( "%s %d : IOCTL_SET_THREAD_INFO returned 0x%X", __FUNCTION__, __LINE__, Status ); 1118 | 1119 | OutputLenght = sizeof( SETINFO_THREAD_PROCESS ); 1120 | } 1121 | break; 1122 | } 1123 | 1124 | case IOCTL_WAIT_FOR_OBJECT: 1125 | { 1126 | const auto Buffer = PWAIT_OBJECT_PROCESS( Irp->AssociatedIrp.SystemBuffer ); 1127 | if ( Buffer && InputLenght >= sizeof( WAIT_OBJECT_PROCESS ) ) 1128 | { 1129 | auto HandleValue = HANDLE( Buffer->ObjectValue ); 1130 | 1131 | HANDLE hHandle{ }; 1132 | 1133 | if ( !CEPTOR_VALID_HANDLE( HandleValue ) ) 1134 | { 1135 | PEPROCESS Process = nullptr; 1136 | Status = PsLookupProcessByProcessId( HandleValue, &Process ); 1137 | if ( !NT_SUCCESS( Status ) ) 1138 | { 1139 | PETHREAD Thread = nullptr; 1140 | Status = PsLookupThreadByThreadId( HandleValue, &Thread ); 1141 | if ( NT_SUCCESS( Status ) ) 1142 | { 1143 | Status = ObOpenObjectByPointer( Thread, 0, 0, SYNCHRONIZE, *PsThreadType, KernelMode, &hHandle ); 1144 | ObDereferenceObject( Thread ); 1145 | } 1146 | } 1147 | else 1148 | { 1149 | Status = ObOpenObjectByPointer( Process, 0, 0, SYNCHRONIZE, *PsProcessType, KernelMode, &hHandle ); 1150 | ObDereferenceObject( Process ); 1151 | } 1152 | // DBGPRINT( "%s %d : IOCTL_WAIT_FOR_OBJECT - NON Ceptor handle returned 0x%X", __FUNCTION__, __LINE__, Status ); 1153 | } 1154 | else 1155 | { 1156 | auto Entry = FindHandleListEntry( HandleValue ); 1157 | if ( Entry ) 1158 | { 1159 | if ( Entry->Thread ) 1160 | { 1161 | if ( AcquireThreadSync( Entry->Thread ) ) 1162 | { 1163 | Status = ObOpenObjectByPointer( Entry->Thread, 0, 0, SYNCHRONIZE, *PsThreadType, KernelMode, &hHandle ); 1164 | } 1165 | } 1166 | else if ( Entry->Process ) 1167 | { 1168 | if ( AcquireProcessSync( Entry->Process ) ) 1169 | { 1170 | Status = ObOpenObjectByPointer( Entry->Process, 0, 0, SYNCHRONIZE, *PsProcessType, KernelMode, &hHandle ); 1171 | ReleaseProcessSync( Entry->Process ); 1172 | } 1173 | } 1174 | // DBGPRINT( "%s %d : IOCTL_WAIT_FOR_OBJECT - Ceptor found and returned 0x%X", __FUNCTION__, __LINE__, Status ); 1175 | } 1176 | //else 1177 | // DBGPRINT( "%s %d : IOCTL_WAIT_FOR_OBJECT Handle: 0x%p not found.", __FUNCTION__, __LINE__, HandleValue ); 1178 | } 1179 | 1180 | if ( NT_SUCCESS( Status ) ) 1181 | { 1182 | Status = ZwWaitForSingleObject( hHandle, Buffer->Alertable, Buffer->Timeout ); 1183 | ZwClose( hHandle ); 1184 | } 1185 | 1186 | if ( !NT_SUCCESS( Status ) ) 1187 | DBGPRINT( "%s %d : IOCTL_WAIT_FOR_OBJECT returned 0x%X", __FUNCTION__, __LINE__, Status ); 1188 | 1189 | OutputLenght = sizeof( WAIT_OBJECT_PROCESS ); 1190 | } 1191 | break; 1192 | } 1193 | 1194 | } 1195 | 1196 | if ( Status != 1337 ) 1197 | { 1198 | Irp->IoStatus.Status = Status; 1199 | Irp->IoStatus.Information = OutputLenght; 1200 | IoCompleteRequest( Irp, IO_NO_INCREMENT ); 1201 | //DBGPRINT( "%s %d : Completed request status 0x%X - SystemBuffer: 0x%p", __FUNCTION__, __LINE__, Status, Irp->AssociatedIrp.SystemBuffer ); 1202 | return Status; 1203 | } 1204 | //else if ( Status == 1337 ) 1205 | // DBGPRINT( "%s %d : Something was invalid, return len: %d", __FUNCTION__, __LINE__, OutputLenght ); 1206 | 1207 | return g_originalDispatcher( DeviceObject, Irp ); 1208 | } 1209 | 1210 | NTSTATUS IoCompletedReq( PDEVICE_OBJECT DeviceObject, PIRP irp ) 1211 | { 1212 | UNREFERENCED_PARAMETER( DeviceObject ); 1213 | 1214 | irp->IoStatus.Status = STATUS_SUCCESS; 1215 | irp->IoStatus.Information = 0; 1216 | 1217 | IoCompleteRequest( irp, IO_NO_INCREMENT ); 1218 | return STATUS_SUCCESS; 1219 | } 1220 | 1221 | void HijackDispatcher() 1222 | { 1223 | UNICODE_STRING driver_name = RTL_CONSTANT_STRING( L"\\Driver\\klhk" ); 1224 | 1225 | auto status = ObReferenceObjectByName( 1226 | &driver_name, 1227 | OBJ_CASE_INSENSITIVE, 1228 | nullptr, 1229 | 0, 1230 | *IoDriverObjectType, 1231 | KernelMode, 1232 | nullptr, 1233 | ( PVOID* )&g_driverObject 1234 | ); 1235 | 1236 | if ( !g_driverObject || !NT_SUCCESS( status ) ) 1237 | { 1238 | DBGPRINT( "%s %d : ObReferenceObjectByName returned 0x%08X driver_object: 0x%016X", __FUNCTION__, __LINE__, status, g_driverObject ); 1239 | return; 1240 | } 1241 | 1242 | //g_driverObject->DeviceObject->Flags |= DO_BUFFERED_IO; 1243 | g_originalDispatcher = g_driverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ]; 1244 | InterlockedExchangePointer( ( volatile PVOID* )&g_driverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ], &IoControl ); 1245 | 1246 | DBGPRINT( "Swapped dispatcher from 0x%llX to 0x%llX", g_originalDispatcher, g_driverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ] ); 1247 | } 1248 | 1249 | void DriverUnload( PDRIVER_OBJECT DriverObject ) 1250 | { 1251 | UNREFERENCED_PARAMETER( DriverObject ); 1252 | 1253 | if ( g_originalDispatcher && g_driverObject ) 1254 | { 1255 | DBGPRINT( "Restored dispatcher from 0x%llX to 0x%llX", g_driverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ], g_originalDispatcher ); 1256 | 1257 | InterlockedExchangePointer( ( volatile PVOID* )&g_driverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ], g_originalDispatcher ); 1258 | ObDereferenceObject( g_driverObject ); 1259 | } 1260 | } 1261 | 1262 | extern "C" NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) 1263 | { 1264 | UNREFERENCED_PARAMETER( RegistryPath ); 1265 | 1266 | KeInitializeSpinLock( &__HANDLES_LOCK ); 1267 | __HANDLES_LIST_HEAD = InitializeHandleList(); 1268 | 1269 | *( PVOID* )&PsResumeThread = resolve_call( FindPattern( "ntoskrnl.exe", "PAGE", PUCHAR( "\xE8\x00\x00\x00\x00\xBA\x00\x00\x00\x00\x48\x8B\x4C\x24\x00\xE8\x00\x00\x00\x00\x90\x48\x85\xDB" ), "x????x????xxxx?x????xxxx" ) ); 1270 | *( PVOID* )&PsSuspendThread = resolve_call( FindPattern( "ntoskrnl.exe", "PAGE", PUCHAR( "\xE8\x00\x00\x00\x00\x48\x8B\xD7\x48\x8B\xCE\xE8\x00\x00\x00\x00\x48\x8B\xF8" ), "x????xxxxxxx????xxx" ) ); 1271 | 1272 | auto sig = FindPattern( "ntoskrnl.exe", "PAGE", PUCHAR( "\x8A\x88\x00\x00\x00\x00\xE8\x00\x00\x00\x00\xF6\xD8" ), "xx????x????xx" ); 1273 | if ( sig ) 1274 | { 1275 | while ( *sig != 0xE8 ) 1276 | ++sig; 1277 | 1278 | *( PVOID* )&KeTestAlertThread = resolve_call( sig ); 1279 | } 1280 | 1281 | DriverObject->DriverUnload = DriverUnload; 1282 | HijackDispatcher(); 1283 | 1284 | return STATUS_SUCCESS; 1285 | } --------------------------------------------------------------------------------