├── README.md ├── cmcallbacks.cpp ├── excallbacks.cpp ├── kmexts.cpp ├── kmexts.h ├── kmexts.sln ├── kmexts.vcxproj ├── obcallbacks.cpp └── pscallbacks.cpp /README.md: -------------------------------------------------------------------------------- 1 | # Kernel Mode Extensions Driver # 2 | This is a very simple driver that registers the callbacks using the following routines: 3 | 4 | - CmRegisterCallback 5 | - CmRegisterCallbackEx 6 | - ExRegisterCallback 7 | - ObRegisterCallbacks 8 | - PsSetCreateProcessNotifyRoutine 9 | - PsSetCreateProcessNotifyRoutineEx 10 | - PsSetCreateProcessNotifyRoutineEx2 11 | - PsSetCreateThreadNotifyRoutine 12 | - PsSetCreateThreadNotifyRoutineEx 13 | - PsSetLoadImageNotifyRoutine 14 | 15 | In each callback registered the driver DbgPrints some minimal amount of information describing the operation. It is meant as a convenient way to play with the behavior and invocation of these callbacks on different versions of Windows. 16 | 17 | # Building # 18 | The provided solution builds in Visual Studio 2015 with the Windows 10 1607 WDK 19 | 20 | # Installation # 21 | 22 | Create a service entry for the driver: 23 | 24 | sc create kmexts binpath=c:\users\osr\desktop\kmexts.sys type=kernel start=demand 25 | 26 | Then start the driver: 27 | 28 | net start kmexts 29 | 30 | Be sure to have DbgPrint messages enabled for your target machine either via the Registry or the debugger. [See Getting DbgPrint Output to Appear in Vista and Later](https://www.osr.com/getting-dbgprint-output-appear-windows-vista-later/). 31 | 32 | 33 | -------------------------------------------------------------------------------- /cmcallbacks.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 OSR Open Systems Resources, Inc. 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are met: 7 | // 8 | // 1. Redistributions of source code must retain the above copyright notice, 9 | // this list of conditions and the following disclaimer. 10 | // 11 | // 2. Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // 15 | // 3. Neither the name of the copyright holder nor the names of its 16 | // contributors may be used to endorse or promote products derived from this 17 | // software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | // ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | // CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | // CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) 28 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | // POSSIBILITY OF SUCH DAMAGE 30 | // 31 | #include "kmexts.h" 32 | 33 | CM_CALLBACK_CONTEXT KmExtsCmCallbackContext; 34 | 35 | _Ret_z_ 36 | PWCHAR 37 | RegNotifyClassToString( 38 | _In_ REG_NOTIFY_CLASS RegNotifyClass 39 | ); 40 | 41 | _Use_decl_annotations_ 42 | NTSTATUS 43 | KmExtsCmRegistryCallback( 44 | PVOID CallbackContext, 45 | PVOID Argument1, 46 | PVOID Argument2) 47 | { 48 | 49 | REG_NOTIFY_CLASS regNotifyClass; 50 | 51 | UNREFERENCED_PARAMETER(CallbackContext); 52 | UNREFERENCED_PARAMETER(Argument2); 53 | 54 | // 55 | // Argument1 is a REG_NOTIFY_CLASS, which will indicate the 56 | // operation being performed. For each REG_NOTIFY_CLASS there is 57 | // an associated data structure passed as Argument2. 58 | // 59 | // See the documentation CmRegisterCallback(Ex) documentation 60 | // for more info. 61 | // 62 | regNotifyClass = (REG_NOTIFY_CLASS)PtrToUlong(Argument1); 63 | 64 | DbgPrint("KmExtsCmRegistryCallback: Called for %ls (0x%x)\n", 65 | RegNotifyClassToString(regNotifyClass), regNotifyClass); 66 | 67 | return STATUS_SUCCESS; 68 | } 69 | 70 | 71 | _Use_decl_annotations_ 72 | PWCHAR 73 | RegNotifyClassToString( 74 | REG_NOTIFY_CLASS RegNotifyClass) 75 | { 76 | switch (RegNotifyClass) { 77 | case RegNtPreDeleteKey: 78 | return L"RegNtPreDeleteKey"; 79 | case RegNtPreSetValueKey: 80 | return L"RegNtPreSetValueKey"; 81 | case RegNtPreDeleteValueKey: 82 | return L"RegNtPreDeleteValueKey"; 83 | case RegNtPreSetInformationKey: 84 | return L"RegNtPreSetInformationKey"; 85 | case RegNtPreRenameKey: 86 | return L"RegNtPreRenameKey"; 87 | case RegNtPreEnumerateKey: 88 | return L"RegNtPreEnumerateKey"; 89 | case RegNtPreEnumerateValueKey: 90 | return L"RegNtPreEnumerateValueKey"; 91 | case RegNtPreQueryKey: 92 | return L"RegNtPreQueryKey"; 93 | case RegNtPreQueryValueKey: 94 | return L"RegNtPreQueryValueKey"; 95 | case RegNtPreQueryMultipleValueKey: 96 | return L"RegNtPreQueryMultipleValueKey"; 97 | case RegNtPreCreateKey: 98 | return L"RegNtPreCreateKey"; 99 | case RegNtPostCreateKey: 100 | return L"RegNtPostCreateKey"; 101 | case RegNtPreOpenKey: 102 | return L"RegNtPreOpenKey"; 103 | case RegNtPostOpenKey: 104 | return L"RegNtPostOpenKey"; 105 | case RegNtPreKeyHandleClose: 106 | return L"RegNtPreKeyHandleClose"; 107 | case RegNtPostDeleteKey: 108 | return L"RegNtPostDeleteKey"; 109 | case RegNtPostSetValueKey: 110 | return L"RegNtPostSetValueKey"; 111 | case RegNtPostDeleteValueKey: 112 | return L"RegNtPostDeleteValueKey"; 113 | case RegNtPostSetInformationKey: 114 | return L"RegNtPostSetInformationKey"; 115 | case RegNtPostRenameKey: 116 | return L"RegNtPostRenameKey"; 117 | case RegNtPostEnumerateKey: 118 | return L"RegNtPostEnumerateKey"; 119 | case RegNtPostEnumerateValueKey: 120 | return L"RegNtPostEnumerateValueKey"; 121 | case RegNtPostQueryKey: 122 | return L"RegNtPostQueryKey"; 123 | case RegNtPostQueryValueKey: 124 | return L"RegNtPostQueryValueKey"; 125 | case RegNtPostQueryMultipleValueKey: 126 | return L"RegNtPostQueryMultipleValueKey"; 127 | case RegNtPostKeyHandleClose: 128 | return L"RegNtPostKeyHandleClose"; 129 | case RegNtPreCreateKeyEx: 130 | return L"RegNtPreCreateKeyEx"; 131 | case RegNtPostCreateKeyEx: 132 | return L"RegNtPostCreateKeyEx"; 133 | case RegNtPreOpenKeyEx: 134 | return L"RegNtPreOpenKeyEx"; 135 | case RegNtPostOpenKeyEx: 136 | return L"RegNtPostOpenKeyEx"; 137 | case RegNtPreFlushKey: 138 | return L"RegNtPreFlushKey"; 139 | case RegNtPostFlushKey: 140 | return L"RegNtPostFlushKey"; 141 | case RegNtPreLoadKey: 142 | return L"RegNtPreLoadKey"; 143 | case RegNtPostLoadKey: 144 | return L"RegNtPostLoadKey"; 145 | case RegNtPreUnLoadKey: 146 | return L"RegNtPreUnLoadKey"; 147 | case RegNtPostUnLoadKey: 148 | return L"RegNtPostUnLoadKey"; 149 | case RegNtPreQueryKeySecurity: 150 | return L"RegNtPreQueryKeySecurity"; 151 | case RegNtPostQueryKeySecurity: 152 | return L"RegNtPostQueryKeySecurity"; 153 | case RegNtPreSetKeySecurity: 154 | return L"RegNtPreSetKeySecurity"; 155 | case RegNtPostSetKeySecurity: 156 | return L"RegNtPostSetKeySecurity"; 157 | case RegNtCallbackObjectContextCleanup: 158 | return L"RegNtCallbackObjectContextCleanup"; 159 | default: 160 | return L"UNKNOWN"; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /excallbacks.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 OSR Open Systems Resources, Inc. 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are met: 7 | // 8 | // 1. Redistributions of source code must retain the above copyright notice, 9 | // this list of conditions and the following disclaimer. 10 | // 11 | // 2. Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // 15 | // 3. Neither the name of the copyright holder nor the names of its 16 | // contributors may be used to endorse or promote products derived from this 17 | // software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | // ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | // CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | // CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) 28 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | // POSSIBILITY OF SUCH DAMAGE 30 | // 31 | #include "kmexts.h" 32 | 33 | EX_CALLBACK_CONTEXT KmExtsExSetTimeCbContext; 34 | EX_CALLBACK_CONTEXT KmExtsExPowerStateCbContext; 35 | EX_CALLBACK_CONTEXT KmExtsExProcAddCbContext; 36 | 37 | _Use_decl_annotations_ 38 | NTSTATUS 39 | KmExtsCreateAndRegisterCallback( 40 | PUNICODE_STRING CallbackName, 41 | PCALLBACK_FUNCTION CallbackFunction, 42 | PEX_CALLBACK_CONTEXT CallbackContext) 43 | { 44 | 45 | OBJECT_ATTRIBUTES oa; 46 | NTSTATUS status; 47 | 48 | // 49 | // Set up our context structure. 50 | // 51 | CallbackContext->MagicNumber = EX_CALLBACK_CONTEXT_MAGIC; 52 | 53 | // 54 | // Set up the object attibutes for the call. 55 | // 56 | InitializeObjectAttributes(&oa, 57 | CallbackName, 58 | OBJ_PERMANENT | OBJ_KERNEL_HANDLE, 59 | NULL, 60 | NULL); 61 | 62 | // 63 | // Now open the executive callback. 64 | // 65 | status = ExCreateCallback(&CallbackContext->ExCallbackObject, 66 | &oa, 67 | FALSE, // Do NOT create the object! 68 | TRUE); 69 | 70 | if (!NT_SUCCESS(status)) { 71 | DbgPrint("ExCreateCallback for %wZ failed! Status 0x%x\n", 72 | CallbackName, status); 73 | goto Exit; 74 | } 75 | 76 | // 77 | // Now that we've opened the callback, we must register for 78 | // notification of it. 79 | // 80 | CallbackContext->RegistrationHandle = 81 | ExRegisterCallback(CallbackContext->ExCallbackObject, 82 | CallbackFunction, 83 | CallbackContext); 84 | 85 | if (CallbackContext->RegistrationHandle == NULL) { 86 | DbgPrint("ExRegisterCallback for %wZ failed!\n", CallbackName); 87 | status = STATUS_UNSUCCESSFUL; 88 | goto Exit; 89 | } 90 | 91 | CallbackContext->CallbackRegistered = TRUE; 92 | status = STATUS_SUCCESS; 93 | 94 | Exit: 95 | return status; 96 | } 97 | 98 | 99 | _Use_decl_annotations_ 100 | VOID 101 | KmExtsExSetSystemTimeCallback( 102 | PVOID CallbackContext, 103 | PVOID Argument1, 104 | PVOID Argument2) 105 | { 106 | 107 | LARGE_INTEGER systemTime; 108 | LARGE_INTEGER localTime; 109 | TIME_FIELDS timeFields; 110 | 111 | UNREFERENCED_PARAMETER(CallbackContext); 112 | UNREFERENCED_PARAMETER(Argument1); 113 | UNREFERENCED_PARAMETER(Argument2); 114 | 115 | DbgPrint("KmExtsExSetSystemTimeCallback: System time has changed!\n"); 116 | 117 | KeQuerySystemTime(&systemTime); 118 | ExSystemTimeToLocalTime(&systemTime, &localTime); 119 | 120 | RtlTimeToTimeFields(&localTime, &timeFields); 121 | 122 | DbgPrint("Current time is %2.2d:%2.2d:%2.2d %d AD\n", 123 | timeFields.Hour, timeFields.Minute, 124 | timeFields.Second, timeFields.Year); 125 | 126 | 127 | return; 128 | } 129 | 130 | _Use_decl_annotations_ 131 | VOID 132 | KmExtsExPowerStateCallback( 133 | PVOID CallbackContext, 134 | PVOID Argument1, 135 | PVOID Argument2) 136 | { 137 | UNREFERENCED_PARAMETER(CallbackContext); 138 | UNREFERENCED_PARAMETER(Argument1); 139 | UNREFERENCED_PARAMETER(Argument2); 140 | 141 | DbgPrint("KmExtsExPowerStateCallback: Power state changing or "\ 142 | "has changed!\n"); 143 | return; 144 | } 145 | 146 | _Use_decl_annotations_ 147 | VOID 148 | KmExtsExProcessorAddCallback( 149 | PVOID CallbackContext, 150 | PVOID Argument1, 151 | PVOID Argument2) 152 | { 153 | UNREFERENCED_PARAMETER(CallbackContext); 154 | UNREFERENCED_PARAMETER(Argument1); 155 | UNREFERENCED_PARAMETER(Argument2); 156 | 157 | DbgPrint("KmExtsExProcessorAddCallback: Processor added!\n"); 158 | return; 159 | } 160 | 161 | -------------------------------------------------------------------------------- /kmexts.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 OSR Open Systems Resources, Inc. 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are met: 7 | // 8 | // 1. Redistributions of source code must retain the above copyright notice, 9 | // this list of conditions and the following disclaimer. 10 | // 11 | // 2. Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // 15 | // 3. Neither the name of the copyright holder nor the names of its 16 | // contributors may be used to endorse or promote products derived from this 17 | // software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | // ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | // CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | // CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) 28 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | // POSSIBILITY OF SUCH DAMAGE 30 | // 31 | #include "kmexts.h" 32 | 33 | _Use_decl_annotations_ 34 | extern "C" 35 | NTSTATUS 36 | DriverEntry( 37 | PDRIVER_OBJECT DriverObject, 38 | PUNICODE_STRING RegistryPath) 39 | { 40 | 41 | NTSTATUS status; 42 | UNICODE_STRING callbackName; 43 | UNICODE_STRING altitude; 44 | 45 | UNREFERENCED_PARAMETER(RegistryPath); 46 | 47 | #if (NTDDI_VERSION >= NTDDI_VISTA) 48 | OB_CALLBACK_REGISTRATION obCbRegistration; 49 | POB_OPERATION_REGISTRATION obOpRegistration = NULL; 50 | ULONG obOpSize; 51 | #endif 52 | 53 | // 54 | // In this driver we're going to register for every callback 55 | // possible. This will include: 56 | // 57 | // Configuration Manager (Cm) registry callbacks 58 | // 59 | // Built in Executive (Ex) callbacks 60 | // 61 | // Object Manager (Ob) object callbacks for every object type 62 | // 63 | // Process Manager (Ps) callbacks for: 64 | // 65 | // - Process creation 66 | // 67 | // - Thread creation 68 | // 69 | // - Image loading 70 | // 71 | // Support for each of these will vary by platform. Instead of 72 | // dynamically determining what's available, we'll do it at 73 | // compile time (only because it means less code for the 74 | // example). 75 | // 76 | 77 | // 78 | // CM CALLBACKS 79 | // 80 | 81 | // 82 | // We'll start with the Cm callbacks. Vista adds the Ex version, 83 | // so we'll use that if appropriate. 84 | // 85 | 86 | // 87 | // We use a global structure as our callback context for 88 | // illustrative purposes. 89 | // 90 | KmExtsCmCallbackContext.MagicNumber = CM_CALLBACK_CONTEXT_MAGIC; 91 | 92 | #if (NTDDI_VERSION < NTDDI_VISTA) 93 | 94 | // 95 | // Legacy platform. Use the old DDI. 96 | // 97 | status = CmRegisterCallback( 98 | KmExtsCmRegistryCallback, 99 | &KmExtsCmCallbackContext, 100 | &KmExtsCmCallbackContext.CallbackRegistrationCookie); 101 | #else 102 | 103 | // 104 | // Pick a random altitude value 105 | // 106 | RtlInitUnicodeString(&altitude, 107 | L"12345"); 108 | 109 | status = CmRegisterCallbackEx( 110 | KmExtsCmRegistryCallback, 111 | &altitude, 112 | DriverObject, 113 | &KmExtsCmCallbackContext, 114 | &KmExtsCmCallbackContext.CallbackRegistrationCookie, 115 | NULL); 116 | #endif 117 | 118 | if (!NT_SUCCESS(status)) { 119 | DbgPrint("CmRegisterCallback failed! Status 0x%x\n", 120 | status); 121 | goto Exit; 122 | } 123 | 124 | // 125 | // Registered that callback 126 | // 127 | KmExtsCmCallbackContext.CallbackRegistered = TRUE; 128 | 129 | // 130 | // SYSTEM DEFINED EX CALLBACKS 131 | // 132 | 133 | // 134 | // Next we'll register for the system defined Ex callbacks. We'll use 135 | // a helper routine since there are a couple of steps and we 136 | // need to do this several times (once for each callback we'd 137 | // like to be notified of) 138 | // 139 | 140 | // 141 | // Register for the time change callback. 142 | // 143 | RtlInitUnicodeString(&callbackName, 144 | L"\\Callback\\SetSystemTime"); 145 | 146 | status = KmExtsCreateAndRegisterCallback(&callbackName, 147 | KmExtsExSetSystemTimeCallback, 148 | &KmExtsExSetTimeCbContext); 149 | if (!NT_SUCCESS(status)) { 150 | DbgPrint("CmRegisterCallback (%wZ) failed! Status 0x%x\n", 151 | &callbackName, 152 | status); 153 | goto Exit; 154 | } 155 | 156 | // 157 | // Now the power state callback. 158 | // 159 | RtlInitUnicodeString(&callbackName, 160 | L"\\Callback\\PowerState"); 161 | 162 | status = KmExtsCreateAndRegisterCallback(&callbackName, 163 | KmExtsExPowerStateCallback, 164 | &KmExtsExPowerStateCbContext); 165 | if (!NT_SUCCESS(status)) { 166 | DbgPrint("CmRegisterCallback (%wZ) failed! Status 0x%x\n", 167 | &callbackName, 168 | status); 169 | goto Exit; 170 | } 171 | 172 | // 173 | // Now the processor add callback. 174 | // 175 | RtlInitUnicodeString(&callbackName, 176 | L"\\Callback\\ProcessorAdd"); 177 | 178 | status = KmExtsCreateAndRegisterCallback(&callbackName, 179 | KmExtsExProcessorAddCallback, 180 | &KmExtsExProcAddCbContext); 181 | if (!NT_SUCCESS(status)) { 182 | 183 | // 184 | // This is a fairly new callback. Let's not fail if it wasn't 185 | // found. 186 | // 187 | if (status != STATUS_OBJECT_NAME_NOT_FOUND) { 188 | DbgPrint("CmRegisterCallback (%wZ) failed! Status 0x%x\n", 189 | &callbackName, 190 | status); 191 | goto Exit; 192 | } else { 193 | DbgPrint("Processor add callback not available. Continuing.\n"); 194 | } 195 | 196 | } 197 | 198 | #if (NTDDI_VERSION >= NTDDI_VISTA) 199 | // 200 | // OBJECT MANAGER CALLBACKS 201 | // 202 | 203 | // 204 | // These are only available in SP1 and later. 205 | // 206 | 207 | // 208 | // We'll register for pre and post operation callbacks for every 209 | // object type that is available. 210 | // 211 | 212 | KmExtsObCbContext.MagicNumber = OB_CALLBACK_CONTEXT_MAGIC; 213 | 214 | // 215 | // Fill in the header portion of the structure. 216 | // 217 | obCbRegistration.Version = OB_FLT_REGISTRATION_VERSION; 218 | obCbRegistration.OperationRegistrationCount = KMEXTS_MAX_OBJECT_TYPE; 219 | obCbRegistration.RegistrationContext = &KmExtsObCbContext; 220 | 221 | // 222 | // Again, a random altitude 223 | // 224 | RtlInitUnicodeString(&obCbRegistration.Altitude, 225 | L"123456"); 226 | 227 | // 228 | // Now allocate and fill in the array of types that we want to 229 | // filter. 230 | // 231 | obOpSize = (sizeof(OB_OPERATION_REGISTRATION) * KMEXTS_MAX_OBJECT_TYPE); 232 | obOpRegistration = (POB_OPERATION_REGISTRATION) 233 | ExAllocatePoolWithTag(NonPagedPool, 234 | obOpSize, 235 | 'POmK'); 236 | 237 | if (obOpRegistration == NULL) { 238 | DbgPrint("No memory for operation registration array!\n"); 239 | status = STATUS_INSUFFICIENT_RESOURCES; 240 | goto Exit; 241 | } 242 | 243 | obCbRegistration.OperationRegistration = obOpRegistration; 244 | 245 | // 246 | // Fill in the common area of each structure. 247 | // 248 | for (ULONG i = 0; i < KMEXTS_MAX_OBJECT_TYPE; i++) { 249 | obOpRegistration[i].Operations = OB_OPERATION_HANDLE_CREATE | 250 | OB_OPERATION_HANDLE_DUPLICATE; 251 | obOpRegistration[i].PreOperation = KmExtsObPreCallback; 252 | obOpRegistration[i].PostOperation = KmExtsObPostCallback; 253 | } 254 | 255 | // 256 | // Now fill in the object types. 257 | // 258 | 259 | // 260 | // Object callbacks are only supported for object types that are 261 | // created with the SupportsObjectCallbacks flag set (currently 262 | // only process and thread) 263 | // 264 | obOpRegistration[KMEXTS_PROCESS_OBJECT_TYPE].ObjectType = PsProcessType; 265 | obOpRegistration[KMEXTS_THREAD_OBJECT_TYPE].ObjectType = PsThreadType; 266 | 267 | // MUST BE LINKED WITH /INTEGRITYCHECK 268 | 269 | // 270 | // Now, yes, finally register for the callbacks... 271 | // 272 | status = ObRegisterCallbacks(&obCbRegistration, 273 | &KmExtsObCbContext.RegistrationHandle); 274 | 275 | 276 | if (!NT_SUCCESS(status)) { 277 | DbgPrint("ObRegisterCallbacks failed! Status 0x%x\n", 278 | status); 279 | goto Exit; 280 | } 281 | 282 | KmExtsObCbContext.CallbackRegistered = TRUE; 283 | 284 | 285 | #endif // #if (NTDDI_VERSION >= NTDDI_VISTA) 286 | 287 | 288 | // 289 | // PS CALLBACKS 290 | // 291 | #if (NTDDI_VERSION < NTDDI_VISTA) 292 | 293 | status = PsSetCreateProcessNotifyRoutine(KmExtsPsCreateProcessNotifyRoutine, 294 | FALSE); 295 | 296 | if (!NT_SUCCESS(status)) { 297 | DbgPrint("PsSetCreateProcessNotifyRoutine failed! Status 0x%x\n", 298 | status); 299 | goto Exit; 300 | } 301 | 302 | KmExtsPsCreateProcessNotifyRoutineRegistered = TRUE; 303 | 304 | #else 305 | 306 | status = PsSetCreateProcessNotifyRoutineEx( 307 | KmExtsPsCreateProcessNotifyRoutineEx, 308 | FALSE); 309 | 310 | if (!NT_SUCCESS(status)) { 311 | DbgPrint("PsSetCreateProcessNotifyRoutineEx failed! Status 0x%x\n", 312 | status); 313 | goto Exit; 314 | } 315 | 316 | KmExtsPsCreateProcessExNotifyRoutineRegistered = TRUE; 317 | 318 | #endif 319 | 320 | #if (NTDDI_VERSION >= NTDDI_WIN10_RS2) 321 | status = PsSetCreateProcessNotifyRoutineEx2(PsCreateProcessNotifySubsystems, 322 | KmExtsPsCreateProcessNotifyRoutineEx2, 323 | FALSE); 324 | 325 | if (!NT_SUCCESS(status)) { 326 | DbgPrint("PsSetCreateProcessNotifyRoutineEx2 failed! Status 0x%x\n", 327 | status); 328 | goto Exit; 329 | } 330 | 331 | KmExtsPsCreateProcessEx2NotifyRoutineRegistered = TRUE; 332 | #endif 333 | 334 | 335 | 336 | status = PsSetCreateThreadNotifyRoutine(KmExtsPsCreateThreadNotifyRoutine); 337 | 338 | if (!NT_SUCCESS(status)) { 339 | DbgPrint("PsSetCreateThreadNotifyRoutine failed! Status 0x%x\n", 340 | status); 341 | goto Exit; 342 | } 343 | 344 | KmExtsPsCreateThreadNotifyRoutineRegistered = TRUE; 345 | 346 | #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) 347 | status = PsSetCreateThreadNotifyRoutineEx(PsCreateThreadNotifyNonSystem, 348 | KmExtsPsCreateThreadNotifyRoutineEx); 349 | 350 | if (!NT_SUCCESS(status)) { 351 | DbgPrint("PsSetCreateThreadNotifyRoutineEx failed! Status 0x%x\n", 352 | status); 353 | goto Exit; 354 | } 355 | 356 | KmExtsPsCreateThreadNotifyRoutineExRegistered = TRUE; 357 | #endif 358 | 359 | status = PsSetLoadImageNotifyRoutine(KmExtsPsLoadImageNotifyRoutine); 360 | 361 | if (!NT_SUCCESS(status)) { 362 | DbgPrint("PsSetLoadImageNotifyRoutine failed! Status 0x%x\n", 363 | status); 364 | goto Exit; 365 | } 366 | 367 | KmExtsPsLoadImageNotifyRoutineRegistered = TRUE; 368 | 369 | DriverObject->DriverUnload = KmExtsUnload; 370 | 371 | status = STATUS_SUCCESS; 372 | 373 | Exit: 374 | 375 | #if (NTDDI_VERSION >= NTDDI_VISTA) 376 | if (obOpRegistration != NULL) { 377 | ExFreePool(obOpRegistration); 378 | } 379 | #endif 380 | 381 | if (!NT_SUCCESS(status)) { 382 | // 383 | // Undo what we've done and fail. 384 | // 385 | KmExtsUnregisterAllCallbacks(); 386 | } 387 | 388 | return status; 389 | } 390 | 391 | 392 | _Use_decl_annotations_ 393 | VOID 394 | KmExtsUnload( 395 | PDRIVER_OBJECT DriverObject) 396 | { 397 | 398 | UNREFERENCED_PARAMETER(DriverObject); 399 | 400 | KmExtsUnregisterAllCallbacks(); 401 | return; 402 | } 403 | 404 | VOID 405 | KmExtsUnregisterAllCallbacks( 406 | VOID) 407 | { 408 | 409 | NTSTATUS status; 410 | 411 | // 412 | // Undo anything we may have done. 413 | // 414 | 415 | if (KmExtsCmCallbackContext.CallbackRegistered == TRUE) { 416 | status = CmUnRegisterCallback( 417 | KmExtsCmCallbackContext.CallbackRegistrationCookie); 418 | 419 | // 420 | // This should work because we know we registered. 421 | // 422 | ASSERT(NT_SUCCESS(status)); 423 | } 424 | 425 | if (KmExtsExSetTimeCbContext.CallbackRegistered == TRUE){ 426 | ExUnregisterCallback(KmExtsExSetTimeCbContext.RegistrationHandle); 427 | } 428 | 429 | if (KmExtsExPowerStateCbContext.CallbackRegistered == TRUE) { 430 | ExUnregisterCallback(KmExtsExPowerStateCbContext.RegistrationHandle); 431 | } 432 | if (KmExtsExProcAddCbContext.CallbackRegistered == TRUE){ 433 | ExUnregisterCallback(KmExtsExProcAddCbContext.RegistrationHandle); 434 | } 435 | if (KmExtsObCbContext.CallbackRegistered) { 436 | ObUnRegisterCallbacks(KmExtsObCbContext.RegistrationHandle); 437 | } 438 | 439 | #if (NTDDI_VERSION < NTDDI_VISTA) 440 | if (KmExtsPsCreateProcessNotifyRoutineRegistered == TRUE) { 441 | status = PsSetCreateProcessNotifyRoutine( 442 | KmExtsPsCreateProcessNotifyRoutine, 443 | TRUE); 444 | // 445 | // This should work because we know we registered. 446 | // 447 | ASSERT(NT_SUCCESS(status)); 448 | } 449 | #else 450 | if (KmExtsPsCreateProcessExNotifyRoutineRegistered == TRUE) { 451 | status = PsSetCreateProcessNotifyRoutineEx( 452 | KmExtsPsCreateProcessNotifyRoutineEx, 453 | TRUE); 454 | // 455 | // This should work because we know we registered. 456 | // 457 | ASSERT(NT_SUCCESS(status)); 458 | } 459 | #endif 460 | 461 | #if (NTDDI_VERSION >= NTDDI_WIN10_RS2) 462 | if (KmExtsPsCreateProcessExNotifyRoutineRegistered == TRUE) { 463 | status = PsSetCreateProcessNotifyRoutineEx2( 464 | PsCreateProcessNotifySubsystems, 465 | KmExtsPsCreateProcessNotifyRoutineEx2, 466 | TRUE); 467 | // 468 | // This should work because we know we registered. 469 | // 470 | ASSERT(NT_SUCCESS(status)); 471 | } 472 | #endif 473 | 474 | if (KmExtsPsCreateThreadNotifyRoutineRegistered == TRUE) { 475 | status = PsRemoveCreateThreadNotifyRoutine( 476 | KmExtsPsCreateThreadNotifyRoutine); 477 | // 478 | // This should work because we know we registered. 479 | // 480 | ASSERT(NT_SUCCESS(status)); 481 | } 482 | 483 | #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) 484 | if (KmExtsPsCreateThreadNotifyRoutineExRegistered == TRUE) { 485 | status = PsRemoveCreateThreadNotifyRoutine( 486 | KmExtsPsCreateThreadNotifyRoutineEx); 487 | // 488 | // This should work because we know we registered. 489 | // 490 | ASSERT(NT_SUCCESS(status)); 491 | } 492 | #endif 493 | 494 | if (KmExtsPsLoadImageNotifyRoutineRegistered == TRUE) { 495 | status = PsRemoveLoadImageNotifyRoutine(KmExtsPsLoadImageNotifyRoutine); 496 | // 497 | // This should work because we know we registered. 498 | // 499 | ASSERT(NT_SUCCESS(status)); 500 | } 501 | 502 | } 503 | -------------------------------------------------------------------------------- /kmexts.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 OSR Open Systems Resources, Inc. 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are met: 7 | // 8 | // 1. Redistributions of source code must retain the above copyright notice, 9 | // this list of conditions and the following disclaimer. 10 | // 11 | // 2. Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // 15 | // 3. Neither the name of the copyright holder nor the names of its 16 | // contributors may be used to endorse or promote products derived from this 17 | // software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | // ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | // CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | // CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) 28 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | // POSSIBILITY OF SUCH DAMAGE 30 | // 31 | #ifndef __KMEXTS_H__ 32 | #define __KMEXTS_H__ 33 | 34 | extern "C" { 35 | #include 36 | } 37 | 38 | //////////////// 39 | // KMEXTS.CPP // 40 | //////////////// 41 | extern "C" DRIVER_INITIALIZE DriverEntry; 42 | 43 | DRIVER_UNLOAD KmExtsUnload; 44 | 45 | VOID 46 | KmExtsUnregisterAllCallbacks( 47 | VOID 48 | ); 49 | 50 | 51 | ///////////////////// 52 | // CMCALLBACKS.CPP // 53 | ///////////////////// 54 | 55 | typedef struct _CM_CALLBACK_CONTEXT { 56 | ULONG MagicNumber; 57 | LARGE_INTEGER CallbackRegistrationCookie; 58 | BOOLEAN CallbackRegistered; 59 | }CM_CALLBACK_CONTEXT, *PCM_CALLBACK_CONTEXT; 60 | 61 | #define CM_CALLBACK_CONTEXT_MAGIC 0xCCCC0508 62 | 63 | extern CM_CALLBACK_CONTEXT KmExtsCmCallbackContext; 64 | 65 | NTSTATUS 66 | KmExtsCmRegistryCallback( 67 | _In_ PVOID CallbackContext, 68 | _In_ PVOID Argument1, 69 | _In_ PVOID Argument2 70 | ); 71 | 72 | 73 | ///////////////////// 74 | // EXCALLBACKS.CPP // 75 | ///////////////////// 76 | 77 | typedef struct _EX_CALLBACK_CONTEXT { 78 | ULONG MagicNumber; 79 | PCALLBACK_OBJECT ExCallbackObject; 80 | PVOID RegistrationHandle; 81 | BOOLEAN CallbackRegistered; 82 | }EX_CALLBACK_CONTEXT, *PEX_CALLBACK_CONTEXT; 83 | 84 | #define EX_CALLBACK_CONTEXT_MAGIC 0x03051980 85 | 86 | extern EX_CALLBACK_CONTEXT KmExtsExSetTimeCbContext; 87 | 88 | CALLBACK_FUNCTION KmExtsExSetSystemTimeCallback; 89 | 90 | extern EX_CALLBACK_CONTEXT KmExtsExPowerStateCbContext; 91 | 92 | CALLBACK_FUNCTION KmExtsExPowerStateCallback; 93 | 94 | extern EX_CALLBACK_CONTEXT KmExtsExProcAddCbContext; 95 | 96 | CALLBACK_FUNCTION KmExtsExProcessorAddCallback; 97 | 98 | NTSTATUS 99 | KmExtsCreateAndRegisterCallback( 100 | _In_ PUNICODE_STRING CallbackName, 101 | _In_ PCALLBACK_FUNCTION CallbackFunction, 102 | _In_ PEX_CALLBACK_CONTEXT CallbackContext 103 | ); 104 | 105 | 106 | ///////////////////// 107 | // OBCALLBACKS.CPP // 108 | ///////////////////// 109 | 110 | #if (NTDDI_VERSION >= NTDDI_VISTA) 111 | 112 | 113 | // 114 | // We'll register for notification of every possible type of 115 | // object. Currently only threads and processes 116 | // 117 | #define KMEXTS_PROCESS_OBJECT_TYPE 0 118 | #define KMEXTS_THREAD_OBJECT_TYPE 1 119 | #define KMEXTS_MAX_OBJECT_TYPE 2 120 | 121 | typedef struct _OB_CALLBACK_CONTEXT { 122 | ULONG MagicNumber; 123 | PVOID RegistrationHandle; 124 | BOOLEAN CallbackRegistered; 125 | }OB_CALLBACK_CONTEXT, *POB_CALLBACK_CONTEXT; 126 | 127 | #define OB_CALLBACK_CONTEXT_MAGIC 0x12311999 128 | 129 | extern OB_CALLBACK_CONTEXT KmExtsObCbContext; 130 | 131 | OB_PREOP_CALLBACK_STATUS 132 | KmExtsObPreCallback( 133 | _In_ PVOID RegistrationContext, 134 | _In_ POB_PRE_OPERATION_INFORMATION OperationInformation 135 | ); 136 | 137 | VOID 138 | KmExtsObPostCallback( 139 | _In_ PVOID RegistrationContext, 140 | _In_ POB_POST_OPERATION_INFORMATION OperationInformation 141 | ); 142 | #endif 143 | 144 | ///////////////////// 145 | // PSCALLBACKS.CPP // 146 | ///////////////////// 147 | 148 | 149 | extern BOOLEAN KmExtsPsCreateProcessNotifyRoutineRegistered; 150 | 151 | VOID 152 | KmExtsPsCreateProcessNotifyRoutine( 153 | _In_ HANDLE ParentId, 154 | _In_ HANDLE ProcessId, 155 | _In_ BOOLEAN Create 156 | ); 157 | 158 | #if (NTDDI_VERSION >= NTDDI_VISTA) 159 | 160 | extern BOOLEAN KmExtsPsCreateProcessExNotifyRoutineRegistered; 161 | 162 | VOID 163 | KmExtsPsCreateProcessNotifyRoutineEx( 164 | _Inout_ PEPROCESS Process, 165 | _In_ HANDLE ProcessId, 166 | _In_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo 167 | ); 168 | #endif 169 | 170 | #if (NTDDI_VERSION >= NTDDI_WIN10_RS2) 171 | 172 | extern BOOLEAN KmExtsPsCreateProcessEx2NotifyRoutineRegistered; 173 | 174 | VOID 175 | KmExtsPsCreateProcessNotifyRoutineEx2( 176 | _Inout_ PEPROCESS Process, 177 | _In_ HANDLE ProcessId, 178 | _In_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo 179 | ); 180 | #endif 181 | 182 | extern BOOLEAN KmExtsPsCreateThreadNotifyRoutineRegistered; 183 | 184 | VOID 185 | KmExtsPsCreateThreadNotifyRoutine( 186 | _In_ HANDLE ProcessId, 187 | _In_ HANDLE ThreadId, 188 | _In_ BOOLEAN Create 189 | ); 190 | 191 | #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) 192 | extern BOOLEAN KmExtsPsCreateThreadNotifyRoutineExRegistered; 193 | 194 | VOID 195 | KmExtsPsCreateThreadNotifyRoutineEx( 196 | _In_ HANDLE ProcessId, 197 | _In_ HANDLE ThreadId, 198 | _In_ BOOLEAN Create 199 | ); 200 | #endif 201 | 202 | extern BOOLEAN KmExtsPsLoadImageNotifyRoutineRegistered; 203 | 204 | VOID 205 | KmExtsPsLoadImageNotifyRoutine( 206 | _In_ PUNICODE_STRING FullImageName, 207 | _In_ HANDLE ProcessId, 208 | _In_ PIMAGE_INFO ImageInfo 209 | ); 210 | 211 | 212 | 213 | 214 | #endif __KMEXTS_H__ 215 | -------------------------------------------------------------------------------- /kmexts.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kmexts", "kmexts.vcxproj", "{423FE84D-7E03-453C-83D3-4AE74C24D6C4}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {423FE84D-7E03-453C-83D3-4AE74C24D6C4}.Debug|x64.ActiveCfg = Debug|x64 17 | {423FE84D-7E03-453C-83D3-4AE74C24D6C4}.Debug|x64.Build.0 = Debug|x64 18 | {423FE84D-7E03-453C-83D3-4AE74C24D6C4}.Debug|x86.ActiveCfg = Debug|Win32 19 | {423FE84D-7E03-453C-83D3-4AE74C24D6C4}.Debug|x86.Build.0 = Debug|Win32 20 | {423FE84D-7E03-453C-83D3-4AE74C24D6C4}.Release|x64.ActiveCfg = Release|x64 21 | {423FE84D-7E03-453C-83D3-4AE74C24D6C4}.Release|x64.Build.0 = Release|x64 22 | {423FE84D-7E03-453C-83D3-4AE74C24D6C4}.Release|x86.ActiveCfg = Release|Win32 23 | {423FE84D-7E03-453C-83D3-4AE74C24D6C4}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /kmexts.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {423FE84D-7E03-453C-83D3-4AE74C24D6C4} 23 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 24 | v4.5 25 | 12.0 26 | Debug 27 | Win32 28 | kmexts 29 | 30 | 31 | 32 | Windows7 33 | true 34 | WindowsKernelModeDriver10.0 35 | Driver 36 | WDM 37 | 38 | 39 | Windows7 40 | false 41 | WindowsKernelModeDriver10.0 42 | Driver 43 | WDM 44 | 45 | 46 | Windows7 47 | true 48 | WindowsKernelModeDriver10.0 49 | Driver 50 | WDM 51 | 52 | 53 | Windows7 54 | false 55 | WindowsKernelModeDriver10.0 56 | Driver 57 | WDM 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | DbgengKernelDebugger 69 | 70 | 71 | DbgengKernelDebugger 72 | 73 | 74 | DbgengKernelDebugger 75 | 76 | 77 | DbgengKernelDebugger 78 | 79 | 80 | 81 | /integritycheck %(AdditionalOptions) 82 | 83 | 84 | 85 | 86 | /integritycheck %(AdditionalOptions) 87 | 88 | 89 | 90 | 91 | /integritycheck %(AdditionalOptions) 92 | 93 | 94 | 95 | 96 | /integritycheck %(AdditionalOptions) 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /obcallbacks.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 OSR Open Systems Resources, Inc. 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are met: 7 | // 8 | // 1. Redistributions of source code must retain the above copyright notice, 9 | // this list of conditions and the following disclaimer. 10 | // 11 | // 2. Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // 15 | // 3. Neither the name of the copyright holder nor the names of its 16 | // contributors may be used to endorse or promote products derived from this 17 | // software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | // ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | // CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | // CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) 28 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | // POSSIBILITY OF SUCH DAMAGE 30 | // 31 | #include "kmexts.h" 32 | 33 | #if (NTDDI_VERSION >= NTDDI_VISTA) 34 | 35 | OB_CALLBACK_CONTEXT KmExtsObCbContext; 36 | 37 | _Ret_z_ 38 | PWCHAR 39 | ObjectTypeToString( 40 | _In_ POBJECT_TYPE ObjectType 41 | ); 42 | 43 | _Use_decl_annotations_ 44 | OB_PREOP_CALLBACK_STATUS 45 | KmExtsObPreCallback( 46 | PVOID RegistrationContext, 47 | POB_PRE_OPERATION_INFORMATION OperationInformation) 48 | { 49 | 50 | POB_PRE_OPERATION_PARAMETERS operationParams; 51 | POB_PRE_CREATE_HANDLE_INFORMATION createParams; 52 | POB_PRE_DUPLICATE_HANDLE_INFORMATION dupParams; 53 | 54 | UNREFERENCED_PARAMETER(RegistrationContext); 55 | 56 | operationParams = OperationInformation->Parameters; 57 | 58 | switch (OperationInformation->Operation) { 59 | case OB_OPERATION_HANDLE_CREATE: { 60 | 61 | createParams = &operationParams->CreateHandleInformation; 62 | 63 | DbgPrint("KmExtsObPreCallback: %s Handle being created to object "\ 64 | "0x%p, which is a %ls. Desired access is 0x%x\n", 65 | OperationInformation->KernelHandle ? "Kernel" : "User", 66 | OperationInformation->Object, 67 | ObjectTypeToString(OperationInformation->ObjectType), 68 | createParams->OriginalDesiredAccess); 69 | break; 70 | } 71 | case OB_OPERATION_HANDLE_DUPLICATE: { 72 | dupParams = &operationParams->DuplicateHandleInformation; 73 | DbgPrint("KmExtsObPreCallback: %s Handle being dup'd to object "\ 74 | "0x%p, which is a %ls. Desired access is 0x%x. "\ 75 | "Source Process 0x%p, Target Process 0x%p\n", 76 | OperationInformation->KernelHandle ? "Kernel" : "User", 77 | OperationInformation->Object, 78 | ObjectTypeToString(OperationInformation->ObjectType), 79 | dupParams->OriginalDesiredAccess, 80 | dupParams->SourceProcess, 81 | dupParams->TargetProcess); 82 | break; 83 | } 84 | default: { 85 | DbgPrint("KmExtsObPreCallback: Unknown operation 0x%x!\n", 86 | OperationInformation->Operation); 87 | break; 88 | } 89 | } 90 | return OB_PREOP_SUCCESS; 91 | } 92 | 93 | _Use_decl_annotations_ 94 | VOID 95 | KmExtsObPostCallback( 96 | PVOID RegistrationContext, 97 | POB_POST_OPERATION_INFORMATION OperationInformation) 98 | { 99 | POB_POST_OPERATION_PARAMETERS operationParams; 100 | POB_POST_CREATE_HANDLE_INFORMATION createParams; 101 | POB_POST_DUPLICATE_HANDLE_INFORMATION dupParams; 102 | 103 | UNREFERENCED_PARAMETER(RegistrationContext); 104 | 105 | operationParams = OperationInformation->Parameters; 106 | 107 | switch (OperationInformation->Operation) { 108 | case OB_OPERATION_HANDLE_CREATE: { 109 | 110 | createParams = &operationParams->CreateHandleInformation; 111 | 112 | DbgPrint("KmExtsObPostCallback: %s Handle create to object "\ 113 | "0x%p, which is a %ls. Result was 0x%x, "\ 114 | "Granted Access 0x%x\n", 115 | OperationInformation->KernelHandle ? "Kernel" : "User", 116 | OperationInformation->Object, 117 | ObjectTypeToString(OperationInformation->ObjectType), 118 | OperationInformation->ReturnStatus, 119 | createParams->GrantedAccess); 120 | break; 121 | } 122 | case OB_OPERATION_HANDLE_DUPLICATE: { 123 | dupParams = &operationParams->DuplicateHandleInformation; 124 | DbgPrint("KmExtsObPostCallback: %s Handle dup to object "\ 125 | "0x%p, which is a %ls. Result was 0x%x, "\ 126 | "Granted Access 0x%x\n", 127 | OperationInformation->KernelHandle ? "Kernel" : "User", 128 | OperationInformation->Object, 129 | ObjectTypeToString(OperationInformation->ObjectType), 130 | OperationInformation->ReturnStatus, 131 | dupParams->GrantedAccess); 132 | break; 133 | } 134 | default: { 135 | DbgPrint("KmExtsObPreCallback: Unknown operation 0x%x!\n", 136 | OperationInformation->Operation); 137 | break; 138 | } 139 | } 140 | return; 141 | } 142 | 143 | _Use_decl_annotations_ 144 | PWCHAR 145 | ObjectTypeToString( 146 | POBJECT_TYPE ObjectType) 147 | { 148 | if (ObjectType == *IoFileObjectType) { 149 | return L"IoFileObjectType"; 150 | } 151 | if (ObjectType == *ExEventObjectType) { 152 | return L"ExEventObjectType"; 153 | } 154 | if (ObjectType == *ExSemaphoreObjectType) { 155 | return L"ExSemaphoreObjectType"; 156 | } 157 | if (ObjectType == *TmTransactionManagerObjectType) { 158 | return L"TmTransactionManagerObjectType"; 159 | } 160 | if (ObjectType == *TmResourceManagerObjectType) { 161 | return L"TmResourceManagerObjectType"; 162 | } 163 | if (ObjectType == *TmEnlistmentObjectType) { 164 | return L"TmEnlistmentObjectType"; 165 | } 166 | if (ObjectType == *TmTransactionObjectType) { 167 | return L"TmTransactionObjectType"; 168 | } 169 | if (ObjectType == *PsProcessType) { 170 | return L"PsProcessType"; 171 | } 172 | if (ObjectType == *PsThreadType) { 173 | return L"PsThreadType"; 174 | } 175 | 176 | return L"UNKNOWN"; 177 | } 178 | 179 | #endif 180 | -------------------------------------------------------------------------------- /pscallbacks.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2017 OSR Open Systems Resources, Inc. 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are met: 7 | // 8 | // 1. Redistributions of source code must retain the above copyright notice, 9 | // this list of conditions and the following disclaimer. 10 | // 11 | // 2. Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // 15 | // 3. Neither the name of the copyright holder nor the names of its 16 | // contributors may be used to endorse or promote products derived from this 17 | // software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | // ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | // CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | // CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) 28 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | // POSSIBILITY OF SUCH DAMAGE 30 | // 31 | #include "kmexts.h" 32 | 33 | BOOLEAN KmExtsPsCreateProcessNotifyRoutineRegistered; 34 | BOOLEAN KmExtsPsCreateProcessExNotifyRoutineRegistered; 35 | #if (NTDDI_VERSION >= NTDDI_WIN10_RS2) 36 | BOOLEAN KmExtsPsCreateProcessEx2NotifyRoutineRegistered; 37 | #endif 38 | BOOLEAN KmExtsPsCreateThreadNotifyRoutineRegistered; 39 | #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) 40 | BOOLEAN KmExtsPsCreateThreadNotifyRoutineExRegistered; 41 | #endif 42 | BOOLEAN KmExtsPsLoadImageNotifyRoutineRegistered; 43 | 44 | _Use_decl_annotations_ 45 | VOID 46 | KmExtsPsCreateProcessNotifyRoutine( 47 | HANDLE ParentId, 48 | HANDLE ProcessId, 49 | BOOLEAN Create) 50 | { 51 | // 52 | // This routine called after creation of first thread in 53 | // process! 54 | // 55 | DbgPrint("KmExtsPsCreateProcessNotifyRoutine: PID 0x%p %s. "\ 56 | "Parent PID 0x%p\n", 57 | ProcessId, 58 | Create ? " being created" : "exiting", 59 | ParentId); 60 | return; 61 | } 62 | 63 | #if (NTDDI_VERSION >= NTDDI_VISTA) 64 | _Use_decl_annotations_ 65 | VOID 66 | KmExtsPsCreateProcessNotifyRoutineEx( 67 | PEPROCESS Process, 68 | HANDLE ProcessId, 69 | PPS_CREATE_NOTIFY_INFO CreateInfo) 70 | { 71 | 72 | if (CreateInfo == NULL) { 73 | DbgPrint("KmExtsPsCreateProcessNotifyRoutine: PID 0x%p exiting. "\ 74 | "Process PID 0x%p\n", 75 | Process, 76 | ProcessId); 77 | return; 78 | } 79 | // 80 | // This routine called after creation of first thread in 81 | // process! 82 | // 83 | DbgPrint("KmExtsPsCreateProcessNotifyRoutine: Process 0x%p (PID 0x%p). "\ 84 | "Parent PID 0x%p. Creating Thread 0x%p.%p\n", 85 | Process, 86 | ProcessId, 87 | CreateInfo->ParentProcessId, 88 | CreateInfo->CreatingThreadId.UniqueProcess, 89 | CreateInfo->CreatingThreadId.UniqueThread); 90 | if (CreateInfo->CommandLine != NULL) { 91 | DbgPrint("\t(0x%p) Command Line %wZ\n", 92 | ProcessId, 93 | CreateInfo->CommandLine); 94 | } 95 | DbgPrint("\t(0x%p) Backing File Object 0x%p\n", 96 | ProcessId, 97 | CreateInfo->FileObject); 98 | 99 | if (CreateInfo->FileOpenNameAvailable) { 100 | DbgPrint("\t(0x%p) Full Image Name %wZ\n", 101 | ProcessId, 102 | CreateInfo->ImageFileName); 103 | } else { 104 | DbgPrint("\t(0x%p) Partial Image Name %wZ\n", 105 | ProcessId, 106 | CreateInfo->ImageFileName); 107 | } 108 | 109 | return; 110 | } 111 | #endif 112 | 113 | #if (NTDDI_VERSION >= NTDDI_WIN10_RS2) 114 | _Use_decl_annotations_ 115 | VOID 116 | KmExtsPsCreateProcessNotifyRoutineEx2( 117 | PEPROCESS Process, 118 | HANDLE ProcessId, 119 | PPS_CREATE_NOTIFY_INFO CreateInfo) 120 | { 121 | if (CreateInfo == NULL) { 122 | DbgPrint("KmExtsPsCreateProcessNotifyRoutineEx2: PID 0x%p exiting. "\ 123 | "Process PID 0x%p\n", 124 | Process, 125 | ProcessId); 126 | return; 127 | } 128 | // 129 | // This routine called after creation of first thread in 130 | // process! 131 | // 132 | DbgPrint("KmExtsPsCreateProcessNotifyRoutineEx2: Process 0x%p (PID 0x%p). "\ 133 | "Parent PID 0x%p. Creating Thread 0x%p.%p\n", 134 | Process, 135 | ProcessId, 136 | CreateInfo->ParentProcessId, 137 | CreateInfo->CreatingThreadId.UniqueProcess, 138 | CreateInfo->CreatingThreadId.UniqueThread); 139 | if (CreateInfo->CommandLine != NULL) { 140 | DbgPrint("\t(0x%p) Command Line %wZ\n", 141 | ProcessId, 142 | CreateInfo->CommandLine); 143 | } 144 | DbgPrint("\t(0x%p) Backing File Object 0x%p\n", 145 | ProcessId, 146 | CreateInfo->FileObject); 147 | 148 | if (CreateInfo->FileOpenNameAvailable) { 149 | DbgPrint("\t(0x%p) Full Image Name %wZ\n", 150 | ProcessId, 151 | CreateInfo->ImageFileName); 152 | } else { 153 | DbgPrint("\t(0x%p) Partial Image Name %wZ\n", 154 | ProcessId, 155 | CreateInfo->ImageFileName); 156 | } 157 | 158 | return; 159 | } 160 | #endif 161 | 162 | _Use_decl_annotations_ 163 | VOID 164 | KmExtsPsCreateThreadNotifyRoutine( 165 | HANDLE ProcessId, 166 | HANDLE ThreadId, 167 | BOOLEAN Create) 168 | { 169 | 170 | // 171 | // When in this routine, target thread has been created and is 172 | // in the INITIALIZED state. It will not transition to READY 173 | // until this routine exits. 174 | // 175 | 176 | DbgPrint("KmExtsPsCreateThreadNotifyRoutine: Thread 0x%p %s in "\ 177 | "Process 0x%p\n", 178 | ThreadId, 179 | Create ? "being created" : "exiting", 180 | ProcessId); 181 | 182 | return; 183 | } 184 | 185 | #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) 186 | _Use_decl_annotations_ 187 | VOID 188 | KmExtsPsCreateThreadNotifyRoutineEx( 189 | HANDLE ProcessId, 190 | HANDLE ThreadId, 191 | BOOLEAN Create) 192 | { 193 | 194 | // 195 | // When in this routine, target thread has been created and is 196 | // in the INITIALIZED state. It will not transition to READY 197 | // until this routine exits. 198 | // 199 | 200 | DbgPrint("KmExtsPsCreateThreadNotifyRoutineEx: Thread 0x%p %s in "\ 201 | "Process 0x%p\n", 202 | ThreadId, 203 | Create ? "being created" : "exiting", 204 | ProcessId); 205 | 206 | return; 207 | } 208 | #endif 209 | 210 | _Use_decl_annotations_ 211 | VOID 212 | KmExtsPsLoadImageNotifyRoutine( 213 | PUNICODE_STRING FullImageName, 214 | HANDLE ProcessId, 215 | PIMAGE_INFO ImageInfo) 216 | { 217 | 218 | PIMAGE_INFO_EX imageInfoEx = NULL; 219 | PFILE_OBJECT backingFileObject; 220 | 221 | // 222 | // IMAGE_INFO_EX available on Vista, which will give us the 223 | // backing file object of the image section. 224 | // 225 | if (ImageInfo->ExtendedInfoPresent) { 226 | 227 | imageInfoEx = CONTAINING_RECORD(ImageInfo, IMAGE_INFO_EX, ImageInfo); 228 | 229 | backingFileObject = imageInfoEx->FileObject; 230 | 231 | } else { 232 | 233 | backingFileObject = NULL; 234 | 235 | } 236 | 237 | 238 | DbgPrint("KmExtsPsLoadImageNotifyRoutine: %wZ being loaded into "\ 239 | "Process 0x%p. Backing File Object %s (0x%p)\n", 240 | FullImageName, 241 | ProcessId, 242 | backingFileObject != NULL ? "Available" : "Unavailable", 243 | backingFileObject); 244 | return; 245 | } 246 | 247 | --------------------------------------------------------------------------------