├── .gitattributes ├── .gitignore ├── 542875F90F9B47F497B64BA219CACF69 ├── PGCbUtil │ ├── PgCbUtil.c │ ├── PgCbUtil.inf │ ├── PgCbUtil.sln │ ├── PgCbUtil.vcxproj │ └── PgCbUtil.vcxproj.filters ├── PgCtx.h ├── README.md ├── checksum_algo.md ├── crypt_decrypt.md ├── hash_algo.md ├── images │ ├── critical_msr.png │ ├── exec_cb_obj.png │ ├── func_int1.png │ ├── gen_dataregion.png │ ├── imp_table.png │ ├── insert_apc.png │ ├── invfunctab.png │ ├── mistake1.png │ ├── mistake1b.png │ ├── objecttype.png │ ├── page_hash_mismatch.png │ ├── pg_init.png │ ├── seckernelintcheck_fct.png │ └── type_pool.png └── pg_entry_dump.py ├── AfdTdxCallback └── README.md ├── EnlightenmentState ├── EnlightenmentState.sln ├── EnlightenmentState │ ├── EnlightenmentState.c │ ├── EnlightenmentState.inf │ ├── EnlightenmentState.vcxproj │ └── EnlightenmentState.vcxproj.filters └── README.md ├── IoExternalDmaUnblock ├── README.md ├── ida_run.py └── ntpowerinfo.py ├── Loader ├── Loader.c ├── Loader.sln ├── Loader.vcxproj └── Loader.vcxproj.filters ├── Phase1InitComplete ├── Phase1InitComplete.sln ├── Phase1InitComplete │ ├── Phase1InitComplete.c │ ├── Phase1InitComplete.inf │ ├── Phase1InitComplete.vcxproj │ └── Phase1InitComplete.vcxproj.filters ├── README.md └── images │ ├── CallExNotifyCallback.png │ └── LoaderParamBlock.png ├── README.md ├── TcpConnectionCallbackTemp ├── README.md ├── TcpConnectionCallbackTemp.sln └── TcpConnectionCallbackTemp │ ├── TcpConnectionCallbackTemp.c │ ├── TcpConnectionCallbackTemp.inf │ ├── TcpConnectionCallbackTemp.vcxproj │ └── TcpConnectionCallbackTemp.vcxproj.filters ├── WdEbNotificationCallback ├── README.md └── images │ ├── CallExNotifyCallback.png │ ├── MpEbUnload.png │ └── WdFilterCopyData.png ├── WdNriNotificationCallback ├── README.md └── images │ ├── callback.png │ └── callback_notif.png └── WdProcessNotificationCallback ├── README.md ├── WdProcessNotificationCallback.sln ├── WdProcessNotificationCallback ├── WdProcessNotificationCallback.c ├── WdProcessNotificationCallback.inf ├── WdProcessNotificationCallback.vcxproj └── WdProcessNotificationCallback.vcxproj.filters └── images ├── obj_creation.png ├── poc.png ├── proc_create_notif.png ├── proc_create_notif2.png ├── proc_create_stack.png ├── proc_termination.png ├── refresh_proc.png ├── set_trusted.png ├── set_untrusted.png ├── set_untrusted_check.png └── stack_frames.png /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/PGCbUtil/PgCbUtil.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | #define PG_CTX_PTAG 'xcgP' 6 | #define PG_CTX_SZ 0x3f024 7 | #define PG_CTX_RVA 0xCFC388 // Adapt RVAs 8 | #define PG_CB_RVA 0x38BDE0 9 | #define NT_DDI_WIN10_20H1 0xA000008 // Adapt DDI version 10 | 11 | 12 | DRIVER_INITIALIZE DriverEntry; 13 | DRIVER_UNLOAD DriverUnload; 14 | 15 | typedef struct _SEC_PROCESSOR_INFO 16 | { 17 | KAFFINITY ActiveLogicalProcessor; 18 | USHORT GroupCounter; 19 | } SEC_PROCESSOR_INFO, *PSEC_PROCESSOR_INFO; 20 | 21 | typedef struct _SEC_USERPROBE_INFO 22 | { 23 | ULONG64 UserProbeAddress; 24 | __int64 PtrSize; 25 | } SEC_USERPROBE_INFO, *PSEC_USERPROBE_INFO; 26 | 27 | typedef union _SEC_PG_INFO 28 | { 29 | SEC_PROCESSOR_INFO SecProcessorInfo; 30 | SEC_USERPROBE_INFO SecUserProbeInfo; 31 | } SEC_PG_INFO, *PSEC_PG_INFO; 32 | 33 | typedef struct _MSSEC_PG_CB_ARG1 34 | { 35 | DWORD64 SizeOfStruct; 36 | DWORD64 NtDdiVersion; 37 | DWORD Reserved80000h; 38 | int UsePgCtxSize; 39 | __int64 field_18; 40 | int field_20; 41 | int field_24; 42 | int field_28; 43 | int Unknown1; 44 | DWORD Option; 45 | DWORD Reserved10h; 46 | PSEC_PG_INFO SecPgInfo; 47 | } MSSEC_PG_CB_ARG1, *PMSSEC_PG_CB_ARG1; 48 | 49 | typedef struct _MSSEC_PG_CB_ARG2 50 | { 51 | int field_0; 52 | int field_4; 53 | __int64 field_8; 54 | __int64 field_10; 55 | __int64 field_18; 56 | __int64 field_20; 57 | __int64 field_28; 58 | } MSSEC_PG_CB_ARG2, *PMSSEC_PG_CB_ARG2; 59 | 60 | typedef NTSTATUS(*PGCALLBACK)(PMSSEC_PG_CB_ARG1, PMSSEC_PG_CB_ARG2); 61 | 62 | NTKERNELAPI 63 | PVOID 64 | NTAPI 65 | RtlPcToFileHeader( 66 | _In_ PVOID PcValue, 67 | _Out_ PVOID *BaseOfImage 68 | ); 69 | 70 | 71 | PVOID GetNtoskrnlBaseAddress(VOID) 72 | { 73 | PVOID NtoskrnlBaseAddress; 74 | 75 | return RtlPcToFileHeader((PVOID)RtlPcToFileHeader, &NtoskrnlBaseAddress); 76 | } 77 | 78 | BOOLEAN DumpPgCtx( 79 | _In_ ULONG_PTR NtosKrnlBaseAddress 80 | ) 81 | { 82 | UNICODE_STRING DumpFileName; 83 | LARGE_INTEGER Delay = { .QuadPart = 1 << 20 }; 84 | LARGE_INTEGER Offset = { .QuadPart = 0 }; 85 | PULONG_PTR pPgCtxAddr = NULL; 86 | PUCHAR PgCtx; 87 | IO_STATUS_BLOCK IoStatusBlock = { 0 }; 88 | OBJECT_ATTRIBUTES ObjAttrib = { 0 }; 89 | HANDLE hPgCtxDump; 90 | NTSTATUS ntStatus; 91 | BOOLEAN bRet = FALSE; 92 | 93 | PgCtx = (PUCHAR)ExAllocatePoolWithTag(NonPagedPoolNx, PG_CTX_SZ, PG_CTX_PTAG); 94 | if (NULL == PgCtx) { 95 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 96 | DPFLTR_ERROR_LEVEL, 97 | __FUNCTION__ "[PgCtxDump] Failed to allocate PgCtx pool.\n"); 98 | 99 | return FALSE; 100 | } 101 | 102 | pPgCtxAddr = (PULONG_PTR)(NtosKrnlBaseAddress + PG_CTX_RVA); 103 | 104 | for (size_t i = 0; i < (1 << 10); i++) { 105 | if ((PVOID)*pPgCtxAddr != NULL) { 106 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 107 | DPFLTR_INFO_LEVEL, 108 | __FUNCTION__ "[PgCtxDump] PgCtx address: %08llx\n", 109 | *pPgCtxAddr); 110 | 111 | RtlCopyMemory(PgCtx, (PVOID)*pPgCtxAddr, PG_CTX_SZ); 112 | 113 | bRet = TRUE; 114 | 115 | break; 116 | } else { 117 | KeDelayExecutionThread(KernelMode, TRUE, &Delay); 118 | } 119 | } 120 | 121 | if (!bRet) { 122 | goto epilogue; 123 | } 124 | 125 | // 126 | // Adapt the path to dump file, if needed 127 | // 128 | if (RtlUnicodeStringInit(&DumpFileName, L"\\Device\\HarddiskVolume4\\PgCtx.dmp") != STATUS_SUCCESS) { 129 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 130 | DPFLTR_ERROR_LEVEL, 131 | __FUNCTION__ "[PgCtxDump] Failed to initialize file name\n"); 132 | 133 | bRet = FALSE; 134 | 135 | goto epilogue; 136 | } 137 | 138 | ObjAttrib.Length = sizeof(OBJECT_ATTRIBUTES); 139 | ObjAttrib.RootDirectory = NULL; 140 | ObjAttrib.ObjectName = &DumpFileName; 141 | ObjAttrib.Attributes = OBJ_CASE_INSENSITIVE; 142 | ObjAttrib.SecurityDescriptor = NULL; 143 | ObjAttrib.SecurityQualityOfService = NULL; 144 | ntStatus = ZwCreateFile(&hPgCtxDump, 145 | GENERIC_WRITE, 146 | &ObjAttrib, 147 | &IoStatusBlock, 148 | NULL, 149 | FILE_ATTRIBUTE_NORMAL, 150 | FILE_SHARE_WRITE, 151 | FILE_OVERWRITE_IF, 152 | FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, 153 | NULL, 154 | 0); 155 | if (ntStatus != STATUS_SUCCESS) { 156 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 157 | DPFLTR_ERROR_LEVEL, 158 | __FUNCTION__ "[PgCtxDump] Failed to create dump file %08lX\n", 159 | ntStatus); 160 | 161 | bRet = FALSE; 162 | } else { 163 | RtlSecureZeroMemory(&IoStatusBlock, sizeof(IO_STATUS_BLOCK)); 164 | ntStatus = ZwWriteFile(hPgCtxDump, 165 | NULL, 166 | NULL, 167 | NULL, 168 | &IoStatusBlock, 169 | PgCtx, 170 | PG_CTX_SZ, 171 | &Offset, 172 | NULL); 173 | 174 | if (ntStatus != STATUS_SUCCESS || IoStatusBlock.Status != STATUS_SUCCESS) { 175 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 176 | DPFLTR_INFO_LEVEL, 177 | __FUNCTION__ "[PgCtxDump] ntStatus: %08lX IO_STATUS_BLOCK.Status: %08lX\n", 178 | ntStatus, 179 | IoStatusBlock.Status); 180 | 181 | bRet = FALSE; 182 | } else { 183 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 184 | DPFLTR_INFO_LEVEL, 185 | __FUNCTION__ "[PgCtxDump] PgCtx was successfully writen to %wZ\n", 186 | DumpFileName); 187 | } 188 | 189 | NtClose(hPgCtxDump); 190 | } 191 | 192 | epilogue: 193 | 194 | ExFreePoolWithTag(PgCtx, PG_CTX_PTAG); 195 | PgCtx = NULL; 196 | 197 | return bRet; 198 | } 199 | 200 | NTSTATUS ExecutePgCallback( 201 | _In_ ULONG_PTR NtosKrnlBaseAddress 202 | ) 203 | { 204 | INT Trials = 5; 205 | SEC_PG_INFO SecPgInfo = { 0 }; 206 | MSSEC_PG_CB_ARG1 MsSecPgArg1 = { 0 }; 207 | MSSEC_PG_CB_ARG2 MsSecPgArg2 = { 0 }; 208 | NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; 209 | PGCALLBACK PgCb = NULL; 210 | 211 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 212 | DPFLTR_INFO_LEVEL, 213 | __FUNCTION__ "[PgCtxDump] KdDebuggerNotPresent: %hhu\n", *KdDebuggerNotPresent); 214 | 215 | PgCb = (PGCALLBACK)(NtosKrnlBaseAddress + PG_CB_RVA); 216 | 217 | MsSecPgArg1.SizeOfStruct = 0x40; 218 | MsSecPgArg1.NtDdiVersion = NT_DDI_WIN10_20H1; 219 | MsSecPgArg1.Reserved80000h = 0x80000; 220 | MsSecPgArg1.Reserved10h = 0x10; 221 | MsSecPgArg1.Option = 0; 222 | if (0 == MsSecPgArg1.Option) { 223 | SecPgInfo.SecUserProbeInfo.UserProbeAddress = MmUserProbeAddress; 224 | SecPgInfo.SecUserProbeInfo.PtrSize = 8; 225 | } else { 226 | SecPgInfo.SecProcessorInfo.GroupCounter = 0; 227 | SecPgInfo.SecProcessorInfo.ActiveLogicalProcessor = KeQueryGroupAffinity(0); 228 | } 229 | MsSecPgArg1.SecPgInfo = &SecPgInfo; 230 | 231 | while (Trials--) { 232 | ntStatus = PgCb(&MsSecPgArg1, &MsSecPgArg2); 233 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 234 | DPFLTR_INFO_LEVEL, 235 | __FUNCTION__ "[PgCtxDump] NtStatus: %08lx\n", ntStatus); 236 | if (STATUS_SUCCESS == ntStatus) { 237 | break; 238 | } 239 | } 240 | 241 | return ntStatus; 242 | } 243 | 244 | VOID DriverUnload( 245 | _In_ PDRIVER_OBJECT DriverObject 246 | ) 247 | { 248 | UNREFERENCED_PARAMETER(DriverObject); 249 | } 250 | 251 | NTSTATUS 252 | DriverEntry( 253 | _In_ PDRIVER_OBJECT DriverObject, 254 | _In_ PUNICODE_STRING RegistryPath 255 | ) 256 | { 257 | UNREFERENCED_PARAMETER(RegistryPath); 258 | 259 | ULONG_PTR NtosKrnlBaseAddress = 0; 260 | 261 | DriverObject->DriverUnload = DriverUnload; 262 | 263 | NtosKrnlBaseAddress = (ULONG_PTR)GetNtoskrnlBaseAddress(); 264 | if (0 == NtosKrnlBaseAddress) { 265 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 266 | DPFLTR_INFO_LEVEL, 267 | __FUNCTION__ "[PgCtxDump] Failed to get Ntoskrnl base address\n"); 268 | } else { 269 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 270 | DPFLTR_INFO_LEVEL, 271 | __FUNCTION__ "[PgCtxDump] Ntoskrnl base address: %08llx\n", 272 | NtosKrnlBaseAddress); 273 | 274 | DumpPgCtx(NtosKrnlBaseAddress); 275 | ExecutePgCallback(NtosKrnlBaseAddress); 276 | } 277 | 278 | return STATUS_SUCCESS; 279 | } -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/PGCbUtil/PgCbUtil.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; PgCbUtil.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=Sample ; TODO: edit Class 8 | ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171} ; TODO: edit ClassGuid 9 | Provider=%ManufacturerName% 10 | CatalogFile=PgCbUtil.cat 11 | DriverVer= ; TODO: set DriverVer in stampinf property pages 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | PgCbUtil_Device_CoInstaller_CopyFiles = 11 16 | 17 | ; ================= Class section ===================== 18 | 19 | [ClassInstall32] 20 | Addreg=SampleClassReg 21 | 22 | [SampleClassReg] 23 | HKR,,,0,%ClassName% 24 | HKR,,Icon,,-5 25 | 26 | [SourceDisksNames] 27 | 1 = %DiskName%,,,"" 28 | 29 | [SourceDisksFiles] 30 | PgCbUtil.sys = 1,, 31 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames 32 | 33 | ;***************************************** 34 | ; Install Section 35 | ;***************************************** 36 | 37 | [Manufacturer] 38 | %ManufacturerName%=Standard,NT$ARCH$ 39 | 40 | [Standard.NT$ARCH$] 41 | %PgCbUtil.DeviceDesc%=PgCbUtil_Device, Root\PgCbUtil ; TODO: edit hw-id 42 | 43 | [PgCbUtil_Device.NT] 44 | CopyFiles=Drivers_Dir 45 | 46 | [Drivers_Dir] 47 | PgCbUtil.sys 48 | 49 | ;-------------- Service installation 50 | [PgCbUtil_Device.NT.Services] 51 | AddService = PgCbUtil,%SPSVCINST_ASSOCSERVICE%, PgCbUtil_Service_Inst 52 | 53 | ; -------------- PgCbUtil driver install sections 54 | [PgCbUtil_Service_Inst] 55 | DisplayName = %PgCbUtil.SVCDESC% 56 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 57 | StartType = 3 ; SERVICE_DEMAND_START 58 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 59 | ServiceBinary = %12%\PgCbUtil.sys 60 | 61 | ; 62 | ;--- PgCbUtil_Device Coinstaller installation ------ 63 | ; 64 | 65 | [PgCbUtil_Device.NT.CoInstallers] 66 | AddReg=PgCbUtil_Device_CoInstaller_AddReg 67 | CopyFiles=PgCbUtil_Device_CoInstaller_CopyFiles 68 | 69 | [PgCbUtil_Device_CoInstaller_AddReg] 70 | HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller" 71 | 72 | [PgCbUtil_Device_CoInstaller_CopyFiles] 73 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll 74 | 75 | [PgCbUtil_Device.NT.Wdf] 76 | KmdfService = PgCbUtil, PgCbUtil_wdfsect 77 | [PgCbUtil_wdfsect] 78 | KmdfLibraryVersion = $KMDFVERSION$ 79 | 80 | [Strings] 81 | SPSVCINST_ASSOCSERVICE= 0x00000002 82 | ManufacturerName="" ;TODO: Replace with your manufacturer name 83 | ClassName="Samples" ; TODO: edit ClassName 84 | DiskName = "PgCbUtil Installation Disk" 85 | PgCbUtil.DeviceDesc = "PgCbUtil Device" 86 | PgCbUtil.SVCDESC = "PgCbUtil Service" 87 | -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/PGCbUtil/PgCbUtil.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29424.173 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PgCbUtil", "PgCbUtil.vcxproj", "{648C4A97-5FB5-43B0-84EF-D1D8201BB3F6}" 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 | {648C4A97-5FB5-43B0-84EF-D1D8201BB3F6}.Debug|x64.ActiveCfg = Debug|x64 17 | {648C4A97-5FB5-43B0-84EF-D1D8201BB3F6}.Debug|x64.Build.0 = Debug|x64 18 | {648C4A97-5FB5-43B0-84EF-D1D8201BB3F6}.Debug|x64.Deploy.0 = Debug|x64 19 | {648C4A97-5FB5-43B0-84EF-D1D8201BB3F6}.Debug|x86.ActiveCfg = Debug|Win32 20 | {648C4A97-5FB5-43B0-84EF-D1D8201BB3F6}.Debug|x86.Build.0 = Debug|Win32 21 | {648C4A97-5FB5-43B0-84EF-D1D8201BB3F6}.Debug|x86.Deploy.0 = Debug|Win32 22 | {648C4A97-5FB5-43B0-84EF-D1D8201BB3F6}.Release|x64.ActiveCfg = Release|x64 23 | {648C4A97-5FB5-43B0-84EF-D1D8201BB3F6}.Release|x64.Build.0 = Release|x64 24 | {648C4A97-5FB5-43B0-84EF-D1D8201BB3F6}.Release|x64.Deploy.0 = Release|x64 25 | {648C4A97-5FB5-43B0-84EF-D1D8201BB3F6}.Release|x86.ActiveCfg = Release|Win32 26 | {648C4A97-5FB5-43B0-84EF-D1D8201BB3F6}.Release|x86.Build.0 = Release|Win32 27 | {648C4A97-5FB5-43B0-84EF-D1D8201BB3F6}.Release|x86.Deploy.0 = Release|Win32 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | GlobalSection(ExtensibilityGlobals) = postSolution 33 | SolutionGuid = {A0628267-3FDE-4209-9573-B0D48FED73C5} 34 | EndGlobalSection 35 | EndGlobal 36 | -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/PGCbUtil/PgCbUtil.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 | {648C4A97-5FB5-43B0-84EF-D1D8201BB3F6} 23 | {1bc93793-694f-48fe-9372-81e2b05556fd} 24 | v4.5 25 | 12.0 26 | Debug 27 | Win32 28 | PgCbUtil 29 | 30 | 31 | 32 | Windows10 33 | true 34 | WindowsKernelModeDriver10.0 35 | Driver 36 | KMDF 37 | Universal 38 | 39 | 40 | Windows10 41 | false 42 | WindowsKernelModeDriver10.0 43 | Driver 44 | KMDF 45 | Universal 46 | 47 | 48 | Windows10 49 | true 50 | WindowsKernelModeDriver10.0 51 | Driver 52 | KMDF 53 | Universal 54 | 55 | 56 | Windows10 57 | false 58 | WindowsKernelModeDriver10.0 59 | Driver 60 | KMDF 61 | Universal 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | DbgengKernelDebugger 72 | 73 | 74 | DbgengKernelDebugger 75 | 76 | 77 | DbgengKernelDebugger 78 | 79 | 80 | DbgengKernelDebugger 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/PGCbUtil/PgCbUtil.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Driver Files 24 | 25 | 26 | 27 | 28 | Source Files 29 | 30 | 31 | -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/PgCtx.h: -------------------------------------------------------------------------------- 1 | typedef struct _PgCtx 2 | { 3 | BYTE CmpAppendDllSection[196]; 4 | DWORD ContextSizeInQwords; 5 | INT64 field_C8; 6 | INT64 field_D0; 7 | INT64 field_D8; 8 | INT64 field_E0; 9 | PVOID ExAcquireResourceSharedLite; 10 | PVOID ExAcquireResourceExclusiveLite; 11 | PVOID ExAllocatePoolWithTag; 12 | PVOID ExFreePoolWithTag; 13 | PVOID ExMapHandleToPointer; 14 | PVOID ExQueueWorkItem; 15 | PVOID ExReleaseResourceLite; 16 | PVOID ExUnlockHandleTableEntry; 17 | PVOID ExAcquirePushLockExclusiveEx; 18 | PVOID ExReleasePushLockExclusiveEx; 19 | PVOID ExAcquirePushLockSharedEx; 20 | PVOID ExReleasePushLockSharedEx; 21 | PVOID KeAcquireInStackQueuedSpinLockAtDpcLevel; 22 | PVOID ExAcquireSpinLockSharedAtDpcLevel; 23 | PVOID KeBugCheckEx; 24 | PVOID KeDelayExecutionThread; 25 | PVOID KeEnterCriticalRegionThread; 26 | PVOID KeLeaveCriticalRegion; 27 | PVOID KeEnterGuardedRegion; 28 | PVOID KeLeaveGuardedRegion; 29 | PVOID MiUnlockWorkingSetCoreExclusive; 30 | PVOID ExReleaseSpinLockSharedFromDpcLevel; 31 | PVOID KeRevertToUserGroupAffinityThread; 32 | PVOID KeProcessorGroupAffinity; 33 | PVOID KeInitializeEnumerationContext; 34 | PVOID KeEnumerateNextProcessor; 35 | PVOID KeCountSetBitsAffinityEx; 36 | PVOID KeQueryAffinityProcess; 37 | PVOID KeQueryAffinityThread; 38 | PVOID KeSetSystemGroupAffinityThread; 39 | PVOID KeSetCoalescableTimer; 40 | PVOID HalPutDmaAdapter; 41 | PVOID ObReferenceObjectByName; 42 | PVOID RtlImageDirectoryEntryToData; 43 | PVOID RtlImageNtHeader; 44 | PVOID RtlLookupFunctionTableEx; 45 | PVOID RtlPcToFileHeader; 46 | PVOID RtlSectionTableFromVirtualAddress; 47 | PVOID DbgPrint; 48 | PVOID MmAllocateIndependentPages; 49 | PVOID MmFreeIndependentPages; 50 | PVOID MmSetPageProtection; 51 | INT64 field_238; 52 | INT64 field_240; 53 | INT64 field_248; 54 | INT64 field_250; 55 | INT64 field_258; 56 | PVOID RtlLookupFunctionEntry; 57 | PVOID KeAcquireSpinLockRaiseToDpc; 58 | PVOID KeReleaseSpinLock; 59 | PVOID MmGetSessionById; 60 | PVOID MmGetNextSession; 61 | PVOID MmQuitNextSession; 62 | PVOID MmAttachSession; 63 | PVOID MmDetachSession; 64 | PVOID MmGetSessionIdEx; 65 | PVOID MmIsSessionAddress; 66 | PVOID MmIsAddressValid; 67 | PVOID MmSessionGetWin32Callouts; 68 | PVOID KeInsertQueueApc; 69 | PVOID KeWaitForSingleObject; 70 | QWORD field_2D0; 71 | PVOID ExReferenceCallBackBlock; 72 | PVOID ExGetCallBackBlockRoutine; 73 | PVOID ExDereferenceCallBackBlock; 74 | PVOID sub_FFFFF8062958AB50; 75 | PVOID PspEnumerateCallback; 76 | PVOID CmpEnumerateCallback; 77 | PVOID DbgEnumerateCallback; 78 | PVOID ExpEnumerateCallback; 79 | PVOID ExpGetNextCallback; 80 | PVOID xHalTimerWatchdogStop; 81 | PVOID KiSchedulerApcTerminate; 82 | PVOID KiSchedulerApc; 83 | PVOID xHalTimerWatchdogStop_; 84 | PVOID sub_FFFFF8062958BBC0; 85 | PVOID MmAllocatePagesForMdlEx; 86 | PVOID MmAllocateMappingAddress; 87 | PVOID MmMapLockedPagesWithReservedMapping; 88 | PVOID MmUnmapReservedMapping; 89 | PVOID PgKCalloutUmapReservedMapping; 90 | PVOID sub_FFFFF80629598300; 91 | PVOID MmAcquireLoadLock; 92 | PVOID MmReleaseLoadLock; 93 | PVOID KeEnumerateQueueApc; 94 | PVOID KeIsApcRunningThread; 95 | PVOID KeQsort; 96 | PVOID PsAcquireProcessExitSynchronization; 97 | PVOID ObDereferenceProcessHandleTable; 98 | PVOID PsGetNextProcess; 99 | PVOID PsQuitNextProcessThread; 100 | PVOID PsGetNextProcessEx; 101 | PVOID MmIsSessionLeaderProcess; 102 | PVOID PsInvokeWin32Callout; 103 | PVOID MmEnumerateAddressSpaceAndReferenceImages; 104 | PVOID PsGetProcessProtection; 105 | PVOID PsGetProcessSignatureLevel; 106 | PVOID PsGetProcessSectionBaseAddress; 107 | PVOID SeCompareSigningLevels; 108 | PVOID KeComputeSha256; 109 | PVOID KeComputeParallelSha256; 110 | PVOID KeSetEvent; 111 | PVOID RtlpConvertFunctionEntry; 112 | PVOID RtlpLookupPrimaryFunctionEntry; 113 | PVOID RtlIsMultiSessionSku; 114 | PVOID KiEnumerateCallback; 115 | PVOID KeStackAttachProcess; 116 | PVOID KeUnstackDetachProcess; 117 | PVOID KeIpiGenericCall; 118 | PVOID InitProbeAndLockMdl; 119 | PVOID MmGetPhysicalAddress; 120 | PVOID MmUnlockPages; 121 | PVOID VslVerifyPage; 122 | PVOID KiGetInterruptObjectAddress; 123 | INT64 field_478; 124 | PVOID PsLookupProcessByProcessId; 125 | PVOID PsGetProcessId; 126 | PVOID MmCheckProcessShadow; 127 | PVOID MmGetImageRetpolineCodePage; 128 | INT64 field_4A0; 129 | INT64 field_4A8; 130 | INT64 field_4B0; 131 | INT64 field_4B8; 132 | PVOID qword_FFFFF80629E0F0C0; 133 | PVOID qword_FFFFF80629E12DE8; 134 | PVOID qword_FFFFF80629E12DF0; 135 | PVOID qword_FFFFF80629E12DF8; 136 | QWORD SystemEProcess; 137 | QWORD KiWaitAlways; 138 | PVOID *KiEntropyTimingRoutine; 139 | PVOID KiProcessListHead; 140 | PVOID KiProcessListLock; 141 | QWORD ObjectTypeRelated; 142 | INT64 IoDriverObjectType; 143 | INT64 PsProcessType; 144 | PVOID PsActiveProcessHead; 145 | PVOID PsInvertedFunctionTable; 146 | PVOID PsLoadedModuleList; 147 | PVOID PsLoadedModuleResource; 148 | PVOID PsLoadedModuleSpinLock; 149 | PVOID PspActiveProcessLock; 150 | PVOID PspCidTable; 151 | PVOID ExpUuidLock; 152 | PVOID AlpcpPortListLock; 153 | PVOID KeServiceDescriptorTable; 154 | PVOID KeServiceDescriptorTableShadow; 155 | PVOID KeServiceDescriptorTableFilter; 156 | PVOID VfThunksExtended; 157 | PVOID PsWin32CallBack; 158 | PPgFault pPgFault; 159 | PVOID KiTableInformation; 160 | PVOID HandleTableListHead; 161 | PVOID HandleTableListLock; 162 | INT64 ObpKernelHandleTable; 163 | INT64 KUserSharedData; 164 | INT64 KiWaitNever; 165 | PVOID SeProtectedMapping; 166 | PVOID KiInterruptThunk; 167 | PVOID KiStackProtectNotifyEvent; 168 | INT64 MmPteBase; 169 | PVOID NtImageBase; 170 | QWORD HalImageBase; 171 | PVOID KeNumberProcessors_0; 172 | PVOID g_PgCtx; 173 | PVOID qword_FFFFF80629EFC390; 174 | PINVERTED_FUNCTION_TABLE RtlpInvertedFunctionTable; 175 | PVOID KiIsrThunkShadow; 176 | INT64 field_620; 177 | INT64 field_628; 178 | INT64 field_630; 179 | INT64 PrcbDpcStackOffset; 180 | INT64 PrcbDpcRoutineActiveOffset; 181 | INT64 CurrentThreadOffset; 182 | INT64 field_650; 183 | INT64 field_658; 184 | INT64 field_660; 185 | INT64 field_668; 186 | INT64 field_670; 187 | INT64 KthreadInitialStackOffset; 188 | INT64 SchedulerApc; 189 | INT64 ApcStateOffset; 190 | INT64 EthreadStartAddressOffset; 191 | INT64 EthreadTerminationPortOffset; 192 | INT64 EthreadWin32StartAddressOffset; 193 | INT64 ApcStateProcessOffset; 194 | INT64 ProcessListEntryOffset; 195 | INT64 Pcb_Visited_Offset; 196 | INT64 EProcessFlags; 197 | INT64 EProcessObjectTable; 198 | INT64 ActiveProcessLinksOffset; 199 | INT64 ProcessFlagsMask; 200 | INT64 field_6E0; 201 | INT64 field_6E8; 202 | INT64 ObjectTypeTypeInfoOffset; 203 | INT64 ObjectTypeCallbackListOffset; 204 | INT64 field_700; 205 | INT64 field_708; 206 | INT64 field_710; 207 | INT64 field_718; 208 | INT64 ObjectTypeTypeFlagsOffset; 209 | INT64 ObjectTypeSupportsObjectCallbacks; 210 | INT64 CidTableIndex; 211 | INT64 QuotaProcessOffset; 212 | INT64 HandleTableListOffset; 213 | INT64 field_748; 214 | INT64 KldrDataTableEntryDllBaseOffset; 215 | INT64 field_758; 216 | INT64 field_760; 217 | INT64 NonPagedPoolNxSz; 218 | INT64 field_770; 219 | INT64 field_778; 220 | INT64 field_780; 221 | INT64 field_788; 222 | INT64 field_790; 223 | INT64 field_798; 224 | INT64 field_7A0; 225 | INT64 field_7A8; 226 | INT64 field_7B0; 227 | INT64 field_7B8; 228 | INT64 field_7C0; 229 | PVOID KernelCalloutAllocPool; 230 | INT64 field_7D0; 231 | INT64 field_7D8; 232 | INT field_7E0; 233 | INT SizeofAllPgEntries; 234 | INT64 field_7E8; 235 | INT field_7F0; 236 | INT OffsetIpiTargetCall; 237 | INT64 field_7F8; 238 | INT64 field_800; 239 | INT SizeOfPgCtx; 240 | DWORD LoopCounter; 241 | INT LoadedModuleTag; 242 | INT RotNum; 243 | INT64 LoopInitValue; 244 | INT MsSecArg2IterCondDefault; 245 | INT MsSecArg2Field4; 246 | INT MsSecRes80000_SumPgDataSizes; 247 | INT Reserved140000h; 248 | INT TypeProcessRelatedFlag; 249 | INT field_834; 250 | INT field_838; 251 | INT field_83C; 252 | INT64 ImgIntegrityCounter; 253 | _KIDTENTRY64 IdtEntryIdx1; 254 | _KIDTENTRY64 IdtEntryIdx2; 255 | _KIDTENTRY64 IdtEntryIdx18h; 256 | SHORT NewIdtDescriptor1; 257 | CHAR PgSyscallHook; 258 | CHAR FeaturesActiveFlags; 259 | BYTE SyscallOpcode1; 260 | BYTE SyscallOpcode2; 261 | INT64 NewIdtDescriptor2; 262 | INT64 field_886; 263 | INT field_88E; 264 | CHAR field_892; 265 | CHAR field_893; 266 | CHAR field_894; 267 | CHAR field_895; 268 | CHAR field_896; 269 | CHAR field_897; 270 | INT64 field_898; 271 | INT64 field_8A0; 272 | SHORT field_8A8; 273 | SHORT StackSegmentReg; 274 | DWORD KInterruptDispatchOffset; 275 | DWORD KServiceRoutineOffset; 276 | DWORD KiIstStackSize; 277 | PVOID HalpPerfInterrupt; 278 | INT64 field_8C0; 279 | PVOID NtosImageBase; 280 | PVOID NtosImageEnd; 281 | PVOID NtosNtImageHeaders; 282 | INT64 pNewIdt; 283 | INT64 pSyscall; 284 | INT PrcbNumber; 285 | INT field_8F4; 286 | INT SomethingWentWrong; 287 | INT field_8FC; 288 | INT64 EncodedPointerPgCtxLocal; 289 | INT64 EncodedPointerPgCtxEntry; 290 | INT64 PgEntryType; 291 | INT64 PgEntryData; 292 | INT field_920; 293 | INT KernelCalloutAllocType; 294 | INT64 LockTypeSwitchValue; 295 | INT64 PAGEVRF_Str; 296 | INT64 PAGESPEC_Str; 297 | INT64 INIT_Str; 298 | INT64 PAGEKD_Str; 299 | INT ProcessTypeShiftConst; 300 | DWORD Magic_0x7E80690F; 301 | INT Win32CalloutFlag; 302 | INT field_95C; 303 | INT64 field_960; 304 | INT64 field_968; 305 | INT SessionState; 306 | INT Win32CalloutBlockSize; 307 | INT64 Win32CalloutBlockStart; 308 | INT64 SessionObject; 309 | INT64 ProcShadowPid; 310 | INT GeneralFlags; 311 | INT ChecksStatusFlags; 312 | INT64 field_998; 313 | INT64 field_9A0; 314 | INT64 field_9A8; 315 | INT64 field_9B0; 316 | INT64 field_9B8; 317 | INT64 field_9C0; 318 | INT64 field_9C8; 319 | INT64 field_9D0; 320 | INT64 field_9D8; 321 | INT64 field_9E0; 322 | PVOID KiDispatchCallout; 323 | PVOID xHalTimerWatchdogStop; 324 | INT64 field_9F8; 325 | INT64 Type3ProcPushLock; 326 | INT64 field_A08; 327 | PDWORD LocalAPICRelated; 328 | INT KCalloutAllocFailuresCounter; 329 | INT MaxPgEntriesSizeRelated; 330 | INT64 field_A20; 331 | INT field_A28; 332 | INT OffsetStartPgEntries; 333 | INT64 XoredRAXRDX; 334 | INT64 XoredRAXRDX2; 335 | INT64 MinimalBarrier; 336 | INT64 field_A48; 337 | INT64 field_A50; 338 | INT64 field_A58; 339 | INT64 ImgIntegrityPgCheckEntry; 340 | INT64 MdlStartVaPlusByteOffset; 341 | INT64 field_A70; 342 | PPgCtx pGlobalPgCtx; 343 | PPgCheckTypeEntry pPgEntry; 344 | INT64 PageHashMismatchRelated; 345 | DWORD64 NonPagedPoolNxSize; 346 | INT64 field_A98; 347 | } PgCtx, *PPgCtx; 348 | 349 | typedef struct _PgFault 350 | { 351 | PVOID Ptr1; 352 | PVOID Ptr2; 353 | INT Id1; 354 | INT Id2; 355 | DWORD XoredChecksum; 356 | } PgFault, *PPgFault; -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/checksum_algo.md: -------------------------------------------------------------------------------- 1 | ```C 2 | PgEntryData = PgEntry->Data; 3 | PgEntry_DataSize = PgEntry->DataSize; 4 | PgEntryData_1 = PgEntryData; 5 | PgCtx->MsSecRes80000_SumPgDataSizes += PgEntry_DataSize; 6 | _RAX = PgEntryData; 7 | NumRot = PgCtx->RotNum; 8 | for (i = PgCtx->LoopInitValue; _RAX < PgEntryData + PgEntry_DataSize; _RAX += 64) 9 | __asm { prefetchnta byte ptr [rax]} 10 | LoopInitValue = PgCtx->LoopInitValue; 11 | Iterations = PgEntry_DataSize >> 7; 12 | if (PgEntry_DataSize >> 7) 13 | { 14 | do 15 | { 16 | Iterations_1 = 8; 17 | do 18 | { 19 | Temp = PgEntryData_1[1] ^ __ROL8__(*PgEntryData_1 ^ LoopInitValue, NumRot); 20 | PgEntryData_1 += 2; 21 | LoopInitValue = __ROL8__(Temp, NumRot); 22 | --Iterations_1; 23 | } while (Iterations_1); 24 | *Temp = (__ROL8__(i ^ (PgEntryData_1 - PgEntryData_11), 17) ^ i ^ (PgEntryData_1 - PgEntryData)) * 0x7010008004002001; 25 | Temp2 = LOBYTE(Temp1[0]) ^ LOBYTE(Temp1[1]) ^ NumRot; 26 | LODWORD(Temp1[1]) = 1; 27 | NumRot = Temp2 & 0x3F; 28 | if (!NumRot) 29 | LOBYTE(NumRot) = 1; 30 | --Iterations; 31 | } while (Iterations); 32 | } 33 | j = PgEntry_DataSize & 0x7F; 34 | if (j >= 8) 35 | { 36 | Iterations_2 = j >> 3; 37 | do 38 | { 39 | LoopInitValue = __ROL8__(*PgEntryData_1 ^ LoopInitValue, NumRot); 40 | ++PgEntryData_1; 41 | j = j - 8; 42 | --Iterations_2; 43 | } while (Iterations_2); 44 | } 45 | for (; j; j = (j - 1)) 46 | { 47 | PgEntryData_Byte = *PgEntryData_1; 48 | PgEntryData_1 = (PgEntryData_1 + 1); 49 | LoopInitValue = __ROL8__(PgEntryData_Byte ^ LoopInitValue, NumRot); 50 | } 51 | for (k = LoopInitValue;; LODWORD(LoopInitValue) = k ^ LoopInitValue) 52 | { 53 | k >>= 31; 54 | if (!k) 55 | break; 56 | } 57 | ComputedChecksum = LoopInitValue & 0x7FFFFFFF; 58 | if (ComputedChecksum == PgEntry->CheckSum) 59 | goto checksum_match; 60 | ``` -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/crypt_decrypt.md: -------------------------------------------------------------------------------- 1 | ```C 2 | __int64 __fastcall EncryptDecryptEntries(PPgCtx PgCtx) 3 | { 4 | int SomeFlags; // er11 5 | __int64 i; // r10 6 | int ChecksStatusFlags; // er9 7 | __int64 OffsetPgEntries; // rcx 8 | __int64 LoopInitValue_Xor; // rbp 9 | unsigned __int64 SizeIterations; // rdi 10 | char *pData; // rbx 11 | unsigned __int64 pDataEnd; // r14 12 | __int64 XoredRAXRDX_1; // r11 13 | __int64 i2; // rsi 14 | __int64 v13; // rdx 15 | _DWORD *pFaultRegion; // rax 16 | int v15; // ecx 17 | unsigned __int64 TimestampCtr; // rax 18 | __int64 XoredRAXRDX; // r11 19 | __int64 a1[2]; 20 | 21 | SomeFlags = PgCtx->SomeFlags; 22 | if ( !_bittest(&SomeFlags, 30u) ) 23 | { 24 | i = 0i64; 25 | while ( 1 ) 26 | { 27 | ChecksStatusFlags = PgCtx->ChecksStatusFlags; 28 | a1[1] = (a1[0] & 0xffffffff) != 0; 29 | if ( a1 == ((PgCtx->ChecksStatusFlags >> 21) & 1) || !(SomeFlags & 2) ) 30 | break; 31 | OffsetPgEntries = PgCtx->OffsetStartPgEntries; 32 | LoopInitValue_Xor = PgCtx->LoopInitValue; 33 | SizeIterations = (PgCtx->SizeofAllPgEntries - OffsetPgEntries) >> 3; 34 | pData = &PgCtx->CmpAppendDllSection[OffsetPgEntries]; 35 | pDataEnd = PgCtx + 8 * SizeIterations + OffsetPgEntries; 36 | if ( a1[0] & 0xffffffff ) 37 | { 38 | TimestampCtr = __rdtsc(); 39 | a1 = (__ROR8__(TimestampCtr, 3) ^ TimestampCtr) * 0x7010008004002001ui64; 40 | XoredRAXRDX = a1[0] ^ a1[1]; 41 | PgCtx->XoredRAXRDX = XoredRAXRDX; 42 | if ( pData > pDataEnd ) 43 | SizeIterations = 0i64; 44 | if ( SizeIterations ) 45 | { 46 | do 47 | { 48 | ++i; 49 | a1[0] = XoredRAXRDX ^ *pData; 50 | a1[1] = LoopInitValue_Xor ^ *pData; 51 | *pData = a1; 52 | XoredRAXRDX = (a[1] + __ROR8__(XoredRAXRDX, XoredRAXRDX & 0x3F)) ^ 0xEFFi64; 53 | pData += 8; 54 | } 55 | while ( i != SizeIterations ); 56 | ChecksStatusFlags = PgCtx->ChecksStatusFlags; 57 | } 58 | PgCtx->XoredRAXRDX2 = XoredRAXRDX; 59 | PgCtx->ChecksStatusFlags = ChecksStatusFlags | 0x200000; 60 | return a1; 61 | } 62 | XoredRAXRDX_1 = PgCtx->XoredRAXRDX; 63 | i2 = 0i64; 64 | if ( pData > pDataEnd ) 65 | SizeIterations = 0i64; 66 | if ( SizeIterations ) 67 | { 68 | do 69 | { 70 | *pData ^= XoredRAXRDX_1; 71 | ++i2; 72 | v13 = *pData; 73 | pData += 8; 74 | XoredRAXRDX_1 = ((LoopInitValue_Xor ^ v13) + __ROR8__(XoredRAXRDX_1, XoredRAXRDX_1 & 0x3F)) ^ 0xEFF; 75 | } 76 | while ( i2 != SizeIterations ); 77 | ChecksStatusFlags = PgCtx->ChecksStatusFlags; 78 | } 79 | PgCtx->ChecksStatusFlags = ChecksStatusFlags & 0xFFDFFFFF; 80 | if ( XoredRAXRDX_1 != PgCtx->XoredRAXRDX2 ) 81 | { 82 | pPgFault = PgCtx->pPgFault; 83 | v15 = PgCtx->SizeofAllPgEntries; 84 | pPgFault->Ptr1 = PgCtx; 85 | pPgFault->Id1 = v15; 86 | if (!PgCtx->SomethingWentWrong;) 87 | { 88 | PgCtx->pPgFault->XoredChecksum = XoredRAXRDX_1 ^ PgCtx->XoredRAXRDX2; 89 | if (!PgCtx->SomethingWentWrong;) 90 | { 91 | PgCtx->EncodedPointerPgCtxEntry = 0i64; 92 | PgCtx->PgEntryType = 0x100i64; 93 | PgCtx->EncodedPointerPgCtxLocal = &PgCtx + 0A3A03F5891C8B4E8h; 94 | a1[0] = 0; 95 | PgCtx->PgEntryData = XoredRAXRDX_1; 96 | PgCtx->SomethingWentWrong = 1; 97 | SomeFlags = PgCtx->SomeFlags; 98 | if ( !_bittest(&SomeFlags, 0x1Eu) ) 99 | continue; 100 | } 101 | } 102 | } 103 | return a1; 104 | } 105 | } 106 | return a1; 107 | } 108 | ``` -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/hash_algo.md: -------------------------------------------------------------------------------- 1 | ```C 2 | void __fastcall ComputeHash(PPgCtx PgCtx, PVOID Data, SIZE_T Size, PVOID OutBuffer) 3 | { 4 | INT64 i; 5 | BYTE v6; 6 | char j; 7 | int TempBuffer[8]; 8 | 9 | KeGuardDispatchICall(PgCtx->KeComputeSha256, Data, Size, OutBuffer); 10 | for ( i = 0i64; i < 4; ++i ) 11 | OutBuffer[i] = TempBuffer[i] ^ TempBuffer[i + 4]; 12 | v6 = *(OutBuffer + 15); 13 | for ( j = *(OutBuffer + 15); ; j ^= v6 ) 14 | { 15 | v6 >>= 7; 16 | if ( !v6 ) 17 | break; 18 | } 19 | *(OutBuffer + 15) = j & 0x7F; 20 | } 21 | ``` -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/images/critical_msr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/542875F90F9B47F497B64BA219CACF69/images/critical_msr.png -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/images/exec_cb_obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/542875F90F9B47F497B64BA219CACF69/images/exec_cb_obj.png -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/images/func_int1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/542875F90F9B47F497B64BA219CACF69/images/func_int1.png -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/images/gen_dataregion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/542875F90F9B47F497B64BA219CACF69/images/gen_dataregion.png -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/images/imp_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/542875F90F9B47F497B64BA219CACF69/images/imp_table.png -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/images/insert_apc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/542875F90F9B47F497B64BA219CACF69/images/insert_apc.png -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/images/invfunctab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/542875F90F9B47F497B64BA219CACF69/images/invfunctab.png -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/images/mistake1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/542875F90F9B47F497B64BA219CACF69/images/mistake1.png -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/images/mistake1b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/542875F90F9B47F497B64BA219CACF69/images/mistake1b.png -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/images/objecttype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/542875F90F9B47F497B64BA219CACF69/images/objecttype.png -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/images/page_hash_mismatch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/542875F90F9B47F497B64BA219CACF69/images/page_hash_mismatch.png -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/images/pg_init.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/542875F90F9B47F497B64BA219CACF69/images/pg_init.png -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/images/seckernelintcheck_fct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/542875F90F9B47F497B64BA219CACF69/images/seckernelintcheck_fct.png -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/images/type_pool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/542875F90F9B47F497B64BA219CACF69/images/type_pool.png -------------------------------------------------------------------------------- /542875F90F9B47F497B64BA219CACF69/pg_entry_dump.py: -------------------------------------------------------------------------------- 1 | import ctypes 2 | import struct 3 | import sys 4 | import traceback 5 | import abc 6 | 7 | 8 | class PgEntry(abc.ABC): 9 | def __init__(self, 10 | pg_type, 11 | data_ptr, 12 | data_size, 13 | checksum, 14 | const1, 15 | const2, 16 | const3, 17 | const4, 18 | const5, 19 | const6): 20 | self._pg_type = pg_type 21 | self._data_ptr = ctypes.c_uint64(data_ptr) 22 | self._data_size = ctypes.c_uint32(data_size) 23 | self._checksum = ctypes.c_uint32(checksum) 24 | self._const1 = ctypes.c_uint32(const1) 25 | self._const2 = ctypes.c_uint32(const2) 26 | self._const3 = ctypes.c_uint32(const3) 27 | self._const4 = ctypes.c_uint32(const4) 28 | self._const5 = ctypes.c_uint32(const5) 29 | self._const6 = ctypes.c_uint32(const6) 30 | 31 | self.next_entry_off = ctypes.c_int64() 32 | 33 | super().__init__() 34 | 35 | 36 | def __str__(self): 37 | return "{0:<10s}: {1:08x}\n" \ 38 | "{2:<10s}: {3:08x}\n" \ 39 | "{4:<10s}: {5:08x}\n" \ 40 | "{6:<10s}: {7:08x}\n" \ 41 | "{8:<10s}: {9:08x}\n" \ 42 | "{10:<10s}: {11:08x}\n" \ 43 | "{12:<10s}: {13:08x}\n" \ 44 | "{14:<10s}: {15:08x}\n" \ 45 | "{16:<10s}: {17:08x}\n" \ 46 | "{18:<10s}: {19:08x}\n".format( 47 | "Type", self.pg_type, 48 | "DataPtr", self.data_ptr.value, 49 | "DataSize", self.data_size.value, 50 | "Checksum", self.checksum.value, 51 | "Const1", self.const1.value, 52 | "Const2", self.const2.value, 53 | "Const3", self.const3.value, 54 | "Const4", self.const4.value, 55 | "Const5", self.const5.value, 56 | "Const6", self.const6.value) 57 | 58 | def __eq__(self, entry2) -> bool: 59 | if not isinstance(entry2, PgEntry): 60 | return False 61 | 62 | return \ 63 | self.pg_type == entry2.pg_type and \ 64 | self.data_ptr.value == entry2.data_ptr.value and \ 65 | self.data_size.value == entry2.data_size.value and \ 66 | self.checksum.value == entry2.checksum.value and \ 67 | self.const1.value == entry2.const1.value and \ 68 | self.const2.value == entry2.const2.value and \ 69 | self.const3.value == entry2.const3.value and \ 70 | self.const4.value == entry2.const4.value and \ 71 | self.const5.value == entry2.const5.value and \ 72 | self.const6.value == entry2.const6.value 73 | 74 | @property 75 | def pg_type(self) -> int: 76 | return self._pg_type 77 | 78 | @pg_type.setter 79 | def pg_type(self, pg_type: int) -> None: 80 | self._pg_type = pg_type 81 | 82 | @property 83 | def data_ptr(self) -> ctypes.POINTER: 84 | return self._data_ptr 85 | 86 | @data_ptr.setter 87 | def data_ptr(self, data_ptr: ctypes.POINTER) -> None: 88 | self._data_ptr = data_ptr 89 | 90 | @property 91 | def data_size(self) -> ctypes.c_uint32: 92 | return self._data_size 93 | 94 | @data_size.setter 95 | def data_size(self, value: ctypes.c_uint32) -> None: 96 | self._data_size = value 97 | 98 | @property 99 | def checksum(self) -> ctypes.c_uint32: 100 | return self._checksum 101 | 102 | @checksum.setter 103 | def checksum(self, checksum: ctypes.c_uint32) -> None: 104 | self._checksum = checksum 105 | 106 | @property 107 | def const1(self) -> ctypes.c_uint32: 108 | return self._const1 109 | 110 | @const1.setter 111 | def const1(self, value: ctypes.c_uint32) -> None: 112 | self._const1 = value 113 | 114 | @property 115 | def const2(self) -> ctypes.c_uint32: 116 | return self._const2 117 | 118 | @const2.setter 119 | def constw(self, value: ctypes.c_uint32) -> None: 120 | self._const2 = value 121 | 122 | @property 123 | def const3(self) -> ctypes.c_uint32: 124 | return self._const3 125 | 126 | @const3.setter 127 | def const3(self, value: ctypes.c_uint32) -> None: 128 | self._const3 = value 129 | 130 | @property 131 | def const4(self) -> ctypes.c_uint32: 132 | return self._const4 133 | 134 | @const4.setter 135 | def const4(self, value: ctypes.c_uint32) -> None: 136 | self._const4 = value 137 | 138 | @property 139 | def const5(self) -> ctypes.c_uint32: 140 | return self._const5 141 | 142 | @const5.setter 143 | def const5(self, value: ctypes.c_uint32) -> None: 144 | self._const5 = value 145 | 146 | @property 147 | def const6(self) -> ctypes.c_uint32: 148 | return self._const6 149 | 150 | @const6.setter 151 | def const6(self, value: ctypes.c_uint32) -> None: 152 | self._const6 = value 153 | 154 | @abc.abstractmethod 155 | def get_next_entry(self): 156 | pass 157 | 158 | 159 | class PgEntryFunctionOrPdata(PgEntry): 160 | """Handles types FunctionOrPdata, SessionFunctionOrPdata and FunctionOrPdata1""" 161 | 162 | def get_next_entry(self) -> ctypes.c_int64: 163 | self.next_entry_off.value = 4 * (self.data_size.value // 0xc) + 0x30 164 | 165 | return self.next_entry_off 166 | 167 | 168 | class PgEntryProcessorProc(PgEntry): 169 | """Handles types FFFFFFFF ProcessorIDT, ProcessorGDT, Type1ProcessList, Type2ProcessList, DebugRoutine, CriticalMSR""" 170 | 171 | def get_next_entry(self) -> ctypes.c_int64: 172 | if self.pg_type == 0x2: 173 | self.next_entry_off.value = 0x30 174 | else: 175 | self.next_entry_off.value = 0x18 * (self.const1.value + 2) #(2 * (self.const1.value + 2) + self.const1.value) << 3 176 | 177 | return self.next_entry_off 178 | 179 | 180 | class PgEntryObjectType(PgEntry): 181 | """Handles type ObjectType""" 182 | 183 | def get_next_entry(self) -> ctypes.c_int64: 184 | self.next_entry_off.value = (self.const3.value & 0xffff) + 0x37 & 0xfffffff8 185 | 186 | return self.next_entry_off 187 | 188 | 189 | class PgEntrySystemServiceFunction(PgEntry): 190 | """Handles type SystemServiceFunction""" 191 | 192 | def get_next_entry(self) -> ctypes.c_int64: 193 | self.next_entry_off.value = (self.const2.value + 3) * 0x10 194 | 195 | return self.next_entry_off 196 | 197 | 198 | class PgEntryDriverObject(PgEntry): 199 | """Handles type DriverObject""" 200 | 201 | def get_next_entry(self) -> ctypes.c_int64: 202 | self.next_entry_off.value = (self.const5.value & 0xffff) + 0x37 & 0xfffffff8 203 | 204 | return self.next_entry_off 205 | 206 | 207 | class PgEntryModulePadding(PgEntry): 208 | """Handles type ModulePadding""" 209 | 210 | def get_next_entry(self) -> ctypes.c_int64: 211 | temp = self.const4.value - 1 if self.const4.value > 0 else 0 212 | self.next_entry_off.value = ((temp // 0xc + 7) & 0xfffffff8) + 0x18 * ((self.const5.value & 0xffff) + 2) 213 | 214 | return self.next_entry_off 215 | 216 | 217 | class PgEntryHashMismatch(PgEntry): 218 | """Handles types PageHashMismatch, SessionPageHashMismatch""" 219 | 220 | def get_next_entry(self) -> ctypes.c_int64: 221 | self.next_entry_off.value = 0x14 * (((self.const3.value & 0xfff) + self.const5.value + 0xfff) >> 12) + 0x30 222 | 223 | return self.next_entry_off 224 | 225 | 226 | class PgEntryGenericType(PgEntry): 227 | """Handles other types not covered by other classes""" 228 | 229 | def get_next_entry(self) -> ctypes.c_int64: 230 | self.next_entry_off.value = 0x30 231 | 232 | return self.next_entry_off 233 | 234 | 235 | class PgEntryFactory(object): 236 | def __init__(self): 237 | pass 238 | 239 | @classmethod 240 | def create(cls, entry): 241 | if entry[0] == 0x1 or entry[0] == 0xc or entry[0] == 0x2b: 242 | return PgEntryFunctionOrPdata(*entry) 243 | elif 2 <= entry[0] <= 7: 244 | return PgEntryProcessorProc(*entry) 245 | elif entry[0] == 0x8: 246 | return PgEntryObjectType(*entry) 247 | elif entry[0] == 0xa: 248 | return PgEntrySystemServiceFunction(*entry) 249 | elif entry[0] == 0x1c: 250 | return PgEntryDriverObject(*entry) 251 | elif entry[0] == 0x1e: 252 | return PgEntryModulePadding(*entry) 253 | elif 0x21 <= entry[0] <= 0x22: 254 | return PgEntryHashMismatch(*entry) 255 | else: 256 | return PgEntryGenericType(*entry) 257 | 258 | @classmethod 259 | def create_null(cls): 260 | return PgEntryGenericType(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 261 | 262 | 263 | assert(len(sys.argv) > 1) 264 | 265 | struct_fmt = "=QQLLLLLLLL" 266 | struct_sz = struct.calcsize(struct_fmt) 267 | struct_unpack = struct.Struct(struct_fmt).unpack_from 268 | 269 | PgEntriesOff = 0xaa0 270 | with open(sys.argv[1], "rb") as f: 271 | null_entry = PgEntryFactory.create_null() 272 | while True: 273 | f.seek(PgEntriesOff) 274 | try: 275 | s = struct_unpack(f.read(struct_sz)) 276 | except struct.error: 277 | traceback.print_exc() 278 | 279 | break 280 | 281 | pg_entry = PgEntryFactory.create(s) 282 | if pg_entry == null_entry: 283 | break 284 | 285 | print(pg_entry) 286 | 287 | PgEntriesOff += pg_entry.get_next_entry().value 288 | -------------------------------------------------------------------------------- /AfdTdxCallback/README.md: -------------------------------------------------------------------------------- 1 | ## AfdTdxCallback 2 | 3 | ### Description 4 | 5 | `Afd.sys` - `Ancillary Function Driver for WinSock`. 6 | 7 | `Tdx.sys` - [TDI](https://en.wikipedia.org/wiki/Transport_Driver_Interface) `Translation Driver`. 8 | 9 | --- 10 | 11 | Another _producer_ (`Tdx.sys`) - _consumer_ (`Afd.sys`) pattern (as in [TcpConnectionCallbackTemp](../TcpConnectionCallbackTemp)). Inside `Tdx.sys` callback object creation is governed by `TdxInitializeTransportAddressModule` function and all notifications (4 call references) on this object are triggered from `TdxActivateTransportAddress` function. `Afd.sys` registers a callback named `AfdTdxCallbackRoutine` inside `AfdTdxInitCallback` function. What is the consumer receiving as `Argument1` and `Argument2`(see [CallbackFunction](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-exregistercallback)) when the callback object is notified? 12 | - `Argument1` is of type `struct _ECP_LIST *`. 13 | - `Argument2` is used as an output argument (communication channel), through which `Afd.sys` passes back data to `Tdx.sys`. Here we can see that the authors are abusing the definition of the [CallbackFunction](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-exregistercallback) which in the documentation has `IN` SAL annotation, but here is used as an `OUT` parameter. 14 | 15 | `Argument1` can be useful in a call to [FsRtlFindExtraCreateParameter](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-fsrtlfindextracreateparameter) (that's the use case in `afd.sys`), where the ECP context structure is obtained through using an appropriate `GUID` (like ones listed in [System-Defined ECPs](https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/system-defined-ecps)). Last note, `afd.sys` uses the following `GUID`: `d37479c1-4502-a067-0e35-2e8cd59134f5`. 16 | -------------------------------------------------------------------------------- /EnlightenmentState/EnlightenmentState.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29411.108 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EnlightenmentState", "EnlightenmentState\EnlightenmentState.vcxproj", "{910F7BEE-8923-4801-B3EE-74114072FFD3}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM = Debug|ARM 11 | Debug|ARM64 = Debug|ARM64 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|ARM = Release|ARM 15 | Release|ARM64 = Release|ARM64 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Debug|ARM.ActiveCfg = Debug|ARM 21 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Debug|ARM.Build.0 = Debug|ARM 22 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Debug|ARM.Deploy.0 = Debug|ARM 23 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Debug|ARM64.ActiveCfg = Debug|ARM64 24 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Debug|ARM64.Build.0 = Debug|ARM64 25 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Debug|ARM64.Deploy.0 = Debug|ARM64 26 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Debug|x64.ActiveCfg = Debug|x64 27 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Debug|x64.Build.0 = Debug|x64 28 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Debug|x64.Deploy.0 = Debug|x64 29 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Debug|x86.ActiveCfg = Debug|Win32 30 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Debug|x86.Build.0 = Debug|Win32 31 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Debug|x86.Deploy.0 = Debug|Win32 32 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Release|ARM.ActiveCfg = Release|ARM 33 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Release|ARM.Build.0 = Release|ARM 34 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Release|ARM.Deploy.0 = Release|ARM 35 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Release|ARM64.ActiveCfg = Release|ARM64 36 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Release|ARM64.Build.0 = Release|ARM64 37 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Release|ARM64.Deploy.0 = Release|ARM64 38 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Release|x64.ActiveCfg = Release|x64 39 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Release|x64.Build.0 = Release|x64 40 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Release|x64.Deploy.0 = Release|x64 41 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Release|x86.ActiveCfg = Release|Win32 42 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Release|x86.Build.0 = Release|Win32 43 | {910F7BEE-8923-4801-B3EE-74114072FFD3}.Release|x86.Deploy.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {39B3A25C-047A-4C61-B484-A5FF80E061A3} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /EnlightenmentState/EnlightenmentState/EnlightenmentState.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | DRIVER_INITIALIZE DriverEntry; 4 | DRIVER_UNLOAD DriverUnload; 5 | CALLBACK_FUNCTION EnlightenmentStateCallback; 6 | 7 | PVOID g_EnlightenmentStateCb; 8 | 9 | VOID 10 | EnlightenmentStateCallback( 11 | _In_opt_ PVOID CallbackContext, 12 | _In_opt_ PVOID Argument1, 13 | _In_opt_ PVOID Argument2 14 | ) 15 | { 16 | 17 | PAGED_CODE(); 18 | 19 | UNREFERENCED_PARAMETER(CallbackContext); 20 | UNREFERENCED_PARAMETER(Argument1); 21 | UNREFERENCED_PARAMETER(Argument2); 22 | 23 | } 24 | 25 | VOID 26 | DriverUnload( 27 | _In_ PDRIVER_OBJECT DriverObject 28 | ) 29 | { 30 | 31 | PAGED_CODE(); 32 | 33 | UNREFERENCED_PARAMETER(DriverObject); 34 | 35 | if (g_EnlightenmentStateCb != NULL) { 36 | ExUnregisterCallback(g_EnlightenmentStateCb); 37 | } 38 | 39 | } 40 | 41 | NTSTATUS 42 | DriverEntry( 43 | _In_ PDRIVER_OBJECT DriverObject, 44 | _In_ PUNICODE_STRING RegistryPath 45 | ) 46 | { 47 | 48 | UNREFERENCED_PARAMETER(RegistryPath); 49 | 50 | UNICODE_STRING EnlightenmentStateObjName; 51 | OBJECT_ATTRIBUTES EnlightenmentStateAttr; 52 | PCALLBACK_OBJECT pEnlightenmentState = NULL; 53 | 54 | DriverObject->DriverUnload = DriverUnload; 55 | 56 | RtlInitUnicodeString(&EnlightenmentStateObjName, L"\\Callback\\EnlightenmentState"); 57 | 58 | InitializeObjectAttributes(&EnlightenmentStateAttr, &EnlightenmentStateObjName, OBJ_CASE_INSENSITIVE, NULL, NULL); 59 | 60 | if (!NT_SUCCESS(ExCreateCallback(&pEnlightenmentState, &EnlightenmentStateAttr, FALSE, FALSE))) { 61 | 62 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, __FUNCTION__ ": Failed to obtain callback object!\n"); 63 | 64 | return STATUS_NOT_FOUND; 65 | } 66 | 67 | g_EnlightenmentStateCb = ExRegisterCallback(pEnlightenmentState, EnlightenmentStateCallback, NULL); 68 | 69 | if (g_EnlightenmentStateCb != NULL) { 70 | 71 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, __FUNCTION__ ": Seems ok!\n"); 72 | 73 | } 74 | else { 75 | 76 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, __FUNCTION__ ": Hmmm, something wrong!\n"); 77 | 78 | return STATUS_UNSUCCESSFUL; 79 | } 80 | 81 | return STATUS_SUCCESS; 82 | 83 | } -------------------------------------------------------------------------------- /EnlightenmentState/EnlightenmentState/EnlightenmentState.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; EnlightenmentState.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=System 8 | ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} 9 | Provider=%ManufacturerName% 10 | DriverVer= 11 | CatalogFile=EnlightenmentState.cat 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | 16 | 17 | [SourceDisksNames] 18 | 1 = %DiskName%,,,"" 19 | 20 | [SourceDisksFiles] 21 | 22 | 23 | [Manufacturer] 24 | %ManufacturerName%=Standard,NT$ARCH$ 25 | 26 | [Standard.NT$ARCH$] 27 | 28 | 29 | [Strings] 30 | ManufacturerName="" ;TODO: Replace with your manufacturer name 31 | ClassName="" 32 | DiskName="EnlightenmentState Source Disk" 33 | -------------------------------------------------------------------------------- /EnlightenmentState/EnlightenmentState/EnlightenmentState.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 | Debug 22 | ARM 23 | 24 | 25 | Release 26 | ARM 27 | 28 | 29 | Debug 30 | ARM64 31 | 32 | 33 | Release 34 | ARM64 35 | 36 | 37 | 38 | {910F7BEE-8923-4801-B3EE-74114072FFD3} 39 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 40 | v4.5 41 | 12.0 42 | Debug 43 | Win32 44 | EnlightenmentState 45 | 46 | 47 | 48 | Windows10 49 | true 50 | WindowsKernelModeDriver10.0 51 | Driver 52 | WDM 53 | 54 | 55 | Windows10 56 | false 57 | WindowsKernelModeDriver10.0 58 | Driver 59 | WDM 60 | 61 | 62 | Windows10 63 | true 64 | WindowsKernelModeDriver10.0 65 | Driver 66 | WDM 67 | 68 | 69 | Windows10 70 | false 71 | WindowsKernelModeDriver10.0 72 | Driver 73 | WDM 74 | 75 | 76 | Windows10 77 | true 78 | WindowsKernelModeDriver10.0 79 | Driver 80 | WDM 81 | 82 | 83 | Windows10 84 | false 85 | WindowsKernelModeDriver10.0 86 | Driver 87 | WDM 88 | 89 | 90 | Windows10 91 | true 92 | WindowsKernelModeDriver10.0 93 | Driver 94 | WDM 95 | 96 | 97 | Windows10 98 | false 99 | WindowsKernelModeDriver10.0 100 | Driver 101 | WDM 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | DbgengKernelDebugger 113 | 114 | 115 | DbgengKernelDebugger 116 | 117 | 118 | DbgengKernelDebugger 119 | 120 | 121 | DbgengKernelDebugger 122 | 123 | 124 | DbgengKernelDebugger 125 | 126 | 127 | DbgengKernelDebugger 128 | 129 | 130 | DbgengKernelDebugger 131 | 132 | 133 | DbgengKernelDebugger 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /EnlightenmentState/EnlightenmentState/EnlightenmentState.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Driver Files 24 | 25 | 26 | 27 | 28 | Source Files 29 | 30 | 31 | -------------------------------------------------------------------------------- /EnlightenmentState/README.md: -------------------------------------------------------------------------------- 1 | ## EnlightenmentState 2 | 3 | **[WIP]** 4 | 5 | This callback is related to Hyper-V Enlightenments. It is notified in function `HvlPhase2Initialize` only if bit 0 of `HvlpRootFlags` is not set. We still need to trace down wich Enlightenment set or not this bit, it looks like this is done in function `HvlpDetermineEnlightenments` which comes from `HvlPhase0Initialize`. 6 | 7 | This still needs a **lot** of investigation since we are not even near to understand how Hyper-V works internally. 8 | -------------------------------------------------------------------------------- /IoExternalDmaUnblock/README.md: -------------------------------------------------------------------------------- 1 | ## IoExternalDmaUnblock 2 | 3 | ### Description 4 | 5 | The callback object is created inside `ntoskrnl.exe`. The root of function tree that frames actions on this callback object is `PiCslInitialize` function, where `PipCslConsoleLockState` is initialized to 0 and `PipCslCreateCallback` is called in order to create the callback object (symbol `PipCslCallbackObject`). After the object is successfully created, the callback function `PipCslStateChangeCallback` is registered. The goal of this callback is to check if `PipCslInitialized` was initialized (not 0), otherwise the system bugchecks (code _0xCA_), then call `PipCslUpdateState` with argument value _1_ or _2_. The latter call compares the value of `PipCslConsoleLockState` with the argument value and if the values are different and the argument value is _1_ - `PipCslUnlockCallback` is called. An outline of what was mentioned: 6 | ```C 7 | NTSTATUS __stdcall PiCslInitialize() 8 | { 9 | NTSTATUS v0; 10 | 11 | PipCslConsoleLockState = 0; 12 | v0 = PipCslCreateCallback(); 13 | if ( v0 >= 0 ) 14 | { 15 | ExRegisterCallback((PCALLBACK_OBJECT)PipCslCallbackObject, (PCALLBACK_FUNCTION)PipCslStateChangeCallback, 0i64); 16 | PipCslInitialized = 1; 17 | } 18 | return v0; 19 | } 20 | ``` 21 | 22 | What is `PipCslUnlockCallback` doing? Skimming the references we observe that the only write to this global function pointer is inside `PipDmgInitPhaseOne` function and the written value is the address of `PipDmgConsoleUnlockCallback` function. It is important to mention that the initialization happens only when `PipDmaGuardPolicy` is not _0_. As described on [Policy CSP - DmaGuard](https://docs.microsoft.com/en-us/windows/client-management/mdm/policy-csp-dmaguard), the value _0_ stands for _most restrictive_ policy, so the callback is going to be initialized in other cases, like when the policy is _1_ or _2_ (there are other undocumented values, like _3_). These primitives seem to be related to [Kernel DMA Protection](https://docs.microsoft.com/en-us/windows/security/information-protection/kernel-dma-protection-for-thunderbolt). In the end, `PipDmgConsoleUnlockCallback` is responsible for calling `PipDmgFlushQueueAndRestartDevices` function when `PipDmaGuardPolicy` is equal to _2_. 23 | 24 | Callback object notifications are sent from `ntoskrnl`'s [NtPowerInformation](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-ntpowerinformation), when `InformationLevel` argument has value _0x5F_, through calling `PnpWinlogonExternalDmaNotification` function. `Argument1` parameter of `ExNotifyCallback` is `NtPowerInformation`'s second parameter named `InputBuffer` and `Argument2` is always set to _0_. 25 | 26 | There's another callback function registered inside `pci.sys` by function `PciCreateConsoleLockCallback`. The callback function name is `PciConsoleLockCallback` which is a wrapper for `PciSetConsoleState`. Inside the wrapper, first argument value (parameter `Argument1`) is checked if _0_ / _NULL_ and if not then the argument to later call is value _1_ otherwise _2_. `PciSetConsoleState` goal is to iterate over every _bus_ in every _PCI segment_ and verify if the _bus_ is affected by console lock (a - `PciBusAffectedByConsoleLock` is called) and should be disabled (b - `PciBusShouldBeDisabledByConsoleLock` is called). If only (a) is satisfied then `IoInvalidateDeviceRelations` is called. It is important to note that all of the above actions are done only when `PciConsoleState` global variable value is different than the value of the argument passed to the function. 27 | 28 | We were curios about any executables, libraries or drivers that make use of `NtPowerInformation` and call it with first argument being _0x5F_. For that we searched recursively inside `%SystemRoot%\System32` looking for files containing the string _NtPowerInformation_ (in different code pages like ANSI, UTF-8, UTF-16). Then using _HexRays decompiler plugin_ and [two scripts](ida_run.py) (watch out, unpolished code!) allowing to run _IDA Pro_ in batch mode we found 91 files calling `NtPowerInformation` at least once. And from those, the only one using _0x5F_ as an argument is inside a function (`NotifyUserPresenceOnDesktopForDMAProtection`) hosted by `winlogon.exe`. Here's the pseudocode: 29 | ```C 30 | // 31 | // When symbols are loaded the function prototype is: 32 | // void __fastcall NotifyUserPresenceOnDesktopForDMAProtection(int, struct _WLSM_GLOBAL_CONTEXT *) 33 | // 34 | void **__fastcall sub_1400391B8(int a1, __int64 a2) 35 | { 36 | __int64 v2; // rcx 37 | void **result; // rax 38 | NTSTATUS v4; // eax 39 | __int64 v5; // rdx 40 | __int64 v6; // r8 41 | __int64 v7; // r9 42 | const wchar_t *v8; // r9 43 | int v9; // [rsp+40h] [rbp+8h] 44 | char InputBuffer; // [rsp+48h] [rbp+10h] 45 | 46 | v9 = a1; 47 | v2 = *(_QWORD *)(a2 + 16); 48 | InputBuffer = 0; 49 | if ( (unsigned int)sub_140027BB8(v2) ) // CSession::IsBoundToConsole 50 | { 51 | InputBuffer = v9; 52 | // 53 | // TraceApplicationPowerMessageEnd - 0x1F 54 | // 55 | v4 = NtPowerInformation(TraceApplicationPowerMessageEnd|0x40, &InputBuffer, 1u, 0i64, 0); 56 | v7 = (unsigned int)v4; 57 | ... 58 | ``` 59 | 60 | EOF 61 | -------------------------------------------------------------------------------- /IoExternalDmaUnblock/ida_run.py: -------------------------------------------------------------------------------- 1 | from sys import exit, argv 2 | from subprocess import run 3 | from os import scandir, chdir, getcwd 4 | 5 | assert len(argv) > 1 6 | 7 | script_file_name_path = getcwd() + "\\ntpowerinfo.py" 8 | with scandir(argv[1]) as fd: 9 | chdir(argv[1]) 10 | for e in fd: 11 | if any(e.name.endswith(ex) for ex in (".exe", ".dll", ".sys")): 12 | print("Process {}".format(e.name)) 13 | p = run(["ida64.exe", "-c", "-A", "-S" + script_file_name_path, e.name]) 14 | -------------------------------------------------------------------------------- /IoExternalDmaUnblock/ntpowerinfo.py: -------------------------------------------------------------------------------- 1 | import ida_ida 2 | import ida_auto 3 | import ida_loader 4 | import ida_hexrays 5 | import ida_idp 6 | import ida_entry 7 | import idautils 8 | import ida_nalt 9 | import ida_pro 10 | 11 | from os.path import basename 12 | 13 | def imp_cb(ea, name, ord): 14 | if "NtPowerInformation" in name: 15 | global nt_power_information 16 | nt_power_information = ea 17 | # False stops iteration over imports 18 | return False 19 | # Continue to iterate over imports 20 | return True 21 | 22 | 23 | nimps = idaapi.get_import_module_qty() 24 | 25 | nt_power_information = None 26 | for i in range(0, nimps): 27 | name = idaapi.get_import_module_name(i) 28 | if not name: 29 | continue 30 | 31 | if "ntdll" in name: 32 | idaapi.enum_import_names(i, imp_cb) 33 | if nt_power_information is not None: 34 | break 35 | 36 | output_filename = basename(ida_nalt.get_input_file_path()) \ 37 | + ida_nalt.get_root_filename() + ".dec" 38 | if nt_power_information: 39 | ida_auto.auto_wait() 40 | 41 | if ida_loader.load_plugin("hexx64") and ida_hexrays.init_hexrays_plugin(): 42 | code_xrefs = idautils.CodeRefsTo(nt_power_information, 1) 43 | for cx in code_xrefs: 44 | cf = ida_hexrays.decompile(cx) 45 | if cf: 46 | with open(output_filename, "a") as fd: 47 | fd.write(str(cf) + '\n') 48 | else: 49 | with open(output_filename, "a") as fd: 50 | fd.write("[!] Decompilation failed\n") 51 | else: 52 | with open(output_filename, "a") as fd: 53 | fd.write("[!] Decompiler loading failed\n") 54 | else: 55 | with open(output_filename, "a") as fd: 56 | fd.write("[+] NtPowerInformation import was not found\n") 57 | 58 | ida_pro.qexit(0) 59 | -------------------------------------------------------------------------------- /Loader/Loader.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #define CALLBACKOBJ_SERVICE_NAMEW L"ExCallbackObjectsSvc" 9 | #define CALLBACKOBJ_SERVICE_INSTALL 0 10 | #define CALLBACKOBJ_SERVICE_UNINSTALL 1 11 | 12 | 13 | typedef struct _EX_CALLBACK_OBJ_TUPLE { 14 | PCWSTR DriverName; 15 | DWORD StartType; 16 | } EX_CALLBACK_OBJ_TUPLE; 17 | 18 | EX_CALLBACK_OBJ_TUPLE g_ExCallbackObjectDrivers[] = { 19 | { L"WdProcessNotificationCallback.sys", SERVICE_DEMAND_START }, 20 | { L"Phase1InitComplete.sys", SERVICE_BOOT_START }, 21 | { L"EnlightenmentState.sys", SERVICE_BOOT_START }, 22 | { L"TcpConnectionCallbackTemp.sys", SERVICE_DEMAND_START } 23 | }; 24 | DWORD g_NumCallbackObjectDrivers = sizeof(g_ExCallbackObjectDrivers) / sizeof(g_ExCallbackObjectDrivers[0]); 25 | 26 | _Success_(return == TRUE) 27 | BOOLEAN 28 | InstallDriver( 29 | _In_ SC_HANDLE hSCManager, 30 | _In_ LPCTSTR ServiceName, 31 | _In_ LPCTSTR DriverPath, 32 | _In_ DWORD StartType 33 | ) 34 | { 35 | SC_HANDLE schService; 36 | DWORD errCode; 37 | 38 | schService = CreateService(hSCManager, 39 | ServiceName, 40 | ServiceName, 41 | SERVICE_ALL_ACCESS, 42 | SERVICE_KERNEL_DRIVER, 43 | StartType, 44 | SERVICE_ERROR_NORMAL, 45 | DriverPath, 46 | NULL, 47 | NULL, 48 | NULL, 49 | NULL, 50 | NULL); 51 | if (NULL == schService) { 52 | errCode = GetLastError(); 53 | 54 | if (ERROR_SERVICE_EXISTS == errCode) { 55 | fprintf(stderr, __FUNCTION__ " Service already exists\n"); 56 | 57 | return TRUE; 58 | } else { 59 | fprintf(stderr, __FUNCTION__ " Failed creating service: %#x\n", errCode); 60 | 61 | return FALSE; 62 | } 63 | } else { 64 | CloseServiceHandle(schService); 65 | 66 | fprintf(stdout, __FUNCTION__ " Service %S was successfully created\n", ServiceName); 67 | 68 | return TRUE; 69 | } 70 | } 71 | 72 | _Success_(return == TRUE) 73 | BOOLEAN 74 | UninstallDriver( 75 | _In_ SC_HANDLE hSCManager, 76 | _In_ LPCTSTR ServiceName 77 | ) 78 | { 79 | SC_HANDLE schService; 80 | BOOLEAN bRetStatus = FALSE; 81 | 82 | schService = OpenService(hSCManager, 83 | ServiceName, 84 | SERVICE_ALL_ACCESS); 85 | if (NULL == schService) { 86 | fprintf(stderr, __FUNCTION__ " Failed opening the service: %#X\n", GetLastError()); 87 | 88 | return bRetStatus; 89 | } 90 | 91 | if (DeleteService(schService)) { 92 | bRetStatus = TRUE; 93 | 94 | fprintf(stdout, __FUNCTION__ " Service %S was successfully deleted\n", ServiceName); 95 | } else { 96 | fprintf(stderr, __FUNCTION__ " Failed deleting the service: %#X\n", GetLastError()); 97 | } 98 | 99 | CloseServiceHandle(schService); 100 | 101 | return bRetStatus; 102 | } 103 | 104 | _Success_(return == TRUE) 105 | BOOLEAN 106 | StartDriver( 107 | _In_ SC_HANDLE hSCManager, 108 | _In_ LPCTSTR ServiceName 109 | ) 110 | { 111 | SC_HANDLE schService; 112 | DWORD errCode; 113 | BOOLEAN bRetStatus = FALSE; 114 | 115 | schService = OpenService(hSCManager, 116 | ServiceName, 117 | SERVICE_ALL_ACCESS); 118 | if (NULL == schService) { 119 | fprintf(stderr, __FUNCTION__ " Failed opening the service: %#X\n", GetLastError()); 120 | 121 | return bRetStatus; 122 | } 123 | 124 | if (!StartService(schService, 125 | 0, 126 | NULL)) { 127 | errCode = GetLastError(); 128 | 129 | if (ERROR_SERVICE_ALREADY_RUNNING == errCode) { 130 | bRetStatus = TRUE; 131 | 132 | fprintf(stdout, __FUNCTION__ " Service %S already running\n", ServiceName); 133 | } else { 134 | fprintf(stderr, __FUNCTION__ " Failed starting the service: %#X\n", errCode); 135 | } 136 | } else { 137 | bRetStatus = TRUE; 138 | 139 | fprintf(stdout, __FUNCTION__ " Service %S was successfully started\n", ServiceName); 140 | } 141 | 142 | CloseServiceHandle(schService); 143 | 144 | return bRetStatus; 145 | } 146 | 147 | _Success_(return == TRUE) 148 | BOOLEAN 149 | StopDriver( 150 | _In_ SC_HANDLE hSCManager, 151 | _In_ LPCTSTR ServiceName 152 | ) 153 | { 154 | SC_HANDLE schService; 155 | SERVICE_STATUS serviceStatus; 156 | BOOLEAN bRetStatus = FALSE; 157 | 158 | schService = OpenService(hSCManager, 159 | ServiceName, 160 | SERVICE_ALL_ACCESS); 161 | if (NULL == schService) { 162 | fprintf(stderr, __FUNCTION__ " Failed opening the service: %#X\n", GetLastError()); 163 | 164 | return bRetStatus; 165 | } 166 | 167 | if (ControlService(schService, 168 | SERVICE_CONTROL_STOP, 169 | &serviceStatus)) { 170 | bRetStatus = TRUE; 171 | 172 | fprintf(stdout, __FUNCTION__ " Service %S was successfully stopped\n", ServiceName); 173 | } else { 174 | fprintf(stderr, __FUNCTION__ " Failed stopping the service: %#X\n", GetLastError()); 175 | } 176 | 177 | CloseServiceHandle(schService); 178 | 179 | return bRetStatus; 180 | } 181 | 182 | _Success_(return == TRUE) 183 | BOOLEAN 184 | ManageDriver( 185 | _In_ LPCTSTR DriverPath, 186 | _In_ LPCTSTR ServiceName, 187 | _In_ SIZE_T Action, 188 | _In_ DWORD StartType 189 | ) 190 | { 191 | SC_HANDLE schSCManager; 192 | BOOLEAN bRetVal = TRUE; 193 | 194 | if (NULL == DriverPath || NULL == ServiceName) { 195 | fprintf(stderr, __FUNCTION__ " Invalid driver name or service name\n"); 196 | 197 | return FALSE; 198 | } 199 | 200 | schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); 201 | if (NULL == schSCManager) { 202 | fprintf(stderr, __FUNCTION__ " Failed opening a connection to SCM: %#X\n", GetLastError()); 203 | 204 | return FALSE; 205 | } 206 | 207 | switch (Action) { 208 | case CALLBACKOBJ_SERVICE_INSTALL: 209 | if (InstallDriver(schSCManager, ServiceName, DriverPath, StartType)) { 210 | if (StartType == SERVICE_DEMAND_START) { 211 | bRetVal = StartDriver(schSCManager, ServiceName); 212 | } else { 213 | fprintf(stderr, __FUNCTION__ " StartType isn't DEMAND_START, the service isn't started\n"); 214 | 215 | bRetVal = TRUE; 216 | } 217 | } else { 218 | bRetVal = FALSE; 219 | } 220 | 221 | break; 222 | case CALLBACKOBJ_SERVICE_UNINSTALL: 223 | if (StopDriver(schSCManager, ServiceName)) { 224 | bRetVal = UninstallDriver(schSCManager, ServiceName); 225 | } else { 226 | bRetVal = FALSE; 227 | } 228 | 229 | break; 230 | default: 231 | fprintf(stderr, __FUNCTION__ " Unknown action: %zu\n", Action); 232 | 233 | bRetVal = FALSE; 234 | 235 | break; 236 | } 237 | 238 | if (CloseServiceHandle(schSCManager) == 0) { 239 | fprintf(stderr, __FUNCTION__ " Failed closing SCM: %#X\n", GetLastError()); 240 | } 241 | 242 | return bRetVal; 243 | } 244 | 245 | DWORD chk_strtoul(PCSTR pStr, PBOOL bFail) { 246 | PCHAR pEndPtr; 247 | DWORD dwNum; 248 | 249 | *bFail = strchr(pStr, '-') != NULL; 250 | 251 | errno = 0; 252 | dwNum = strtoul(pStr, &pEndPtr, 10); 253 | if (errno || pEndPtr == pStr || *pEndPtr) { 254 | *bFail = 1; 255 | } 256 | 257 | return dwNum; 258 | } 259 | 260 | int __cdecl main(int argc, char* argv[]) 261 | { 262 | DWORD retCode = EXIT_SUCCESS; 263 | DWORD dwBufferLength = 0; 264 | DWORD dwCallbackId = 0; 265 | BOOL bFail = FALSE; 266 | LPWSTR lpBuffer = NULL; 267 | LPCWSTR lpDriverName = NULL; 268 | 269 | if (argc > 2) { 270 | dwCallbackId = chk_strtoul(argv[2], &bFail); 271 | if (bFail) { 272 | fwprintf(stderr, L"Failed to parse callback id\n"); 273 | 274 | return EXIT_FAILURE;; 275 | } 276 | if (dwCallbackId >= g_NumCallbackObjectDrivers) { 277 | fwprintf(stderr, L"Maximum id number is %lu\n", g_NumCallbackObjectDrivers - 1); 278 | 279 | retCode = EXIT_FAILURE; 280 | 281 | goto usage; 282 | } 283 | 284 | fprintf(stdout, "Selected callback object: %ls\n", g_ExCallbackObjectDrivers[dwCallbackId].DriverName); 285 | 286 | if (_strnicmp(argv[1], "load", strlen("load")) == 0) { 287 | lpDriverName = g_ExCallbackObjectDrivers[dwCallbackId].DriverName; 288 | 289 | if (g_ExCallbackObjectDrivers[dwCallbackId].StartType == SERVICE_BOOT_START) { 290 | // FIXME: User env variable expansion or read system drive letter instead of hardcoding. 291 | LPCWSTR lpSystem32W = L"C:\\Windows\\System32\\"; 292 | lpBuffer = calloc(wcslen(lpSystem32W) + wcslen(lpDriverName) + 1, sizeof(WCHAR)); 293 | if (NULL == lpBuffer) { 294 | retCode = GetLastError(); 295 | fwprintf(stderr, L"Failed allocating a buffer for System32: %08X\n", retCode); 296 | 297 | goto free_buff; 298 | } 299 | if (wcsncpy_s(lpBuffer, 300 | wcslen(lpSystem32W) + wcslen(lpDriverName) + 1, 301 | lpSystem32W, 302 | wcslen(lpSystem32W)) != 0) { 303 | retCode = GetLastError(); 304 | fwprintf(stderr, L"wcsncpy_s failed: %08X\n", retCode); 305 | 306 | free(lpBuffer); 307 | lpBuffer = NULL; 308 | 309 | goto free_buff; 310 | } 311 | if (wcsncat_s(lpBuffer, 312 | wcslen(lpSystem32W) + wcslen(lpDriverName) + 1, 313 | lpDriverName, 314 | wcslen(lpDriverName)) != 0) { 315 | retCode = GetLastError(); 316 | fwprintf(stderr, L"wcsncat_s failed: %08X\n", retCode); 317 | 318 | free(lpBuffer); 319 | lpBuffer = NULL; 320 | 321 | goto free_buff; 322 | } 323 | 324 | if (!CopyFile(lpDriverName, lpBuffer, TRUE)) { 325 | retCode = GetLastError(); 326 | fwprintf(stderr, L"CopyFile failed: %08X\n", retCode); 327 | } else { 328 | fwprintf(stdout, L"%lS was successfully copied\n", lpBuffer); 329 | } 330 | } else if (g_ExCallbackObjectDrivers[dwCallbackId].StartType == SERVICE_DEMAND_START) { 331 | dwBufferLength = GetCurrentDirectory(dwBufferLength, lpBuffer); 332 | if (!dwBufferLength) { 333 | retCode = GetLastError(); 334 | fwprintf(stderr, L"Failed to query current directory length: %08X\n", retCode); 335 | 336 | return retCode; 337 | } else { 338 | lpBuffer = calloc(dwBufferLength + wcslen(lpDriverName) + 2, sizeof(WCHAR)); // + 2: 1 for \ and 1 for NULL 339 | if (NULL == lpBuffer) { 340 | retCode = GetLastError(); 341 | fwprintf(stderr, L"Failed allocating a buffer for current directory: %08X\n", retCode); 342 | 343 | return retCode; 344 | } 345 | 346 | if (!GetCurrentDirectory(dwBufferLength, lpBuffer)) { 347 | retCode = GetLastError(); 348 | fwprintf(stderr, L"Failed to query current directory length: %08X\n", retCode); 349 | 350 | goto free_buff; 351 | } 352 | } 353 | 354 | if (wcsncat_s(lpBuffer, 355 | dwBufferLength + wcslen(lpDriverName) + 1, 356 | L"\\", 357 | wcslen(L"\\")) != 0) { 358 | retCode = GetLastError(); 359 | fwprintf(stderr, L"wcsncat_s failed: %08X\n", retCode); 360 | 361 | goto free_buff; 362 | } 363 | if (wcsncat_s(lpBuffer, 364 | dwBufferLength + wcslen(lpDriverName) + 1, 365 | lpDriverName, 366 | wcslen(lpDriverName)) != 0) { 367 | retCode = GetLastError(); 368 | fwprintf(stderr, L"wcsncat_s failed: %08X\n", retCode); 369 | 370 | goto free_buff; 371 | } 372 | } else { 373 | fwprintf(stderr, L"Unknown service start option: %08X\n", g_ExCallbackObjectDrivers[dwCallbackId].StartType); 374 | 375 | return EXIT_FAILURE; 376 | } 377 | 378 | fwprintf(stdout, L"Absolute path of the driver to load: %lS\n", lpBuffer); 379 | 380 | ManageDriver(lpBuffer, CALLBACKOBJ_SERVICE_NAMEW, CALLBACKOBJ_SERVICE_INSTALL, g_ExCallbackObjectDrivers[dwCallbackId].StartType); 381 | 382 | free_buff: 383 | free(lpBuffer); 384 | lpBuffer = NULL; 385 | } else { 386 | goto usage; 387 | } 388 | } else if (argc > 1) { 389 | if (_strnicmp(argv[1], "unload", strlen("unload")) == 0) { 390 | ManageDriver(L"", CALLBACKOBJ_SERVICE_NAMEW, CALLBACKOBJ_SERVICE_UNINSTALL, ULONG_MAX); 391 | } else { 392 | goto usage; 393 | } 394 | } else { 395 | usage: 396 | fwprintf(stdout, L"[*] Usage: %hs [ load | unload ]\n", argv[0]); 397 | fwprintf(stdout, L"[*] Available callback object drivers:\n"); 398 | for (size_t i = 0; i < g_NumCallbackObjectDrivers; i++) { 399 | fwprintf(stdout, L"[+] %zu: %ls\n", i, g_ExCallbackObjectDrivers[i].DriverName); 400 | } 401 | } 402 | 403 | return retCode; 404 | } -------------------------------------------------------------------------------- /Loader/Loader.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29411.108 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Loader", "Loader.vcxproj", "{0B8757DD-22F0-4F9C-934D-79FE1E8CCB42}" 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 | {0B8757DD-22F0-4F9C-934D-79FE1E8CCB42}.Debug|x64.ActiveCfg = Debug|Win32 17 | {0B8757DD-22F0-4F9C-934D-79FE1E8CCB42}.Debug|x64.Build.0 = Debug|Win32 18 | {0B8757DD-22F0-4F9C-934D-79FE1E8CCB42}.Debug|x86.ActiveCfg = Debug|Win32 19 | {0B8757DD-22F0-4F9C-934D-79FE1E8CCB42}.Debug|x86.Build.0 = Debug|Win32 20 | {0B8757DD-22F0-4F9C-934D-79FE1E8CCB42}.Release|x64.ActiveCfg = Release|x64 21 | {0B8757DD-22F0-4F9C-934D-79FE1E8CCB42}.Release|x64.Build.0 = Release|x64 22 | {0B8757DD-22F0-4F9C-934D-79FE1E8CCB42}.Release|x86.ActiveCfg = Release|Win32 23 | {0B8757DD-22F0-4F9C-934D-79FE1E8CCB42}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {EE6A6E9D-32D9-4A03-A3FA-EB79560F3CF0} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Loader/Loader.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 | 23 | 24 | 25 | {0B8757DD-22F0-4F9C-934D-79FE1E8CCB42} 26 | {504102d4-2172-473c-8adf-cd96e308f257} 27 | v4.5 28 | 12.0 29 | Debug 30 | Win32 31 | Loader 32 | 33 | 34 | 35 | Windows10 36 | true 37 | WindowsApplicationForDrivers10.0 38 | Application 39 | Universal 40 | Unicode 41 | 42 | 43 | Windows10 44 | false 45 | WindowsApplicationForDrivers10.0 46 | Application 47 | Universal 48 | Unicode 49 | 50 | 51 | Windows10 52 | true 53 | WindowsApplicationForDrivers10.0 54 | Application 55 | Universal 56 | Unicode 57 | 58 | 59 | Windows10 60 | false 61 | WindowsApplicationForDrivers10.0 62 | Application 63 | Universal 64 | Unicode 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | _DEBUG;WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions) 76 | MultiThreadedDebugDLL 77 | 78 | 79 | %(AdditionalDependencies);onecoreuap.lib 80 | 81 | 82 | 83 | 84 | WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions) 85 | 86 | 87 | %(AdditionalDependencies);onecoreuap.lib 88 | 89 | 90 | 91 | 92 | _DEBUG;WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions) 93 | MultiThreadedDebugDLL 94 | 95 | 96 | %(AdditionalDependencies);onecoreuap.lib 97 | 98 | 99 | 100 | 101 | WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions) 102 | 103 | 104 | %(AdditionalDependencies);onecoreuap.lib 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /Loader/Loader.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /Phase1InitComplete/Phase1InitComplete.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29411.108 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Phase1InitComplete", "Phase1InitComplete\Phase1InitComplete.vcxproj", "{FE59AFEB-AEC5-425E-A480-00E6D43ED87F}" 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 | {FE59AFEB-AEC5-425E-A480-00E6D43ED87F}.Debug|x64.ActiveCfg = Debug|x64 17 | {FE59AFEB-AEC5-425E-A480-00E6D43ED87F}.Debug|x64.Build.0 = Debug|x64 18 | {FE59AFEB-AEC5-425E-A480-00E6D43ED87F}.Debug|x64.Deploy.0 = Debug|x64 19 | {FE59AFEB-AEC5-425E-A480-00E6D43ED87F}.Debug|x86.ActiveCfg = Debug|Win32 20 | {FE59AFEB-AEC5-425E-A480-00E6D43ED87F}.Debug|x86.Build.0 = Debug|Win32 21 | {FE59AFEB-AEC5-425E-A480-00E6D43ED87F}.Debug|x86.Deploy.0 = Debug|Win32 22 | {FE59AFEB-AEC5-425E-A480-00E6D43ED87F}.Release|x64.ActiveCfg = Release|x64 23 | {FE59AFEB-AEC5-425E-A480-00E6D43ED87F}.Release|x64.Build.0 = Release|x64 24 | {FE59AFEB-AEC5-425E-A480-00E6D43ED87F}.Release|x64.Deploy.0 = Release|x64 25 | {FE59AFEB-AEC5-425E-A480-00E6D43ED87F}.Release|x86.ActiveCfg = Release|Win32 26 | {FE59AFEB-AEC5-425E-A480-00E6D43ED87F}.Release|x86.Build.0 = Release|Win32 27 | {FE59AFEB-AEC5-425E-A480-00E6D43ED87F}.Release|x86.Deploy.0 = Release|Win32 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | GlobalSection(ExtensibilityGlobals) = postSolution 33 | SolutionGuid = {F9E279BF-4CC9-45AD-9F95-214CE6711E88} 34 | EndGlobalSection 35 | EndGlobal 36 | -------------------------------------------------------------------------------- /Phase1InitComplete/Phase1InitComplete/Phase1InitComplete.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DRIVER_INITIALIZE DriverEntry; 5 | DRIVER_UNLOAD DriverUnload; 6 | CALLBACK_FUNCTION Phase1Callback; 7 | 8 | PVOID g_Phase1Callback; 9 | 10 | VOID 11 | Phase1Callback( 12 | _In_opt_ PVOID CallbackContext, 13 | _In_opt_ PVOID Argument1, 14 | _In_opt_ PVOID Argument2 15 | ) 16 | { 17 | 18 | PAGED_CODE(); 19 | 20 | UNREFERENCED_PARAMETER(CallbackContext); 21 | 22 | PVOID pvAddressOfReturnAddress; 23 | PVOID pLoaderParamBlock; 24 | 25 | // Make sure we are getting notified by the kernel 26 | if (Argument1 != NULL && Argument2 != NULL) { 27 | 28 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, __FUNCTION__ ": Wrong Arguments!!"); 29 | 30 | return; 31 | } 32 | 33 | 34 | pvAddressOfReturnAddress = _AddressOfReturnAddress(); 35 | 36 | /* In Windows 10 ver 1903 (OS Build 19002.1002) adding 0x68 to the return addres of this callback we get a pointer to the LOADER_PARAMETER_BLOCK. This is of course not reliable, just throwing out some ideas :) 37 | */ 38 | pLoaderParamBlock = (PVOID)((char *)pvAddressOfReturnAddress + 0x68); 39 | 40 | } 41 | 42 | VOID 43 | DriverUnload( 44 | _In_ PDRIVER_OBJECT DriverObject 45 | ) 46 | { 47 | 48 | PAGED_CODE(); 49 | 50 | UNREFERENCED_PARAMETER(DriverObject); 51 | 52 | if (g_Phase1Callback != NULL) { 53 | ExUnregisterCallback(g_Phase1Callback); 54 | } 55 | 56 | } 57 | 58 | NTSTATUS 59 | DriverEntry( 60 | _In_ PDRIVER_OBJECT DriverObject, 61 | _In_ PUNICODE_STRING RegistryPath 62 | ) 63 | { 64 | 65 | UNREFERENCED_PARAMETER(RegistryPath); 66 | 67 | UNICODE_STRING Phase1ObjName; 68 | OBJECT_ATTRIBUTES Phase1ObjAttr; 69 | PCALLBACK_OBJECT pPhase1InitComplete = NULL; 70 | 71 | DriverObject->DriverUnload = DriverUnload; 72 | 73 | RtlInitUnicodeString(&Phase1ObjName, L"\\Callback\\Phase1InitComplete"); 74 | 75 | InitializeObjectAttributes(&Phase1ObjAttr, &Phase1ObjName, OBJ_CASE_INSENSITIVE, NULL, NULL); 76 | 77 | if (!NT_SUCCESS(ExCreateCallback(&pPhase1InitComplete, &Phase1ObjAttr, FALSE, FALSE))) { 78 | 79 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, __FUNCTION__ ": Failed to obtain callback object!\n"); 80 | 81 | return STATUS_NOT_FOUND; 82 | } 83 | 84 | g_Phase1Callback = ExRegisterCallback(pPhase1InitComplete, Phase1Callback, NULL); 85 | 86 | if (g_Phase1Callback != NULL) { 87 | 88 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, __FUNCTION__ ": Seems ok!\n"); 89 | 90 | } else { 91 | 92 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, __FUNCTION__ ": Hmmm, something wrong!\n"); 93 | 94 | return STATUS_UNSUCCESSFUL; 95 | } 96 | 97 | return STATUS_SUCCESS; 98 | 99 | } -------------------------------------------------------------------------------- /Phase1InitComplete/Phase1InitComplete/Phase1InitComplete.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; Phase1InitComplete.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=System 8 | ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} 9 | Provider=%ManufacturerName% 10 | DriverVer= 11 | CatalogFile=Phase1InitComplete.cat 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | 16 | 17 | [SourceDisksNames] 18 | 1 = %DiskName%,,,"" 19 | 20 | [SourceDisksFiles] 21 | 22 | 23 | [Manufacturer] 24 | %ManufacturerName%=Standard,NT$ARCH$ 25 | 26 | [Standard.NT$ARCH$] 27 | 28 | 29 | [Strings] 30 | ManufacturerName="" ;TODO: Replace with your manufacturer name 31 | ClassName="" 32 | DiskName="Phase1InitComplete Source Disk" 33 | -------------------------------------------------------------------------------- /Phase1InitComplete/Phase1InitComplete/Phase1InitComplete.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 | Debug 22 | ARM 23 | 24 | 25 | Release 26 | ARM 27 | 28 | 29 | Debug 30 | ARM64 31 | 32 | 33 | Release 34 | ARM64 35 | 36 | 37 | 38 | {FE59AFEB-AEC5-425E-A480-00E6D43ED87F} 39 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 40 | v4.5 41 | 12.0 42 | Debug 43 | Win32 44 | Phase1InitComplete 45 | 46 | 47 | 48 | Windows10 49 | true 50 | WindowsKernelModeDriver10.0 51 | Driver 52 | WDM 53 | 54 | 55 | Windows10 56 | false 57 | WindowsKernelModeDriver10.0 58 | Driver 59 | WDM 60 | 61 | 62 | Windows10 63 | true 64 | WindowsKernelModeDriver10.0 65 | Driver 66 | WDM 67 | 68 | 69 | Windows10 70 | false 71 | WindowsKernelModeDriver10.0 72 | Driver 73 | WDM 74 | 75 | 76 | Windows10 77 | true 78 | WindowsKernelModeDriver10.0 79 | Driver 80 | WDM 81 | 82 | 83 | Windows10 84 | false 85 | WindowsKernelModeDriver10.0 86 | Driver 87 | WDM 88 | 89 | 90 | Windows10 91 | true 92 | WindowsKernelModeDriver10.0 93 | Driver 94 | WDM 95 | 96 | 97 | Windows10 98 | false 99 | WindowsKernelModeDriver10.0 100 | Driver 101 | WDM 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | DbgengKernelDebugger 113 | 114 | 115 | DbgengKernelDebugger 116 | 117 | 118 | DbgengKernelDebugger 119 | 120 | 121 | DbgengKernelDebugger 122 | 123 | 124 | DbgengKernelDebugger 125 | 126 | 127 | DbgengKernelDebugger 128 | 129 | 130 | DbgengKernelDebugger 131 | 132 | 133 | DbgengKernelDebugger 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /Phase1InitComplete/Phase1InitComplete/Phase1InitComplete.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Driver Files 24 | 25 | 26 | 27 | 28 | Source Files 29 | 30 | 31 | -------------------------------------------------------------------------------- /Phase1InitComplete/README.md: -------------------------------------------------------------------------------- 1 | ## Phase1InitComplete 2 | 3 | Initial investigation show that this callback is only notified one time (Phase1 only happens one time so this makes total sense). The function `ExNotifyCallback` for this callback object is called inside `Phase1InitializationIoReady`. As seen on the MSDN the prototype for [`ExNotifyCallback`](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-exnotifycallback) is the following: 4 | 5 | ```C 6 | void ExNotifyCallback( 7 | PVOID CallbackObject, 8 | PVOID Argument1, 9 | PVOID Argument2 10 | ); 11 | ``` 12 | 13 | With the help of IDA we can see that this function is called with the following parameters: 14 | 15 | ![ExNotifyCallback Phase1InitComple](images/CallExNotifyCallback.png) 16 | 17 | The variable `ExCbPhase1InitComplete` holds the pointer to the `CALLBACK_OBJECT`. And the `Argument1` and `Argument2` are zero, this means that our callback won't receive any interesting arguments. 18 | 19 | ### Remarks 20 | For this driver to work, it must be loaded at Boot time that means that the `StartType` of this services must be set to `SERVICE_BOOT_START`. Also, for the bootloader to load the driver this must be in the folder `%SYSTEMROOT%\System32\drivers\` 21 | 22 | Having this in mind, the use case of this is quite small. But just for fun, we decided to add some code in the callback that allow us to retreive the address of the `LOADER_PARAMETER_BLOCK`. To do this, we basically obtain the address of the return address (Using the intrinsic [_AddressOfReturnAddress](https://docs.microsoft.com/en-us/cpp/intrinsics/addressofreturnaddress?view=vs-2019)) we checked using IDA and WinDbg how much we need to add to this value in order to obtain the pointer to the `LOADER_PARAMETER_BLOCK`. To make this short, the callback gets called from `ExNotifyWithProcessing` which substracts 0x30 to `rsp` (We add 0x8 for the retn addr from this function) this comes from `ExNotifyCallback` which substracts 0x28 (Again we add 0x8 for the retn addr) finally we found out the next value (At least on In Windows 10 ver 1903 (OS Build 19002.1002)) in the stack corresponds with the `LOADER_PARAMETER_BLOCK` (This is inside `Phase1InitializationIoReady`) so in the end would be: 23 | `0x30 + 0x8 + 0x28 + 0x8 = 0x68`. In the following image it can be seen how the code is adding 0x68 to `rax` and then we can use this value (pointer) to dispay the type `LOADER_PARAMETER_BLOCK`: 24 | 25 | ![Obtaining LOADER_PARAMETER_BLOCK](images/LoaderParamBlock.png) 26 | -------------------------------------------------------------------------------- /Phase1InitComplete/images/CallExNotifyCallback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/Phase1InitComplete/images/CallExNotifyCallback.png -------------------------------------------------------------------------------- /Phase1InitComplete/images/LoaderParamBlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/Phase1InitComplete/images/LoaderParamBlock.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ExecutiveCallbackObjects 2 | Research on Windows Kernel Executive Callback Objects 3 | 4 | OS Version: Windows 10 Pro Insiders Preview 20H1 19008 or later 5 | 6 | # List of researched callback objects 7 | 8 | ## [542875F90F9B47F497B64BA219CACF69](542875F90F9B47F497B64BA219CACF69) 9 | 10 | ## [AfdTdxCallback](AfdTdxCallback) 11 | 12 | ## [EnlightenmentState](EnlightenmentState) 13 | 14 | ## [IoExternalDmaUnblock](IoExternalDmaUnblock) 15 | 16 | ## IoSessionNotifications 17 | 18 | ## LicensingData 19 | 20 | ## LLTDCallbackMapper 21 | 22 | ## LLTDCallbackRspndr 23 | 24 | ## NdisBindUnbind 25 | 26 | ## [Phase1InitComplete](Phase1InitComplete) 27 | 28 | ## PowerState 29 | 30 | ## ProcessorAdd 31 | 32 | ## SeImageVerificationDriverInfo 33 | 34 | ## SetSystemState 35 | 36 | ## SetSystemTime 37 | 38 | ## [TcpConnectionCallbackTemp](TcpConnectionCallbackTemp) 39 | 40 | ## TcpTimerStarvationCallbackTemp 41 | 42 | ## VidPhu 43 | 44 | ## [WdEbNotificationCallback](WdEbNotificationCallback) 45 | 46 | ## [WdNriNotificationCallback](WdNriNotificationCallback) 47 | 48 | ## [WdProcessNotificationCallback](WdProcessNotificationCallback) 49 | 50 | # Disclaimer 51 | This investigation is just being held for research purpose, we don't take part nor encourage any illegitimate use of what is explained in this repository. Also if you find any mistakes or different behaviours please feel free to contribute, we would gladly appreciate any contribution. 52 | 53 | # Acknowledgments 54 | 55 | [hFiref0x](https://twitter.com/hfiref0x) for [WinObjEx64](https://github.com/hfiref0x/WinObjEx64) 56 | -------------------------------------------------------------------------------- /TcpConnectionCallbackTemp/README.md: -------------------------------------------------------------------------------- 1 | ## TcpConnectionCallbackTemp 2 | 3 | ### Description 4 | 5 | **This is still work in progress!** 6 | 7 | This callback object can be created in `tcpip.sys` or `rasacd.sys`. In both drivers the symbol for the object is `TcpCcbObject`. 8 | A strong friendship relationship is observed in `tcpip.sys`, where _9_ references lead to `ExNotifyCallback`, while `rasacd.sys` has _1_ reference leading to `ExRegisterCallback`. So our understanding comes to a conclusion that we have a _producer_ - _consumer_ pattern between these _2_ drivers. 9 | 10 | There seem to be 3 possible values for the `Argument1`, they are the following: 11 | - 1: Default case 12 | - 2: Seems to be related to `TCP_SYN_ATTACK_ENTRY` 13 | - 3: Seems to be related to `TCP_SYN_ATTACK_EXIT` 14 | 15 | For `Argument2`, only when `Argument1` is equal to `1`, we get a pointer to a structure: 16 | ```C 17 | typedef struct _TCP_CB 18 | { 19 | UINT16 Magic; // 2 20 | UINT16 Reserved; 21 | DWORD32 Unknown0; // observed values: 1, 3, 5, 6, 7, 10, 11 22 | DWORD64 NotificationType; // observed values: 1, 3, 4, 5 23 | PVOID pSrcIpAddr; 24 | PVOID pDstIpAddr; 25 | UINT16 pSrcPort; 26 | UINT16 pDstPort; 27 | DWORD32 Unknown1; // observed values: 0xe0000001 28 | DWORD32 Unknown2; // observed values: 0xe0000001 29 | DWORD32 Unknown3; // 0x21, 0x1 30 | } TCP_CB, *PTCP_CB; 31 | ``` 32 | 33 | ### POC 34 | 35 | [TcpConnectionCallbackTemp](TcpConnectionCallbackTemp) 36 | -------------------------------------------------------------------------------- /TcpConnectionCallbackTemp/TcpConnectionCallbackTemp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29411.108 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TcpConnectionCallbackTemp", "TcpConnectionCallbackTemp\TcpConnectionCallbackTemp.vcxproj", "{0B8A304E-E1CA-4E1E-B369-84B109AFCD19}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {0B8A304E-E1CA-4E1E-B369-84B109AFCD19}.Debug|x64.ActiveCfg = Debug|x64 15 | {0B8A304E-E1CA-4E1E-B369-84B109AFCD19}.Debug|x64.Build.0 = Debug|x64 16 | {0B8A304E-E1CA-4E1E-B369-84B109AFCD19}.Debug|x64.Deploy.0 = Debug|x64 17 | {0B8A304E-E1CA-4E1E-B369-84B109AFCD19}.Release|x64.ActiveCfg = Release|x64 18 | {0B8A304E-E1CA-4E1E-B369-84B109AFCD19}.Release|x64.Build.0 = Release|x64 19 | {0B8A304E-E1CA-4E1E-B369-84B109AFCD19}.Release|x64.Deploy.0 = Release|x64 20 | EndGlobalSection 21 | GlobalSection(SolutionProperties) = preSolution 22 | HideSolutionNode = FALSE 23 | EndGlobalSection 24 | GlobalSection(ExtensibilityGlobals) = postSolution 25 | SolutionGuid = {F6B6CF74-E51C-4A4B-8053-461D04B0F865} 26 | EndGlobalSection 27 | EndGlobal 28 | -------------------------------------------------------------------------------- /TcpConnectionCallbackTemp/TcpConnectionCallbackTemp/TcpConnectionCallbackTemp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define IPByte1(x) ((int)((x) & 0xff)) 4 | #define IPByte2(x) ((int)(((x) >> 8) & 0xff)) 5 | #define IPByte3(x) ((int)(((x) >> 16) & 0xff)) 6 | #define IPByte4(x) ((int)(((x) >> 24) & 0xff)) 7 | 8 | DRIVER_INITIALIZE DriverEntry; 9 | DRIVER_UNLOAD DriverUnload; 10 | 11 | PVOID g_TcpConnRegisteredCallback; 12 | CALLBACK_FUNCTION TcpConnCallback; 13 | 14 | typedef struct _TCP_CB 15 | { 16 | UINT16 Magic; 17 | UINT16 Reserved; 18 | DWORD32 Unknown0; // observed values: 1, 3, 5, 6, 7, 10, 11 19 | DWORD64 NotificationType; // observed values: 1, 3, 4, 5 20 | PVOID pSrcIpAddr; 21 | PVOID pDstIpAddr; 22 | UINT16 pSrcPort; 23 | UINT16 pDstPort; 24 | DWORD32 Unknown1; // observed values: 0xe0000001 25 | DWORD32 Unknown2; // observed values: 0xe0000001 26 | DWORD32 Unknown3; // 0x21, 0x1 27 | } TCP_CB, *PTCP_CB; 28 | 29 | VOID 30 | TcpConnCallback( 31 | _In_opt_ PVOID CallbackContext, 32 | _In_opt_ PVOID Argument1, 33 | _In_opt_ PVOID Argument2 34 | ) 35 | { 36 | UNREFERENCED_PARAMETER(CallbackContext); 37 | 38 | PTCP_CB pTcpCb = (PTCP_CB)Argument2; 39 | ULONG IPv4Addr; 40 | 41 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 42 | DPFLTR_INFO_LEVEL, 43 | __FUNCTION__ ": [+] Argument1: %#08llX\n", (DWORD64)Argument1); 44 | 45 | if (pTcpCb != NULL) { 46 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 47 | DPFLTR_INFO_LEVEL, 48 | __FUNCTION__ ": [*] Magic: %#06x Reserved: %#06x\n", 49 | pTcpCb->Magic, 50 | pTcpCb->Reserved 51 | ); 52 | 53 | switch (pTcpCb->NotificationType) { 54 | case 1: 55 | if (pTcpCb->Unknown0 == 11) { 56 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 57 | DPFLTR_INFO_LEVEL, 58 | __FUNCTION__ ": [~1] Called from TcpShutdownTimeWaitTcb\n" 59 | ); 60 | } else if (pTcpCb->Unknown0 == 10) { 61 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 62 | DPFLTR_INFO_LEVEL, 63 | __FUNCTION__ ": [~1] Called from TcpTcbCarefulDatagram\n" 64 | ); 65 | } else { 66 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 67 | DPFLTR_INFO_LEVEL, 68 | __FUNCTION__ ": [~1] Called from TcpShutdownTcb or TcpInvokeCcb. Unknown0: %#10lx\n", 69 | pTcpCb->Unknown0 70 | ); 71 | } 72 | 73 | break; 74 | case 3: 75 | if (pTcpCb->Unknown0 == 1) { 76 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 77 | DPFLTR_INFO_LEVEL, 78 | __FUNCTION__ ": [~2] Called from TcpCreateAndConnectTcbRateLimitComplete\n" 79 | ); 80 | } else { 81 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 82 | DPFLTR_INFO_LEVEL, 83 | __FUNCTION__ ": [~2] Called from ?\n" 84 | ); 85 | } 86 | 87 | break; 88 | case 4: 89 | if (pTcpCb->Unknown0 == 1) { 90 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 91 | DPFLTR_INFO_LEVEL, 92 | __FUNCTION__ ": [~3] Called from TcpCreateAndAcceptTcb\n" 93 | ); 94 | } else { 95 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 96 | DPFLTR_INFO_LEVEL, 97 | __FUNCTION__ ": [~3] Called from ?\n" 98 | ); 99 | } 100 | 101 | break; 102 | case 5: 103 | if (pTcpCb->Unknown0 == 3) { 104 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 105 | DPFLTR_INFO_LEVEL, 106 | __FUNCTION__ ": [~4] Called from TcpCreateAndConnectTcbComplete\n" 107 | ); 108 | } else { 109 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 110 | DPFLTR_INFO_LEVEL, 111 | __FUNCTION__ ": [~4] Called from ?\n" 112 | ); 113 | } 114 | 115 | break; 116 | default: 117 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 118 | DPFLTR_INFO_LEVEL, 119 | __FUNCTION__ ": [~5] Called from InvokeCcb. NotificationType: %#10llx Unknown0: %#10lx\n", 120 | pTcpCb->NotificationType, 121 | pTcpCb->Unknown0 122 | ); 123 | 124 | break; 125 | } 126 | 127 | 128 | if (pTcpCb->pSrcIpAddr && pTcpCb->pDstIpAddr) { 129 | IPv4Addr = *(PULONG)pTcpCb->pSrcIpAddr; 130 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 131 | DPFLTR_INFO_LEVEL, 132 | __FUNCTION__ ": [<] Source IP: %d.%d.%d.%d Port: %u\n", 133 | IPByte1(IPv4Addr), 134 | IPByte2(IPv4Addr), 135 | IPByte3(IPv4Addr), 136 | IPByte4(IPv4Addr), 137 | pTcpCb->pSrcPort 138 | ); 139 | IPv4Addr = *(PULONG)pTcpCb->pDstIpAddr; 140 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 141 | DPFLTR_INFO_LEVEL, 142 | __FUNCTION__ ": [>] Destination IP: %d.%d.%d.%d Port: %u\n", 143 | IPByte1(IPv4Addr), 144 | IPByte2(IPv4Addr), 145 | IPByte3(IPv4Addr), 146 | IPByte4(IPv4Addr), 147 | pTcpCb->pDstPort 148 | ); 149 | } 150 | 151 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 152 | DPFLTR_INFO_LEVEL, 153 | __FUNCTION__ ": [-] Unknown1: %#10x Unknown2: %#10x Unknown3: %#10x\n", 154 | pTcpCb->Unknown1, 155 | pTcpCb->Unknown1, 156 | pTcpCb->Unknown3 157 | ); 158 | } else { 159 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 160 | DPFLTR_ERROR_LEVEL, 161 | __FUNCTION__ ": [!] Argument2 isn't available\n"); 162 | } 163 | } 164 | 165 | VOID DriverUnload( 166 | _In_ PDRIVER_OBJECT DriverObject 167 | ) 168 | { 169 | UNREFERENCED_PARAMETER(DriverObject); 170 | 171 | if (g_TcpConnRegisteredCallback != NULL) { 172 | ExUnregisterCallback(g_TcpConnRegisteredCallback); 173 | } 174 | } 175 | 176 | NTSTATUS 177 | DriverEntry( 178 | _In_ PDRIVER_OBJECT DriverObject, 179 | _In_ PUNICODE_STRING RegistryPath 180 | ) 181 | { 182 | UNREFERENCED_PARAMETER(RegistryPath); 183 | 184 | DriverObject->DriverUnload = DriverUnload; 185 | 186 | PCALLBACK_OBJECT pTcpConnCb = NULL; 187 | UNICODE_STRING TcpConnObjName = RTL_CONSTANT_STRING(L"\\Callback\\TcpConnectionCallbackTemp"); 188 | OBJECT_ATTRIBUTES TcpConnObjAttr; 189 | RtlSecureZeroMemory(&TcpConnObjAttr, sizeof(OBJECT_ATTRIBUTES)); 190 | TcpConnObjAttr.Length = sizeof(OBJECT_ATTRIBUTES); 191 | TcpConnObjAttr.ObjectName = &TcpConnObjName; 192 | TcpConnObjAttr.Attributes = 0x50; 193 | 194 | if (!NT_SUCCESS(ExCreateCallback(&pTcpConnCb, &TcpConnObjAttr, TRUE, TRUE))) { 195 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 196 | DPFLTR_ERROR_LEVEL, 197 | __FUNCTION__ ": Failed to obtain callback object!\n"); 198 | 199 | return STATUS_NOT_FOUND; 200 | } 201 | 202 | g_TcpConnRegisteredCallback = ExRegisterCallback(pTcpConnCb, TcpConnCallback, NULL); 203 | if (g_TcpConnRegisteredCallback != NULL) { 204 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 205 | DPFLTR_INFO_LEVEL, 206 | __FUNCTION__ ": Callback was successfully registered!\n"); 207 | 208 | } else { 209 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 210 | DPFLTR_ERROR_LEVEL, 211 | __FUNCTION__ ": Hmmm, something wrong!\n"); 212 | 213 | } 214 | 215 | return STATUS_SUCCESS; 216 | } -------------------------------------------------------------------------------- /TcpConnectionCallbackTemp/TcpConnectionCallbackTemp/TcpConnectionCallbackTemp.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; TcpConnectionCallbackTemp.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=System 8 | ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} 9 | Provider=%ManufacturerName% 10 | DriverVer= 11 | CatalogFile=TcpConnectionCallbackTemp.cat 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | 16 | 17 | [SourceDisksNames] 18 | 1 = %DiskName%,,,"" 19 | 20 | [SourceDisksFiles] 21 | 22 | 23 | [Manufacturer] 24 | %ManufacturerName%=Standard,NT$ARCH$ 25 | 26 | [Standard.NT$ARCH$] 27 | 28 | 29 | [Strings] 30 | ManufacturerName="" ;TODO: Replace with your manufacturer name 31 | ClassName="" 32 | DiskName="TcpConnectionCallbackTemp Source Disk" 33 | -------------------------------------------------------------------------------- /TcpConnectionCallbackTemp/TcpConnectionCallbackTemp/TcpConnectionCallbackTemp.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {0B8A304E-E1CA-4E1E-B369-84B109AFCD19} 15 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 16 | v4.5 17 | 12.0 18 | Debug 19 | Win32 20 | TcpConnectionCallbackTemp 21 | 22 | 23 | 24 | Windows10 25 | true 26 | WindowsKernelModeDriver10.0 27 | Driver 28 | WDM 29 | 30 | 31 | Windows10 32 | false 33 | WindowsKernelModeDriver10.0 34 | Driver 35 | WDM 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | DbgengKernelDebugger 47 | 48 | 49 | DbgengKernelDebugger 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /TcpConnectionCallbackTemp/TcpConnectionCallbackTemp/TcpConnectionCallbackTemp.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Driver Files 24 | 25 | 26 | 27 | 28 | Source Files 29 | 30 | 31 | -------------------------------------------------------------------------------- /WdEbNotificationCallback/README.md: -------------------------------------------------------------------------------- 1 | ## WdEbNotificationCallback 2 | 3 | The main function of this callback is to notify `WdFilter` when a `KnonwBadImage` has tried to be loaded. Of course, this callback is notified from within `WdBoot` (Windows Defender ELAM driver), more specifically from the [`BOOT_DRIVER_CALLBACK_FUNCTION`](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/nc-ntddk-boot_driver_callback_function) of this driver. 4 | 5 | To trigger this callback the parameter [`BDCB_CALLBACK_TYPE`](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ne-ntddk-_bdcb_callback_type) must be set to `BdCbStatusUpdate` (A status update provided by the system to a boot-start driver) and the structure [`_BDCB_IMAGE_INFORMATION`](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-_bdcb_image_information) must have the field Classification set to `BdCbClassificationKnownBadImage`. 6 | 7 | ![WdBoot ExNotifyCallback](images/CallExNotifyCallback.png) 8 | 9 | In the previous image we can see the call that executes `WdBoot` to notify the callback routines. Argument1 is a pointer to MpEbGlobals.Magic and Argument2 is set to 0x28. The MpEbGlobals structure has the following definition 10 | 11 | ```c 12 | // sizeof(MP_EP_GLOBALS) == 0xB0 13 | struct __declspec(align(4)) MP_EP_GLOBALS 14 | { 15 | UNICODE_STRING RegistryPath; 16 | PVOID pHandleRegistration; 17 | PVOID IoUnregisterBootDriverCallback; 18 | DWORD Magic; // Set to 0x28EB01 19 | DWORD SignaturesVersionMajor; 20 | DWORD SignaturesVersionMinor; 21 | DWORD Unk_Unused; 22 | LIST_ENTRY DriversListEntry; 23 | PSLIST_ENTRY pSlistEntry; 24 | PCALLBACK_OBJECT WdCallbackObject; 25 | LARGE_INTEGER Cookie; 26 | _QWORD Unk_Unused1; 27 | SLIST_HEADER SlistHeader; 28 | DWORD LoadedDriversCount; 29 | DWORD LoadedDriversArrayLen; 30 | PVOID LoadedDriversArray; 31 | DWORD TotalModulesEntryLen; 32 | BYTE EntryPointWdFilter[32]; 33 | BYTE FlagWdOrMp; 34 | BYTE FlagTestMode; 35 | BYTE FlagPersistElamInfo; 36 | BYTE Alignment; 37 | _QWORD Unk_Unused2; 38 | }; 39 | ``` 40 | > Sorry for the own advertisement 😆 41 | > but if you want to learn more about `WdBoot`check this post https://n4r1b.netlify.com/en/posts/2019/11/understanding-wdboot-windows-defender-elam/ 42 | 43 | As we can see, this structure has some quite interesting fields that we will be able to access if we register a routine for this callback. 44 | 45 | ### Possible use cases 46 | > The following cases haven't been tested, is just theorical. We still need to write POCs to test them on the other hand there're some big downsides which make this quite useless. 47 | 48 | - As we can see on MP_EP_GLOBALS, if we go back in the structure from the Magic field we can get the value of IoUnregisterBootDriverCallback. This function will be called when `WdBoot` is unloaded from memory. So there's a chance to change to change that pointer to our own function (Kinda hooking) so our function will be automatically called when `WdBoot`is unloaded from memory. Of course there's a big downside here, this callback is execute only when a `KnonwBadImage` is found, and of course if this happens the system will probably Bug Check. So not really a big deal here. 49 | 50 | ![MpEbUnload](images/MpEbUnload.png) 51 | 52 | - This one needs further investigation on `WdFilter`, but it may be possible to access the DriversListEntry(Refer to the post to see the structure used in this field) and modify the Classification that was set by the ELAM driver. This could possibly lead to `WdFilter` believing this a `KnownGoodImage`, since `WdFilter` will use this information too. The downside here is that the routine registered by `WdFilter` execute before our registered routine, but this could probably be changed modifying the CALLBACK_OBJECT.CallbackFunctions LIST_ENTRY in order to make our routine first. (**This still needs investigation**) 53 | 54 | ![WdFilter Saving DriverClassification](images/WdFilterCopyData.png) 55 | -------------------------------------------------------------------------------- /WdEbNotificationCallback/images/CallExNotifyCallback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdEbNotificationCallback/images/CallExNotifyCallback.png -------------------------------------------------------------------------------- /WdEbNotificationCallback/images/MpEbUnload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdEbNotificationCallback/images/MpEbUnload.png -------------------------------------------------------------------------------- /WdEbNotificationCallback/images/WdFilterCopyData.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdEbNotificationCallback/images/WdFilterCopyData.png -------------------------------------------------------------------------------- /WdNriNotificationCallback/README.md: -------------------------------------------------------------------------------- 1 | ## WdNriNotificationCallback 2 | 3 | ### Description 4 | 5 | The callback object can be created in 2 places: `WdFilter.sys` and `WdNisDrv.sys`. But a callback function is registered only in `WdFilter.sys`, last time we checked the callback was named `MpNriNotificationCallback`. The callback in itself isn't very interesting and in essence is just a wrapper around `MpRefreshProcessNotifications`, which we already sketched in [WdProcessNotificationCallback](../WdProcessNotificationCallback). Callback's code is provided just as a future reference: 6 | 7 | ![callback](images/callback.png) 8 | 9 | We observed that this callback object is notified from `WdNisDrv.sys` - `set_process_exceptions(PMP_DATA , PIRP *)`. 10 | 11 | ![callback_notif](images/callback_notif.png) 12 | -------------------------------------------------------------------------------- /WdNriNotificationCallback/images/callback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdNriNotificationCallback/images/callback.png -------------------------------------------------------------------------------- /WdNriNotificationCallback/images/callback_notif.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdNriNotificationCallback/images/callback_notif.png -------------------------------------------------------------------------------- /WdProcessNotificationCallback/README.md: -------------------------------------------------------------------------------- 1 | ## WdProcessNotificationCallback 2 | 3 | ### Description 4 | 5 | `WdProcessNotificationCallback` callback object is "born" either from `WdFilter.sys` or `WdNisDrv.sys`. In both cases it is created by a wrapper function called `MpCreateCallback`. 6 | But `WdFilter` is a bit special, because the callback object can be named `MpProcessNotificationCallback`(observe the difference of 2 characters in the prefix). This change of behavior 7 | is controlled byte a `boolean` flag(exhausting his existence at offset `+0x6B1`) in `MpData` context structure maintained by the driver - `MpData`. If the value of the `boolean` flag is `1`, look 8 | for `WdProcessNotificationCallback`... 9 | ![obj_creation](images/obj_creation.png) 10 | 11 | Unsurprisingly, the code path that ends in notifying this object goes through `WdFilter.sys` and last 4 stack frames, in case of process creation or termination, can be stamped as: 12 | 13 | ![stack_frames](images/stack_frames.png) 14 | 15 | Before going further, it is necessary to know when our callback will receive a notification for the callback object we've registered. Extending the thought from above and observing that there are _5_ 16 | calls to `ExNotifyCallback` having their first argument `MpData + 0x6D8`, standing for `CallbackObject` parameter as presented in [MSDN](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-exnotifycallback), it is possible to affirm that the following operations are going to "disturb" our callback: 17 | - **Process creation** 18 | - **Process termination**, both called from `MpHandleProcessNotification` 19 | - **Refresh process notifications**, called from `MpRefreshProcessNotification` 20 | - **Set trusted process**, called from `MpSetTrustedProcess` 21 | - **Set untrusted process**, called from `MpSetUntrustedProcess` 22 | 23 | In order to understand what data our callback will obtain, we have to peel the onion level by level. Let's start with process creation and termination. At the outer level, an easy target, we find `MpCreateProcessNotifyRoutineEx` which receives 3 arguments. 24 | For convenience, the [prototype](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/nc-ntddk-pcreate_process_notify_routine_ex) of this function is: 25 | ```C 26 | void PcreateProcessNotifyRoutineEx( 27 | PEPROCESS Process, 28 | HANDLE ProcessId, 29 | PPS_CREATE_NOTIFY_INFO CreateInfo 30 | ) 31 | ``` 32 | The last parameter is a pointer to `PS_CREATE_NOTIFY_INFO` structure, created inside `PspCallProcessNotifyRoutines`, having the following [definition](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-_ps_create_notify_info): 33 | ```C 34 | typedef struct _PS_CREATE_NOTIFY_INFO { 35 | SIZE_T Size; 36 | union { 37 | ULONG Flags; 38 | struct { 39 | ULONG FileOpenNameAvailable : 1; 40 | ULONG IsSubsystemProcess : 1; 41 | ULONG Reserved : 30; 42 | }; 43 | }; 44 | HANDLE ParentProcessId; 45 | CLIENT_ID CreatingThreadId; 46 | struct _FILE_OBJECT *FileObject; 47 | PCUNICODE_STRING ImageFileName; 48 | PCUNICODE_STRING CommandLine; 49 | NTSTATUS CreationStatus; 50 | } PS_CREATE_NOTIFY_INFO, *PPS_CREATE_NOTIFY_INFO; 51 | ``` 52 | 53 | Skipping some details in `MpCreateProcessNotifyRoutineEx`, our attention can be directed to the call into `MpHandleProcessNotification`. Here's an attempt of outlining a prototype for this routine: 54 | ```C 55 | VOID MpHandleProcessNotification(PEPROCESS Process, 56 | HANDLE PPid, 57 | HANDLE Pid, 58 | BOOL Create, 59 | BOOL IsTransactedFileOperation, 60 | PUNICODE_STRING ImageFileName, 61 | PUNICODE_STRING CommandLine, 62 | PVOID pOutput); 63 | ``` 64 | 65 | Fourth parameter, `Create`, when `TRUE` indicates that `WdFilter` has to handle _process creation_ and _process termination_ for the opposite case. 66 | Before sending a notification for _process creation_, a couple of other interesting actions are taken. Let's start with: 67 | ```C 68 | NTSTATUS MpCreateProcessContext(HANDLE Pid, 69 | LONGLONG ProcessCreationTime, 70 | PCUNICODE_STRING *ImageFileName, 71 | MP_PROCESS_CONTEXT **ProcessContextListEntry) 72 | ``` 73 | 74 | The purpose of `MpCreateProcessContext` is clear from its name, but our interest is what is the definition of a process context. First things first, every created process that reaches this code path 75 | will have a process context inside `WdFilter`. There's a global structure, whose structure definition we named `MP_PROCESS_TABLE`, pointed by `MpProcessTable` global variable that keeps 76 | record of what processes were created. Currently, based on the code that initializes this structure - `MpInitializeProcessTable`, `WdFilter` keeps track of maximum _128_ processes. Some of this structure's 77 | fields we hadn't observed being used, thus we consider them to be reserved or simply unused currently( or we made some mistake, we hope not). Our definition for it is: 78 | 79 | ```C 80 | typedef struct _MP_PROCESS_TABLE 81 | { 82 | DWORD64 Magic; // 0x1C0DA13, 0x1C0 is the size of the structure, so the first field can be the SizeOfStruct, but... 83 | ERESOURCE MpProcessTableEresource; 84 | PVOID Reserved1; 85 | PVOID Reserved2; 86 | NPAGED_LOOKASIDE_LIST PagedLookasideList1; 87 | NPAGED_LOOKASIDE_LIST PagedLookasideList2; 88 | PLIST_ENTRY ProcessContexts; 89 | KEVENT MpProcessTableKevent; 90 | __int64 AddendTrustedProcess; 91 | __int64 AddendUntrustedProcess; 92 | __int64 Addend3; 93 | PVOID Reserved3; 94 | } MP_PROCESS_TABLE, *PMP_PROCESS_TABLE; 95 | ``` 96 | 97 | Every new process gets a "seat" inside the list named `ProcessContexts`. Every member actually is part of another structure, which we named(surprise, surprise) - `MP_PROCESS_CONTEXT`. The fields of 98 | each process context are initialized inside `MpCreateProcessContext`. Unfortunately, as before, some fields remain a mystery to us, for some of them the semantics isn't well understood and for others no trace of usage. Living those as reserved, the definition looks like so: 99 | 100 | ```C 101 | typedef struct _MP_PROCESS_CONTEXT 102 | { 103 | DWORD64 Magic; // 0xC0DA0F; previous version of WdFilter used 0xC8DA0F, 8 bytes more and it was containing the field that is commented `FileNameInformation` 104 | LIST_ENTRY ListEntry; 105 | HANDLE Pid; 106 | LONGLONG ProcessCreationTime; 107 | PUNICODE_STRING ProcessCommandLine; 108 | INT32 Addend; 109 | DWORD32 ProcessFlags; 110 | DWORD32 Reserved1; 111 | DWORD32 Reserved2; 112 | INT64 Reserved3; 113 | INT64 Reserved4; 114 | PMP_DOC_OPEN_RULE MpDocOpenRule; 115 | PFLT_COMPLETED_ASYNC_IO_CALLBACK PfltCompletedAsyncIoCallback; 116 | INT32 Addend2; 117 | INT32 Addend3; 118 | INT64 Addend4; 119 | INT64 Reserved5; 120 | SUBSYSTEM_INFORMATION_TYPE ProcessSubsystemInfo; 121 | PUNICODE_STRING ProcessName; 122 | _m128 Reserved6; 123 | _m128 Reserved7; 124 | _m128 Reserved8; 125 | _PS_PROTECTION ProcessProtectionInfo; 126 | INT32 Reserved9; // initialized to 0 127 | // PFLT_FILE_NAME_INFORMATION FileNameInformation; 128 | } MP_PROCESS_CONTEXT, *PMP_PROCESS_CONTEXT; 129 | ``` 130 | 131 | An interesting member residing in the above definition is `MpDocOpenRule`. There are a set of functions that contain the pattern `DocOpenRule`, into which we didn't dig, but it was easy to understand 132 | that the data structures follow the same architectural pattern as before, a global struct in this case named `MpBmDocOpenRules` containing a linked list where members are stored. The definitions that we derived are: 133 | 134 | ```C 135 | typedef struct _MP_DOC_OPEN_RULES 136 | { 137 | DWORD64 Magic; // 0x100DA14 138 | PLIST_ENTRY ListEntryHead; 139 | ERESOURCE MpDocEresource; 140 | PVOID Reserved; 141 | PAGED_LOOKASIDE_LIST MpDocLookasideList; 142 | } MP_DOC_OPEN_RULES, *PMP_DOC_OPEN_RULES; 143 | ``` 144 | 145 | ```C 146 | typedef struct _MP_DOC_OPEN_RULE 147 | { 148 | DWORD32 Magic; // 0x228DA15 149 | INT32 Addend; 150 | PLIST_ENTRY ListEntryHead; 151 | WCHAR pBuffer[261]; 152 | PVOID PagedPoolBuffer; 153 | } MP_DOC_OPEN_RULE, *PMP_DOC_OPEN_RULE; 154 | ``` 155 | For example the above buffer, `pBuffer` can contain data like: 156 | ``` 157 | 0: kd> db ffff9588`dfd99dd0 158 | ffff9588`dfd99dd0 41 00 63 00 72 00 6f 00-52 00 64 00 33 00 32 00 A.c.r.o.R.d.3.2. 159 | ffff9588`dfd99de0 2e 00 65 00 78 00 65 00-00 00 00 00 00 00 00 00 ..e.x.e......... 160 | ``` 161 | And `PagedPoolBuffer`: 162 | ``` 163 | 0: kd> db ffff9588`dfdd8eaa La 164 | ffff9588`dfdd8eaa 70 00 64 00 66 00 00 00-00 00 p.d.f..... 165 | ``` 166 | 167 | Seems like a _surjective function_ mapping a tool to a file extension such that `WD` can check if a `pdf` is opened with an expected tool? Not sure. They deserve some more research(for another time). 168 | 169 | Ok, next are following a couple of other interesting function calls, let's welcome - `MpSetProcessDocOpenRule`, `MpSetProcessPreScanHook`, `MpSetProcessExempt`, `MpSetProcessHardening` and `MpSetProcessHardeningExclusion`. 170 | Just from their names we see how appealing this functions are, but for the sake of keeping these notes as short as possible(and easy to understand) and not reversing the whole driver we're not going to dig into them now. 171 | The next station(/call) is our destination, it's where we're meeting - [ExNotifyCallback](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-exnotifycallback). We already know what is going to be the first argument, the third one is `NULL` for both cases(_process creation_ and _process termination_). We walked through to see what is going to be served for `Argument1`(second parameter). To understand it easier let's see a snippet from the code: 172 | 173 | ![proc_create_notif](images/proc_create_notif.png) 174 | 175 | So this is the structure filled with sweets that we're going to get a pointer to. In a rush we quickly sputter a definition: 176 | ```C 177 | typedef struct _WD_PS_NOTIFY_INFO 178 | { 179 | HANDLE Pid; 180 | PHANDLE pPPid; 181 | PUNICODE_STRING ImageFileName; 182 | DWORD32 OperationType; 183 | BOOLEAN IsTrustedProcess; 184 | } WD_PS_NOTIFY_INFO, *PWD_PS_NOTIFY_INFO; 185 | ``` 186 | 187 | But the sparkling thing in all that structure seems to be it's second field(highlighted in the image). And we think that's because we have a pointer to _parent pid_ instead of having it's value. Moreover that pointer is to a stack location. Why is that so? 188 | 189 | ![proc_create_stack](images/proc_create_stack.png) 190 | 191 | So, in our opinion that second field is a pointer because this way we can get access to more information abstracted by the pointer to `MP_PROCESS_CONTEXT`. An updated structure definition and image: 192 | 193 | ```C 194 | typedef struct _WD_PS_NOTIFY_INFO_EX 195 | { 196 | PMP_PROCESS_CONTEXT pMpProcessContext; 197 | HANDLE PPid; 198 | WD_PS_NOTIFY_INFO WdPsNotifyInfo; 199 | } WD_PS_NOTIFY_INFO_EX, *PWD_PS_NOTIFY_INFO_EX; 200 | ``` 201 | ![proc_create_notif2](images/proc_create_notif2.png) 202 | 203 | Until now we were in the realm of _process creation_. For _process termination_ there's not much to say, only two fields carrying useful information, `Pid` and `OperationType`. 204 | 205 | ![proc_termination](images/proc_termination.png) 206 | 207 | When it comes to _set trusted process_ and _set untrusted process_ there's no much difference between them, both can be identified by `OperationType` being equal to _3_: 208 | ![set_trusted](images/set_trusted.png) 209 | ![set_untrusted](images/set_untrusted.png) 210 | 211 | Both changes in state can be triggered from `MpUpdateProcessesWithExclusions` or `MpSetProcessInfoByContext`. State of being _trusted_ or _untrusted_ can be also obtained from `MP_PROCESS_CONTEXT.ProcessFlags` by checking _7th_ bit. For example this is how it is checked inside `MpSetUntrustedProcess`: 212 | ![set_untrusted_check](images/set_untrusted_check.png) 213 | 214 | At last, _refresh process notifications_ in essence is an iteration over the list of process contexts with the purpose of sending a notification regarding fields that are also present in _set trusted process_ and _set untrusted process_. It is being called from `MpNriNotificationCallback`. 215 | 216 | ![refresh_proc](images/refresh_proc.png) 217 | (_SOTSOG_) 218 | 219 | ### POC 220 | 221 | [WdProcessNotificationCallback](WdProcessNotificationCallback) is a simple proof of concept driver to show how this feature can be used. 222 | 223 | ![poc](images/poc.png) 224 | 225 | **To our knowledge, the only registered callback function for this callback object belongs to `WdNisDrv.sys` and is named `process_notification_callback`** 226 | 227 | ## EOF -------------------------------------------------------------------------------- /WdProcessNotificationCallback/WdProcessNotificationCallback.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.757 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wk_callback_hook", "WdProcessNotificationCallback\WdProcessNotificationCallback.vcxproj", "{92ED4119-0E78-47E1-89BE-59E54D0C8E59}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {92ED4119-0E78-47E1-89BE-59E54D0C8E59}.Debug|x64.ActiveCfg = Debug|x64 15 | {92ED4119-0E78-47E1-89BE-59E54D0C8E59}.Debug|x64.Build.0 = Debug|x64 16 | {92ED4119-0E78-47E1-89BE-59E54D0C8E59}.Debug|x64.Deploy.0 = Debug|x64 17 | {92ED4119-0E78-47E1-89BE-59E54D0C8E59}.Release|x64.ActiveCfg = Release|x64 18 | {92ED4119-0E78-47E1-89BE-59E54D0C8E59}.Release|x64.Build.0 = Release|x64 19 | {92ED4119-0E78-47E1-89BE-59E54D0C8E59}.Release|x64.Deploy.0 = Release|x64 20 | EndGlobalSection 21 | GlobalSection(SolutionProperties) = preSolution 22 | HideSolutionNode = FALSE 23 | EndGlobalSection 24 | GlobalSection(ExtensibilityGlobals) = postSolution 25 | SolutionGuid = {0BB26D7F-B8FF-4229-9372-7A96BE3BBC47} 26 | EndGlobalSection 27 | EndGlobal 28 | -------------------------------------------------------------------------------- /WdProcessNotificationCallback/WdProcessNotificationCallback/WdProcessNotificationCallback.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | DRIVER_INITIALIZE DriverEntry; 4 | DRIVER_UNLOAD DriverUnload; 5 | 6 | PVOID g_WdRegisteredCallback; 7 | 8 | #pragma warning(disable:4214 4201) 9 | typedef struct _PS_PROTECTION { 10 | union { 11 | UCHAR Level; 12 | struct { 13 | UCHAR Type : 3; 14 | UCHAR Audit : 1; // Reserved 15 | UCHAR Signer : 4; 16 | }; 17 | }; 18 | } PS_PROTECTION, *PPS_PROTECTION; 19 | 20 | // 21 | // 1 Creation of a process, 2 process deleted, 3 set trusted/untrusted process 22 | // 23 | typedef enum _WD_PROC_CB_TYPE { WD_PROC_CREATE = 1, WD_PROC_TERMINATE, WD_PROC_SET_TRUSTED_UNTRUSTED_REFRESH } WD_PROC_CB_TYPE; 24 | 25 | // 26 | // Magic values for each structure, to help keeping track when they change 27 | // 28 | typedef enum _MP_MAGICS { MP_MAGIC_PROC_CTX = 0xC0DA0F, MP_MAGIC_DOC_RULE = 0x228DA15 } MP_MAGICS; 29 | 30 | // 31 | // Expected size of each structure 32 | // 33 | typedef enum _MP_STRUCT_SIZE { MP_STSZ_PROC_CTX = 0xC0, MP_STSZ_DOC_RULE = 0x228 } MP_STRUCT_SIZE; 34 | 35 | 36 | typedef struct _MP_DOC_OPEN_RULE 37 | { 38 | DWORD32 Magic; // 0x228DA15 39 | INT32 Addend; 40 | PLIST_ENTRY ListEntryHead; 41 | WCHAR pBuffer[261]; 42 | PVOID PagedPoolBuffer; 43 | } MP_DOC_OPEN_RULE, *PMP_DOC_OPEN_RULE; 44 | 45 | typedef struct _MP_PROCESS_CONTEXT 46 | { 47 | DWORD64 Magic; // 0xC0DA0F; previous version of WdFilter used 0xC8DA0F 48 | LIST_ENTRY ListEntry; 49 | HANDLE Pid; 50 | LONGLONG ProcessCreationTime; 51 | PUNICODE_STRING ProcessCommandLine; 52 | INT32 Addend; 53 | DWORD32 ProcessFlags; 54 | DWORD32 Reserved1; 55 | DWORD32 Reserved2; 56 | INT64 Reserved3; 57 | INT64 Reserved4; 58 | PMP_DOC_OPEN_RULE MpDocOpenRule; 59 | PFLT_COMPLETED_ASYNC_IO_CALLBACK PfltCompletedAsyncIoCallback; 60 | INT32 Addend2; 61 | INT32 Addend3; 62 | INT64 Addend4; 63 | INT64 Reserved5; 64 | SUBSYSTEM_INFORMATION_TYPE ProcessSubsystemInfo; 65 | PUNICODE_STRING ProcessName; 66 | UCHAR Reserved6[48]; 67 | PS_PROTECTION ProcessProtectionInfo; 68 | INT32 Reserved9; // initialized to 0 69 | // PFLT_FILE_NAME_INFORMATION FileNameInformation; // was available in a previous version of the structure 70 | } MP_PROCESS_CONTEXT, *PMP_PROCESS_CONTEXT; 71 | 72 | typedef struct _WD_PS_NOTIFY_INFO 73 | { 74 | HANDLE Pid; 75 | PHANDLE pPPid; 76 | PUNICODE_STRING ImageFileName; 77 | DWORD32 OperationType; 78 | BOOLEAN IsTrustedProcess; 79 | } WD_PS_NOTIFY_INFO, *PWD_PS_NOTIFY_INFO; 80 | 81 | typedef struct _WD_PS_NOTIFY_INFO_EX 82 | { 83 | PMP_PROCESS_CONTEXT pMpProcessContext; 84 | HANDLE PPid; 85 | WD_PS_NOTIFY_INFO WdPsNotifyInfo; 86 | } WD_PS_NOTIFY_INFO_EX, *PWD_PS_NOTIFY_INFO_EX; 87 | 88 | CALLBACK_FUNCTION WdProcCallback; 89 | 90 | static_assert(sizeof(WD_PS_NOTIFY_INFO) == 0x20, "Incorrect WD_PS_NOTIFY_INFO structure size"); 91 | static_assert(sizeof(WD_PS_NOTIFY_INFO_EX) == 0x30, "Incorrect WD_PS_NOTIFY_INFO_EX structure size"); 92 | static_assert(sizeof(MP_PROCESS_CONTEXT) == MP_STSZ_PROC_CTX, "Incorrect MP_PROCESS_CONTEXT structure size"); 93 | static_assert(sizeof(MP_DOC_OPEN_RULE) == MP_STSZ_DOC_RULE, "Incorrect MP_DOC_OPEN_RULE structure size"); 94 | 95 | VOID 96 | WdProcCallback( 97 | _In_opt_ PVOID CallbackContext, 98 | _In_opt_ PVOID Argument1, 99 | _In_opt_ PVOID Argument2 100 | ) 101 | { 102 | UNREFERENCED_PARAMETER(CallbackContext); 103 | UNREFERENCED_PARAMETER(Argument2); 104 | 105 | if (NULL == Argument1) { 106 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 107 | DPFLTR_INFO_LEVEL, 108 | __FUNCTION__ ": Argument1 NULL !?"); 109 | 110 | return; 111 | } 112 | 113 | PWD_PS_NOTIFY_INFO pWdProcNotifInfo = (PWD_PS_NOTIFY_INFO)Argument1; 114 | switch (pWdProcNotifInfo->OperationType) 115 | { 116 | case WD_PROC_CREATE: 117 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 118 | DPFLTR_INFO_LEVEL, 119 | __FUNCTION__ ": [+] New process with PID: %08x ImageFileName: %wZ\n", 120 | HandleToULong(pWdProcNotifInfo->Pid), 121 | pWdProcNotifInfo->ImageFileName 122 | ); 123 | 124 | if (pWdProcNotifInfo->pPPid != NULL) { 125 | PWD_PS_NOTIFY_INFO_EX pWdProcNotifInfoEx = CONTAINING_RECORD(pWdProcNotifInfo->pPPid, WD_PS_NOTIFY_INFO_EX, PPid); 126 | if (NULL == pWdProcNotifInfoEx) { 127 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 128 | DPFLTR_ERROR_LEVEL, 129 | __FUNCTION__ ": [!] Extended info isn't available!\n" 130 | ); 131 | 132 | return; 133 | } 134 | if (pWdProcNotifInfoEx->pMpProcessContext->Magic != MP_MAGIC_PROC_CTX) { 135 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 136 | DPFLTR_ERROR_LEVEL, 137 | __FUNCTION__ ": [!] MP_PROC_CONTEXT.Magic isn't matching: %08llX\n", 138 | pWdProcNotifInfoEx->pMpProcessContext->Magic 139 | ); 140 | } else { 141 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 142 | DPFLTR_INFO_LEVEL, 143 | __FUNCTION__ ": [+] ProcessCreationTime: %lld ProcessCmdLine: %wZ PPID: %08x\n", 144 | pWdProcNotifInfoEx->pMpProcessContext->ProcessCreationTime, 145 | pWdProcNotifInfoEx->pMpProcessContext->ProcessCommandLine, 146 | HandleToULong(pWdProcNotifInfoEx->PPid) 147 | ); 148 | 149 | if (pWdProcNotifInfoEx->pMpProcessContext->MpDocOpenRule != NULL) { 150 | if (pWdProcNotifInfoEx->pMpProcessContext->MpDocOpenRule->Magic != MP_MAGIC_DOC_RULE) { 151 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 152 | DPFLTR_ERROR_LEVEL, 153 | __FUNCTION__ ": [!] MP_DOC_OPEN_RULE.Magic isn't matching: %04X\n", 154 | pWdProcNotifInfoEx->pMpProcessContext->MpDocOpenRule->Magic 155 | ); 156 | } else { 157 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 158 | DPFLTR_INFO_LEVEL, 159 | __FUNCTION__ ": [+] Doc Rule buffer: %lS\n", 160 | pWdProcNotifInfoEx->pMpProcessContext->MpDocOpenRule->pBuffer 161 | ); 162 | } 163 | } 164 | } 165 | // 166 | // An earlier version of WdFilter(on Windows 10 Insiders Preview 19008) MP_PROCESS_CONTEXT had a PFLT_FILE_NAME_INFORMATION 167 | // pointer as its last field, so the size of the structure was 0xC8DA0F. Later that field was removed and the size of the 168 | // structure became 0xC0DA0F. Leaving this piece of code as a reference or maybe they'll rethink and add it back ;) 169 | // 170 | #if 0 171 | if ((pWdProcNotifInfoEx->pMpProcessContext->Magic == 0xC8DA0F) && 172 | (pWdProcNotifInfoEx->pMpProcessContext->FileNameInformation != NULL)) { 173 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 174 | DPFLTR_INFO_LEVEL, 175 | "File name: %wZ", 176 | &pWdProcNotifInfoEx->pMpProcessContext->FileNameInformation->Name 177 | ); 178 | 179 | if ((pWdProcNotifInfoEx->pMpProcessContext->FileNameInformation->NamesParsed & FLTFL_FILE_NAME_PARSED_EXTENSION) && 180 | (pWdProcNotifInfoEx->pMpProcessContext->FileNameInformation->Extension.Length != 0)) { 181 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 182 | DPFLTR_INFO_LEVEL, 183 | "File extension: %wZ", 184 | pWdProcNotifInfoEx->pMpProcessContext->FileNameInformation->Extension 185 | ); 186 | } 187 | if ((pWdProcNotifInfoEx->pMpProcessContext->FileNameInformation->NamesParsed & FLTFL_FILE_NAME_PARSED_PARENT_DIR) && 188 | (pWdProcNotifInfoEx->pMpProcessContext->FileNameInformation->ParentDir.Length != 0)) { 189 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 190 | DPFLTR_INFO_LEVEL, 191 | "File parent dir: %wZ", 192 | &pWdProcNotifInfoEx->pMpProcessContext->FileNameInformation->ParentDir 193 | ); 194 | } 195 | } 196 | #endif 197 | } 198 | 199 | break; 200 | 201 | case WD_PROC_TERMINATE: 202 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 203 | DPFLTR_INFO_LEVEL, 204 | __FUNCTION__ ": [-] Process terminated PID %08x\n", HandleToULong(pWdProcNotifInfo->Pid)); 205 | 206 | break; 207 | case WD_PROC_SET_TRUSTED_UNTRUSTED_REFRESH: 208 | if (pWdProcNotifInfo->IsTrustedProcess) { 209 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 210 | DPFLTR_INFO_LEVEL, 211 | __FUNCTION__ ": [*] Set trusted process PID %08x\n", HandleToULong(pWdProcNotifInfo->Pid)); 212 | } else { 213 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 214 | DPFLTR_INFO_LEVEL, 215 | __FUNCTION__ ": [*] Set untrusted process PID %08x\n", HandleToULong(pWdProcNotifInfo->Pid)); 216 | } 217 | 218 | break; 219 | default: 220 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 221 | DPFLTR_INFO_LEVEL, 222 | __FUNCTION__ ": [!] Why are you not treating me equally: %08x!?\n", pWdProcNotifInfo->OperationType); 223 | break; 224 | } 225 | } 226 | 227 | VOID DriverUnload( 228 | _In_ PDRIVER_OBJECT DriverObject 229 | ) 230 | { 231 | UNREFERENCED_PARAMETER(DriverObject); 232 | 233 | // 234 | // The check is needed as ExUnregisterCallback doesn't check for a NULL pointer 235 | // 236 | if (g_WdRegisteredCallback != NULL) { 237 | ExUnregisterCallback(g_WdRegisteredCallback); 238 | } 239 | } 240 | 241 | NTSTATUS 242 | DriverEntry( 243 | _In_ PDRIVER_OBJECT DriverObject, 244 | _In_ PUNICODE_STRING RegistryPath 245 | ) 246 | { 247 | UNREFERENCED_PARAMETER(RegistryPath); 248 | 249 | DriverObject->DriverUnload = DriverUnload; 250 | 251 | PCALLBACK_OBJECT pWdProcessNotifCb = NULL; 252 | UNICODE_STRING WdObjName = RTL_CONSTANT_STRING(L"\\Callback\\WdProcessNotificationCallback"); 253 | OBJECT_ATTRIBUTES WdProcNotifObjAttr; // InitializeObjectAttributes would be recommended to use, but... 254 | RtlSecureZeroMemory(&WdProcNotifObjAttr, sizeof(OBJECT_ATTRIBUTES)); 255 | WdProcNotifObjAttr.Length = sizeof(OBJECT_ATTRIBUTES); 256 | WdProcNotifObjAttr.ObjectName = &WdObjName; 257 | WdProcNotifObjAttr.Attributes = 0x210; 258 | 259 | if (!NT_SUCCESS(ExCreateCallback(&pWdProcessNotifCb, &WdProcNotifObjAttr, FALSE, FALSE))) { 260 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 261 | DPFLTR_ERROR_LEVEL, 262 | __FUNCTION__ ": Failed to obtain callback object!\n"); 263 | 264 | return STATUS_NOT_FOUND; 265 | } 266 | 267 | g_WdRegisteredCallback = ExRegisterCallback(pWdProcessNotifCb, WdProcCallback, NULL); 268 | if (g_WdRegisteredCallback != NULL) { 269 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 270 | DPFLTR_INFO_LEVEL, 271 | __FUNCTION__ ": Callback was successfully registered!\n"); 272 | 273 | } else { 274 | DbgPrintEx(DPFLTR_IHVDRIVER_ID, 275 | DPFLTR_INFO_LEVEL, 276 | __FUNCTION__ ": Hmmm, something wrong!\n"); 277 | 278 | } 279 | 280 | return STATUS_SUCCESS; 281 | } -------------------------------------------------------------------------------- /WdProcessNotificationCallback/WdProcessNotificationCallback/WdProcessNotificationCallback.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; WdProcessNotificationCallback.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=Sample ; TODO: edit Class 8 | ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171} ; TODO: edit ClassGuid 9 | Provider=%ManufacturerName% 10 | CatalogFile=WdProcessNotificationCallback.cat 11 | DriverVer= ; TODO: set DriverVer in stampinf property pages 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | WdProcessNotificationCallback_Device_CoInstaller_CopyFiles = 11 16 | 17 | ; ================= Class section ===================== 18 | 19 | [ClassInstall32] 20 | Addreg=SampleClassReg 21 | 22 | [SampleClassReg] 23 | HKR,,,0,%ClassName% 24 | HKR,,Icon,,-5 25 | 26 | [SourceDisksNames] 27 | 1 = %DiskName%,,,"" 28 | 29 | [SourceDisksFiles] 30 | WdProcessNotificationCallback.sys = 1,, 31 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames 32 | 33 | ;***************************************** 34 | ; Install Section 35 | ;***************************************** 36 | 37 | [Manufacturer] 38 | %ManufacturerName%=Standard,NT$ARCH$ 39 | 40 | [Standard.NT$ARCH$] 41 | %WdProcessNotificationCallback.DeviceDesc%=WdProcessNotificationCallback_Device, Root\WdProcessNotificationCallback ; TODO: edit hw-id 42 | 43 | [WdProcessNotificationCallback_Device.NT] 44 | CopyFiles=Drivers_Dir 45 | 46 | [Drivers_Dir] 47 | WdProcessNotificationCallback.sys 48 | 49 | ;-------------- Service installation 50 | [WdProcessNotificationCallback_Device.NT.Services] 51 | AddService = WdProcessNotificationCallback,%SPSVCINST_ASSOCSERVICE%, WdProcessNotificationCallback_Service_Inst 52 | 53 | ; -------------- WdProcessNotificationCallback driver install sections 54 | [WdProcessNotificationCallback_Service_Inst] 55 | DisplayName = %WdProcessNotificationCallback.SVCDESC% 56 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 57 | StartType = 3 ; SERVICE_DEMAND_START 58 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 59 | ServiceBinary = %12%\WdProcessNotificationCallback.sys 60 | 61 | ; 62 | ;--- WdProcessNotificationCallback_Device Coinstaller installation ------ 63 | ; 64 | 65 | [WdProcessNotificationCallback_Device.NT.CoInstallers] 66 | AddReg=WdProcessNotificationCallback_Device_CoInstaller_AddReg 67 | CopyFiles=WdProcessNotificationCallback_Device_CoInstaller_CopyFiles 68 | 69 | [WdProcessNotificationCallback_Device_CoInstaller_AddReg] 70 | HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller" 71 | 72 | [WdProcessNotificationCallback_Device_CoInstaller_CopyFiles] 73 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll 74 | 75 | [WdProcessNotificationCallback_Device.NT.Wdf] 76 | KmdfService = WdProcessNotificationCallback, WdProcessNotificationCallback_wdfsect 77 | [WdProcessNotificationCallback_wdfsect] 78 | KmdfLibraryVersion = $KMDFVERSION$ 79 | 80 | [Strings] 81 | SPSVCINST_ASSOCSERVICE= 0x00000002 82 | ManufacturerName="" ;TODO: Replace with your manufacturer name 83 | ClassName="Samples" ; TODO: edit ClassName 84 | DiskName = "WdProcessNotificationCallback Installation Disk" 85 | WdProcessNotificationCallback.DeviceDesc = "WdProcessNotificationCallback Device" 86 | WdProcessNotificationCallback.SVCDESC = "WdProcessNotificationCallback Service" 87 | -------------------------------------------------------------------------------- /WdProcessNotificationCallback/WdProcessNotificationCallback/WdProcessNotificationCallback.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {92ED4119-0E78-47E1-89BE-59E54D0C8E59} 15 | {1bc93793-694f-48fe-9372-81e2b05556fd} 16 | v4.5 17 | 12.0 18 | Debug 19 | Win32 20 | WdProcessNotificationCallback 21 | WdProcessNotificationCallback 22 | 23 | 24 | 25 | Windows10 26 | true 27 | WindowsKernelModeDriver10.0 28 | Driver 29 | KMDF 30 | Universal 31 | 32 | 33 | Windows10 34 | false 35 | WindowsKernelModeDriver10.0 36 | Driver 37 | KMDF 38 | Universal 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | DbgengKernelDebugger 50 | 51 | 52 | DbgengKernelDebugger 53 | 54 | 55 | 56 | true 57 | 58 | 59 | 60 | 61 | true 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /WdProcessNotificationCallback/WdProcessNotificationCallback/WdProcessNotificationCallback.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Driver Files 24 | 25 | 26 | 27 | 28 | Source Files 29 | 30 | 31 | -------------------------------------------------------------------------------- /WdProcessNotificationCallback/images/obj_creation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdProcessNotificationCallback/images/obj_creation.png -------------------------------------------------------------------------------- /WdProcessNotificationCallback/images/poc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdProcessNotificationCallback/images/poc.png -------------------------------------------------------------------------------- /WdProcessNotificationCallback/images/proc_create_notif.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdProcessNotificationCallback/images/proc_create_notif.png -------------------------------------------------------------------------------- /WdProcessNotificationCallback/images/proc_create_notif2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdProcessNotificationCallback/images/proc_create_notif2.png -------------------------------------------------------------------------------- /WdProcessNotificationCallback/images/proc_create_stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdProcessNotificationCallback/images/proc_create_stack.png -------------------------------------------------------------------------------- /WdProcessNotificationCallback/images/proc_termination.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdProcessNotificationCallback/images/proc_termination.png -------------------------------------------------------------------------------- /WdProcessNotificationCallback/images/refresh_proc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdProcessNotificationCallback/images/refresh_proc.png -------------------------------------------------------------------------------- /WdProcessNotificationCallback/images/set_trusted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdProcessNotificationCallback/images/set_trusted.png -------------------------------------------------------------------------------- /WdProcessNotificationCallback/images/set_untrusted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdProcessNotificationCallback/images/set_untrusted.png -------------------------------------------------------------------------------- /WdProcessNotificationCallback/images/set_untrusted_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdProcessNotificationCallback/images/set_untrusted_check.png -------------------------------------------------------------------------------- /WdProcessNotificationCallback/images/stack_frames.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xcpu/ExecutiveCallbackObjects/b04c7cd396efbf0ab57c2c519c4d93690ad08843/WdProcessNotificationCallback/images/stack_frames.png --------------------------------------------------------------------------------