├── src ├── app │ ├── utils │ │ ├── cmnDriver.cpp │ │ ├── cmnUtils.h │ │ ├── ReadMe.txt │ │ ├── cmnGuards.h │ │ ├── cmnErrors.h │ │ ├── utils.vcproj │ │ └── cmnDriver.h │ └── unhooker │ │ ├── main.cpp │ │ └── unhooker.vcproj ├── driver │ ├── drvMain │ │ ├── Makefile │ │ ├── drvUnhookerDevice.h │ │ ├── Sources │ │ ├── drvMain.cpp │ │ ├── drvCommonPortableDefs.h │ │ ├── drvMain.vcproj │ │ └── drvUnhookerDevice.cpp │ └── drvUtils │ │ ├── Makefile │ │ ├── drvCpp.cpp │ │ ├── drvUtils.h │ │ ├── Sources │ │ ├── drvFiles.h │ │ ├── drvCpp.h │ │ ├── drvSmart.h │ │ ├── pe_utils.h │ │ ├── drvSyncQueue.cpp │ │ ├── drvVirginity2.h │ │ ├── drvExtensions.h │ │ ├── drvVirginity.h │ │ ├── drvSync.h │ │ ├── drvUtils.vcproj │ │ ├── drvSyncQueue.h │ │ ├── drvFiles.cpp │ │ ├── pe_utils.c │ │ ├── ntddk_module.h │ │ ├── drvVirginity.cpp │ │ ├── drv_NtDefinitions.h │ │ └── drvVirginity2.cpp ├── ddk_build.bat └── UnhookerMain.sln ├── readme.md └── license.txt /src/app/utils/cmnDriver.cpp: -------------------------------------------------------------------------------- 1 | #include "cmnDriver.h" 2 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/antirootkit-anti-splicer/HEAD/readme.md -------------------------------------------------------------------------------- /src/driver/drvMain/Makefile: -------------------------------------------------------------------------------- 1 | # Do not edit this file. 2 | !include $(NTMAKEENV)\makefile.def 3 | 4 | -------------------------------------------------------------------------------- /src/driver/drvUtils/Makefile: -------------------------------------------------------------------------------- 1 | # Do not edit this file. 2 | !include $(NTMAKEENV)\makefile.def 3 | 4 | -------------------------------------------------------------------------------- /src/driver/drvUtils/drvCpp.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/antirootkit-anti-splicer/HEAD/src/driver/drvUtils/drvCpp.cpp -------------------------------------------------------------------------------- /src/app/utils/cmnUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef CMN_UTILS_H 2 | #define CMN_UTILS_H 3 | 4 | #include "iostream" 5 | #include "cmnDriver.h" 6 | 7 | #endif -------------------------------------------------------------------------------- /src/driver/drvUtils/drvUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef DRV_UTILS_H 2 | #define DRV_UTILS_H 3 | 4 | extern "C" 5 | { 6 | #include "ntddk.h" 7 | } 8 | 9 | #include "drvExtensions.h" 10 | #include "drvCpp.h" 11 | #include "drvSmart.h" 12 | 13 | #endif -------------------------------------------------------------------------------- /src/driver/drvMain/drvUnhookerDevice.h: -------------------------------------------------------------------------------- 1 | #ifndef DRV_UNHOOKER_DEVICE_H 2 | #define DRV_UNHOOKER_DEVICE_H 3 | 4 | #include "drvUtils.h" 5 | 6 | namespace drv 7 | { 8 | 9 | NTSTATUS CreateUnhookerDevice(IN PDRIVER_OBJECT pDriverObject, 10 | OUT drv::CDeviceOwner & deviceObject); 11 | 12 | } 13 | #endif -------------------------------------------------------------------------------- /src/driver/drvUtils/Sources: -------------------------------------------------------------------------------- 1 | TARGETNAME=drvUtils 2 | TARGETPATH=..\..\..\lib\$(PROJECT_CONFIGURATION_NAME) 3 | TARGETTYPE=DRIVER_LIBRARY 4 | DRIVERTYPE=FS 5 | 6 | MSC_WARNING_LEVEL = /W1 7 | 8 | INCLUDES= 9 | 10 | SOURCES=\ 11 | drvCpp.cpp \ 12 | drvFiles.cpp \ 13 | drvSyncQueue.cpp \ 14 | drvVirginity.cpp \ 15 | pe_utils.c \ 16 | drvVirginity2.cpp -------------------------------------------------------------------------------- /src/driver/drvUtils/drvFiles.h: -------------------------------------------------------------------------------- 1 | #ifndef DRV_FILES_H 2 | #define DRV_FILES_H 3 | 4 | extern "C" 5 | { 6 | #include "ntddk.h" 7 | } 8 | 9 | typedef struct _drv_MappedFile 10 | { 11 | PVOID section; 12 | PCHAR pData; 13 | LARGE_INTEGER fileSize; 14 | }drv_MappedFile; 15 | 16 | NTSTATUS drv_MapAllFile(HANDLE hFile, drv_MappedFile * pMappedFile); 17 | void drv_UnMapFile(drv_MappedFile * pMappedFile); 18 | 19 | #endif -------------------------------------------------------------------------------- /src/driver/drvMain/Sources: -------------------------------------------------------------------------------- 1 | TARGETNAME=drvUnhooker 2 | TARGETPATH=..\..\..\bin\$(PROJECT_CONFIGURATION_NAME) 3 | TARGETTYPE=DRIVER 4 | DRIVERTYPE=FS 5 | 6 | MSC_WARNING_LEVEL = /W1 7 | 8 | INCLUDES=..\drvUtils; 9 | 10 | TARGETLIBS= $(BASEDIR)\lib\w2k\i386\ntoskrnl.lib \ 11 | $(BASEDIR)\lib\w2k\i386\hal.lib \ 12 | $(BASEDIR)\lib\w2k\i386\ntstrsafe.lib \ 13 | $(BASEDIR)\lib\w2k\i386\ndis.lib \ 14 | $(BASEDIR)\lib\w2k\i386\tdi.lib \ 15 | ..\..\..\lib\$(PROJECT_CONFIGURATION_NAME)\*\drvUtils.lib \ 16 | 17 | SOURCES = \ 18 | drvMain.cpp \ 19 | drvUnhookerDevice.cpp -------------------------------------------------------------------------------- /src/ddk_build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set comspec=%windir%\System32\cmd.exe 3 | 4 | rem check DDK path 5 | if not "%1" == "" goto SET_BASE_DDK_PATH 6 | echo specify base DDKPath (param 1) 7 | goto ERROR 8 | 9 | :SET_BASE_DDK_PATH 10 | SET BASE_DDK_PATH=%1 11 | 12 | if not "%2" == "" goto SET_PROJECT_DIR 13 | echo specify project directory (param 2) 14 | goto ERROR 15 | 16 | :SET_PROJECT_DIR 17 | SET PROJECT_DIR=%3 18 | 19 | if not "%3" == "" goto SET_DDK_CONF_TYPE 20 | echo specify configuration name 21 | goto ERROR 22 | 23 | :SET_DDK_CONF_TYPE 24 | SET PROJECT_CONFIGURATION_NAME=%2 25 | 26 | if "%2" == "Debug" SET DDK_CONF_TYPE=chk 27 | if "%2" == "Release" SET DDK_CONF_TYPE=free 28 | 29 | if "%DDK_CONF_TYPE%" == "" goto ERROR 30 | 31 | 32 | call %BASE_DDK_PATH%\bin\setenv.bat %BASE_DDK_PATH% %DDK_CONF_TYPE% WXP 33 | 34 | SET BUILD_ALLOW_LINKER_WARNINGS=1 35 | cd /d %PROJECT_DIR% 36 | build.exe -I /cE 37 | goto :EOF 38 | :ERROR 39 | echo FATAL ERROR ! -------------------------------------------------------------------------------- /src/app/utils/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | STATIC LIBRARY : utils Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this utils library project for you. 6 | No source files were created as part of your project. 7 | 8 | 9 | utils.vcproj 10 | This is the main project file for VC++ projects generated using an Application Wizard. 11 | It contains information about the version of Visual C++ that generated the file, and 12 | information about the platforms, configurations, and project features selected with the 13 | Application Wizard. 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | Other notes: 17 | 18 | AppWizard uses "TODO:" comments to indicate parts of the source code you 19 | should add to or customize. 20 | 21 | ///////////////////////////////////////////////////////////////////////////// 22 | -------------------------------------------------------------------------------- /src/driver/drvMain/drvMain.cpp: -------------------------------------------------------------------------------- 1 | #include "drvUtils.h" 2 | #include "drvUnhookerDevice.h" 3 | 4 | static 5 | NTSTATUS RootDispatch( 6 | IN PDEVICE_OBJECT DeviceObject, 7 | IN PIRP Irp 8 | ) 9 | { 10 | return drv::RootDispatch(DeviceObject, Irp); 11 | } 12 | 13 | 14 | // DriverEntry 15 | extern "C" 16 | NTSTATUS 17 | DriverEntry(IN PDRIVER_OBJECT pDriverObject, 18 | IN PUNICODE_STRING RegistryPath 19 | ) 20 | { 21 | drv::CLibCpp libCpp; 22 | 23 | 24 | for (int i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) 25 | { 26 | pDriverObject->MajorFunction[i] = RootDispatch; 27 | } 28 | 29 | drv::CDeviceOwner deviceObject; 30 | NT_CHECK(drv::CreateUnhookerDevice(pDriverObject, deviceObject)); 31 | 32 | 33 | pDriverObject->DriverUnload = 0; 34 | pDriverObject->FastIoDispatch = NULL; 35 | 36 | deviceObject.release(); 37 | libCpp.release(); 38 | return STATUS_SUCCESS; 39 | } 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/driver/drvUtils/drvCpp.h: -------------------------------------------------------------------------------- 1 | #ifndef DRV_CPP_H 2 | #define DRV_CPP_H 3 | 4 | extern "C" 5 | { 6 | #include "ntddk.h" 7 | } 8 | 9 | void* __cdecl operator new (size_t size, void *ptr); 10 | void* __cdecl operator new[] (size_t size, void *ptr); 11 | void __cdecl operator delete (void *ptr, void *); 12 | void __cdecl operator delete[] (void *ptr, void *); 13 | 14 | NTSTATUS __cdecl libcpp_init(); 15 | void __cdecl libcpp_exit(); 16 | 17 | #define NT_CHECK(x) {if (!(NT_SUCCESS((x)))) return x;} 18 | #define NT_CHECK_ALLOC(p) {if (!p) return STATUS_NO_MEMORY;} 19 | #define NT_OK STATUS_SUCCESS 20 | 21 | namespace drv 22 | { 23 | 24 | class CLibCpp 25 | { 26 | bool m_inited; 27 | public: 28 | CLibCpp() 29 | : m_inited(false) 30 | { 31 | } 32 | NTSTATUS Init() 33 | { 34 | return libcpp_init(); 35 | } 36 | void release() 37 | { 38 | m_inited = false; 39 | } 40 | ~CLibCpp() 41 | { 42 | if (m_inited) 43 | { 44 | libcpp_exit(); 45 | } 46 | } 47 | }; 48 | 49 | } // drv 50 | #endif -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2017 Apriorit 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/driver/drvUtils/drvSmart.h: -------------------------------------------------------------------------------- 1 | #ifndef DRV_SMART_H 2 | #define DRV_SMART_H 3 | 4 | #include "drvExtensions.h" 5 | 6 | namespace drv 7 | { 8 | 9 | class CDeviceOwner 10 | { 11 | _DEVICE_OBJECT * m_pDevice; 12 | public: 13 | CDeviceOwner(_DEVICE_OBJECT * pDevice=0) 14 | : m_pDevice(pDevice) 15 | { 16 | } 17 | CDeviceOwner(CDeviceOwner & owner) 18 | : m_pDevice(0) 19 | { 20 | reset(owner.release()); 21 | } 22 | CDeviceOwner & operator = (CDeviceOwner & owner) 23 | { 24 | reset(owner.release()); 25 | return *this; 26 | } 27 | ~CDeviceOwner() 28 | { 29 | reset(0); 30 | } 31 | _DEVICE_OBJECT * get() 32 | { 33 | return m_pDevice; 34 | } 35 | _DEVICE_OBJECT * operator ->() 36 | { 37 | return m_pDevice; 38 | } 39 | _DEVICE_OBJECT * release() 40 | { 41 | _DEVICE_OBJECT * pOldDevice = m_pDevice; 42 | m_pDevice = 0; 43 | return pOldDevice; 44 | } 45 | void reset(_DEVICE_OBJECT * pDevice) 46 | { 47 | _DEVICE_OBJECT * pOldDevice = m_pDevice; 48 | m_pDevice = pDevice; 49 | if (pOldDevice) 50 | { 51 | CommonDeviceExtension * pDevExt = (CommonDeviceExtension*)pOldDevice->DeviceExtension; 52 | pDevExt->m_cleanProc(pDevExt); 53 | IoDeleteDevice(pOldDevice); 54 | } 55 | } 56 | _DEVICE_OBJECT ** GetPtr2() 57 | { 58 | return &m_pDevice; 59 | } 60 | }; 61 | 62 | 63 | } // drv 64 | #endif -------------------------------------------------------------------------------- /src/app/utils/cmnGuards.h: -------------------------------------------------------------------------------- 1 | #ifndef CMN_GUARDS_H 2 | #define CMN_GUARDS_H 3 | 4 | #include "windows.h" 5 | #include "winsvc.h" 6 | namespace cmn 7 | { 8 | template 9 | class CBaseGuard 10 | { 11 | typename ImplType::TypeName m_handle; 12 | 13 | CBaseGuard(const CBaseGuard&); 14 | CBaseGuard& operator=(const CBaseGuard&); 15 | public: 16 | explicit CBaseGuard(typename ImplType::TypeName handle=0) 17 | :m_handle(handle) 18 | { 19 | } 20 | ~CBaseGuard() 21 | { 22 | if(m_handle) 23 | ImplType::Close(m_handle); 24 | } 25 | typename ImplType::TypeName get() const 26 | { 27 | return m_handle; 28 | } 29 | typename ImplType::TypeName release() 30 | { 31 | typename ImplType::TypeName tmp = m_handle; 32 | m_handle = 0; 33 | return tmp; 34 | } 35 | void reset(typename ImplType::TypeName handle) 36 | { 37 | if(m_handle) 38 | ImplType::Close(m_handle); 39 | m_handle = handle; 40 | } 41 | }; 42 | 43 | // HandleGuard 44 | struct HandleImpl 45 | { 46 | typedef HANDLE TypeName; 47 | static void Close(HANDLE h) 48 | { 49 | CloseHandle(h); 50 | } 51 | }; 52 | typedef CBaseGuard HandleGuard; 53 | 54 | // SCHandleGuard 55 | struct SCHandleImpl 56 | { 57 | typedef SC_HANDLE TypeName; 58 | static void Close(SC_HANDLE h) 59 | { 60 | CloseServiceHandle(h); 61 | } 62 | }; 63 | typedef CBaseGuard SCHandleGuard; 64 | 65 | 66 | } // cmn 67 | #endif 68 | 69 | -------------------------------------------------------------------------------- /src/driver/drvUtils/pe_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef PE_UTILS_H 2 | #define PE_UTILS_H 3 | 4 | #include 5 | #include 6 | #include "drv_ntdefinitions.h" 7 | 8 | typedef struct _DrvFindSectionInfo 9 | { 10 | char * m_pModuleAddress; 11 | int m_currentNumber; 12 | int m_numberOfSections; 13 | PIMAGE_SECTION_HEADER m_currentSection; 14 | char * m_sectionStart; 15 | char * m_sectionEnd; 16 | }DrvFindSectionInfo; 17 | 18 | 19 | NTSTATUS drv_FindFirstSection(char * pModule, 20 | DrvFindSectionInfo * pSectionInfo); 21 | 22 | NTSTATUS drv_FindNextSection(DrvFindSectionInfo * pSectionInfo, 23 | int * pbDone); 24 | 25 | 26 | 27 | typedef NTSTATUS (__stdcall *drv_SectionHandlerType)(PIMAGE_SECTION_HEADER pSection, 28 | void * pContext, 29 | int * bContinueSearch); // out 30 | 31 | 32 | NTSTATUS drv_EnumSections(char * pModule, 33 | drv_SectionHandlerType pSectionHandler, 34 | void * pContext); 35 | NTSTATUS Drv_ResolveSectionAddress(PVOID pModuleAddress, PVOID pAddress, IMAGE_SECTION_HEADER ** ppSection); 36 | 37 | NTSTATUS Drv_FindSection(PVOID pModuleAddress, 38 | UCHAR Name[IMAGE_SIZEOF_SHORT_NAME], 39 | IMAGE_SECTION_HEADER ** ppSection); 40 | 41 | NTSTATUS 42 | Drv_GetProcAddrEx(PVOID DllBase, 43 | PCHAR FunctionName, 44 | ULONG lMaxSize, 45 | PIMAGE_EXPORT_DIRECTORY ExportDirectory, 46 | PUSHORT NameOrdinalTableBase, 47 | ULONG ExportSize, 48 | USHORT * OrdinalNumber); 49 | #endif -------------------------------------------------------------------------------- /src/driver/drvUtils/drvSyncQueue.cpp: -------------------------------------------------------------------------------- 1 | #include "drvSyncQueue.h" 2 | 3 | namespace drv 4 | { 5 | 6 | CSyncQueue::CSyncQueue() 7 | : m_destroyed(0) 8 | { 9 | } 10 | 11 | CSyncQueue::~CSyncQueue() 12 | { 13 | DestroyNoLock(); 14 | } 15 | 16 | void CSyncQueue::Destroy() 17 | { 18 | CAutoTask taskGuard; 19 | DestroyNoLock(); 20 | } 21 | 22 | void CSyncQueue::DestroyNoLock() 23 | { 24 | CAutoTask taskGuard; 25 | 26 | if (InterlockedIncrement(&m_destroyed) != 1) 27 | return; 28 | 29 | PLIST_ENTRY listEntry; 30 | for ( listEntry = m_list.Flink; 31 | listEntry != &m_list; 32 | listEntry = listEntry->Flink ) 33 | { 34 | CCommonTask * pTask = CONTAINING_RECORD(listEntry, CCommonTask, m_entry); 35 | taskGuard.reset(pTask); 36 | } 37 | } 38 | 39 | NTSTATUS CSyncQueue::Init() 40 | { 41 | InitializeListHead( &m_list ); 42 | NT_CHECK(m_lock.Init()); 43 | return NT_OK; 44 | } 45 | 46 | NTSTATUS CSyncQueue::PushBack(CAutoTask & task) 47 | { 48 | drv::AutoFastMutex guard(m_lock); 49 | if (m_destroyed) 50 | return STATUS_LOCAL_DISCONNECT; 51 | 52 | InsertTailList(&m_list, &task->m_entry); 53 | task.release(); 54 | return NT_OK; 55 | } 56 | 57 | NTSTATUS CSyncQueue::PopFirst(CAutoTask & task, 58 | bool * pEmpty) 59 | { 60 | pEmpty = false; 61 | drv::AutoFastMutex guard(m_lock); 62 | 63 | if (m_destroyed) 64 | return STATUS_LOCAL_DISCONNECT; 65 | 66 | if (IsListEmpty(&m_list)) 67 | { 68 | *pEmpty = true; 69 | return NT_OK; 70 | } 71 | 72 | CCommonTask * pTask = CONTAINING_RECORD(m_list.Flink, CCommonTask, m_entry); 73 | task.reset(pTask); 74 | RemoveEntryList( &pTask->m_entry ); 75 | return NT_OK; 76 | } 77 | 78 | 79 | 80 | } -------------------------------------------------------------------------------- /src/driver/drvMain/drvCommonPortableDefs.h: -------------------------------------------------------------------------------- 1 | #ifndef DRV_COMMON_PORTABLE_DEFS_H 2 | #define DRV_COMMON_PORTABLE_DEFS_H 3 | 4 | 5 | // drvUnhookerDevice 6 | #define DRV_UNHOOKER_DEVICE_TYPE 0x8100 7 | 8 | #define DRV_UNHOOKER_UNHOOK CTL_CODE( \ 9 | DRV_UNHOOKER_DEVICE_TYPE,0x08000, METHOD_BUFFERED, FILE_ANY_ACCESS) 10 | 11 | #define DRV_UNHOOKER_GET_STATUS CTL_CODE( \ 12 | DRV_UNHOOKER_DEVICE_TYPE,0x08001, METHOD_BUFFERED, FILE_ANY_ACCESS) 13 | 14 | #define DRV_UNHOOKER_DEVICE_NAME L"\\Device\\drvUnhooker" 15 | #define DRV_UNHOOKER_DEVICE_SYMBOLIC_LINK L"\\??\\drvUnhooker" 16 | #define DRV_UNHOOKER_USERMODE_SYMBOLIC_LINK L"\\\\.\\drvUnhooker" 17 | 18 | #define SERVICE_NAME L"drvUnhooker" 19 | #define DRIVER_FILENAME L"drvUnhooker.sys" 20 | 21 | #pragma pack(push, 1) 22 | 23 | typedef enum { dreInvalid, dreSST, dreModification} DrvReportEntry_type; 24 | 25 | typedef struct _DRV_REPORT 26 | { 27 | __int32 m_countOfModifiedSSTEntries; 28 | __int32 m_countOfReportEntries; 29 | __int32 m_countOfModifiedImageEntries; 30 | __int32 m_reportEntryOffsets; 31 | }DRV_REPORT; 32 | 33 | typedef struct _DRV_REPORT_ENTRY 34 | { 35 | __int32 m_sizeOfEntry; 36 | DrvReportEntry_type m_type; 37 | }DRV_REPORT_ENTRY; 38 | 39 | typedef struct _DRV_REPORT_SST_ENTRY 40 | { 41 | DRV_REPORT_ENTRY m_base; 42 | unsigned __int64 m_moduleAddress; 43 | unsigned __int64 m_newAddress; 44 | __int32 m_nameOffset; 45 | __int32 m_nameSize; 46 | __int32 m_sstIndex; 47 | }DRV_REPORT_SST_ENTRY; 48 | 49 | typedef struct _DRV_REPORT_MODIFICATION_ENTRY 50 | { 51 | DRV_REPORT_ENTRY m_base; 52 | unsigned __int64 m_offsetInSection; 53 | __int32 m_sizeOfModification; 54 | unsigned __int64 m_address; 55 | char m_sectionName[12]; 56 | }DRV_REPORT_MODIFICATION_ENTRY; 57 | 58 | #pragma pack(pop) 59 | 60 | #endif -------------------------------------------------------------------------------- /src/driver/drvUtils/drvVirginity2.h: -------------------------------------------------------------------------------- 1 | #ifndef DRV_VIRGINITY2_H 2 | #define DRV_VIRGINITY2_H 3 | 4 | #include "drvVirginity.h" 5 | 6 | extern "C" 7 | { 8 | #include "pe_utils.h" 9 | } 10 | 11 | #define DRV_SECTIONS_COUNT 2 12 | 13 | typedef struct _Drv_VirginityContext2 14 | { 15 | Drv_VirginityContext m_parent; 16 | 17 | Drv_Resolver m_resolver; 18 | 19 | DrvFindSectionInfo m_currentSectionInfo; 20 | 21 | int m_startOfModification; 22 | int m_endOfModification; 23 | PIMAGE_SECTION_HEADER m_pMappedSection; 24 | 25 | STRING m_sectionsToCheck[DRV_SECTIONS_COUNT]; 26 | }Drv_VirginityContext2; 27 | 28 | 29 | NTSTATUS Drv_InitVirginityContext2(Drv_VirginityContext2 * pContext); 30 | void Drv_FreeVirginityContext2(Drv_VirginityContext2 * pContext); 31 | 32 | NTSTATUS Drv_GetFirstModification(Drv_VirginityContext2 * pContext, 33 | void ** ppStart, 34 | int * pSize); 35 | NTSTATUS Drv_GetNextModification(Drv_VirginityContext2 * pContext, 36 | void ** ppStart, 37 | int * pSize); 38 | 39 | const char * Drv_GetMappedSectionStart(const Drv_VirginityContext2 * pContext); 40 | 41 | void Drv_GetRealSSTValue2(Drv_VirginityContext2 * pContext, long index, void ** ppValue); 42 | 43 | class CAutoVirginity2 44 | { 45 | Drv_VirginityContext2 * m_pContext; 46 | 47 | CAutoVirginity2(const CAutoVirginity2&); 48 | CAutoVirginity2&operator = (const CAutoVirginity2&); 49 | public: 50 | CAutoVirginity2() 51 | : m_pContext(0) 52 | { 53 | } 54 | NTSTATUS Init(Drv_VirginityContext2 * pContext) 55 | { 56 | NT_CHECK(Drv_InitVirginityContext2(pContext)); 57 | m_pContext = pContext; 58 | return NT_OK; 59 | } 60 | ~CAutoVirginity2() 61 | { 62 | if (m_pContext) 63 | Drv_FreeVirginityContext2(m_pContext); 64 | } 65 | }; 66 | 67 | 68 | #endif -------------------------------------------------------------------------------- /src/app/utils/cmnErrors.h: -------------------------------------------------------------------------------- 1 | #ifndef CMN_ERRORS_H 2 | #define CMN_ERRORS_H 3 | 4 | #include "windows.h" 5 | #include "string" 6 | #include "vector" 7 | #include "exception" 8 | 9 | namespace cmn 10 | { 11 | class CWinException:public std::runtime_error 12 | { 13 | DWORD m_dwErrorCode; 14 | public: 15 | CWinException(const std::string & str, DWORD dwErrorCode) 16 | : std::runtime_error(str), m_dwErrorCode(dwErrorCode) 17 | { 18 | } 19 | 20 | DWORD GetErrorCode() const 21 | { 22 | return m_dwErrorCode; 23 | } 24 | }; 25 | 26 | inline std::wstring GetErrorText(DWORD dwError, DWORD dwLangId= MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)) 27 | { 28 | HLOCAL hlocal = NULL; // Buffer that gets the error message string 29 | 30 | // Get the error code's textual description 31 | BOOL fOk = FormatMessageW( 32 | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, 33 | NULL, dwError, dwLangId, 34 | (LPWSTR) &hlocal, 0, NULL); 35 | 36 | if (!fOk) { 37 | // Is it a network-related error? 38 | HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, 39 | DONT_RESOLVE_DLL_REFERENCES); 40 | 41 | if (hDll != NULL) { 42 | FormatMessageW( 43 | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM, 44 | hDll, dwError, dwLangId, 45 | (LPWSTR) &hlocal, 0, NULL); 46 | FreeLibrary(hDll); 47 | } 48 | } 49 | 50 | if (hlocal != NULL) 51 | { 52 | std::wstring sErr= (const wchar_t*) LocalLock(hlocal); 53 | LocalFree(hlocal); 54 | return sErr; 55 | } 56 | else 57 | { 58 | return L"Unknown error"; 59 | } 60 | } 61 | 62 | 63 | #define CMN_THROW_WIN32(X) { DWORD dwLastError = GetLastError(); throw cmn::CWinException(X, dwLastError); } 64 | } 65 | #endif -------------------------------------------------------------------------------- /src/driver/drvMain/drvMain.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 10 | 11 | 12 | 17 | 21 | 22 | 27 | 31 | 32 | 33 | 34 | 35 | 36 | 39 | 41 | 42 | 44 | 45 | 46 | 49 | 51 | 52 | 54 | 55 | 56 | 59 | 60 | 62 | 63 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /src/driver/drvUtils/drvExtensions.h: -------------------------------------------------------------------------------- 1 | #ifndef DRV_EXTENSIONS_H 2 | #define DRV_EXTENSIONS_H 3 | 4 | extern "C" 5 | { 6 | #include "ntddk.h" 7 | } 8 | 9 | namespace drv 10 | { 11 | 12 | 13 | inline NTSTATUS CompleteIrp(IRP * pIrp, NTSTATUS status = STATUS_SUCCESS, ULONG outSize = 0) 14 | { 15 | pIrp->IoStatus.Status = status; 16 | pIrp->IoStatus.Information = outSize; 17 | IoCompleteRequest( pIrp, IO_NO_INCREMENT ); 18 | return status; 19 | } 20 | 21 | 22 | struct CommonDeviceExtension; 23 | typedef NTSTATUS (*DeviceDispatchProc)( 24 | IN PDEVICE_OBJECT DeviceObject, 25 | IN PIRP Irp, 26 | CommonDeviceExtension * pExtension 27 | ); 28 | typedef void (*CleanProc)(CommonDeviceExtension * pExtension); 29 | 30 | struct CommonDeviceExtension 31 | { 32 | DeviceDispatchProc m_deviceDispatchFnc; 33 | CleanProc m_cleanProc; 34 | }; 35 | 36 | template 37 | struct TypeComparer 38 | { 39 | typedef void * Result_type; 40 | }; 41 | template 42 | struct TypeComparer 47 | { 48 | typedef ArgType * Result_type; 49 | }; 50 | 51 | struct TwoChars{ char buf[2]; }; 52 | static char TestFunction(...); 53 | static TwoChars TestFunction(CommonDeviceExtension * pExtension); 54 | 55 | 56 | template 57 | inline typename TypeComparer::Result_type 58 | InitCommonDeviceExtension(IN PDEVICE_OBJECT pDeviceObject, 59 | IN DeviceDispatchType pDeviceDispatchFnc, 60 | IN CleanupFncType pCleanupFnc ) 61 | { 62 | typedef TypeComparer::Result_type ExtensionPtr_type; 63 | volatile char invalidTypeSpecified[sizeof(TestFunction((ExtensionPtr_type)0)) - 1]; 64 | 65 | CommonDeviceExtension * pDevExt = (CommonDeviceExtension*)pDeviceObject->DeviceExtension; 66 | pDevExt->m_deviceDispatchFnc = (DeviceDispatchProc)pDeviceDispatchFnc; 67 | pDevExt->m_cleanProc = (CleanProc)pCleanupFnc; 68 | return (ExtensionPtr_type)pDevExt; 69 | } 70 | 71 | inline 72 | NTSTATUS RootDispatch( 73 | IN PDEVICE_OBJECT pDeviceObject, 74 | IN PIRP pIrp 75 | ) 76 | { 77 | drv::CommonDeviceExtension * pDevExt = (drv::CommonDeviceExtension*)pDeviceObject->DeviceExtension; 78 | return pDevExt->m_deviceDispatchFnc(pDeviceObject, pIrp, pDevExt); 79 | } 80 | 81 | } // drv 82 | 83 | 84 | #endif -------------------------------------------------------------------------------- /src/driver/drvUtils/drvVirginity.h: -------------------------------------------------------------------------------- 1 | #ifndef DRV_VIRGINITY_H 2 | #define DRV_VIRGINITY_H 3 | 4 | #include "drvFiles.h" 5 | #include "drvCpp.h" 6 | extern "C" 7 | { 8 | #include "drv_NtDefinitions.h" 9 | } 10 | 11 | typedef struct _Drv_VirginityContext 12 | { 13 | drv_MappedFile m_mapped; 14 | HANDLE m_hFile; 15 | UCHAR m_SectionName[IMAGE_SIZEOF_SHORT_NAME+1]; 16 | ULONG m_sstOffsetInSection; 17 | char * m_mappedSST; 18 | ULONG m_imageBase; 19 | char * m_pSectionStart; 20 | char * m_pMappedSectionStart; 21 | char * m_pLoadedNtAddress; 22 | }Drv_VirginityContext; 23 | 24 | NTSTATUS Drv_VirginityInit(Drv_VirginityContext * pContext); 25 | void Drv_VirginityFree(Drv_VirginityContext * pContext); 26 | void Drv_GetRealSSTValue(Drv_VirginityContext * pContext, long index, void ** pValue); 27 | 28 | ULONG Drv_GetSizeOfNtosSST(); 29 | void ** Drv_GetNtosSSTEntry(int index); 30 | 31 | ULONG DisableKernelDefence(KIRQL * OldIrql); 32 | VOID EnableKernelDefence(ULONG OldCr0, KIRQL OldIrql); 33 | 34 | void Drv_HookSST(PVOID * ppPlaceToHook, PVOID pNewHook); 35 | void Drv_HookMemCpy(void * dest, 36 | const void * src, 37 | size_t count); 38 | 39 | class CAutoVirginity 40 | { 41 | Drv_VirginityContext * m_pContext; 42 | CAutoVirginity(const CAutoVirginity&); 43 | CAutoVirginity&operator = (const CAutoVirginity&); 44 | public: 45 | CAutoVirginity() 46 | : m_pContext(0) 47 | { 48 | } 49 | NTSTATUS Init(Drv_VirginityContext * pContext) 50 | { 51 | NT_CHECK(Drv_VirginityInit(pContext)); 52 | m_pContext = pContext; 53 | return NT_OK; 54 | } 55 | ~CAutoVirginity() 56 | { 57 | if (m_pContext) 58 | Drv_VirginityFree(m_pContext); 59 | } 60 | }; 61 | 62 | 63 | typedef struct _Drv_ResolverContext 64 | { 65 | PSYSTEM_MODULE_INFORMATION m_pModInfo; 66 | } 67 | Drv_ResolverContext; 68 | 69 | NTSTATUS Drv_ResolverContextInit(Drv_ResolverContext * pContext); 70 | void Drv_ResolverContextFree(Drv_ResolverContext * pContext); 71 | SYSTEM_MODULE * Drv_ResolverLookupModule(Drv_ResolverContext * pContext, const void * pPointer); 72 | SYSTEM_MODULE * Drv_ResolverLookupModule2(Drv_ResolverContext * pContext, const char * pName); 73 | 74 | class Drv_Resolver 75 | { 76 | Drv_ResolverContext m_context; 77 | int m_bInited; 78 | Drv_Resolver(const Drv_Resolver & ); 79 | Drv_Resolver&operator =(const Drv_Resolver & ); 80 | public: 81 | Drv_Resolver(); 82 | ~Drv_Resolver(); 83 | NTSTATUS Init(); 84 | SYSTEM_MODULE * LookupModule(const void * pPointer); 85 | SYSTEM_MODULE * LookupModule(const char * pName); 86 | }; 87 | 88 | NTSTATUS GetNtoskrnlInfo(SYSTEM_MODULE * pInfo); 89 | NTSTATUS drv_MapFile(drv_MappedFile * pMmapped, 90 | UNICODE_STRING * pNtosName, 91 | HANDLE * phFile); 92 | 93 | #endif -------------------------------------------------------------------------------- /src/driver/drvUtils/drvSync.h: -------------------------------------------------------------------------------- 1 | #ifndef DRV_SYNC_H 2 | #define DRV_SYNC_H 3 | 4 | #include "drvCpp.h" 5 | 6 | namespace drv 7 | { 8 | 9 | template 10 | class auto_ptr 11 | { 12 | ResourceType * m_pResource; 13 | public: 14 | auto_ptr() 15 | : m_pResource(0) 16 | { 17 | } 18 | 19 | explicit auto_ptr(ResourceType * pResource) 20 | : m_pResource( pResource ) 21 | { 22 | } 23 | auto_ptr(auto_ptr & source_ptr) 24 | : m_pResource( source_ptr.get() ) 25 | { 26 | source_ptr.m_pResource = 0; 27 | } 28 | 29 | auto_ptr & operator = (auto_ptr & source_ptr) 30 | { 31 | if (m_pResource) 32 | delete m_pResource; 33 | 34 | m_pResource = source_ptr.get(); 35 | source_ptr.m_pResource = 0; 36 | return *this; 37 | } 38 | 39 | ~auto_ptr() 40 | { 41 | if (m_pResource) 42 | delete m_pResource; 43 | } 44 | 45 | void reset(ResourceType * pResource = 0) 46 | { 47 | if (m_pResource) 48 | delete m_pResource; 49 | m_pResource = pResource; 50 | } 51 | const ResourceType * get() const { return m_pResource; } 52 | ResourceType * get() { return m_pResource; } 53 | 54 | ResourceType * release() 55 | { 56 | ResourceType * pRes = m_pResource; 57 | m_pResource = 0; 58 | return pRes; 59 | } 60 | 61 | ResourceType * operator -> () { return m_pResource; } 62 | const ResourceType * operator -> () const { return m_pResource; } 63 | ResourceType & operator * () { return *m_pResource; } 64 | const ResourceType & operator * () const { return *m_pResource; } 65 | }; 66 | 67 | 68 | class FastMutex 69 | { 70 | drv::auto_ptr pFastMutex_; 71 | FastMutex(const FastMutex& ); 72 | FastMutex& operator = (const FastMutex& ); 73 | public: 74 | FastMutex() 75 | { 76 | } 77 | 78 | NTSTATUS Init() 79 | { 80 | FAST_MUTEX * p = new FAST_MUTEX; 81 | NT_CHECK_ALLOC(p); 82 | pFastMutex_.reset(p); 83 | ExInitializeFastMutex(pFastMutex_.get()); 84 | return NT_OK; 85 | } 86 | FAST_MUTEX * get() 87 | { 88 | return pFastMutex_.get(); 89 | } 90 | void enter() 91 | { 92 | ExAcquireFastMutex(pFastMutex_.get()); 93 | } 94 | void leave() 95 | { 96 | ExReleaseFastMutex(pFastMutex_.get()); 97 | } 98 | }; 99 | 100 | template 101 | class AutoGuard 102 | { 103 | Guard & guard_; 104 | AutoGuard(); 105 | AutoGuard(AutoGuard&); 106 | AutoGuard& operator = (const AutoGuard& ); 107 | public: 108 | explicit AutoGuard(Guard& guard) 109 | :guard_(guard) 110 | { 111 | KeEnterCriticalRegion(); 112 | guard_.enter(); 113 | } 114 | ~AutoGuard() 115 | { 116 | guard_.leave(); 117 | KeLeaveCriticalRegion(); 118 | } 119 | }; 120 | 121 | typedef AutoGuard AutoFastMutex; 122 | 123 | 124 | 125 | } // drv 126 | #endif 127 | -------------------------------------------------------------------------------- /src/driver/drvUtils/drvUtils.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 11 | 12 | 13 | 19 | 23 | 24 | 30 | 34 | 35 | 36 | 37 | 38 | 39 | 43 | 45 | 46 | 48 | 49 | 51 | 52 | 54 | 55 | 57 | 58 | 60 | 61 | 62 | 66 | 68 | 69 | 71 | 72 | 74 | 75 | 77 | 78 | 80 | 81 | 83 | 84 | 86 | 87 | 89 | 90 | 92 | 93 | 95 | 96 | 98 | 99 | 100 | 104 | 105 | 107 | 108 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /src/app/unhooker/main.cpp: -------------------------------------------------------------------------------- 1 | #include "cmnUtils.h" 2 | #include "cmnDriver.h" 3 | #include "drvCommonPortableDefs.h" 4 | #include "iomanip" 5 | 6 | 7 | void outHex(size_t value) 8 | { 9 | int iSize = sizeof(value)*2; 10 | std::cout<< std::hex << std::setw(iSize) 11 | << std::setfill('0') 12 | << value; 13 | } 14 | 15 | void OnSSTEntry(DRV_REPORT_SST_ENTRY * pCurrentEntry) 16 | { 17 | char * pName = (char*)pCurrentEntry + pCurrentEntry->m_nameOffset; 18 | std::string str(pName, pName + pCurrentEntry->m_nameSize); 19 | outHex(pCurrentEntry->m_sstIndex); 20 | std::cout<<" module: "<m_moduleAddress); 22 | std::cout<<" hooked address: "; 23 | outHex((size_t)pCurrentEntry->m_newAddress); 24 | std::cout<<"\n"; 25 | } 26 | 27 | 28 | void OnModificationEntry(DRV_REPORT_MODIFICATION_ENTRY * pCurrentEntry) 29 | { 30 | std::cout<<" "; 31 | outHex((size_t)pCurrentEntry->m_address); 32 | std::cout<<" ( "<m_sectionName<<"+"<m_offsetInSection 33 | <<" ) - "<m_sizeOfModification<<" bytes\n"; 34 | } 35 | 36 | int do_stat(int argc, wchar_t * argv[]) 37 | { 38 | cmn::CDriver driver(DRV_UNHOOKER_USERMODE_SYMBOLIC_LINK); 39 | DWORD dwRes = 0; 40 | 41 | std::vector data(1024*1024); 42 | 43 | driver.SendIoCtl(DRV_UNHOOKER_GET_STATUS, &data.front(), (DWORD)data.size(), 0, &dwRes); 44 | 45 | DRV_REPORT * pReport = (DRV_REPORT * )&data.front(); 46 | if (pReport->m_countOfReportEntries) 47 | { 48 | std::cout<<"Result: Ntoskernel IS PATCHED!\n"; 49 | 50 | std::cout<m_countOfModifiedSSTEntries<<" SST entries modified\n"; 51 | std::cout<m_countOfModifiedImageEntries<<" Image entries modified\n------\n"; 52 | std::cout<m_countOfReportEntries<<" entries reported:\n"; 53 | 54 | DRV_REPORT_ENTRY * pEntryBegin = (DRV_REPORT_ENTRY *)((char *)pReport + pReport->m_reportEntryOffsets); 55 | DRV_REPORT_ENTRY * pCurrentEntry = pEntryBegin; 56 | for(int i = 0; i< pReport->m_countOfReportEntries; ++i) 57 | { 58 | switch(pCurrentEntry->m_type) 59 | { 60 | case dreSST: 61 | OnSSTEntry((DRV_REPORT_SST_ENTRY *)pCurrentEntry); 62 | break; 63 | case dreModification: 64 | OnModificationEntry((DRV_REPORT_MODIFICATION_ENTRY *)pCurrentEntry); 65 | } 66 | 67 | pCurrentEntry = (DRV_REPORT_ENTRY *)((char*)pCurrentEntry + pCurrentEntry->m_sizeOfEntry); 68 | } 69 | std::cout<<"\n"; 70 | } 71 | else 72 | { 73 | std::cout<<"Result: Ntoskernel is clean \n\n"; 74 | } 75 | return 0; 76 | } 77 | 78 | int do_unhook(int argc, wchar_t * argv[]) 79 | { 80 | cmn::CDriver driver(DRV_UNHOOKER_USERMODE_SYMBOLIC_LINK); 81 | DWORD dwRes = 0; 82 | driver.SendIoCtl(DRV_UNHOOKER_UNHOOK, 0,0,0, &dwRes); 83 | 84 | std::cout<<"Success\n\n"; 85 | return 0; 86 | } 87 | 88 | static void PrintUsage() 89 | { 90 | std::cout<<"Usage: [stat] or [unhook]\n"; 91 | } 92 | 93 | int wmain(int argc, wchar_t * argv[]) 94 | { 95 | try 96 | { 97 | if (argc != 2) 98 | { 99 | PrintUsage(); 100 | return 0; 101 | } 102 | if (wcscmp(argv[1], L"stat") == 0) 103 | { 104 | return do_stat(argc, argv); 105 | } 106 | if (wcscmp(argv[1], L"unhook") == 0) 107 | { 108 | return do_unhook(argc, argv); 109 | } 110 | PrintUsage(); 111 | return 0; 112 | } 113 | catch(std::exception & e) 114 | { 115 | std::cout< 2 | 8 | 9 | 11 | 12 | 13 | 19 | 31 | 33 | 36 | 38 | 40 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 55 | 61 | 70 | 72 | 75 | 77 | 79 | 81 | 83 | 85 | 87 | 89 | 91 | 93 | 94 | 95 | 96 | 97 | 98 | 102 | 104 | 105 | 106 | 110 | 112 | 113 | 115 | 116 | 118 | 119 | 121 | 122 | 123 | 127 | 128 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /src/app/unhooker/unhooker.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 11 | 12 | 13 | 19 | 32 | 34 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 56 | 58 | 60 | 62 | 63 | 69 | 79 | 81 | 90 | 92 | 94 | 96 | 98 | 100 | 102 | 104 | 106 | 108 | 110 | 111 | 112 | 113 | 114 | 115 | 119 | 121 | 122 | 123 | 127 | 128 | 132 | 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /src/driver/drvUtils/drvSyncQueue.h: -------------------------------------------------------------------------------- 1 | #ifndef DRV_SYNC_QUEUE_H 2 | #define DRV_SYNC_QUEUE_H 3 | 4 | #include "drvSync.h" 5 | 6 | namespace drv 7 | { 8 | 9 | class CCommonTask 10 | { 11 | CCommonTask(const CCommonTask&); 12 | CCommonTask&operator =(const CCommonTask&); 13 | public: 14 | LIST_ENTRY m_entry; 15 | CCommonTask() 16 | { 17 | m_entry.Blink = 0; 18 | m_entry.Flink = 0; 19 | } 20 | virtual ~CCommonTask() 21 | { 22 | } 23 | virtual void Execute()=0; 24 | virtual void Cleanup()=0; 25 | }; 26 | 27 | class CAutoTask 28 | { 29 | CCommonTask * m_pCommonTask; 30 | 31 | CAutoTask(const CAutoTask&); 32 | CAutoTask&operator = (const CAutoTask&); 33 | public: 34 | CAutoTask(CCommonTask * pCommonTask = 0) 35 | : m_pCommonTask(pCommonTask) 36 | { 37 | } 38 | CCommonTask * get () 39 | { 40 | return m_pCommonTask; 41 | } 42 | const CCommonTask * get ()const 43 | { 44 | return m_pCommonTask; 45 | } 46 | 47 | CCommonTask * operator -> () 48 | { 49 | return m_pCommonTask; 50 | } 51 | const CCommonTask * operator -> ()const 52 | { 53 | return m_pCommonTask; 54 | } 55 | CCommonTask * release() 56 | { 57 | CCommonTask * pCommonTask = m_pCommonTask; 58 | m_pCommonTask = 0; 59 | return pCommonTask; 60 | } 61 | 62 | void reset(CCommonTask * pTask) 63 | { 64 | if (pTask == m_pCommonTask) 65 | return; 66 | 67 | CCommonTask * pCommonTask = m_pCommonTask; 68 | m_pCommonTask = pTask; 69 | if (pCommonTask) 70 | pCommonTask->Cleanup(); 71 | } 72 | ~CAutoTask() 73 | { 74 | if (m_pCommonTask) 75 | m_pCommonTask->Cleanup(); 76 | } 77 | }; 78 | 79 | template 80 | class CAutoTask_t 81 | { 82 | CAutoTask m_impl; 83 | public: 84 | CAutoTask_t(CommonTaskType * pCommonTask = 0) 85 | : m_impl(pCommonTask) 86 | { 87 | } 88 | 89 | CommonTaskType * get () 90 | { 91 | return (CommonTaskType *)m_impl.get(); 92 | } 93 | const CommonTaskType * get ()const 94 | { 95 | return (CommonTaskType *)m_impl.get(); 96 | } 97 | 98 | CommonTaskType * operator -> () 99 | { 100 | return (CommonTaskType *)m_impl.get(); 101 | } 102 | const CommonTaskType * operator -> ()const 103 | { 104 | return (CommonTaskType *)m_impl.get(); 105 | } 106 | CommonTaskType * release() 107 | { 108 | return (CommonTaskType *)m_impl.release(); 109 | } 110 | 111 | void reset(CommonTaskType * pTask) 112 | { 113 | m_impl.reset(pTask); 114 | } 115 | }; 116 | 117 | class CSharedTask:public CCommonTask 118 | { 119 | KEVENT m_event; 120 | long m_counter; 121 | 122 | virtual void ExecuteImpl()=0; 123 | virtual void CleanupImpl() { delete this; } 124 | public: 125 | CSharedTask() 126 | : m_counter(1) 127 | { 128 | KeInitializeEvent( &m_event, NotificationEvent, FALSE ); 129 | } 130 | void AddRef() 131 | { 132 | InterlockedIncrement(&m_counter); 133 | } 134 | void Wait() 135 | { 136 | KeWaitForSingleObject( 137 | &m_event, 138 | Executive, 139 | KernelMode, 140 | FALSE, 141 | NULL 142 | ); 143 | } 144 | virtual void Execute() 145 | { 146 | ExecuteImpl(); 147 | KeSetEvent( &m_event, 0, FALSE ); 148 | } 149 | virtual void Cleanup() 150 | { 151 | KeSetEvent( &m_event, 0, FALSE ); 152 | if (InterlockedDecrement(&m_counter)==0) 153 | CleanupImpl(); 154 | } 155 | }; 156 | 157 | class CSyncQueue 158 | { 159 | long m_destroyed; 160 | LIST_ENTRY m_list; 161 | FastMutex m_lock; 162 | 163 | void DestroyNoLock(); 164 | public: 165 | CSyncQueue(); 166 | ~CSyncQueue(); 167 | NTSTATUS Init(); 168 | void Destroy(); 169 | NTSTATUS PushBack(CAutoTask & task); 170 | NTSTATUS PopFirst(CAutoTask & task, 171 | bool * pEmpty); 172 | 173 | 174 | template 175 | NTSTATUS PushBackSharedTask(CAutoTask_t & task) 176 | { 177 | drv::AutoFastMutex guard(m_lock); 178 | if (m_destroyed) 179 | return STATUS_LOCAL_DISCONNECT; 180 | 181 | task->AddRef(); 182 | InsertTailList(&m_list, &task->m_entry); 183 | return NT_OK; 184 | } 185 | 186 | }; 187 | 188 | 189 | } //drv 190 | #endif -------------------------------------------------------------------------------- /src/driver/drvUtils/drvFiles.cpp: -------------------------------------------------------------------------------- 1 | #include "drvFiles.h" 2 | 3 | extern "C" 4 | { 5 | NTSTATUS 6 | MmCreateSection ( 7 | OUT PVOID *SectionObject, 8 | IN ACCESS_MASK DesiredAccess, 9 | IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 10 | IN PLARGE_INTEGER MaximumSize, 11 | IN ULONG SectionPageProtection, 12 | IN ULONG AllocationAttributes, 13 | IN HANDLE FileHandle OPTIONAL, 14 | IN PFILE_OBJECT File OPTIONAL 15 | ); 16 | 17 | 18 | NTSTATUS 19 | MmMapViewOfSection( 20 | IN PVOID SectionToMap, 21 | IN PEPROCESS Process, 22 | IN OUT PVOID *CapturedBase, 23 | IN ULONG_PTR ZeroBits, 24 | IN SIZE_T CommitSize, 25 | IN OUT PLARGE_INTEGER SectionOffset, 26 | IN OUT PSIZE_T CapturedViewSize, 27 | IN SECTION_INHERIT InheritDisposition, 28 | IN ULONG AllocationType, 29 | IN ULONG Protect 30 | ); 31 | 32 | 33 | NTSTATUS 34 | MmUnmapViewOfSection( 35 | IN PEPROCESS Process, 36 | IN PVOID BaseAddress 37 | ); 38 | 39 | VOID 40 | NTAPI 41 | ObMakeTemporaryObject( 42 | IN PVOID Object 43 | ); 44 | 45 | NTSTATUS 46 | NTAPI 47 | NtQueryInformationFile( 48 | IN HANDLE FileHandle, 49 | OUT PIO_STATUS_BLOCK IoStatusBlock, 50 | OUT PVOID FileInformation, 51 | IN ULONG Length, 52 | IN FILE_INFORMATION_CLASS FileInformationClass 53 | ); 54 | 55 | } 56 | 57 | 58 | NTSTATUS drv_MapAllFileEx(HANDLE hFile OPTIONAL, 59 | drv_MappedFile * pMappedFile, 60 | LARGE_INTEGER * pFileSize, 61 | ULONG Protect) 62 | { 63 | NTSTATUS status = STATUS_SUCCESS; 64 | PVOID section = 0; 65 | PCHAR pData=0; 66 | LARGE_INTEGER offset; 67 | 68 | offset.QuadPart = 0; 69 | 70 | // check zero results 71 | if (!pFileSize->QuadPart) 72 | goto calc_exit; 73 | 74 | status = MmCreateSection (§ion, 75 | SECTION_MAP_READ, 76 | 0, // OBJECT ATTRIBUTES 77 | pFileSize, // MAXIMUM SIZE 78 | Protect, 79 | 0x8000000, 80 | hFile, 81 | 0 82 | ); 83 | 84 | 85 | if (status!= STATUS_SUCCESS) 86 | goto calc_exit; 87 | 88 | 89 | status = MmMapViewOfSection(section, 90 | PsGetCurrentProcess(), 91 | (PVOID*)&pData, 92 | 0, 93 | 0, 94 | &offset, 95 | &pFileSize->LowPart, 96 | ViewUnmap, 97 | 0, 98 | Protect); 99 | 100 | if (status!= STATUS_SUCCESS) 101 | goto calc_exit; 102 | 103 | 104 | 105 | calc_exit: 106 | 107 | if (NT_SUCCESS(status)) 108 | { 109 | pMappedFile->fileSize.QuadPart = pFileSize->QuadPart; 110 | pMappedFile->pData = pData; 111 | pMappedFile->section = section; 112 | } 113 | else 114 | { 115 | if (pData) 116 | MmUnmapViewOfSection(PsGetCurrentProcess(), 117 | pData); 118 | 119 | if (section) 120 | { 121 | ObMakeTemporaryObject(section); 122 | ObDereferenceObject(section); 123 | } 124 | } 125 | return status; 126 | } 127 | 128 | 129 | NTSTATUS drv_GetSizeOfFile(HANDLE hFile, PLARGE_INTEGER pFileSize) 130 | { 131 | IO_STATUS_BLOCK IoBlock; 132 | FILE_STANDARD_INFORMATION FileInfo; 133 | NTSTATUS status = 0; 134 | 135 | pFileSize->QuadPart=0; 136 | status = NtQueryInformationFile(hFile,&IoBlock,&FileInfo,sizeof(FileInfo),FileStandardInformation); 137 | if (status == STATUS_SUCCESS) 138 | { 139 | pFileSize->QuadPart = FileInfo.EndOfFile.QuadPart; 140 | } 141 | return status; 142 | } 143 | 144 | 145 | NTSTATUS drv_MapAllFile(HANDLE hFile, drv_MappedFile * pMappedFile) 146 | { 147 | LARGE_INTEGER fileSize; 148 | NTSTATUS status; 149 | status = drv_GetSizeOfFile(hFile, &fileSize); 150 | if (!NT_SUCCESS(status)) 151 | return status; 152 | return drv_MapAllFileEx(hFile, pMappedFile, &fileSize, PAGE_WRITECOPY); 153 | } 154 | 155 | void drv_UnMapFile(drv_MappedFile * pMappedFile) 156 | { 157 | if (pMappedFile->pData) 158 | { 159 | MmUnmapViewOfSection(PsGetCurrentProcess(), 160 | pMappedFile->pData); 161 | } 162 | 163 | if (pMappedFile->section) 164 | { 165 | ObMakeTemporaryObject(pMappedFile->section); 166 | ObDereferenceObject(pMappedFile->section); 167 | } 168 | memset(pMappedFile, 0, sizeof(drv_MappedFile)); 169 | } 170 | -------------------------------------------------------------------------------- /src/driver/drvUtils/pe_utils.c: -------------------------------------------------------------------------------- 1 | #include "pe_utils.h" 2 | #include "ntddk_module.h" 3 | 4 | typedef struct _drv_ResolveParams 5 | { 6 | void * pModuleAddress; 7 | PVOID pAddress; 8 | IMAGE_SECTION_HEADER * pSection; 9 | }drv_ResolveParams; 10 | NTSTATUS __stdcall Drv_ResolveSectionAddressFnc(PIMAGE_SECTION_HEADER pSection, 11 | void * pContext, 12 | int * bContinueSearch) 13 | { 14 | drv_ResolveParams * pResolveParams = pContext; 15 | char * pStart = (char *)pResolveParams->pModuleAddress + pSection->VirtualAddress; 16 | char * pEnd = pStart + pSection->Misc.VirtualSize; 17 | 18 | *bContinueSearch = 1; 19 | 20 | // does pResolveParams->pAddress relate to this section? 21 | if (pResolveParams->pAddress >= pStart && pResolveParams->pAddress <= pEnd) 22 | { 23 | *bContinueSearch = 0; 24 | pResolveParams->pSection = pSection; 25 | } 26 | return STATUS_SUCCESS; 27 | } 28 | 29 | 30 | NTSTATUS drv_EnumSections(char * pModule, 31 | drv_SectionHandlerType pSectionHandler, 32 | void * pContext) 33 | { 34 | NTSTATUS status = 0; 35 | PIMAGE_NT_HEADERS pPE = (PIMAGE_NT_HEADERS)(pModule+((PIMAGE_DOS_HEADER)pModule)->e_lfanew); 36 | short NumberOfSections = pPE->FileHeader.NumberOfSections; 37 | long SectionAlign=pPE->OptionalHeader.SectionAlignment; 38 | 39 | PIMAGE_SECTION_HEADER Section = (PIMAGE_SECTION_HEADER)((char*)&(pPE->FileHeader)+ 40 | pPE->FileHeader.SizeOfOptionalHeader+ 41 | sizeof(IMAGE_FILE_HEADER)); 42 | 43 | { 44 | int i = 0, iContinueSearch = 0; 45 | for (i=0; ie_lfanew); 65 | short NumberOfSections = pPE->FileHeader.NumberOfSections; 66 | long SectionAlign=pPE->OptionalHeader.SectionAlignment; 67 | 68 | PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)((char*)&(pPE->FileHeader)+ 69 | pPE->FileHeader.SizeOfOptionalHeader+ 70 | sizeof(IMAGE_FILE_HEADER)); 71 | pSectionInfo->m_currentNumber = 0; 72 | pSectionInfo->m_currentSection = pSection; 73 | pSectionInfo->m_numberOfSections = NumberOfSections; 74 | pSectionInfo->m_pModuleAddress = pModule; 75 | 76 | pSectionInfo->m_sectionStart = (char *)pModule + pSection->VirtualAddress; 77 | pSectionInfo->m_sectionEnd = pSectionInfo->m_sectionStart + pSection->Misc.VirtualSize; 78 | return status; 79 | } 80 | 81 | NTSTATUS drv_FindNextSection(DrvFindSectionInfo * pSectionInfo, 82 | int * pbDone) 83 | { 84 | PIMAGE_SECTION_HEADER pSection = 0; 85 | *pbDone = 0; 86 | ++pSectionInfo->m_currentNumber; 87 | if (pSectionInfo->m_currentNumber >= pSectionInfo->m_numberOfSections) 88 | { 89 | pSectionInfo->m_currentSection = 0; 90 | *pbDone = 1; 91 | return STATUS_SUCCESS; 92 | } 93 | ++pSectionInfo->m_currentSection; 94 | pSection = pSectionInfo->m_currentSection; 95 | 96 | pSectionInfo->m_sectionStart = (char *)pSectionInfo->m_pModuleAddress + pSection->VirtualAddress; 97 | pSectionInfo->m_sectionEnd = pSectionInfo->m_sectionStart + pSection->Misc.VirtualSize; 98 | return STATUS_SUCCESS; 99 | } 100 | 101 | NTSTATUS Drv_ResolveSectionAddress(PVOID pModuleAddress, PVOID pAddress, IMAGE_SECTION_HEADER ** ppSection) 102 | { 103 | drv_ResolveParams resolveParams; 104 | NTSTATUS status = 0; 105 | resolveParams.pModuleAddress = pModuleAddress; 106 | resolveParams.pSection = 0; 107 | resolveParams.pAddress = pAddress; 108 | 109 | status = drv_EnumSections(pModuleAddress, Drv_ResolveSectionAddressFnc, &resolveParams); 110 | if (!NT_SUCCESS(status)) 111 | return status; 112 | 113 | if (!resolveParams.pSection) 114 | return STATUS_NOT_FOUND; 115 | *ppSection = resolveParams.pSection; 116 | return STATUS_SUCCESS; 117 | } 118 | 119 | 120 | // find section in file 121 | NTSTATUS Drv_FindSection(PVOID pModuleAddress, 122 | UCHAR Name[IMAGE_SIZEOF_SHORT_NAME], 123 | IMAGE_SECTION_HEADER ** ppSection) 124 | { 125 | PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)pModuleAddress; 126 | PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((char*)dosHeader + dosHeader->e_lfanew); 127 | PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader); 128 | 129 | unsigned i; 130 | 131 | for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ ) 132 | { 133 | int k, found = 1; 134 | for(k=0;kName[k]) 137 | { 138 | found = 0; 139 | break; 140 | } 141 | } 142 | if (found) 143 | { 144 | *ppSection = section; 145 | return STATUS_SUCCESS; 146 | } 147 | } 148 | return STATUS_NOT_FOUND; 149 | } 150 | 151 | 152 | NTSTATUS 153 | Drv_GetProcAddrEx(PVOID DllBase, 154 | PCHAR FunctionName, 155 | ULONG lMaxSize, 156 | PIMAGE_EXPORT_DIRECTORY ExportDirectory, 157 | PUSHORT NameOrdinalTableBase, 158 | ULONG ExportSize, 159 | USHORT * OrdinalNumber) 160 | { 161 | PULONG NameTableBase = 0; 162 | ULONG Low = 0; 163 | ULONG Middle = 0; 164 | ULONG High = 0; 165 | LONG Result = 0; 166 | 167 | 168 | 169 | if (((char*)ExportDirectory<(char*)DllBase || (char*)ExportDirectory > (char*)DllBase+lMaxSize)) 170 | { 171 | return STATUS_INVALID_PARAMETER; 172 | } 173 | 174 | NameTableBase = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNames); 175 | if (((char*)NameTableBase<(char*)DllBase || (char*)NameTableBase > (char*)DllBase+lMaxSize)) 176 | { 177 | return STATUS_INVALID_PARAMETER; 178 | } 179 | 180 | NameOrdinalTableBase = (PUSHORT)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals); 181 | if (((char*)NameOrdinalTableBase<(char*)DllBase || 182 | (char*)NameOrdinalTableBase > (char*)DllBase+lMaxSize)) 183 | { 184 | return STATUS_INVALID_PARAMETER; 185 | } 186 | 187 | Low = 0; 188 | High = ExportDirectory->NumberOfNames - 1; 189 | 190 | // test High 191 | if (((char*)(NameTableBase+High)<(char*)DllBase || 192 | (char*)(NameTableBase+High)> (char*)DllBase+lMaxSize)) 193 | { 194 | return STATUS_INVALID_PARAMETER; 195 | } 196 | 197 | while (High >= Low && (LONG)High >= 0) 198 | { 199 | Middle = (Low + High) >> 1; 200 | 201 | // test NameOrdinalTableBase[Middle] 202 | if (NameTableBase[Middle] > lMaxSize) 203 | { 204 | return STATUS_INVALID_PARAMETER; 205 | } 206 | 207 | Result = strcmp(FunctionName, 208 | (PCHAR)((PCHAR)DllBase + NameTableBase[Middle])); 209 | if (Result < 0) 210 | { 211 | High = Middle - 1; 212 | } 213 | else if (Result > 0) 214 | { 215 | Low = Middle + 1; 216 | } 217 | else 218 | { 219 | break; 220 | } 221 | } 222 | 223 | 224 | if ((LONG)High >= (LONG)Low) 225 | { 226 | // test NameOrdinalTableBase[Middle] 227 | if (((char*)(NameOrdinalTableBase+Middle)<(char*)DllBase || 228 | (char*)(NameOrdinalTableBase+Middle)> (char*)DllBase+lMaxSize)) 229 | return 0; 230 | 231 | *OrdinalNumber = NameOrdinalTableBase[Middle]; 232 | return STATUS_SUCCESS; 233 | } 234 | return STATUS_NOT_FOUND; 235 | } 236 | -------------------------------------------------------------------------------- /src/driver/drvUtils/ntddk_module.h: -------------------------------------------------------------------------------- 1 | #ifndef NTDDK_MODULE__H__ 2 | #define NTDDK_MODULE__H__ 3 | 4 | //============================================================================= 5 | #if 1 6 | #include 7 | #else 8 | // Copied from (that is absent in Win2000 DDK headers) 9 | 10 | // Directory Entries 11 | 12 | #define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory 13 | #define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory 14 | #define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory 15 | #define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory 16 | #define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory 17 | #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table 18 | #define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory 19 | // IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage) 20 | #define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data 21 | #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP 22 | #define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory 23 | #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory 24 | #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers 25 | #define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table 26 | #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors 27 | #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor 28 | 29 | 30 | // 31 | // DLL support. 32 | // 33 | 34 | // 35 | // Export Format 36 | // 37 | 38 | typedef struct _IMAGE_EXPORT_DIRECTORY { 39 | ULONG Characteristics; 40 | ULONG TimeDateStamp; 41 | USHORT MajorVersion; 42 | USHORT MinorVersion; 43 | ULONG Name; 44 | ULONG Base; 45 | ULONG NumberOfFunctions; 46 | ULONG NumberOfNames; 47 | ULONG AddressOfFunctions; // RVA from base of image 48 | ULONG AddressOfNames; // RVA from base of image 49 | ULONG AddressOfNameOrdinals; // RVA from base of image 50 | } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; 51 | 52 | #endif // 0 53 | 54 | //============================================================================= 55 | NTSYSAPI 56 | PVOID 57 | NTAPI 58 | RtlImageDirectoryEntryToData( 59 | PVOID BaseOfImage, 60 | BOOLEAN MappedAsImage, 61 | USHORT DirectoryEntry, 62 | PULONG Size 63 | ); 64 | 65 | //============================================================================= 66 | 67 | // 68 | // System Information Classes. 69 | // 70 | 71 | typedef enum _SYSTEM_INFORMATION_CLASS { 72 | SystemBasicInformation, 73 | SystemProcessorInformation, // obsolete...delete 74 | SystemPerformanceInformation, 75 | SystemTimeOfDayInformation, 76 | SystemPathInformation, 77 | SystemProcessInformation, 78 | SystemCallCountInformation, 79 | SystemDeviceInformation, 80 | SystemProcessorPerformanceInformation, 81 | SystemFlagsInformation, 82 | SystemCallTimeInformation, 83 | SystemModuleInformation, 84 | SystemLocksInformation, 85 | SystemStackTraceInformation, 86 | SystemPagedPoolInformation, 87 | SystemNonPagedPoolInformation, 88 | SystemHandleInformation, 89 | SystemObjectInformation, 90 | SystemPageFileInformation, 91 | SystemVdmInstemulInformation, 92 | SystemVdmBopInformation, 93 | SystemFileCacheInformation, 94 | SystemPoolTagInformation, 95 | SystemInterruptInformation, 96 | SystemDpcBehaviorInformation, 97 | SystemFullMemoryInformation, 98 | SystemLoadGdiDriverInformation, 99 | SystemUnloadGdiDriverInformation, 100 | SystemTimeAdjustmentInformation, 101 | SystemSummaryMemoryInformation, 102 | SystemMirrorMemoryInformation, 103 | SystemPerformanceTraceInformation, 104 | SystemObsolete0, 105 | SystemExceptionInformation, 106 | SystemCrashDumpStateInformation, 107 | SystemKernelDebuggerInformation, 108 | SystemContextSwitchInformation, 109 | SystemRegistryQuotaInformation, 110 | SystemExtendServiceTableInformation, 111 | SystemPrioritySeperation, 112 | SystemVerifierAddDriverInformation, 113 | SystemVerifierRemoveDriverInformation, 114 | SystemProcessorIdleInformation, 115 | SystemLegacyDriverInformation, 116 | SystemCurrentTimeZoneInformation, 117 | SystemLookasideInformation, 118 | SystemTimeSlipNotification, 119 | SystemSessionCreate, 120 | SystemSessionDetach, 121 | SystemSessionInformation, 122 | SystemRangeStartInformation, 123 | SystemVerifierInformation, 124 | SystemVerifierThunkExtend, 125 | SystemSessionProcessInformation, 126 | SystemLoadGdiDriverInSystemSpace, 127 | SystemNumaProcessorMap, 128 | SystemPrefetcherInformation, 129 | SystemExtendedProcessInformation, 130 | SystemRecommendedSharedDataAlignment, 131 | SystemComPlusPackage, 132 | SystemNumaAvailableMemory, 133 | SystemProcessorPowerInformation, 134 | SystemEmulationBasicInformation, 135 | SystemEmulationProcessorInformation, 136 | SystemExtendedHandleInformation, 137 | SystemLostDelayedWriteInformation, 138 | SystemBigPoolInformation, 139 | SystemSessionPoolTagInformation, 140 | SystemSessionMappedViewInformation, 141 | SystemHotpatchInformation, 142 | SystemObjectSecurityMode, 143 | SystemWatchdogTimerHandler, 144 | SystemWatchdogTimerInformation, 145 | SystemLogicalProcessorInformation, 146 | SystemWow64SharedInformation, 147 | SystemRegisterFirmwareTableInformationHandler, 148 | SystemFirmwareTableInformation, 149 | SystemModuleInformationEx, 150 | SystemVerifierTriageInformation, 151 | SystemSuperfetchInformation, 152 | SystemMemoryListInformation, 153 | SystemFileCacheInformationEx, 154 | MaxSystemInfoClass // MaxSystemInfoClass should always be the last enum 155 | } SYSTEM_INFORMATION_CLASS; 156 | 157 | //----------------------------------------------------------------------------- 158 | NTSYSAPI 159 | NTSTATUS 160 | NTAPI 161 | ZwQuerySystemInformation ( 162 | IN SYSTEM_INFORMATION_CLASS SystemInformationClass, 163 | OUT PVOID SystemInformation OPTIONAL, 164 | IN ULONG SystemInformationLength, 165 | OUT PULONG ReturnLength OPTIONAL 166 | ); 167 | NTSYSAPI 168 | NTSTATUS 169 | NTAPI 170 | NtQuerySystemInformation ( 171 | IN SYSTEM_INFORMATION_CLASS SystemInformationClass, 172 | OUT PVOID SystemInformation OPTIONAL, 173 | IN ULONG SystemInformationLength, 174 | OUT PULONG ReturnLength OPTIONAL 175 | ); 176 | 177 | //----------------------------------------------------------------------------- 178 | NTSYSAPI 179 | NTSTATUS 180 | NTAPI 181 | ZwSetSystemInformation ( 182 | IN SYSTEM_INFORMATION_CLASS SystemInformationClass, 183 | IN PVOID SystemInformation OPTIONAL, 184 | IN ULONG SystemInformationLength 185 | ); 186 | 187 | //============================================================================= 188 | // ZwQuerySystemInformation( SystemModuleInformation, ... ) 189 | 190 | typedef struct _RTL_PROCESS_MODULE_INFORMATION { 191 | HANDLE Section; // Not filled in 192 | PVOID MappedBase; 193 | PVOID ImageBase; 194 | ULONG ImageSize; 195 | ULONG Flags; 196 | USHORT LoadOrderIndex; 197 | USHORT InitOrderIndex; 198 | USHORT LoadCount; 199 | USHORT OffsetToFileName; 200 | UCHAR FullPathName[ 256 ]; 201 | } RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; 202 | 203 | typedef struct _RTL_PROCESS_MODULES { 204 | ULONG NumberOfModules; 205 | RTL_PROCESS_MODULE_INFORMATION Modules[ 1 ]; 206 | } RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; 207 | 208 | //============================================================================= 209 | // ZwSetSystemInformation( SystemLoadGdiDriverInSystemSpace, ... ) 210 | // ZwSetSystemInformation( SystemLoadGdiDriverInformation, ... ) 211 | 212 | typedef struct _SYSTEM_GDI_DRIVER_INFORMATION { 213 | UNICODE_STRING DriverName; 214 | PVOID ImageAddress; 215 | PVOID SectionPointer; 216 | PVOID EntryPoint; 217 | PIMAGE_EXPORT_DIRECTORY ExportSectionPointer; 218 | ULONG ImageLength; 219 | } SYSTEM_GDI_DRIVER_INFORMATION, *PSYSTEM_GDI_DRIVER_INFORMATION; 220 | 221 | //============================================================================= 222 | typedef struct _NON_PAGED_DEBUG_INFO NON_PAGED_DEBUG_INFO, *PNON_PAGED_DEBUG_INFO; 223 | 224 | 225 | // 226 | // Private flags for loader data table entries 227 | // 228 | 229 | #define LDRP_STATIC_LINK 0x00000002 230 | #define LDRP_IMAGE_DLL 0x00000004 231 | #define LDRP_LOAD_IN_PROGRESS 0x00001000 232 | #define LDRP_UNLOAD_IN_PROGRESS 0x00002000 233 | #define LDRP_ENTRY_PROCESSED 0x00004000 234 | #define LDRP_ENTRY_INSERTED 0x00008000 235 | #define LDRP_CURRENT_LOAD 0x00010000 236 | #define LDRP_FAILED_BUILTIN_LOAD 0x00020000 237 | #define LDRP_DONT_CALL_FOR_THREADS 0x00040000 238 | #define LDRP_PROCESS_ATTACH_CALLED 0x00080000 239 | #define LDRP_DEBUG_SYMBOLS_LOADED 0x00100000 240 | #define LDRP_IMAGE_NOT_AT_BASE 0x00200000 241 | #define LDRP_COR_IMAGE 0x00400000 242 | #define LDRP_COR_OWNS_UNMAP 0x00800000 243 | #define LDRP_SYSTEM_MAPPED 0x01000000 244 | #define LDRP_IMAGE_VERIFYING 0x02000000 245 | #define LDRP_DRIVER_DEPENDENT_DLL 0x04000000 246 | #define LDRP_ENTRY_NATIVE 0x08000000 247 | #define LDRP_REDIRECTED 0x10000000 248 | #define LDRP_NON_PAGED_DEBUG_INFO 0x20000000 249 | #define LDRP_MM_LOADED 0x40000000 250 | #define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000 251 | 252 | 253 | typedef struct _KLDR_DATA_TABLE_ENTRY { 254 | LIST_ENTRY InLoadOrderLinks; 255 | PVOID ExceptionTable; 256 | ULONG ExceptionTableSize; 257 | // ULONG padding on IA64 258 | PVOID GpValue; 259 | PNON_PAGED_DEBUG_INFO NonPagedDebugInfo; 260 | PVOID DllBase; 261 | PVOID EntryPoint; 262 | ULONG SizeOfImage; 263 | UNICODE_STRING FullDllName; 264 | UNICODE_STRING BaseDllName; 265 | ULONG Flags; 266 | USHORT LoadCount; 267 | USHORT __Unused5; 268 | PVOID SectionPointer; 269 | ULONG CheckSum; 270 | // ULONG padding on IA64 271 | PVOID LoadedImports; 272 | PVOID PatchInformation; 273 | } KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY; 274 | 275 | 276 | //============================================================================= 277 | #endif /* !defined(NTDDK_MODULE__H__) */ 278 | -------------------------------------------------------------------------------- /src/driver/drvUtils/drvVirginity.cpp: -------------------------------------------------------------------------------- 1 | #include "drvVirginity.h" 2 | 3 | extern "C" 4 | { 5 | #include "pe_utils.h" 6 | #include "ntddk_module.h" 7 | 8 | extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable; 9 | 10 | } 11 | 12 | 13 | 14 | 15 | ULONG DisableKernelDefence(KIRQL * OldIrql) 16 | { 17 | ULONG OldCr0=0; 18 | 19 | __asm 20 | { 21 | cli 22 | mov eax, cr0 23 | mov OldCr0, eax 24 | and eax, 0xFFFEFFFF 25 | mov cr0, eax 26 | } 27 | return OldCr0; 28 | } 29 | 30 | VOID EnableKernelDefence(ULONG OldCr0, KIRQL OldIrql) 31 | { 32 | __asm 33 | { 34 | mov eax, OldCr0 35 | mov cr0, eax 36 | sti 37 | } 38 | } 39 | 40 | 41 | void Drv_HookSST(PVOID * ppPlaceToHook, PVOID pNewHook) 42 | { 43 | PVOID result; 44 | KIRQL OldIrqL; 45 | ULONG OldCr0; 46 | 47 | OldCr0 = DisableKernelDefence(&OldIrqL); 48 | *ppPlaceToHook = pNewHook; 49 | EnableKernelDefence(OldCr0, OldIrqL); 50 | } 51 | 52 | void Drv_HookMemCpy(void * dest, 53 | const void * src, 54 | size_t count) 55 | { 56 | PVOID result; 57 | KIRQL OldIrqL; 58 | ULONG OldCr0; 59 | 60 | OldCr0 = DisableKernelDefence(&OldIrqL); 61 | 62 | memcpy(dest, src, count); 63 | 64 | EnableKernelDefence(OldCr0, OldIrqL); 65 | } 66 | 67 | void ** Drv_GetNtosSSTEntry(int index) 68 | { 69 | return (void ** )(KeServiceDescriptorTable->ntoskrnl.ServiceTable + index); 70 | } 71 | 72 | ULONG Drv_GetSizeOfNtosSST() 73 | { 74 | return KeServiceDescriptorTable->ntoskrnl.ServiceLimit; 75 | } 76 | 77 | NTSTATUS GetAllModulesInfo(PULONG * pRes) 78 | { 79 | ULONG i; 80 | NTSTATUS status = STATUS_NOT_FOUND; 81 | 82 | unsigned long Base = 0; 83 | 84 | status = NtQuerySystemInformation( SystemModuleInformation, &i, 0, &i ); // system module info 85 | if (status != STATUS_INFO_LENGTH_MISMATCH) 86 | return status; 87 | 88 | *pRes = (PULONG)ExAllocatePool(NonPagedPool, sizeof(ULONG)*i); 89 | 90 | if (!*pRes) 91 | return STATUS_NO_MEMORY; 92 | 93 | status = NtQuerySystemInformation( SystemModuleInformation, *pRes, i * sizeof(ULONG), 0); 94 | if (status != STATUS_SUCCESS) 95 | { 96 | ExFreePool(*pRes); 97 | return STATUS_UNSUCCESSFUL; 98 | } 99 | return STATUS_SUCCESS; 100 | } 101 | 102 | BOOLEAN iskernelName(CHAR* name) 103 | { 104 | if (!_strnicmp(name, "nt", 2) || !_strnicmp(name, "wrkx", 4)) 105 | return TRUE; 106 | return FALSE; 107 | } 108 | 109 | NTSTATUS GetNtoskrnlInfo(SYSTEM_MODULE * pInfo) 110 | { 111 | ULONG i; 112 | NTSTATUS status = STATUS_SUCCESS; 113 | PULONG pBuf = 0; 114 | PSYSTEM_MODULE_INFORMATION pModInfo; 115 | status = GetAllModulesInfo(&pBuf); 116 | if(status != STATUS_SUCCESS) 117 | return status; 118 | 119 | pModInfo = (PSYSTEM_MODULE_INFORMATION)pBuf; 120 | status = STATUS_NOT_FOUND; 121 | 122 | for (i=0; (i<*pBuf) && i<2; i++) 123 | { 124 | if (iskernelName((CHAR*)pModInfo->aSM[i].abName + pModInfo->aSM[i].wNameOffset)) 125 | { 126 | *pInfo=pModInfo->aSM[i]; 127 | status = STATUS_SUCCESS; 128 | break; 129 | } 130 | } 131 | ExFreePool(pBuf); 132 | return status; 133 | } 134 | 135 | 136 | NTSTATUS drv_MapFile(drv_MappedFile * pMmapped, 137 | UNICODE_STRING * pNtosName, 138 | HANDLE * phFile) 139 | { 140 | NTSTATUS status = 0; 141 | HANDLE hFile = 0; 142 | OBJECT_ATTRIBUTES oa; 143 | IO_STATUS_BLOCK iosb; 144 | 145 | InitializeObjectAttributes(&oa,pNtosName,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,NULL,NULL); 146 | 147 | status = IoCreateFile(&hFile, 148 | GENERIC_READ, 149 | &oa, 150 | &iosb, 151 | 0, 152 | 0, 153 | FILE_SHARE_WRITE|FILE_SHARE_READ, 154 | FILE_OPEN, 155 | FILE_NON_DIRECTORY_FILE, 156 | 0, 157 | 0, 158 | CreateFileTypeNone, 159 | 0, 160 | IO_NO_PARAMETER_CHECKING); 161 | if (!NT_SUCCESS(status)) 162 | goto clean; 163 | 164 | // map file 165 | status = drv_MapAllFile(hFile, pMmapped); 166 | if (!NT_SUCCESS(status)) 167 | goto clean; 168 | 169 | // commit 170 | *phFile = hFile; 171 | 172 | hFile = 0; 173 | clean: 174 | if (hFile) 175 | NtClose(hFile); 176 | return status; 177 | } 178 | 179 | static NTSTATUS ResolveSST(Drv_VirginityContext * pContext, SYSTEM_MODULE * pNtOsInfo) 180 | { 181 | PIMAGE_SECTION_HEADER pSection = 0; 182 | PIMAGE_SECTION_HEADER pMappedSection = 0; 183 | NTSTATUS status = 0; 184 | PNTPROC pStartSST = KeServiceDescriptorTable->ntoskrnl.ServiceTable; 185 | char * pSectionStart = 0; 186 | char * pMappedSectionStart = 0; 187 | 188 | pContext->m_pLoadedNtAddress = (char*)pNtOsInfo->pAddress; 189 | status = Drv_ResolveSectionAddress(pNtOsInfo->pAddress, pStartSST, &pSection); 190 | if (!NT_SUCCESS(status)) 191 | goto clean; 192 | 193 | memcpy(pContext->m_SectionName, pSection->Name, IMAGE_SIZEOF_SHORT_NAME); 194 | 195 | pSectionStart = (char *)pNtOsInfo->pAddress + pSection->VirtualAddress; 196 | pContext->m_sstOffsetInSection = (char*)pStartSST - pSectionStart; 197 | 198 | status = Drv_FindSection(pContext->m_mapped.pData, pSection->Name, &pMappedSection); 199 | if (!NT_SUCCESS(status)) 200 | goto clean; 201 | 202 | pMappedSectionStart = (char *)pContext->m_mapped.pData + pMappedSection->PointerToRawData; 203 | pContext->m_mappedSST = pMappedSectionStart+pContext->m_sstOffsetInSection; 204 | 205 | { 206 | PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)pContext->m_mapped.pData; 207 | PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((char*)dosHeader + dosHeader->e_lfanew); 208 | pContext->m_imageBase = pNTHeader->OptionalHeader.ImageBase; 209 | } 210 | 211 | pContext->m_pSectionStart = pSectionStart; 212 | pContext->m_pMappedSectionStart = pMappedSectionStart; 213 | clean: 214 | return status; 215 | } 216 | 217 | NTSTATUS Drv_VirginityInit(Drv_VirginityContext * pContext) 218 | { 219 | NTSTATUS status = 0; 220 | SYSTEM_MODULE * pNtOsInfo = 0; 221 | ANSI_STRING kernelAnsiName; 222 | UNICODE_STRING kernelUnicodeName; 223 | wchar_t * pNtosFileName = 0; 224 | UNICODE_STRING ntosName; 225 | 226 | kernelUnicodeName.Buffer = 0; 227 | 228 | memset(pContext, 0, sizeof(Drv_VirginityContext)); 229 | pNtOsInfo = (SYSTEM_MODULE*)ExAllocatePool(PagedPool, sizeof(SYSTEM_MODULE)); 230 | if (!pNtOsInfo) 231 | { 232 | status = STATUS_NO_MEMORY; 233 | goto clean; 234 | } 235 | 236 | memset(pNtOsInfo, 0, sizeof(*pNtOsInfo)); 237 | status = GetNtoskrnlInfo(pNtOsInfo); 238 | if (!NT_SUCCESS(status)) 239 | goto clean; 240 | 241 | pNtosFileName = (wchar_t*)ExAllocatePool(PagedPool, 1024); 242 | if (!pNtosFileName) 243 | { 244 | status = STATUS_NO_MEMORY; 245 | goto clean; 246 | } 247 | ntosName.Buffer = pNtosFileName; 248 | ntosName.Length = 0; 249 | ntosName.MaximumLength = 1024; 250 | 251 | status = RtlAppendUnicodeToString(&ntosName, L"\\SystemRoot\\system32\\"); 252 | if (!NT_SUCCESS(status)) 253 | goto clean; 254 | 255 | RtlInitAnsiString(&kernelAnsiName, (char*)pNtOsInfo->abName + pNtOsInfo->wNameOffset); 256 | 257 | status = RtlAnsiStringToUnicodeString(&kernelUnicodeName, &kernelAnsiName, TRUE); 258 | if (!NT_SUCCESS(status)) 259 | goto clean; 260 | 261 | status = RtlAppendUnicodeStringToString(&ntosName, &kernelUnicodeName); 262 | if (!NT_SUCCESS(status)) 263 | goto clean; 264 | 265 | // now in ntosName - fullPath 266 | // open file 267 | status = drv_MapFile(&pContext->m_mapped, &ntosName, &pContext->m_hFile); 268 | if (!NT_SUCCESS(status)) 269 | goto clean; 270 | 271 | // parse file - find sst address 272 | status = ResolveSST(pContext, pNtOsInfo); 273 | if (!NT_SUCCESS(status)) 274 | goto clean; 275 | clean: 276 | if (!NT_SUCCESS(status)) 277 | { 278 | // free 279 | Drv_VirginityFree(pContext); 280 | } 281 | if (pNtOsInfo) 282 | ExFreePool(pNtOsInfo); 283 | if (pNtosFileName) 284 | ExFreePool(pNtosFileName); 285 | if (kernelUnicodeName.Buffer) 286 | ExFreePool(kernelUnicodeName.Buffer); 287 | return status; 288 | 289 | } 290 | void Drv_VirginityFree(Drv_VirginityContext * pContext) 291 | { 292 | drv_UnMapFile(&pContext->m_mapped); 293 | 294 | if (pContext->m_hFile) 295 | { 296 | NtClose(pContext->m_hFile); 297 | } 298 | } 299 | 300 | void Drv_GetRealSSTValue(Drv_VirginityContext * pContext, long index, void ** ppValue) 301 | { 302 | char * pSST = pContext->m_pMappedSectionStart + pContext->m_sstOffsetInSection; 303 | ULONG * pValue = ((ULONG *) pSST)+index; 304 | *ppValue = (void*)(*pValue + (ULONG)pContext->m_pLoadedNtAddress - pContext->m_imageBase); 305 | } 306 | 307 | 308 | 309 | NTSTATUS Drv_ResolverContextInit(Drv_ResolverContext * pContext) 310 | { 311 | PSYSTEM_MODULE_INFORMATION pModInfo; 312 | NTSTATUS status = 0; 313 | 314 | pContext->m_pModInfo = 0; 315 | 316 | status = GetAllModulesInfo((PULONG*)&pModInfo); 317 | if(!NT_SUCCESS(status)) 318 | return status; 319 | 320 | pContext->m_pModInfo = pModInfo; 321 | return status; 322 | } 323 | void Drv_ResolverContextFree(Drv_ResolverContext * pContext) 324 | { 325 | if (pContext->m_pModInfo) 326 | ExFreePool(pContext->m_pModInfo); 327 | } 328 | 329 | SYSTEM_MODULE * Drv_ResolverLookupModule(Drv_ResolverContext * pContext, const void * pPointer) 330 | { 331 | for (int i=0; i < pContext->m_pModInfo->dCount; i++) 332 | { 333 | SYSTEM_MODULE * pModule = pContext->m_pModInfo->aSM + i; 334 | if ((char*)pPointer > (char*)pModule->pAddress && (char*)pPointer < ((char*)pModule->pAddress + pModule->dSize)) 335 | { 336 | return pModule; 337 | } 338 | } 339 | return 0; 340 | } 341 | SYSTEM_MODULE * Drv_ResolverLookupModule2(Drv_ResolverContext * pContext, const char * pName) 342 | { 343 | STRING dllName; 344 | RtlInitAnsiString(&dllName, pName); 345 | 346 | STRING halName; 347 | halName.Buffer = "hal.dll"; 348 | halName.Length = 7; 349 | halName.MaximumLength = 7; 350 | 351 | for (int i=0; i < pContext->m_pModInfo->dCount; i++) 352 | { 353 | SYSTEM_MODULE * pModule = pContext->m_pModInfo->aSM + i; 354 | int moduleNameSize = (int)strlen(pModule->abName); 355 | 356 | if (moduleNameSize > dllName.Length) 357 | { 358 | char * pShortName = pModule->abName + moduleNameSize - dllName.Length; 359 | STRING moduleName; 360 | moduleName.Buffer = pShortName; 361 | moduleName.Length = dllName.Length; 362 | moduleName.MaximumLength = dllName.MaximumLength; 363 | 364 | if (RtlCompareString(&dllName, &moduleName, TRUE) == 0) 365 | return pModule; 366 | } 367 | 368 | // cratch for HAL 369 | if (i == 1) 370 | { 371 | if (RtlCompareString(&dllName, &halName, TRUE) == 0) 372 | { 373 | // client wants hal.dll 374 | // but it has the name like this: 375 | // "\SystemRoot\system32\halmacpi.dll" 376 | // return 1st module 377 | return pModule; 378 | } 379 | } 380 | } 381 | return 0; 382 | } 383 | 384 | Drv_Resolver::Drv_Resolver() 385 | : m_bInited(false) 386 | { 387 | memset(&m_context, 0, sizeof(m_context)); 388 | } 389 | Drv_Resolver::~Drv_Resolver() 390 | { 391 | if (m_bInited) 392 | { 393 | Drv_ResolverContextFree(&m_context); 394 | } 395 | } 396 | NTSTATUS Drv_Resolver::Init() 397 | { 398 | NT_CHECK(Drv_ResolverContextInit(&m_context)); 399 | m_bInited = 1; 400 | return NT_OK; 401 | } 402 | SYSTEM_MODULE * Drv_Resolver::LookupModule(const void * pPointer) 403 | { 404 | return Drv_ResolverLookupModule(&m_context, pPointer); 405 | } 406 | SYSTEM_MODULE * Drv_Resolver::LookupModule(const char * pName) 407 | { 408 | return Drv_ResolverLookupModule2(&m_context, pName); 409 | } -------------------------------------------------------------------------------- /src/app/utils/cmnDriver.h: -------------------------------------------------------------------------------- 1 | #ifndef CMN_DRIVER_H 2 | #define CMN_DRIVER_H 3 | 4 | #include "cmnGuards.h" 5 | #include "cmnErrors.h" 6 | 7 | 8 | namespace cmn 9 | { 10 | 11 | class CDriver 12 | { 13 | HandleGuard m_handle; 14 | 15 | public: 16 | CDriver() 17 | { 18 | } 19 | CDriver(const std::wstring & name) 20 | { 21 | Connect(name); 22 | } 23 | 24 | // bug here 25 | void SendIoCtl(DWORD dwCode, LPVOID pBuffer, DWORD BufferSize, DWORD * pResBufferSize) 26 | { 27 | if (!m_handle.get()) 28 | throw std::exception("Driver.SendIoCtl.NotConnected"); 29 | 30 | BOOL result = DeviceIoControl( m_handle.get(), 31 | dwCode, 32 | pBuffer, 33 | BufferSize, 34 | pBuffer, 35 | BufferSize, 36 | pResBufferSize, 37 | NULL ); 38 | if (!result) 39 | { 40 | throw CWinException("Driver.SendIoCtl.CallFailed", GetLastError()); 41 | } 42 | } 43 | void SendIoCtl(DWORD dwCode, LPVOID pBuffer, DWORD MaxBufferSize, DWORD InBufferSize, DWORD * pResBufferSize) 44 | { 45 | if (!m_handle.get()) 46 | throw std::exception("Driver.SendIoCtl.NotConnected"); 47 | 48 | BOOL result = DeviceIoControl( m_handle.get(), 49 | dwCode, 50 | pBuffer, 51 | InBufferSize, 52 | pBuffer, 53 | MaxBufferSize, 54 | pResBufferSize, 55 | NULL ); 56 | if (!result) 57 | { 58 | throw CWinException("Driver.SendIoCtl.CallFailed", GetLastError()); 59 | } 60 | } 61 | bool IsConnected() const 62 | { 63 | return m_handle.get() != 0; 64 | } 65 | bool Connect(const std::wstring & name, bool bSilent=false) 66 | { 67 | HANDLE hdev = CreateFileW( name.c_str(), 68 | GENERIC_READ | GENERIC_WRITE, 69 | FILE_SHARE_READ | FILE_SHARE_WRITE, 70 | NULL, 71 | OPEN_EXISTING, 72 | 0, 73 | NULL); 74 | 75 | if (hdev == INVALID_HANDLE_VALUE) 76 | { 77 | if (!bSilent) 78 | throw CWinException("Driver.Connect.ConnectFailed", GetLastError()); 79 | return false; 80 | } 81 | m_handle.reset( hdev ); 82 | return true; 83 | } 84 | void CreateAndStartService(const std::wstring &serviceName, const std::wstring & fullFileName) 85 | { 86 | SC_HANDLE scm = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); 87 | if(scm == NULL) 88 | { 89 | throw CWinException("Driver.Install.OpenSCManagerFailed", GetLastError()); 90 | } 91 | SCHandleGuard scmGuard(scm); 92 | 93 | // create service 94 | SC_HANDLE service = 95 | CreateServiceW ( scm, 96 | serviceName.c_str(), 97 | serviceName.c_str(), 98 | SERVICE_ALL_ACCESS, 99 | SERVICE_KERNEL_DRIVER, 100 | SERVICE_DEMAND_START, 101 | SERVICE_ERROR_NORMAL, 102 | fullFileName.c_str(), 103 | NULL,NULL, NULL, NULL, NULL); 104 | if (service == NULL) 105 | { 106 | DWORD err = GetLastError(); 107 | if (err == ERROR_SERVICE_EXISTS) 108 | { 109 | service = OpenServiceW(scm, serviceName.c_str(), SERVICE_ALL_ACCESS); 110 | if (service == NULL) 111 | { 112 | throw CWinException("Driver.Install.OpenServiceFailed", GetLastError()); 113 | } 114 | } 115 | else 116 | { 117 | throw CWinException("Driver.Install.CreateServiceFailed", GetLastError()); 118 | } 119 | } 120 | SCHandleGuard serviceGuard(service); 121 | BOOL ret = StartService( service, 122 | 0, 123 | NULL ); 124 | if (!ret) 125 | { 126 | DWORD err = GetLastError(); 127 | if (err == ERROR_SERVICE_ALREADY_RUNNING) 128 | ret = TRUE; 129 | else 130 | { 131 | throw CWinException("Driver.Install.StartFailed", GetLastError()); 132 | } 133 | } 134 | } 135 | }; 136 | 137 | 138 | inline void DeleteServiceSync(const std::wstring & svc_name) 139 | { 140 | SC_HANDLE scm = OpenSCManager(NULL, 141 | NULL, 142 | SC_MANAGER_ALL_ACCESS); 143 | if(scm == NULL) 144 | { 145 | throw CWinException("Driver.DeleteServiceSync.OpenSCManagerFailed", GetLastError()); 146 | } 147 | SCHandleGuard scmGuard(scm); 148 | SC_HANDLE serviceHandle = OpenServiceW(scm, 149 | svc_name.c_str(), 150 | SERVICE_ALL_ACCESS); 151 | 152 | if (serviceHandle == NULL) 153 | { 154 | if (GetLastError()==ERROR_SERVICE_DOES_NOT_EXIST) 155 | return; 156 | CMN_THROW_WIN32("Driver.DeleteServiceSync.OpenServiceW"); 157 | } 158 | SCHandleGuard serviceGuard(serviceHandle); 159 | 160 | DWORD retValue = 0; 161 | SERVICE_STATUS ss; 162 | int ret = ControlService(serviceHandle, SERVICE_CONTROL_STOP, &ss); 163 | while (true) 164 | { 165 | SERVICE_STATUS status = {0}; 166 | if (!QueryServiceStatus(serviceHandle , &status)) 167 | CMN_THROW_WIN32("Driver.DeleteServiceSync.QueryServiceStatus"); 168 | 169 | if (status.dwCurrentState == SERVICE_STOPPED) 170 | break; 171 | 172 | Sleep(500); 173 | } 174 | if (!DeleteService(serviceHandle)) 175 | CMN_THROW_WIN32("Driver.DeleteServiceSync.DeleteService"); 176 | } 177 | 178 | inline bool GetServiceStatus(const std::wstring & svc_name, SERVICE_STATUS * pStatus) 179 | { 180 | memset(pStatus, 0, sizeof(*pStatus)); 181 | SC_HANDLE scm = OpenSCManager(NULL, 182 | NULL, 183 | SC_MANAGER_CONNECT| 184 | SC_MANAGER_ENUMERATE_SERVICE| 185 | SC_MANAGER_QUERY_LOCK_STATUS| 186 | STANDARD_RIGHTS_READ); 187 | if(scm == NULL) 188 | { 189 | throw CWinException("Driver.IsServiceInstalled.OpenSCManagerFailed", GetLastError()); 190 | } 191 | SCHandleGuard scmGuard(scm); 192 | SC_HANDLE service = OpenServiceW(scm, 193 | svc_name.c_str(), 194 | READ_CONTROL| 195 | SERVICE_ENUMERATE_DEPENDENTS| 196 | SERVICE_INTERROGATE| 197 | SERVICE_QUERY_CONFIG| 198 | SERVICE_QUERY_STATUS| 199 | SERVICE_USER_DEFINED_CONTROL); 200 | 201 | if (service == NULL) 202 | { 203 | return false; 204 | } 205 | SCHandleGuard serviceGuard(service); 206 | 207 | BOOL bRes = QueryServiceStatus(service, pStatus); 208 | if (!bRes) 209 | { 210 | throw CWinException("Driver.IsServiceInstalled.QueryServiceStatus", GetLastError()); 211 | } 212 | return true; 213 | } 214 | 215 | inline bool CmnStartService(const std::wstring & svc_name) 216 | { 217 | SC_HANDLE scm = OpenSCManager(NULL, 218 | NULL, 219 | SC_MANAGER_CONNECT| 220 | SC_MANAGER_ENUMERATE_SERVICE| 221 | SC_MANAGER_QUERY_LOCK_STATUS| 222 | STANDARD_RIGHTS_READ); 223 | if(scm == NULL) 224 | { 225 | throw CWinException("Driver.IsServiceInstalled.OpenSCManagerFailed", GetLastError()); 226 | } 227 | SCHandleGuard scmGuard(scm); 228 | SC_HANDLE service = OpenServiceW(scm, 229 | svc_name.c_str(), 230 | READ_CONTROL| 231 | SERVICE_ENUMERATE_DEPENDENTS| 232 | SERVICE_INTERROGATE| 233 | SERVICE_QUERY_CONFIG| 234 | SERVICE_QUERY_STATUS| 235 | SERVICE_USER_DEFINED_CONTROL| 236 | SERVICE_START); 237 | 238 | if (service == NULL) 239 | { 240 | return false; 241 | } 242 | SCHandleGuard serviceGuard(service); 243 | 244 | 245 | BOOL bRes = StartService(service, 0, 0); 246 | if (!bRes) 247 | { 248 | if (GetLastError()!=ERROR_SERVICE_ALREADY_RUNNING) 249 | throw CWinException("Driver.StartService", GetLastError()); 250 | } 251 | return true; 252 | } 253 | 254 | inline bool CmnContinueService(const std::wstring & svc_name) 255 | { 256 | SC_HANDLE scm = OpenSCManager(NULL, 257 | NULL, 258 | SC_MANAGER_CONNECT| 259 | SC_MANAGER_ENUMERATE_SERVICE| 260 | SC_MANAGER_QUERY_LOCK_STATUS| 261 | STANDARD_RIGHTS_READ); 262 | if(scm == NULL) 263 | { 264 | throw CWinException("Driver.IsServiceInstalled.OpenSCManagerFailed", GetLastError()); 265 | } 266 | SCHandleGuard scmGuard(scm); 267 | SC_HANDLE service = OpenServiceW(scm, 268 | svc_name.c_str(), 269 | READ_CONTROL| 270 | SERVICE_ENUMERATE_DEPENDENTS| 271 | SERVICE_INTERROGATE| 272 | SERVICE_QUERY_CONFIG| 273 | SERVICE_QUERY_STATUS| 274 | SERVICE_USER_DEFINED_CONTROL| 275 | SERVICE_CONTROL_CONTINUE); 276 | 277 | if (service == NULL) 278 | { 279 | return false; 280 | } 281 | SCHandleGuard serviceGuard(service); 282 | 283 | 284 | SERVICE_STATUS status; 285 | BOOL bRes = ControlService(service, SERVICE_CONTROL_CONTINUE, &status); 286 | if (!bRes) 287 | { 288 | throw CWinException("Driver.ContinueService", GetLastError()); 289 | } 290 | return true; 291 | } 292 | 293 | struct IServiceStateObserver 294 | { 295 | virtual ~IServiceStateObserver(){} 296 | virtual void on_service_continue_pending()=0; // the service continue is pending. 297 | virtual void on_service_pause_pending()=0; // the service pause is pending. 298 | virtual void on_service_paused()=0; // the service is paused. 299 | virtual void on_service_running()=0; // the service is running. 300 | virtual void on_service_start_pending()=0; // the service is starting. 301 | virtual void on_service_stop_pending()=0; //the service is stopping. 302 | virtual void on_service_stopped()=0; 303 | virtual void on_invalid_status()=0; 304 | }; 305 | 306 | 307 | 308 | inline void DispatchServiceState(DWORD dwState, IServiceStateObserver * pObserver) 309 | { 310 | switch(dwState) 311 | { 312 | case SERVICE_CONTINUE_PENDING: 313 | pObserver->on_service_continue_pending(); 314 | return; 315 | case SERVICE_PAUSE_PENDING: 316 | pObserver->on_service_pause_pending(); 317 | return; 318 | case SERVICE_PAUSED: 319 | pObserver->on_service_paused(); 320 | return; 321 | case SERVICE_RUNNING: 322 | pObserver->on_service_running(); 323 | return; 324 | case SERVICE_START_PENDING: 325 | pObserver->on_service_start_pending(); 326 | return; 327 | case SERVICE_STOP_PENDING: 328 | pObserver->on_service_stop_pending(); 329 | return; 330 | case SERVICE_STOPPED: 331 | pObserver->on_service_stopped(); 332 | return; 333 | default: 334 | pObserver->on_invalid_status(); 335 | return; 336 | } 337 | } 338 | 339 | 340 | struct GetNameServiceStateObserver:IServiceStateObserver 341 | { 342 | std::wstring m_status; 343 | 344 | virtual void on_service_continue_pending() 345 | { 346 | m_status = L"continue_pending"; 347 | } 348 | virtual void on_service_pause_pending() 349 | { 350 | m_status = L"pause_pending"; 351 | } 352 | virtual void on_service_paused() 353 | { 354 | m_status = L"paused"; 355 | } 356 | virtual void on_service_running() 357 | { 358 | m_status = L"service_running"; 359 | } 360 | virtual void on_service_start_pending() 361 | { 362 | m_status = L"start_pending"; 363 | } 364 | virtual void on_service_stop_pending() 365 | { 366 | m_status = L"stop_pending"; 367 | } 368 | virtual void on_service_stopped() 369 | { 370 | m_status = L"stopped"; 371 | } 372 | virtual void on_invalid_status() 373 | { 374 | m_status = L"invalid"; 375 | } 376 | }; 377 | 378 | inline std::wstring GetServiceStatusDefaultName(DWORD dwStatus) 379 | { 380 | GetNameServiceStateObserver observer; 381 | DispatchServiceState(dwStatus, &observer); 382 | return observer.m_status; 383 | } 384 | 385 | 386 | inline std::wstring SymLinkUndecorate(const std::wstring & wstr) 387 | { 388 | size_t to_skip = 0; 389 | for(;to_skip 23 | NTSTATUS AddTaskAndWait(drv::CAutoTask_t & task); 24 | }; 25 | 26 | 27 | NTSTATUS UnhookerDeviceDispatch::Init() 28 | { 29 | // zero variables 30 | KeInitializeEvent( &m_waitEvent, SynchronizationEvent, FALSE ); 31 | KeInitializeEvent( &m_stopEvent, NotificationEvent, FALSE ); 32 | m_pThread = 0; 33 | m_pQueue = 0; 34 | 35 | // init 36 | m_pQueue = new CSyncQueue; 37 | NT_CHECK_ALLOC(m_pQueue); 38 | NT_CHECK(m_pQueue->Init()); 39 | 40 | // start thread 41 | HANDLE hThread = 0; 42 | NTSTATUS status =0; 43 | OBJECT_ATTRIBUTES oa; 44 | 45 | InitializeObjectAttributes(&oa, 0, OBJ_KERNEL_HANDLE, 0, 0); 46 | 47 | status = PsCreateSystemThread(&hThread, 48 | (ACCESS_MASK) 0L, 49 | &oa, 50 | NULL, 51 | NULL, 52 | (PKSTART_ROUTINE)ThreadWorker, 53 | this 54 | ); 55 | if (!NT_SUCCESS(status)) 56 | return status; 57 | 58 | status = ObReferenceObjectByHandle( hThread, 0, NULL, KernelMode, &m_pThread, NULL); 59 | if (!NT_SUCCESS(status)) 60 | { 61 | ZwClose( hThread ); 62 | return status; 63 | } 64 | ZwClose( hThread ); 65 | return STATUS_SUCCESS; 66 | } 67 | 68 | void UnhookerDeviceCleanupRoutine( UnhookerDeviceDispatch * pExtension ) 69 | { 70 | if (pExtension->m_pThread) 71 | { 72 | KeSetEvent( &pExtension->m_stopEvent, 0, FALSE ); 73 | KeWaitForSingleObject(pExtension->m_pThread, Executive, KernelMode, FALSE, NULL); 74 | ObDereferenceObject(pExtension->m_pThread); 75 | } 76 | if (pExtension->m_pQueue) 77 | { 78 | delete pExtension->m_pQueue; 79 | } 80 | } 81 | 82 | template 83 | NTSTATUS UnhookerDeviceDispatch::AddTaskAndWait(drv::CAutoTask_t & task) 84 | { 85 | NT_CHECK(m_pQueue->PushBackSharedTask(task)); 86 | KeSetEvent( &m_waitEvent, 0, FALSE ); 87 | task->Wait(); 88 | return NT_OK; 89 | } 90 | 91 | void ThreadWorker( UnhookerDeviceDispatch * pExtension ) 92 | { 93 | PVOID events[2] = { &pExtension->m_waitEvent, &pExtension->m_stopEvent}; 94 | KWAIT_BLOCK waitBlocks[2]; 95 | 96 | while ( STATUS_WAIT_0 == KeWaitForMultipleObjects 97 | ( 98 | 2, 99 | events, 100 | WaitAny, 101 | Executive, 102 | KernelMode, 103 | FALSE, 104 | NULL, 105 | waitBlocks 106 | ) 107 | ) 108 | { 109 | bool bEmpty = false; 110 | do 111 | { 112 | drv::CAutoTask task; 113 | bEmpty = true; 114 | 115 | NTSTATUS status = pExtension->m_pQueue->PopFirst(task, &bEmpty); 116 | if (!NT_SUCCESS(status)) 117 | { 118 | return; 119 | } 120 | 121 | if (task.get()) 122 | task->Execute(); 123 | } 124 | while(!bEmpty); 125 | 126 | } 127 | } 128 | 129 | class CScanTask:public CSharedTask 130 | { 131 | NTSTATUS m_status; 132 | PVOID m_pRtlPrefetchMemoryNonTemporal; 133 | 134 | Drv_VirginityContext2 m_virginityContext; 135 | 136 | virtual NTSTATUS DoInit() { return NT_OK; } 137 | virtual NTSTATUS OnSSTPatch(void ** pCurrentHandler, 138 | void * pRealHandler, 139 | int , 140 | bool * pNeedBreak) 141 | { 142 | // restore SST 143 | Drv_HookSST(pCurrentHandler, pRealHandler); 144 | *pNeedBreak = false; 145 | return NT_OK; 146 | } 147 | 148 | virtual NTSTATUS OnModification(const Drv_VirginityContext2 * pContext, 149 | bool * pNeedBreak) 150 | { 151 | const char * pMappedSectionStart = Drv_GetMappedSectionStart( pContext ); 152 | char * pMemorySectionStart = (char * )pContext->m_currentSectionInfo.m_sectionStart; 153 | 154 | Drv_HookMemCpy(pContext->m_startOfModification + pMemorySectionStart, 155 | pContext->m_startOfModification + pMappedSectionStart, 156 | pContext->m_endOfModification - pContext->m_startOfModification); 157 | 158 | *pNeedBreak = false; 159 | return NT_OK; 160 | } 161 | 162 | virtual NTSTATUS ScanSST() 163 | { 164 | for(int i = 0, sstSize = Drv_GetSizeOfNtosSST(); 165 | i < sstSize; 166 | ++i) 167 | { 168 | void ** pCurrentHandler = Drv_GetNtosSSTEntry(i); 169 | 170 | void * pRealHandler = 0; 171 | Drv_GetRealSSTValue2(&m_virginityContext, i, &pRealHandler); 172 | if (pRealHandler != *pCurrentHandler) 173 | { 174 | bool needBreak = false; 175 | NT_CHECK(OnSSTPatch(pCurrentHandler, pRealHandler, i, &needBreak)); 176 | } 177 | } 178 | return STATUS_SUCCESS; 179 | } 180 | 181 | virtual NTSTATUS ScanAllModule() 182 | { 183 | void * pStart = 0; 184 | int size = 0; 185 | NT_CHECK(Drv_GetFirstModification(&m_virginityContext, 186 | &pStart, 187 | &size)); 188 | while(pStart) 189 | { 190 | bool needBreak = false; 191 | 192 | // check RtlPrefetchMemoryNonTemporal 193 | bool bSkip = false; 194 | 195 | { 196 | char * pMemorySectionStart = (char * )m_virginityContext.m_currentSectionInfo.m_sectionStart; 197 | if (m_virginityContext.m_startOfModification + pMemorySectionStart == m_pRtlPrefetchMemoryNonTemporal 198 | && m_virginityContext.m_endOfModification - m_virginityContext.m_startOfModification == 1) 199 | { 200 | // skip it 201 | bSkip = true; 202 | } 203 | } 204 | 205 | if (!bSkip) 206 | { 207 | NT_CHECK(OnModification(&m_virginityContext, &needBreak)); 208 | } 209 | 210 | NT_CHECK( Drv_GetNextModification(&m_virginityContext, 211 | &pStart, 212 | &size)); 213 | 214 | } 215 | return STATUS_SUCCESS; 216 | } 217 | 218 | virtual NTSTATUS ExecuteReal() 219 | { 220 | CAutoVirginity2 initer; 221 | NT_CHECK(initer.Init(&m_virginityContext)); 222 | 223 | UNICODE_STRING fncName; 224 | RtlInitUnicodeString(&fncName, L"RtlPrefetchMemoryNonTemporal"); 225 | m_pRtlPrefetchMemoryNonTemporal = MmGetSystemRoutineAddress(&fncName); 226 | 227 | NT_CHECK(DoInit()); 228 | 229 | NT_CHECK(ScanSST()); 230 | 231 | NT_CHECK(ScanAllModule()); 232 | 233 | return NT_OK; 234 | } 235 | virtual void ExecuteImpl() 236 | { 237 | m_status = ExecuteReal(); 238 | } 239 | protected: 240 | Drv_VirginityContext2 * GetVirginityContext() { return &m_virginityContext; } 241 | 242 | public: 243 | CScanTask() 244 | { 245 | m_pRtlPrefetchMemoryNonTemporal = 0; 246 | m_status = STATUS_UNSUCCESSFUL; 247 | } 248 | NTSTATUS GetStatus() 249 | { 250 | return m_status; 251 | } 252 | }; 253 | 254 | static 255 | NTSTATUS DispatchUnhook(PDEVICE_OBJECT pDeviceObject, 256 | drv::UnhookerDeviceDispatch * pExtension, 257 | void * pBuffer, 258 | size_t size, 259 | size_t outSizeIn, 260 | size_t * pOutSizeOut) 261 | { 262 | drv::CAutoTask_t task(new CScanTask()); 263 | NT_CHECK_ALLOC(task.get()); 264 | NT_CHECK(pExtension->AddTaskAndWait(task)); 265 | NT_CHECK(task->GetStatus()); 266 | return STATUS_SUCCESS; 267 | } 268 | 269 | class CReportingScanTask:public CScanTask 270 | { 271 | int m_countOfModifiedSSTEntries; 272 | 273 | char * m_pPackBegin; 274 | char * m_pPackEnd; 275 | char * m_pPackCur; 276 | DRV_REPORT * m_pReport; 277 | 278 | 279 | virtual NTSTATUS OnSSTPatch(void ** pCurrentHandler, 280 | void * pRealHandler, 281 | int index, 282 | bool * pNeedBreak) 283 | { 284 | *pNeedBreak = false; 285 | 286 | ++m_pReport->m_countOfModifiedSSTEntries; 287 | SYSTEM_MODULE * pModule = GetVirginityContext()->m_resolver.LookupModule(*pCurrentHandler); 288 | 289 | ANSI_STRING kernelAnsiName; 290 | if (pModule) 291 | { 292 | RtlInitAnsiString(&kernelAnsiName, (char*)pModule->abName + pModule->wNameOffset); 293 | } 294 | else 295 | { 296 | RtlInitAnsiString(&kernelAnsiName, "-unknown-"); 297 | } 298 | 299 | 300 | if (m_pPackCur + kernelAnsiName.Length + sizeof(DRV_REPORT_SST_ENTRY) <= m_pPackEnd) 301 | { 302 | DRV_REPORT_SST_ENTRY * pPackedEntry = (DRV_REPORT_SST_ENTRY * )m_pPackCur; 303 | memset(pPackedEntry, 0, sizeof(DRV_REPORT_SST_ENTRY)); 304 | 305 | pPackedEntry->m_base.m_type = dreSST; 306 | pPackedEntry->m_base.m_sizeOfEntry = kernelAnsiName.Length + sizeof(DRV_REPORT_SST_ENTRY); 307 | pPackedEntry->m_sstIndex = index; 308 | if (pModule) 309 | { 310 | pPackedEntry->m_moduleAddress = (size_t)pModule->pAddress; 311 | } 312 | else 313 | { 314 | pPackedEntry->m_moduleAddress = 0; 315 | } 316 | pPackedEntry->m_newAddress = (size_t)*pCurrentHandler; 317 | 318 | pPackedEntry->m_nameOffset = sizeof(DRV_REPORT_SST_ENTRY); 319 | pPackedEntry->m_nameSize = kernelAnsiName.Length; 320 | memcpy(pPackedEntry+1, kernelAnsiName.Buffer, kernelAnsiName.Length); 321 | 322 | ++m_pReport->m_countOfReportEntries; 323 | m_pPackCur += pPackedEntry->m_base.m_sizeOfEntry; 324 | } 325 | return NT_OK; 326 | } 327 | 328 | virtual NTSTATUS OnModification(const Drv_VirginityContext2 * pContext, 329 | bool * pNeedBreak) 330 | { 331 | *pNeedBreak = false; 332 | 333 | ++m_pReport->m_countOfModifiedImageEntries; 334 | 335 | if (m_pPackCur + sizeof(DRV_REPORT_MODIFICATION_ENTRY) <= m_pPackEnd) 336 | { 337 | DRV_REPORT_MODIFICATION_ENTRY * pPackedEntry = (DRV_REPORT_MODIFICATION_ENTRY * )m_pPackCur; 338 | memset(pPackedEntry, 0, sizeof(DRV_REPORT_MODIFICATION_ENTRY)); 339 | 340 | pPackedEntry->m_base.m_type = dreModification; 341 | pPackedEntry->m_base.m_sizeOfEntry = sizeof(DRV_REPORT_MODIFICATION_ENTRY); 342 | 343 | char * pMemorySectionStart = (char * )pContext->m_currentSectionInfo.m_sectionStart; 344 | pPackedEntry->m_address = (unsigned long long)(pMemorySectionStart + pContext->m_startOfModification); 345 | 346 | pPackedEntry->m_offsetInSection = pContext->m_startOfModification; 347 | pPackedEntry->m_sizeOfModification = pContext->m_endOfModification - pContext->m_startOfModification; 348 | memcpy(pPackedEntry->m_sectionName, 349 | pContext->m_pMappedSection->Name, 350 | sizeof(pContext->m_pMappedSection->Name)); 351 | 352 | ++m_pReport->m_countOfReportEntries; 353 | m_pPackCur += pPackedEntry->m_base.m_sizeOfEntry; 354 | } 355 | return NT_OK; 356 | } 357 | 358 | public: 359 | CReportingScanTask(DRV_REPORT * pReport, size_t outSizeIn) 360 | : m_pReport(pReport) 361 | { 362 | memset(pReport, 0, sizeof(DRV_REPORT)); 363 | pReport->m_countOfModifiedImageEntries = 0; 364 | pReport->m_countOfModifiedSSTEntries = 0; 365 | pReport->m_countOfReportEntries = 0; 366 | pReport->m_reportEntryOffsets = sizeof(DRV_REPORT); 367 | 368 | m_pPackBegin = (char*)m_pReport + m_pReport->m_reportEntryOffsets; 369 | m_pPackCur = m_pPackBegin; 370 | m_pPackEnd = (char*)m_pReport + outSizeIn; 371 | } 372 | 373 | size_t GetReportSize() const 374 | { 375 | return (char*)m_pPackCur - (char*)m_pReport; 376 | } 377 | }; 378 | 379 | 380 | static 381 | NTSTATUS DispatchGetStatus(PDEVICE_OBJECT pDeviceObject, 382 | drv::UnhookerDeviceDispatch * pExtension, 383 | void * pBuffer, 384 | size_t size, 385 | size_t outSizeIn, 386 | size_t * pOutSizeOut) 387 | { 388 | if (outSizeIn < sizeof(DRV_REPORT)) 389 | { 390 | return STATUS_BUFFER_OVERFLOW; 391 | } 392 | 393 | DRV_REPORT * pReport = (DRV_REPORT * )pBuffer; 394 | 395 | drv::CAutoTask_t task(new CReportingScanTask(pReport, outSizeIn)); 396 | NT_CHECK_ALLOC(task.get()); 397 | NT_CHECK(pExtension->AddTaskAndWait(task)); 398 | NT_CHECK(task->GetStatus()); 399 | 400 | // pack out param 401 | *pOutSizeOut = task->GetReportSize();; 402 | return STATUS_SUCCESS; 403 | } 404 | 405 | 406 | static 407 | NTSTATUS UnhookerDeviceDispatchRoutine( 408 | IN PDEVICE_OBJECT pDeviceObject, 409 | IN PIRP pIrp, 410 | IN drv::UnhookerDeviceDispatch * pExtension 411 | ) 412 | { 413 | PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(pIrp); 414 | switch(irpSp->MajorFunction) 415 | { 416 | case IRP_MJ_CREATE: return CompleteIrp(pIrp); 417 | case IRP_MJ_CLOSE: return CompleteIrp(pIrp); 418 | case IRP_MJ_DEVICE_CONTROL: 419 | { 420 | NTSTATUS status = 0; 421 | size_t minor = irpSp->Parameters.DeviceIoControl.IoControlCode; 422 | size_t outSizeIn = irpSp->Parameters.DeviceIoControl.OutputBufferLength; 423 | size_t outSizeOut = 0; 424 | 425 | switch(minor) 426 | { 427 | case DRV_UNHOOKER_GET_STATUS: 428 | { 429 | status = DispatchGetStatus(pDeviceObject, 430 | pExtension, 431 | pIrp->AssociatedIrp.SystemBuffer, 432 | irpSp->Parameters.DeviceIoControl.InputBufferLength, 433 | outSizeIn, 434 | &outSizeOut); 435 | break; 436 | } 437 | case DRV_UNHOOKER_UNHOOK: 438 | { 439 | status = DispatchUnhook(pDeviceObject, 440 | pExtension, 441 | pIrp->AssociatedIrp.SystemBuffer, 442 | irpSp->Parameters.DeviceIoControl.InputBufferLength, 443 | outSizeIn, 444 | &outSizeOut); 445 | break; 446 | } 447 | default: 448 | status = STATUS_INVALID_DEVICE_REQUEST; 449 | } 450 | return CompleteIrp(pIrp, status, outSizeOut); 451 | } 452 | }; 453 | return CompleteIrp(pIrp, STATUS_INVALID_DEVICE_REQUEST); 454 | } 455 | 456 | 457 | NTSTATUS CreateUnhookerDevice(IN PDRIVER_OBJECT pDriverObject, 458 | OUT drv::CDeviceOwner & deviceObject) 459 | { 460 | UNICODE_STRING devName; 461 | RtlInitUnicodeString(&devName, DRV_UNHOOKER_DEVICE_NAME); 462 | 463 | NT_CHECK(IoCreateDevice(pDriverObject, 464 | sizeof(drv::UnhookerDeviceDispatch), 465 | &devName, 466 | FILE_DEVICE_UNKNOWN, 467 | 0, 468 | FALSE, 469 | deviceObject.GetPtr2())); 470 | 471 | 472 | drv::UnhookerDeviceDispatch * pExtension = InitCommonDeviceExtension(deviceObject.get(), 473 | UnhookerDeviceDispatchRoutine, 474 | UnhookerDeviceCleanupRoutine 475 | ); 476 | NT_CHECK(pExtension->Init()); 477 | 478 | 479 | 480 | // create symlink 481 | UNICODE_STRING devSymLink; 482 | RtlInitUnicodeString(&devSymLink, DRV_UNHOOKER_DEVICE_SYMBOLIC_LINK); 483 | 484 | NT_CHECK(IoCreateSymbolicLink(&devSymLink, &devName)); 485 | return STATUS_SUCCESS; 486 | } 487 | 488 | 489 | } 490 | -------------------------------------------------------------------------------- /src/driver/drvUtils/drv_NtDefinitions.h: -------------------------------------------------------------------------------- 1 | #ifndef DRV_NT_DEFINITIONS_H 2 | #define DRV_NT_DEFINITIONS_H 3 | 4 | //--------------------------------------------------------------------------------------- 5 | // versions 6 | 7 | typedef struct _OSVERSIONINFOEXW_CMN { 8 | ULONG dwOSVersionInfoSize; 9 | ULONG dwMajorVersion; 10 | ULONG dwMinorVersion; 11 | ULONG dwBuildNumber; 12 | ULONG dwPlatformId; 13 | WCHAR szCSDVersion[ 128 ]; // Maintenance string for PSS usage 14 | USHORT wServicePackMajor; 15 | USHORT wServicePackMinor; 16 | USHORT wSuiteMask; 17 | UCHAR wProductType; 18 | UCHAR wReserved; 19 | } OSVERSIONINFOEXW_CMN, 20 | *POSVERSIONINFOEXW_CMN, 21 | *LPOSVERSIONINFOEXW_CMN, 22 | RTL_OSVERSIONINFOEXW_CMN, 23 | *PRTL_OSVERSIONINFOEXW_CMN; 24 | 25 | 26 | typedef NTSTATUS 27 | (*RtlGetVersionProc)( 28 | OUT POSVERSIONINFOEXW_CMN lpVersionInformation 29 | ); 30 | 31 | //--------------------------------------------------------------------------------------- 32 | // Hooking supply 33 | //--------------------------------------------------------------------------------------- 34 | #define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1) 35 | 36 | typedef NTSTATUS (NTAPI *NTPROC) (); 37 | typedef NTPROC *PNTPROC; 38 | typedef struct _SYSTEM_SERVICE_TABLE 39 | { 40 | /*000*/ PNTPROC ServiceTable; // array of entry points 41 | /*004*/ ULONG * CounterTable; // array of usage counters 42 | /*008*/ ULONG ServiceLimit; // number of table entries 43 | /*00C*/ UCHAR * ArgumentTable; // array of byte counts 44 | /*010*/ 45 | }SYSTEM_SERVICE_TABLE, * PSYSTEM_SERVICE_TABLE, **PPSYSTEM_SERVICE_TABLE; 46 | 47 | typedef struct _SERVICE_DESCRIPTOR_TABLE 48 | { 49 | /*000*/ SYSTEM_SERVICE_TABLE ntoskrnl; // ntoskrnl.exe (native api) 50 | /*010*/ SYSTEM_SERVICE_TABLE win32k; // win32k.sys (gdi/user) 51 | /*020*/ SYSTEM_SERVICE_TABLE Table3; // not used 52 | /*030*/ SYSTEM_SERVICE_TABLE Table4; // not used 53 | /*040*/ 54 | }SERVICE_DESCRIPTOR_TABLE, * PSERVICE_DESCRIPTOR_TABLE, **PPSERVICE_DESCRIPTOR_TABLE; 55 | 56 | //--------------------------------------------------------------------------------------- 57 | // TOKENS 58 | //--------------------------------------------------------------------------------------- 59 | NTSTATUS 60 | ZwOpenProcessToken( 61 | HANDLE Token, 62 | ULONG TokenRights, 63 | PVOID pointHandle 64 | ); 65 | 66 | NTSTATUS 67 | ZwOpenThreadToken(IN HANDLE ThreadHandle, 68 | IN ACCESS_MASK DesiredAccess, 69 | IN BOOLEAN OpenAsSelf, 70 | OUT PHANDLE TokenHandle); 71 | 72 | //--------------------------------------------------------------------------------------- 73 | // QUERIES 74 | //--------------------------------------------------------------------------------------- 75 | typedef NTSTATUS (*ZwDelayExecutionProc)(IN BOOLEAN Alertable, IN PLARGE_INTEGER Interval); 76 | // 77 | // Process Device Map information 78 | // NtQueryInformationProcess using ProcessDeviceMap 79 | // NtSetInformationProcess using ProcessDeviceMap 80 | // 81 | 82 | 83 | typedef struct _SYSTEM_MODULE 84 | { 85 | ULONG dReserved01; 86 | ULONG d04; 87 | PVOID pAddress; 88 | ULONG dSize; // bytes 89 | ULONG dFlags; 90 | USHORT wId; // zero based 91 | USHORT wRank; // 0 if not assigned 92 | USHORT w18; 93 | USHORT wNameOffset; 94 | CHAR abName [MAXIMUM_FILENAME_LENGTH]; 95 | } SYSTEM_MODULE, * PSYSTEM_MODULE, **PPSYSTEM_MODULE; 96 | 97 | #define SYSTEM_MODULE_ \ 98 | sizeof (SYSTEM_MODULE) 99 | 100 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 101 | 102 | typedef struct _SYSTEM_MODULE_INFORMATION 103 | { 104 | ULONG dCount; 105 | SYSTEM_MODULE aSM [1]; 106 | } 107 | SYSTEM_MODULE_INFORMATION, 108 | * PSYSTEM_MODULE_INFORMATION, 109 | **PPSYSTEM_MODULE_INFORMATION; 110 | 111 | #define SYSTEM_MODULE_INFORMATION_ \ 112 | sizeof (SYSTEM_MODULE_INFORMATION) 113 | 114 | #define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1) 115 | 116 | typedef unsigned __int64 QWORD; 117 | 118 | typedef struct _SYSTEM_THREAD 119 | { 120 | QWORD qKernelTime; // 100 nsec units 121 | QWORD qUserTime; // 100 nsec units 122 | QWORD qCreateTime; // relative to 01-01-1601 123 | ULONG d18; 124 | PVOID pStartAddress; 125 | CLIENT_ID Cid; // process/thread ids 126 | ULONG dPriority; 127 | ULONG dBasePriority; 128 | ULONG dContextSwitches; 129 | ULONG dThreadState; // 2=running, 5=waiting 130 | KWAIT_REASON WaitReason; 131 | ULONG dReserved01; 132 | } 133 | SYSTEM_THREAD, 134 | * PSYSTEM_THREAD, 135 | **PPSYSTEM_THREAD; 136 | 137 | #define SYSTEM_THREAD_ \ 138 | sizeof (SYSTEM_THREAD) 139 | 140 | typedef struct _SYSTEM_THREAD_INFORMATION { 141 | LARGE_INTEGER KernelTime; 142 | LARGE_INTEGER UserTime; 143 | LARGE_INTEGER CreateTime; 144 | ULONG WaitTime; 145 | PVOID StartAddress; 146 | CLIENT_ID ClientId; 147 | KPRIORITY Priority; 148 | LONG BasePriority; 149 | ULONG ContextSwitches; 150 | ULONG ThreadState; 151 | ULONG WaitReason; 152 | } SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; 153 | 154 | // 155 | // Process Virtual Memory read\write 156 | // 157 | 158 | typedef 159 | NTSTATUS 160 | (*ZwWriteVirtualMemoryProc)( 161 | HANDLE ProcessHandle, 162 | PVOID BaseAddress, 163 | PVOID Buffer, 164 | ULONG BufferSize, 165 | PULONG NumberOfBytesWritten 166 | ); 167 | 168 | typedef 169 | NTSTATUS 170 | (*ZwReadVirtualMemoryProc)( 171 | HANDLE ProcessHandle, 172 | PVOID BaseAddress, 173 | PVOID Buffer, 174 | ULONG BufferSize, 175 | PULONG NumberOfBytesRead 176 | ); 177 | 178 | // 179 | // Process Virtual Memory Counters 180 | // NtQueryInformationProcess using ProcessVmCounters 181 | // 182 | 183 | 184 | 185 | typedef PVOID POBJECT; 186 | #define MAXPATHLEN 1024 187 | #define MAXNTPATH 260 188 | 189 | #define DRIVE_UNKNOWN 0 190 | #define DRIVE_NO_ROOT_DIR 1 191 | #define DRIVE_REMOVABLE 2 192 | #define DRIVE_FIXED 3 193 | #define DRIVE_REMOTE 4 194 | #define DRIVE_CDROM 5 195 | #define DRIVE_RAMDISK 6 196 | 197 | 198 | typedef struct _OBJECT_DIRECTORY_INFORMATION { 199 | UNICODE_STRING ObjectName; 200 | UNICODE_STRING ObjectType; 201 | WCHAR StringData[1]; 202 | } OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION; 203 | 204 | typedef USHORT SECURITY_DESCRIPTOR_CONTROL, *PSECURITY_DESCRIPTOR_CONTROL; 205 | 206 | 207 | typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { 208 | LARGE_INTEGER IdleTime; 209 | LARGE_INTEGER KernelTime; 210 | LARGE_INTEGER UserTime; 211 | LARGE_INTEGER Reserved1[2]; 212 | ULONG Reserved2; 213 | } SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; 214 | #define MAX_PROCESSOR 32 215 | 216 | typedef struct _SYSTEM_BASIC_INFORMATION { 217 | CHAR Reserved1[24]; 218 | PVOID Reserved2[4]; 219 | CHAR NumberOfProcessors; 220 | } SYSTEM_BASIC_INFORMATION; 221 | 222 | 223 | typedef enum _SECTION_INFORMATION_CLASS 224 | { 225 | SectionBasicInformation, 226 | SectionImageInformation 227 | }SECTION_INFORMATION_CLASS; 228 | 229 | typedef struct _SECTION_BASIC_INFORMATION 230 | { 231 | PVOID BaseAddress; 232 | LARGE_INTEGER MaximumSize; 233 | ULONG AllocationAttributes; 234 | } SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION; 235 | 236 | typedef struct _SECTION_IMAGE_INFORMATION 237 | { 238 | ULONG EntryPoint; 239 | ULONG StackZeroBits; 240 | ULONG_PTR StackReserve; 241 | ULONG_PTR StackCommit; 242 | ULONG Subsystem; 243 | USHORT MinorSubsystemVersion; 244 | USHORT MajorSubsystemVersion; 245 | ULONG Unknown2; 246 | ULONG Characteristics; 247 | USHORT ImageNumber; 248 | BOOLEAN Executable; 249 | UCHAR Unknown3; 250 | ULONG Unknown4[3]; 251 | } SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION; 252 | 253 | #define SIZE_OF_TOKEN_INFORMATION \ 254 | sizeof( TOKEN_USER ) \ 255 | + sizeof( SID ) \ 256 | + sizeof( ULONG ) * SID_MAX_SUB_AUTHORITIES 257 | 258 | 259 | 260 | #define SEC_COMMIT 0x8000000 261 | 262 | typedef enum _OBJECT_INFORMATION_CLASS 263 | { 264 | ObjectBasicInformation, 265 | ObjectNameInformation, 266 | ObjectTypeInformation, 267 | ObjectAllTypesInformation, 268 | ObjectHandleFlagInformation 269 | } OBJECT_INFORMATION_CLASS; 270 | 271 | typedef struct _OBJECT_BASIC_INFORMATION 272 | { 273 | ULONG Attributes; 274 | ACCESS_MASK GrantedAccess; 275 | ULONG HandleCount; 276 | ULONG PointerCount; 277 | ULONG PagedPoolCharge; 278 | ULONG NonPagedPoolCharge; 279 | LARGE_INTEGER CreationTime; 280 | ULONG NameInfoSize; 281 | ULONG TypeInfoSize; 282 | ULONG SecurityDescriptorSize; 283 | CHAR Unknown2[8]; 284 | } OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION; 285 | 286 | //--------------------------------------------------------------------------------------- 287 | // COMMON PROTOTYPES 288 | //--------------------------------------------------------------------------------------- 289 | 290 | 291 | NTKERNELAPI 292 | NTSTATUS 293 | ObOpenObjectByName( 294 | IN POBJECT_ATTRIBUTES ObjectAttributes, 295 | IN POBJECT_TYPE ObjectType, 296 | IN KPROCESSOR_MODE AccessMode, 297 | IN OUT PACCESS_STATE PassedAccessState OPTIONAL, 298 | IN ACCESS_MASK DesiredAccess OPTIONAL, 299 | IN OUT PVOID ParseContext OPTIONAL, 300 | OUT PHANDLE Handle 301 | ); 302 | 303 | NTSYSAPI 304 | NTSTATUS 305 | NTAPI 306 | ZwCreateSection ( 307 | OUT PHANDLE SectionHandle, 308 | IN ACCESS_MASK DesiredAccess, 309 | IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 310 | IN PLARGE_INTEGER MaximumSize OPTIONAL, 311 | IN ULONG SectionPageProtection, 312 | IN ULONG AllocationAttributes, 313 | IN HANDLE FileHandle OPTIONAL 314 | ); 315 | 316 | NTSYSAPI 317 | NTSTATUS 318 | NTAPI 319 | ZwUnmapViewOfSection( 320 | IN HANDLE ProcessHandle, 321 | IN PVOID BaseAddress 322 | ); 323 | 324 | NTSYSAPI 325 | NTSTATUS 326 | NTAPI 327 | ZwAllocateVirtualMemory( 328 | IN HANDLE ProcessHandle, 329 | IN OUT PVOID *BaseAddress, 330 | IN ULONG ZeroBits, 331 | IN OUT PSIZE_T RegionSize, 332 | IN ULONG AllocationType, 333 | IN ULONG Protect 334 | ); 335 | 336 | NTSYSAPI 337 | NTSTATUS 338 | NTAPI 339 | ZwReadVirtualMemory ( 340 | IN HANDLE ProcessHandle, 341 | IN PVOID BaseAddress, 342 | OUT PVOID Buffer, 343 | IN ULONG BufferSize, 344 | OUT PULONG NumberOfBytesRead 345 | ); 346 | 347 | NTSYSAPI 348 | NTSTATUS 349 | NTAPI 350 | ZwFreeVirtualMemory( 351 | IN HANDLE ProcessHandle, 352 | IN OUT PVOID *BaseAddress, 353 | IN OUT PSIZE_T RegionSize, 354 | IN ULONG FreeType 355 | ); 356 | NTSYSAPI 357 | NTSTATUS 358 | NTAPI 359 | ZwQueryDirectoryFile( 360 | IN HANDLE FileHandle, 361 | IN HANDLE Event OPTIONAL, 362 | IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 363 | IN PVOID ApcContext OPTIONAL, 364 | OUT PIO_STATUS_BLOCK IoStatusBlock, 365 | OUT PVOID FileInformation, 366 | IN ULONG Length, 367 | IN FILE_INFORMATION_CLASS FileInformationClass, 368 | IN BOOLEAN ReturnSingleEntry, 369 | IN PUNICODE_STRING FileName OPTIONAL, 370 | IN BOOLEAN RestartScan 371 | ); 372 | 373 | NTSYSAPI 374 | NTSTATUS 375 | NTAPI 376 | ZwQueryInformationProcess( 377 | IN HANDLE ProcessHandle, 378 | IN PROCESSINFOCLASS ProcessInformationClass, 379 | OUT PVOID ProcessInformation, 380 | IN ULONG ProcessInformationLength, 381 | OUT PULONG ReturnLength OPTIONAL 382 | ); 383 | NTSTATUS 384 | ObReferenceObjectByName( 385 | IN PUNICODE_STRING ObjectName, 386 | IN ULONG Attributes, 387 | IN PACCESS_STATE PassedAccessState OPTIONAL, 388 | IN ACCESS_MASK DesiredAccess OPTIONAL, 389 | IN POBJECT_TYPE ObjectType, 390 | IN KPROCESSOR_MODE AccessMode, 391 | IN OUT PVOID ParseContext OPTIONAL, 392 | OUT PVOID *Object 393 | ); 394 | NTSYSAPI 395 | NTSTATUS 396 | NTAPI 397 | ZwOpenDirectoryObject( 398 | OUT PHANDLE DirectoryHandle, 399 | IN ACCESS_MASK DesiredAccess, 400 | IN POBJECT_ATTRIBUTES ObjectAttributes 401 | ); 402 | NTSYSAPI 403 | NTSTATUS 404 | NTAPI 405 | ZwQueryDirectoryObject ( 406 | IN HANDLE DirectoryHandle, 407 | OUT PVOID Buffer, 408 | IN ULONG Length, 409 | IN BOOLEAN ReturnSingleEntry, 410 | IN BOOLEAN RestartScan, 411 | IN OUT PULONG Context, 412 | OUT PULONG ReturnLength OPTIONAL 413 | ); 414 | 415 | NTSYSAPI 416 | NTSTATUS 417 | NTAPI 418 | ZwOpenSymbolicLinkObject( 419 | OUT PHANDLE LinkHandle, 420 | IN ACCESS_MASK DesiredAccess, 421 | IN POBJECT_ATTRIBUTES ObjectAttributes 422 | ); 423 | 424 | NTSYSAPI 425 | NTSTATUS 426 | NTAPI 427 | ZwQuerySymbolicLinkObject( 428 | IN HANDLE LinkHandle, 429 | IN OUT PUNICODE_STRING LinkTarget, 430 | OUT PULONG ReturnedLength OPTIONAL 431 | ); 432 | 433 | NTSYSAPI 434 | NTSTATUS 435 | NTAPI 436 | ZwQueryVolumeInformationFile( 437 | IN HANDLE FileHandle, 438 | OUT PIO_STATUS_BLOCK IoStatusBlock, 439 | OUT PVOID FsInformation, 440 | IN ULONG Length, 441 | IN FS_INFORMATION_CLASS FsInformationClass 442 | ); 443 | 444 | NTSYSCALLAPI 445 | NTSTATUS 446 | NTAPI 447 | NtOpenFile( 448 | OUT PHANDLE FileHandle, 449 | IN ACCESS_MASK DesiredAccess, 450 | IN POBJECT_ATTRIBUTES ObjectAttributes, 451 | OUT PIO_STATUS_BLOCK IoStatusBlock, 452 | IN ULONG ShareAccess, 453 | IN ULONG OpenOptions 454 | ); 455 | 456 | NTSYSCALLAPI 457 | NTSTATUS 458 | NTAPI 459 | NtClose( 460 | IN HANDLE Handle 461 | ); 462 | 463 | NTSYSCALLAPI 464 | NTSTATUS 465 | NTAPI 466 | ZwOpenProcess ( 467 | OUT PHANDLE ProcessHandle, 468 | IN ACCESS_MASK DesiredAccess, 469 | IN POBJECT_ATTRIBUTES ObjectAttributes, 470 | IN PCLIENT_ID ClientId OPTIONAL 471 | ); 472 | 473 | NTSYSCALLAPI 474 | NTSTATUS 475 | NTAPI 476 | ZwQuerySection( 477 | IN HANDLE SectionHandle, 478 | IN SECTION_INFORMATION_CLASS SectionInformationClass, 479 | OUT PVOID SectionInformation, 480 | IN ULONG SectionInformationLength, 481 | OUT PULONG ReturnLength OPTIONAL 482 | ); 483 | 484 | NTSYSCALLAPI 485 | NTSTATUS 486 | NTAPI 487 | ZwFsControlFile( 488 | IN HANDLE FileHandle, 489 | IN HANDLE Event OPTIONAL, 490 | IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 491 | IN PVOID ApcContext OPTIONAL, 492 | OUT PIO_STATUS_BLOCK IoStatusBlock, 493 | IN ULONG FsControlCode, 494 | IN PVOID InputBuffer OPTIONAL, 495 | IN ULONG InputBufferLength, 496 | OUT PVOID OutputBuffer OPTIONAL, 497 | IN ULONG OutputBufferLength 498 | ); 499 | 500 | NTSYSCALLAPI 501 | NTSTATUS 502 | NTAPI 503 | ZwQueryObject ( 504 | IN HANDLE Handle, 505 | IN OBJECT_INFORMATION_CLASS ObjectInformationClass, 506 | OUT PVOID ObjectInformation, 507 | IN ULONG ObjectInformationLength, 508 | OUT PULONG ReturnLength OPTIONAL 509 | ); 510 | 511 | NTKERNELAPI 512 | NTSTATUS 513 | ObQueryNameString(PVOID Object, 514 | POBJECT_NAME_INFORMATION ObjectNameInfo, 515 | ULONG Length, 516 | PULONG ReturnLength); 517 | 518 | 519 | NTSTATUS 520 | ZwOpenEvent( 521 | OUT PHANDLE EventHandle, 522 | IN ACCESS_MASK DesiredAccess, 523 | IN POBJECT_ATTRIBUTES ObjectAttributes 524 | ); 525 | 526 | NTSTATUS 527 | ZwNotifyChangeKey( 528 | IN HANDLE KeyHandle, 529 | IN HANDLE Event, 530 | IN PIO_APC_ROUTINE ApcRoutine, 531 | IN PVOID ApcContext, 532 | OUT PIO_STATUS_BLOCK IoStatusBlock, 533 | IN ULONG CompletionFilter, 534 | IN BOOLEAN WatchTree, 535 | OUT PVOID Buffer, 536 | IN ULONG BufferSize, 537 | IN BOOLEAN Asynchronous 538 | ); 539 | 540 | 541 | 542 | 543 | #define IMAGE_SIZEOF_SHORT_NAME 8 544 | 545 | #endif 546 | -------------------------------------------------------------------------------- /src/driver/drvUtils/drvVirginity2.cpp: -------------------------------------------------------------------------------- 1 | #include "drvVirginity2.h" 2 | 3 | extern "C" 4 | { 5 | NTSYSAPI 6 | PIMAGE_NT_HEADERS 7 | NTAPI 8 | RtlImageNtHeader(IN PVOID ModuleAddress ); 9 | 10 | NTSYSAPI 11 | PVOID 12 | NTAPI 13 | RtlImageDirectoryEntryToData ( 14 | PVOID, 15 | BOOLEAN, 16 | ULONG, 17 | ULONG *); 18 | } 19 | 20 | static 21 | ULONG ConvertVAToRaw(PIMAGE_NT_HEADERS pNtHeaders, 22 | ULONG virtualAddr) 23 | { 24 | PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((char*)&(pNtHeaders->FileHeader)+ 25 | pNtHeaders->FileHeader.SizeOfOptionalHeader+ 26 | sizeof(IMAGE_FILE_HEADER)); 27 | for(int i=0;i < pNtHeaders->FileHeader.NumberOfSections;i++, ++pSectionHeader) 28 | { 29 | if ((virtualAddr >= pSectionHeader->VirtualAddress) && 30 | (virtualAddr < pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize)) 31 | { 32 | if (!pSectionHeader->SizeOfRawData) 33 | return 0; 34 | 35 | ULONG va = pSectionHeader->VirtualAddress; 36 | ULONG raw = pSectionHeader->PointerToRawData; 37 | ULONG res = virtualAddr - va + raw; 38 | return res; 39 | } 40 | } 41 | return 0; 42 | } 43 | 44 | static 45 | PIMAGE_BASE_RELOCATION ProcessRelocationEntry(PIMAGE_NT_HEADERS pNtHeaders, 46 | void * pMappedImage, 47 | ULONG virtualAddress, 48 | ULONG subEntriesCount, 49 | PUSHORT pSubEntry, 50 | LONG diff 51 | ) 52 | { 53 | for(int i = 0; i < subEntriesCount; ++i, ++pSubEntry) 54 | { 55 | USHORT offset = *pSubEntry & (USHORT)0xfff; 56 | ULONG rawTarget = (ULONG)ConvertVAToRaw(pNtHeaders, virtualAddress + offset); 57 | 58 | if (!rawTarget) 59 | { 60 | continue; 61 | } 62 | 63 | // calculate the target inside our mapped image 64 | PUCHAR pTarget = (PUCHAR)pMappedImage + rawTarget; 65 | LONG tempVal = 0; 66 | 67 | 68 | // done it 69 | switch ((*pSubEntry) >> 12) 70 | { 71 | case IMAGE_REL_BASED_HIGHLOW : 72 | *(LONG UNALIGNED *)pTarget += diff; 73 | break; 74 | 75 | case IMAGE_REL_BASED_HIGH : 76 | tempVal = *(PUSHORT)pTarget << 16; 77 | tempVal += diff; 78 | *(PUSHORT)pTarget = (USHORT)(tempVal >> 16); 79 | break; 80 | 81 | case IMAGE_REL_BASED_ABSOLUTE : 82 | break; 83 | 84 | default : 85 | return NULL; 86 | } 87 | 88 | } 89 | return (PIMAGE_BASE_RELOCATION)pSubEntry; 90 | } 91 | 92 | 93 | static 94 | NTSTATUS FixRelocs(void * pMappedImage, 95 | void * pLoadedNtAddress) 96 | { 97 | PIMAGE_NT_HEADERS pNtHeaders = RtlImageNtHeader( pMappedImage ); 98 | ULONG oldBase = pNtHeaders->OptionalHeader.ImageBase; 99 | 100 | 101 | // scan for relocation section 102 | ULONG bytesCount = 0; 103 | PIMAGE_BASE_RELOCATION pRelocationEntry = 104 | (PIMAGE_BASE_RELOCATION)RtlImageDirectoryEntryToData((char*)pMappedImage, 105 | FALSE, 106 | IMAGE_DIRECTORY_ENTRY_BASERELOC, 107 | &bytesCount); 108 | 109 | if (!pRelocationEntry) 110 | { 111 | // no relocations there 112 | return STATUS_NOT_FOUND; 113 | } 114 | 115 | 116 | // calculate the difference 117 | ULONG diff = (LONG)pLoadedNtAddress - (LONG)oldBase; 118 | 119 | while ((int)bytesCount > 0) 120 | { 121 | // process next entry 122 | bytesCount -= pRelocationEntry->SizeOfBlock; 123 | 124 | // parse offsets 125 | PUSHORT pFirstSubEntry = (PUSHORT)((ULONG)pRelocationEntry + sizeof(IMAGE_BASE_RELOCATION)); 126 | int iSubEntriesCount = (pRelocationEntry->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION))/sizeof(USHORT); 127 | 128 | pRelocationEntry = ProcessRelocationEntry(pNtHeaders, 129 | pMappedImage, 130 | pRelocationEntry->VirtualAddress, 131 | iSubEntriesCount, 132 | pFirstSubEntry, 133 | diff); 134 | if (!pRelocationEntry) 135 | { 136 | return STATUS_UNSUCCESSFUL; 137 | } 138 | } 139 | return STATUS_SUCCESS; 140 | } 141 | 142 | static 143 | NTSTATUS FindOrdinal(SYSTEM_MODULE * pModule, 144 | PIMAGE_THUNK_DATA pThunk, 145 | PIMAGE_EXPORT_DIRECTORY pExport, 146 | USHORT * pOrdinal, 147 | ULONG sizeOfExportTable) 148 | { 149 | 150 | PULONG pNameTable = (PULONG)((ULONG)pModule->pAddress + 151 | (ULONG)pExport->AddressOfNames); 152 | 153 | PUSHORT pOrdinalTable = (PUSHORT)((ULONG)pModule->pAddress + 154 | (ULONG)pExport->AddressOfNameOrdinals); 155 | 156 | PIMAGE_IMPORT_BY_NAME pAddressOfData = (PIMAGE_IMPORT_BY_NAME)pThunk->u1.AddressOfData; 157 | USHORT hint = pAddressOfData->Hint; 158 | 159 | if ((hint < pExport->NumberOfNames) && 160 | (strcmp((char*)pAddressOfData->Name, (PCHAR)pModule->pAddress + pNameTable[hint]) == 0)) 161 | { 162 | // ordinal found 163 | *pOrdinal = pOrdinalTable[hint]; 164 | return STATUS_SUCCESS; 165 | } 166 | 167 | // resolving by name 168 | 169 | return Drv_GetProcAddrEx(pModule->pAddress, 170 | (char*)pAddressOfData->Name, 171 | pModule->dSize, 172 | pExport, 173 | pOrdinalTable, 174 | sizeOfExportTable, 175 | pOrdinal); 176 | 177 | } 178 | 179 | static 180 | NTSTATUS LinkThunk(SYSTEM_MODULE * pModule, 181 | PIMAGE_THUNK_DATA pThunk, 182 | PIMAGE_EXPORT_DIRECTORY pExport, 183 | ULONG sizeOfExportTable, 184 | void * pMappedImage, 185 | PIMAGE_NT_HEADERS pNtHeaders, 186 | void * pLoadedNtAddress) 187 | { 188 | USHORT ordinal = 0; 189 | if (IMAGE_SNAP_BY_ORDINAL(pThunk->u1.Ordinal)) 190 | { 191 | ordinal = (ULONG)(IMAGE_ORDINAL(pThunk->u1.Ordinal) - pExport->Base); 192 | } 193 | else 194 | { 195 | // import by name 196 | ULONG oldAddressOfDataRaw = ConvertVAToRaw(pNtHeaders, pThunk->u1.AddressOfData); 197 | pThunk->u1.AddressOfData = (ULONG)pMappedImage + oldAddressOfDataRaw; 198 | 199 | NTSTATUS status = FindOrdinal(pModule, 200 | pThunk, 201 | pExport, 202 | &ordinal, 203 | sizeOfExportTable); 204 | if (!NT_SUCCESS(status)) 205 | return status; 206 | 207 | } 208 | 209 | if (ordinal >= pExport->NumberOfFunctions) 210 | return STATUS_UNSUCCESSFUL; 211 | 212 | 213 | PULONG pAddressOfFunctions = (PULONG)((char *)pModule->pAddress + pExport->AddressOfFunctions); 214 | PCHAR pTargetFunction = (PCHAR)pModule->pAddress + pAddressOfFunctions[ordinal]; 215 | 216 | pThunk->u1.Function = (ULONG)pTargetFunction; 217 | return STATUS_SUCCESS; 218 | } 219 | 220 | static 221 | NTSTATUS FixImports(Drv_Resolver * pResolver, 222 | void * pMappedImage, 223 | void * pLoadedNtAddress) 224 | { 225 | PIMAGE_NT_HEADERS pNtHeaders = RtlImageNtHeader( pMappedImage ); 226 | ULONG oldBase = pNtHeaders->OptionalHeader.ImageBase; 227 | 228 | 229 | // scan for import section 230 | ULONG bytesCount = 0; 231 | PIMAGE_IMPORT_DESCRIPTOR pImportEntry = 232 | (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData((char*)pMappedImage, 233 | FALSE, 234 | IMAGE_DIRECTORY_ENTRY_IMPORT, 235 | &bytesCount); 236 | 237 | if (!pImportEntry) 238 | { 239 | // no imports there 240 | return STATUS_NOT_FOUND; 241 | } 242 | 243 | // process all import entries 244 | for (;pImportEntry->Name && pImportEntry->FirstThunk; ++pImportEntry) 245 | { 246 | PCHAR pDllName = (PCHAR)pMappedImage + (ULONG)ConvertVAToRaw(pNtHeaders, pImportEntry->Name); 247 | PCHAR pFirstThunk = (PCHAR)pMappedImage + (ULONG)ConvertVAToRaw(pNtHeaders, pImportEntry->FirstThunk); 248 | 249 | SYSTEM_MODULE * pModule = pResolver->LookupModule(pDllName); 250 | 251 | if (!pModule) 252 | { 253 | continue; 254 | } 255 | 256 | // get module exports 257 | ULONG sizeOfExportTable = 0; 258 | PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(pModule->pAddress, 259 | TRUE, 260 | IMAGE_DIRECTORY_ENTRY_EXPORT, 261 | &sizeOfExportTable); 262 | 263 | 264 | // process all thunks 265 | PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)pFirstThunk; 266 | for(; pThunk->u1.AddressOfData; ++pThunk) 267 | { 268 | NTSTATUS status = LinkThunk(pModule, 269 | pThunk, 270 | pExport, 271 | sizeOfExportTable, 272 | pMappedImage, 273 | pNtHeaders, 274 | pLoadedNtAddress); 275 | NT_CHECK(status); 276 | } 277 | } 278 | return STATUS_SUCCESS; 279 | } 280 | 281 | const char * g_pageSectionName = "PAGE"; 282 | const char * g_textSectionName = ".text"; 283 | 284 | NTSTATUS Drv_InitVirginityContext2(Drv_VirginityContext2 * pContext) 285 | { 286 | NTSTATUS status = pContext->m_resolver.Init(); 287 | if (!NT_SUCCESS(status)) 288 | return status; 289 | 290 | // fill sections to scan 291 | RtlInitAnsiString( pContext->m_sectionsToCheck + 0, g_pageSectionName); 292 | RtlInitAnsiString( pContext->m_sectionsToCheck + 1, g_textSectionName); 293 | 294 | status = Drv_VirginityInit(&pContext->m_parent); 295 | if (!NT_SUCCESS(status)) 296 | return status; 297 | 298 | status = FixRelocs(pContext->m_parent.m_mapped.pData, 299 | pContext->m_parent.m_pLoadedNtAddress); 300 | 301 | if (!NT_SUCCESS(status)) 302 | { 303 | Drv_FreeVirginityContext2(pContext); 304 | return status; 305 | } 306 | 307 | status = FixImports(&pContext->m_resolver, 308 | pContext->m_parent.m_mapped.pData, 309 | pContext->m_parent.m_pLoadedNtAddress); 310 | 311 | if (!NT_SUCCESS(status)) 312 | { 313 | Drv_FreeVirginityContext2(pContext); 314 | } 315 | return status; 316 | } 317 | void Drv_FreeVirginityContext2(Drv_VirginityContext2 * pContext) 318 | { 319 | Drv_VirginityFree(&pContext->m_parent); 320 | } 321 | 322 | 323 | const char * Drv_GetMappedSectionStart(const Drv_VirginityContext2 * pContext) 324 | { 325 | char * pMappedSectionStart = 326 | (char *)pContext->m_parent.m_mapped.pData + pContext->m_pMappedSection->PointerToRawData; 327 | 328 | return pMappedSectionStart; 329 | } 330 | 331 | void Drv_GetRealSSTValue2(Drv_VirginityContext2 * pContext, long index, void ** ppValue) 332 | { 333 | char * pSST = pContext->m_parent.m_pMappedSectionStart + pContext->m_parent.m_sstOffsetInSection; 334 | ULONG * pValue = ((ULONG *) pSST)+index; 335 | *ppValue = (void*)*pValue; 336 | } 337 | 338 | static int GetStartingEqualBytesCount(int a, int b) 339 | { 340 | int iCount = 0; 341 | 342 | if (a == b) 343 | { 344 | KeBugCheck(1); 345 | } 346 | 347 | if ((a&0x000000FF) == (b&0x000000FF)) 348 | { 349 | ++iCount; 350 | if ((a&0x0000FF00) == (b&0x0000FF00)) 351 | { 352 | ++iCount; 353 | if ((a&0x00FF0000) == (b&0x00FF0000)) 354 | { 355 | ++iCount; 356 | } 357 | } 358 | } 359 | return iCount; 360 | } 361 | static int GetTailingEqualBytesCount(int a, int b) 362 | { 363 | int iCount = 0; 364 | 365 | if (a == b) 366 | { 367 | KeBugCheck(1); 368 | } 369 | 370 | if ((a&0xFF000000) == (b&0xFF000000)) 371 | { 372 | ++iCount; 373 | if ((a&0x00FF0000) == (b&0x00FF0000)) 374 | { 375 | ++iCount; 376 | if ((a&0x0000FF00) == (b&0x0000FF00)) 377 | { 378 | ++iCount; 379 | } 380 | } 381 | } 382 | return iCount; 383 | } 384 | 385 | 386 | static 387 | NTSTATUS FindModificationInSection(Drv_VirginityContext2 * pContext, 388 | void ** ppStart, 389 | int * pSize) 390 | { 391 | ULONG isDiscardable = pContext->m_currentSectionInfo.m_currentSection->Characteristics & IMAGE_SCN_MEM_DISCARDABLE; 392 | ULONG isExecutable = pContext->m_currentSectionInfo.m_currentSection->Characteristics & IMAGE_SCN_MEM_EXECUTE; 393 | ULONG isWritable = pContext->m_currentSectionInfo.m_currentSection->Characteristics & IMAGE_SCN_MEM_WRITE; 394 | 395 | pContext->m_startOfModification = 0; 396 | 397 | if (isDiscardable || (!isExecutable) || isWritable) 398 | { 399 | STRING sectionName; 400 | sectionName.Buffer = (PCHAR)pContext->m_currentSectionInfo.m_currentSection->Name; 401 | sectionName.Length = sizeof(pContext->m_currentSectionInfo.m_currentSection->Name); 402 | sectionName.MaximumLength = sectionName.Length; 403 | 404 | bool bNeedToCheck = false; 405 | for(int i = 0; i < DRV_SECTIONS_COUNT; ++i) 406 | { 407 | if (RtlCompareString(§ionName, pContext->m_sectionsToCheck + i, TRUE) == 0) 408 | { 409 | bNeedToCheck = true; 410 | break; 411 | } 412 | } 413 | if (!bNeedToCheck) 414 | return STATUS_SUCCESS; 415 | } 416 | 417 | // normal executable non-writable section, scan it 418 | const char * pMappedSectionStart = Drv_GetMappedSectionStart( pContext ); 419 | 420 | // ready to compare them 421 | int sizeInInts = (pContext->m_currentSectionInfo.m_sectionEnd - pContext->m_currentSectionInfo.m_sectionStart)/4; 422 | 423 | int bInModification = 0; 424 | int * pMappedSectionStartInt = (int*)pMappedSectionStart; 425 | int * pOriginalSectionStartInt = (int*)pContext->m_currentSectionInfo.m_sectionStart; 426 | int i = pContext->m_endOfModification; 427 | for(; 428 | i < sizeInInts; 429 | ++i) 430 | { 431 | if (pOriginalSectionStartInt[i] != pMappedSectionStartInt[i]) 432 | { 433 | if (!bInModification) 434 | { 435 | // make it more accurate 436 | int iRealStartOfModification = i*4; 437 | 438 | iRealStartOfModification += GetStartingEqualBytesCount(pOriginalSectionStartInt[i], 439 | pMappedSectionStartInt[i]); 440 | 441 | pContext->m_startOfModification = iRealStartOfModification; 442 | bInModification = 1; 443 | } 444 | continue; 445 | } 446 | else 447 | { 448 | // we got 4 equal bytes 449 | if (bInModification) 450 | { 451 | break; 452 | } 453 | } 454 | } 455 | 456 | if (bInModification) 457 | { 458 | pContext->m_endOfModification = i*4; 459 | 460 | pContext->m_endOfModification -= GetTailingEqualBytesCount(pOriginalSectionStartInt[i-1], 461 | pMappedSectionStartInt[i-1]); 462 | 463 | *pSize = pContext->m_endOfModification - pContext->m_startOfModification; 464 | *ppStart = (int *)pOriginalSectionStartInt + i; 465 | } 466 | return STATUS_SUCCESS; 467 | } 468 | 469 | static 470 | NTSTATUS FindModificationImpl(Drv_VirginityContext2 * pContext, 471 | void ** ppStart, 472 | int * pSize) 473 | { 474 | *ppStart = 0; 475 | *pSize = 0; 476 | 477 | NTSTATUS status = 0; 478 | while(1) 479 | { 480 | status = FindModificationInSection(pContext, 481 | ppStart, 482 | pSize); 483 | if (!NT_SUCCESS(status)) 484 | return status; 485 | 486 | // check if smth found 487 | if (*ppStart) 488 | return STATUS_SUCCESS; 489 | 490 | // not found, try next section 491 | pContext->m_endOfModification = 0; 492 | 493 | int bSectionNotFound = 0; 494 | status = drv_FindNextSection(&pContext->m_currentSectionInfo, &bSectionNotFound); 495 | if (!NT_SUCCESS(status)) 496 | return status; 497 | 498 | if (bSectionNotFound) 499 | return STATUS_SUCCESS; 500 | 501 | // find appropriate section in the mapped file 502 | status = Drv_FindSection(pContext->m_parent.m_mapped.pData, 503 | pContext->m_currentSectionInfo.m_currentSection->Name, 504 | &pContext->m_pMappedSection); 505 | if (!NT_SUCCESS(status)) 506 | return status; 507 | 508 | } 509 | 510 | return STATUS_SUCCESS; 511 | } 512 | 513 | NTSTATUS Drv_GetFirstModification(Drv_VirginityContext2 * pContext, 514 | void ** ppStart, 515 | int * pSize) 516 | { 517 | int done = 0; 518 | NTSTATUS status = drv_FindFirstSection(pContext->m_parent.m_pLoadedNtAddress, 519 | &pContext->m_currentSectionInfo); 520 | if (!NT_SUCCESS(status)) 521 | return status; 522 | 523 | pContext->m_endOfModification = 0; 524 | 525 | // scan for section in mapped file 526 | status = Drv_FindSection(pContext->m_parent.m_mapped.pData, 527 | pContext->m_currentSectionInfo.m_currentSection->Name, 528 | &pContext->m_pMappedSection); 529 | if (!NT_SUCCESS(status)) 530 | return status; 531 | 532 | return FindModificationImpl(pContext, ppStart, pSize); 533 | } 534 | 535 | NTSTATUS Drv_GetNextModification(Drv_VirginityContext2 * pContext, 536 | void ** ppStart, 537 | int * pSize) 538 | { 539 | return FindModificationImpl(pContext, ppStart, pSize); 540 | } --------------------------------------------------------------------------------