├── .gitattributes ├── .gitignore ├── KasperskyHook.sln ├── KasperskyHookDrv ├── KasperskyHookDrv.inf ├── KasperskyHookDrv.vcxproj ├── KasperskyHookDrv.vcxproj.filters ├── driver.cpp ├── hooks.cpp ├── hooks.hpp ├── kaspersky.cpp ├── kaspersky.hpp ├── kernel_modules.cpp ├── kernel_modules.hpp ├── pe.cpp ├── pe.hpp ├── utils.cpp └── utils.hpp ├── KasperskyHookLoader ├── KasperskyHookLoader.vcxproj ├── KasperskyHookLoader.vcxproj.filters ├── kasperskyhook.cpp ├── kasperskyhook.hpp ├── klhk.cpp ├── klhk.hpp ├── loader.cpp ├── loader.hpp └── main.cpp ├── LICENSE ├── README.md ├── demo.gif └── klhk └── klhk.sys /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # JustCode is a .NET coding add-in 131 | .JustCode 132 | 133 | # TeamCity is a build add-in 134 | _TeamCity* 135 | 136 | # DotCover is a Code Coverage Tool 137 | *.dotCover 138 | 139 | # AxoCover is a Code Coverage Tool 140 | .axoCover/* 141 | !.axoCover/settings.json 142 | 143 | # Visual Studio code coverage results 144 | *.coverage 145 | *.coveragexml 146 | 147 | # NCrunch 148 | _NCrunch_* 149 | .*crunch*.local.xml 150 | nCrunchTemp_* 151 | 152 | # MightyMoose 153 | *.mm.* 154 | AutoTest.Net/ 155 | 156 | # Web workbench (sass) 157 | .sass-cache/ 158 | 159 | # Installshield output folder 160 | [Ee]xpress/ 161 | 162 | # DocProject is a documentation generator add-in 163 | DocProject/buildhelp/ 164 | DocProject/Help/*.HxT 165 | DocProject/Help/*.HxC 166 | DocProject/Help/*.hhc 167 | DocProject/Help/*.hhk 168 | DocProject/Help/*.hhp 169 | DocProject/Help/Html2 170 | DocProject/Help/html 171 | 172 | # Click-Once directory 173 | publish/ 174 | 175 | # Publish Web Output 176 | *.[Pp]ublish.xml 177 | *.azurePubxml 178 | # Note: Comment the next line if you want to checkin your web deploy settings, 179 | # but database connection strings (with potential passwords) will be unencrypted 180 | *.pubxml 181 | *.publishproj 182 | 183 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 184 | # checkin your Azure Web App publish settings, but sensitive information contained 185 | # in these scripts will be unencrypted 186 | PublishScripts/ 187 | 188 | # NuGet Packages 189 | *.nupkg 190 | # NuGet Symbol Packages 191 | *.snupkg 192 | # The packages folder can be ignored because of Package Restore 193 | **/[Pp]ackages/* 194 | # except build/, which is used as an MSBuild target. 195 | !**/[Pp]ackages/build/ 196 | # Uncomment if necessary however generally it will be regenerated when needed 197 | #!**/[Pp]ackages/repositories.config 198 | # NuGet v3's project.json files produces more ignorable files 199 | *.nuget.props 200 | *.nuget.targets 201 | 202 | # Microsoft Azure Build Output 203 | csx/ 204 | *.build.csdef 205 | 206 | # Microsoft Azure Emulator 207 | ecf/ 208 | rcf/ 209 | 210 | # Windows Store app package directories and files 211 | AppPackages/ 212 | BundleArtifacts/ 213 | Package.StoreAssociation.xml 214 | _pkginfo.txt 215 | *.appx 216 | *.appxbundle 217 | *.appxupload 218 | 219 | # Visual Studio cache files 220 | # files ending in .cache can be ignored 221 | *.[Cc]ache 222 | # but keep track of directories ending in .cache 223 | !?*.[Cc]ache/ 224 | 225 | # Others 226 | ClientBin/ 227 | ~$* 228 | *~ 229 | *.dbmdl 230 | *.dbproj.schemaview 231 | *.jfm 232 | *.pfx 233 | *.publishsettings 234 | orleans.codegen.cs 235 | 236 | # Including strong name files can present a security risk 237 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 238 | #*.snk 239 | 240 | # Since there are multiple workflows, uncomment next line to ignore bower_components 241 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 242 | #bower_components/ 243 | 244 | # RIA/Silverlight projects 245 | Generated_Code/ 246 | 247 | # Backup & report files from converting an old project file 248 | # to a newer Visual Studio version. Backup files are not needed, 249 | # because we have git ;-) 250 | _UpgradeReport_Files/ 251 | Backup*/ 252 | UpgradeLog*.XML 253 | UpgradeLog*.htm 254 | ServiceFabricBackup/ 255 | *.rptproj.bak 256 | 257 | # SQL Server files 258 | *.mdf 259 | *.ldf 260 | *.ndf 261 | 262 | # Business Intelligence projects 263 | *.rdl.data 264 | *.bim.layout 265 | *.bim_*.settings 266 | *.rptproj.rsuser 267 | *- [Bb]ackup.rdl 268 | *- [Bb]ackup ([0-9]).rdl 269 | *- [Bb]ackup ([0-9][0-9]).rdl 270 | 271 | # Microsoft Fakes 272 | FakesAssemblies/ 273 | 274 | # GhostDoc plugin setting file 275 | *.GhostDoc.xml 276 | 277 | # Node.js Tools for Visual Studio 278 | .ntvs_analysis.dat 279 | node_modules/ 280 | 281 | # Visual Studio 6 build log 282 | *.plg 283 | 284 | # Visual Studio 6 workspace options file 285 | *.opt 286 | 287 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 288 | *.vbw 289 | 290 | # Visual Studio LightSwitch build output 291 | **/*.HTMLClient/GeneratedArtifacts 292 | **/*.DesktopClient/GeneratedArtifacts 293 | **/*.DesktopClient/ModelManifest.xml 294 | **/*.Server/GeneratedArtifacts 295 | **/*.Server/ModelManifest.xml 296 | _Pvt_Extensions 297 | 298 | # Paket dependency manager 299 | .paket/paket.exe 300 | paket-files/ 301 | 302 | # FAKE - F# Make 303 | .fake/ 304 | 305 | # CodeRush personal settings 306 | .cr/personal 307 | 308 | # Python Tools for Visual Studio (PTVS) 309 | __pycache__/ 310 | *.pyc 311 | 312 | # Cake - Uncomment if you are using it 313 | # tools/** 314 | # !tools/packages.config 315 | 316 | # Tabs Studio 317 | *.tss 318 | 319 | # Telerik's JustMock configuration file 320 | *.jmconfig 321 | 322 | # BizTalk build output 323 | *.btp.cs 324 | *.btm.cs 325 | *.odx.cs 326 | *.xsd.cs 327 | 328 | # OpenCover UI analysis results 329 | OpenCover/ 330 | 331 | # Azure Stream Analytics local run output 332 | ASALocalRun/ 333 | 334 | # MSBuild Binary and Structured Log 335 | *.binlog 336 | 337 | # NVidia Nsight GPU debugger configuration file 338 | *.nvuser 339 | 340 | # MFractors (Xamarin productivity tool) working folder 341 | .mfractor/ 342 | 343 | # Local History for Visual Studio 344 | .localhistory/ 345 | 346 | # BeatPulse healthcheck temp database 347 | healthchecksdb 348 | 349 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 350 | MigrationBackup/ 351 | 352 | # Ionide (cross platform F# VS Code tools) working folder 353 | .ionide/ 354 | -------------------------------------------------------------------------------- /KasperskyHook.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29926.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KasperskyHookDrv", "KasperskyHookDrv\KasperskyHookDrv.vcxproj", "{0931F5CD-729C-4256-AC34-4FF8F7F3E294}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KasperskyHookLoader", "KasperskyHookLoader\KasperskyHookLoader.vcxproj", "{AC843DC7-AE89-45D5-AD78-EDCB560ACCC3}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|ARM = Debug|ARM 13 | Debug|ARM64 = Debug|ARM64 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|ARM = Release|ARM 17 | Release|ARM64 = Release|ARM64 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Debug|ARM.ActiveCfg = Debug|ARM 23 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Debug|ARM.Build.0 = Debug|ARM 24 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Debug|ARM.Deploy.0 = Debug|ARM 25 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Debug|ARM64.ActiveCfg = Debug|ARM64 26 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Debug|ARM64.Build.0 = Debug|ARM64 27 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Debug|ARM64.Deploy.0 = Debug|ARM64 28 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Debug|x64.ActiveCfg = Debug|x64 29 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Debug|x64.Build.0 = Debug|x64 30 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Debug|x64.Deploy.0 = Debug|x64 31 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Debug|x86.ActiveCfg = Debug|Win32 32 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Debug|x86.Build.0 = Debug|Win32 33 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Debug|x86.Deploy.0 = Debug|Win32 34 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Release|ARM.ActiveCfg = Release|ARM 35 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Release|ARM.Build.0 = Release|ARM 36 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Release|ARM.Deploy.0 = Release|ARM 37 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Release|ARM64.ActiveCfg = Release|ARM64 38 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Release|ARM64.Build.0 = Release|ARM64 39 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Release|ARM64.Deploy.0 = Release|ARM64 40 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Release|x64.ActiveCfg = Release|x64 41 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Release|x64.Build.0 = Release|x64 42 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Release|x64.Deploy.0 = Release|x64 43 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Release|x86.ActiveCfg = Release|Win32 44 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Release|x86.Build.0 = Release|Win32 45 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294}.Release|x86.Deploy.0 = Release|Win32 46 | {AC843DC7-AE89-45D5-AD78-EDCB560ACCC3}.Debug|ARM.ActiveCfg = Debug|Win32 47 | {AC843DC7-AE89-45D5-AD78-EDCB560ACCC3}.Debug|ARM64.ActiveCfg = Debug|Win32 48 | {AC843DC7-AE89-45D5-AD78-EDCB560ACCC3}.Debug|x64.ActiveCfg = Debug|x64 49 | {AC843DC7-AE89-45D5-AD78-EDCB560ACCC3}.Debug|x64.Build.0 = Debug|x64 50 | {AC843DC7-AE89-45D5-AD78-EDCB560ACCC3}.Debug|x86.ActiveCfg = Debug|Win32 51 | {AC843DC7-AE89-45D5-AD78-EDCB560ACCC3}.Debug|x86.Build.0 = Debug|Win32 52 | {AC843DC7-AE89-45D5-AD78-EDCB560ACCC3}.Release|ARM.ActiveCfg = Release|Win32 53 | {AC843DC7-AE89-45D5-AD78-EDCB560ACCC3}.Release|ARM64.ActiveCfg = Release|Win32 54 | {AC843DC7-AE89-45D5-AD78-EDCB560ACCC3}.Release|x64.ActiveCfg = Release|x64 55 | {AC843DC7-AE89-45D5-AD78-EDCB560ACCC3}.Release|x64.Build.0 = Release|x64 56 | {AC843DC7-AE89-45D5-AD78-EDCB560ACCC3}.Release|x86.ActiveCfg = Release|Win32 57 | {AC843DC7-AE89-45D5-AD78-EDCB560ACCC3}.Release|x86.Build.0 = Release|Win32 58 | EndGlobalSection 59 | GlobalSection(SolutionProperties) = preSolution 60 | HideSolutionNode = FALSE 61 | EndGlobalSection 62 | GlobalSection(ExtensibilityGlobals) = postSolution 63 | SolutionGuid = {7CA8CCCE-5E05-4A8F-B974-BF3B4C238648} 64 | EndGlobalSection 65 | EndGlobal 66 | -------------------------------------------------------------------------------- /KasperskyHookDrv/KasperskyHookDrv.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; KasperskyHookDrv.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=KasperskyHookDrv.cat 11 | DriverVer= ; TODO: set DriverVer in stampinf property pages 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | KasperskyHookDrv_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 | KasperskyHookDrv.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 | %KasperskyHookDrv.DeviceDesc%=KasperskyHookDrv_Device, Root\KasperskyHookDrv ; TODO: edit hw-id 42 | 43 | [KasperskyHookDrv_Device.NT] 44 | CopyFiles=Drivers_Dir 45 | 46 | [Drivers_Dir] 47 | KasperskyHookDrv.sys 48 | 49 | ;-------------- Service installation 50 | [KasperskyHookDrv_Device.NT.Services] 51 | AddService = KasperskyHookDrv,%SPSVCINST_ASSOCSERVICE%, KasperskyHookDrv_Service_Inst 52 | 53 | ; -------------- KasperskyHookDrv driver install sections 54 | [KasperskyHookDrv_Service_Inst] 55 | DisplayName = %KasperskyHookDrv.SVCDESC% 56 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 57 | StartType = 3 ; SERVICE_DEMAND_START 58 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 59 | ServiceBinary = %12%\KasperskyHookDrv.sys 60 | 61 | ; 62 | ;--- KasperskyHookDrv_Device Coinstaller installation ------ 63 | ; 64 | 65 | [KasperskyHookDrv_Device.NT.CoInstallers] 66 | AddReg=KasperskyHookDrv_Device_CoInstaller_AddReg 67 | CopyFiles=KasperskyHookDrv_Device_CoInstaller_CopyFiles 68 | 69 | [KasperskyHookDrv_Device_CoInstaller_AddReg] 70 | HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller" 71 | 72 | [KasperskyHookDrv_Device_CoInstaller_CopyFiles] 73 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll 74 | 75 | [KasperskyHookDrv_Device.NT.Wdf] 76 | KmdfService = KasperskyHookDrv, KasperskyHookDrv_wdfsect 77 | [KasperskyHookDrv_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 = "KasperskyHookDrv Installation Disk" 85 | KasperskyHookDrv.DeviceDesc = "KasperskyHookDrv Device" 86 | KasperskyHookDrv.SVCDESC = "KasperskyHookDrv Service" 87 | -------------------------------------------------------------------------------- /KasperskyHookDrv/KasperskyHookDrv.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 | {0931F5CD-729C-4256-AC34-4FF8F7F3E294} 39 | {1bc93793-694f-48fe-9372-81e2b05556fd} 40 | v4.5 41 | 12.0 42 | Debug 43 | Win32 44 | KasperskyHookDrv 45 | 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 | Windows8 65 | true 66 | WindowsKernelModeDriver10.0 67 | Driver 68 | KMDF 69 | Desktop 70 | 71 | 72 | Windows8 73 | false 74 | WindowsKernelModeDriver10.0 75 | Driver 76 | KMDF 77 | Desktop 78 | 79 | 80 | Windows10 81 | true 82 | WindowsKernelModeDriver10.0 83 | Driver 84 | KMDF 85 | Universal 86 | 87 | 88 | Windows10 89 | false 90 | WindowsKernelModeDriver10.0 91 | Driver 92 | KMDF 93 | Universal 94 | 95 | 96 | Windows10 97 | true 98 | WindowsKernelModeDriver10.0 99 | Driver 100 | KMDF 101 | Universal 102 | 103 | 104 | Windows10 105 | false 106 | WindowsKernelModeDriver10.0 107 | Driver 108 | KMDF 109 | Universal 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | DbgengKernelDebugger 121 | 122 | 123 | DbgengKernelDebugger 124 | 125 | 126 | DbgengKernelDebugger 127 | 128 | 129 | DbgengKernelDebugger 130 | 131 | 132 | DbgengKernelDebugger 133 | 134 | 135 | DbgengKernelDebugger 136 | 137 | 138 | DbgengKernelDebugger 139 | 140 | 141 | DbgengKernelDebugger 142 | 143 | 144 | 145 | SHA256 146 | 147 | 148 | DriverEntry 149 | 150 | 151 | stdcpplatest 152 | 153 | 154 | 155 | 156 | SHA256 157 | 158 | 159 | DriverEntry 160 | 161 | 162 | stdcpplatest 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /KasperskyHookDrv/KasperskyHookDrv.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 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | Source Files 58 | 59 | 60 | Source Files 61 | 62 | 63 | -------------------------------------------------------------------------------- /KasperskyHookDrv/driver.cpp: -------------------------------------------------------------------------------- 1 | #include "kaspersky.hpp" 2 | #include "hooks.hpp" 3 | #include "utils.hpp" 4 | 5 | // 6 | // DriverUnload routine. 7 | // 8 | DRIVER_UNLOAD DriverUnload; 9 | 10 | // 11 | // This is just a demo, don't hardcode SSDT indexes 12 | // 13 | constexpr unsigned short NtCreateFile_index = 0x0055; 14 | 15 | // 16 | // Driver initialization routine. 17 | // 18 | EXTERN_C NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath ) 19 | { 20 | UNREFERENCED_PARAMETER( RegistryPath ); 21 | 22 | // 23 | // Setup DriverUnload routine so this driver can unload safely. 24 | // 25 | DriverObject->DriverUnload = &DriverUnload; 26 | 27 | // 28 | // Initialize global pointers that are used by this driver. 29 | // 30 | if ( !utils::init( ) ) 31 | { 32 | log( "Failed to initialize kernel pointers!" ); 33 | return STATUS_ORDINAL_NOT_FOUND; 34 | } 35 | 36 | // 37 | // klhk-related initialization. 38 | // 39 | if ( !kaspersky::is_klhk_loaded( ) || !kaspersky::initialize( ) ) 40 | { 41 | log( "Failed to initialize klhk.sys data!" ); 42 | return STATUS_NOT_FOUND; 43 | } 44 | 45 | // 46 | // Initialize the hypervisor. 47 | // 48 | const auto status = kaspersky::hvm_init( ); 49 | 50 | // 51 | // Failed to initialize the hypervisor. 52 | // 53 | if ( !NT_SUCCESS( status ) ) 54 | { 55 | log( "hvm_init failed! Status code: 0x%X", status ); 56 | return status; 57 | } 58 | 59 | // 60 | // Initialize SSDT hooks. 61 | // 62 | const auto success = kaspersky::hook_ssdt_routine( NtCreateFile_index, &hooks::hk_NtCreateFile, 63 | reinterpret_cast< void** >( &o_NtCreateFile ) ); 64 | 65 | return success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 66 | } 67 | 68 | // 69 | // Driver cleanup. Undo hooks. 70 | // 71 | void DriverUnload( PDRIVER_OBJECT DriverObject ) 72 | { 73 | UNREFERENCED_PARAMETER( DriverObject ); 74 | 75 | // 76 | // Unhook NtCreateFile if klhk.sys is still loaded. 77 | // 78 | if ( !kaspersky::is_klhk_loaded( ) ) 79 | return; 80 | 81 | // 82 | // Undo hooks. 83 | // 84 | if ( !kaspersky::unhook_ssdt_routine( NtCreateFile_index, o_NtCreateFile ) ) 85 | log( "Failed to unhook NtCreateFile. Probably not hooked." ); 86 | 87 | // 88 | // Delay execution to make sure no thread is executing our hook. (Better solution: implement a synchronization mechanism). 89 | // 90 | LARGE_INTEGER LargeInteger { }; 91 | LargeInteger.QuadPart = -10000000; 92 | 93 | KeDelayExecutionThread( KernelMode, FALSE, &LargeInteger ); 94 | } -------------------------------------------------------------------------------- /KasperskyHookDrv/hooks.cpp: -------------------------------------------------------------------------------- 1 | #include "hooks.hpp" 2 | #include "utils.hpp" 3 | 4 | // 5 | // Our hook to NtCreateFile. It's just a demonstration. 6 | // 7 | NTSTATUS hooks::hk_NtCreateFile 8 | ( 9 | PHANDLE FileHandle, 10 | ACCESS_MASK DesiredAccess, 11 | POBJECT_ATTRIBUTES ObjectAttributes, 12 | PIO_STATUS_BLOCK IoStatusBlock, 13 | PLARGE_INTEGER AllocationSize, 14 | ULONG FileAttributes, 15 | ULONG ShareAccess, 16 | ULONG CreateDisposition, 17 | ULONG CreateOptions, 18 | PVOID EaBuffer, 19 | ULONG EaLength 20 | ) 21 | { 22 | if ( ObjectAttributes && ObjectAttributes->ObjectName && ObjectAttributes->ObjectName->Buffer ) 23 | { 24 | const auto name = ObjectAttributes->ObjectName->Buffer; 25 | 26 | // 27 | // Deny access to any file called "you_wont_open_this.txt". 28 | // 29 | if ( wcsstr( name, L"you_wont_open_this.txt" ) ) 30 | return STATUS_ACCESS_DENIED; 31 | } 32 | 33 | // 34 | // Call the original function. 35 | // 36 | return o_NtCreateFile( FileHandle, 37 | DesiredAccess, 38 | ObjectAttributes, 39 | IoStatusBlock, 40 | AllocationSize, 41 | FileAttributes, 42 | ShareAccess, 43 | CreateDisposition, 44 | CreateOptions, 45 | EaBuffer, 46 | EaLength ); 47 | } -------------------------------------------------------------------------------- /KasperskyHookDrv/hooks.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // 7 | // Function typedefs. 8 | // 9 | using f_NtCreateFile = NTSTATUS( * ) 10 | ( 11 | PHANDLE FileHandle, 12 | ACCESS_MASK DesiredAccess, 13 | POBJECT_ATTRIBUTES ObjectAttributes, 14 | PIO_STATUS_BLOCK IoStatusBlock, 15 | PLARGE_INTEGER AllocationSize, 16 | ULONG FileAttributes, 17 | ULONG ShareAccess, 18 | ULONG CreateDisposition, 19 | ULONG CreateOptions, 20 | PVOID EaBuffer, 21 | ULONG EaLength 22 | ); 23 | 24 | // 25 | // Functions (hooks). 26 | // 27 | namespace hooks 28 | { 29 | NTSTATUS hk_NtCreateFile 30 | ( 31 | PHANDLE FileHandle, 32 | ACCESS_MASK DesiredAccess, 33 | POBJECT_ATTRIBUTES ObjectAttributes, 34 | PIO_STATUS_BLOCK IoStatusBlock, 35 | PLARGE_INTEGER AllocationSize, 36 | ULONG FileAttributes, 37 | ULONG ShareAccess, 38 | ULONG CreateDisposition, 39 | ULONG CreateOptions, 40 | PVOID EaBuffer, 41 | ULONG EaLength 42 | ); 43 | } 44 | 45 | // 46 | // Function pointers to original functions. 47 | // 48 | inline f_NtCreateFile o_NtCreateFile = nullptr; -------------------------------------------------------------------------------- /KasperskyHookDrv/kaspersky.cpp: -------------------------------------------------------------------------------- 1 | #include "kaspersky.hpp" 2 | #include "kernel_modules.hpp" 3 | #include "utils.hpp" 4 | 5 | // 6 | // Global pointers for klhk.sys variables. 7 | // 8 | PETHREAD* hvm_thread_object = nullptr; 9 | PLONG hvm_run_requests = nullptr; 10 | PRKEVENT hvm_notification_event = nullptr; 11 | PRKEVENT hvm_sync_event = nullptr; 12 | PNTSTATUS hvm_status = nullptr; 13 | void*** system_dispatch_array = nullptr; 14 | unsigned int* ssdt_service_count = nullptr; 15 | unsigned int* shadow_ssdt_service_count = nullptr; 16 | unsigned int* provider = nullptr; 17 | 18 | // 19 | // Checks if klhk.sys is loaded. 20 | // 21 | bool kaspersky::is_klhk_loaded( ) 22 | { 23 | return kernel_modules::get_kernel_module_base( L"klhk.sys" ) != 0; 24 | } 25 | 26 | // 27 | // Finds required addresses by pattern scanning klhk.sys. 28 | // 29 | bool kaspersky::initialize( ) 30 | { 31 | // 32 | // Find klhk's hvm thread object. 33 | // 34 | auto presult = utils::find_pattern_km( L"klhk.sys", ".text", "\x48\x39\x2D\x00\x00\x00\x00\x89", "xxx????x" ); 35 | 36 | if ( !presult ) 37 | return false; 38 | 39 | hvm_thread_object = reinterpret_cast< PETHREAD* >( presult + *reinterpret_cast< int* >( presult + 0x3 ) + 0x7 ); 40 | 41 | // 42 | // Find klhk's hvm run counter. 43 | // 44 | presult = utils::find_pattern_km( L"klhk.sys", ".text", "\xF0\xFF\x05\x00\x00\x00\x00\x48\x8D\x0D", "xxx????xxx" ); 45 | 46 | if ( !presult ) 47 | return false; 48 | 49 | hvm_run_requests = reinterpret_cast< PLONG >( presult + *reinterpret_cast< int* >( presult + 0x3 ) + 0x7 ); 50 | 51 | // 52 | // Find klhk's hvm notification event. 53 | // 54 | presult += 0x7; 55 | hvm_notification_event = reinterpret_cast< PRKEVENT >( presult + *reinterpret_cast< int* >( presult + 0x3 ) + 0x7 ); 56 | 57 | // 58 | // Find klhk's hvm synchronization event. 59 | // 60 | presult = utils::find_pattern_km( L"klhk.sys", ".text", "\x48\x8D\x05\x00\x00\x00\x00\x49\x89\x73", "xxx????xxx" ); 61 | 62 | if ( !presult ) 63 | return false; 64 | 65 | hvm_sync_event = reinterpret_cast< PRKEVENT >( presult + *reinterpret_cast< int* >( presult + 0x3 ) + 0x7 ); 66 | 67 | // 68 | // Find klhk's hvm status. 69 | // 70 | presult = utils::find_pattern_km( L"klhk.sys", ".text", "\x8B\x1D\x00\x00\x00\x00\x89", "xx????x" ); 71 | 72 | if ( !presult ) 73 | return false; 74 | 75 | hvm_status = reinterpret_cast< PNTSTATUS >( presult + *reinterpret_cast< int* >( presult + 0x2 ) + 0x6 ); 76 | 77 | // 78 | // Find klhk's service table. 79 | // 80 | presult = utils::find_pattern_km( L"klhk.sys", "_hvmcode", "\x4C\x8D\x0D\x00\x00\x00\x00\x4D", "xxx????x" ); 81 | 82 | if ( !presult ) 83 | return false; 84 | 85 | system_dispatch_array = reinterpret_cast< void*** >( presult + *reinterpret_cast< int* >( presult + 0x3 ) + 0x7 ); 86 | 87 | // 88 | // Find number of services (SSDT). 89 | // 90 | presult = utils::find_pattern_km( L"klhk.sys", ".text", "\x89\x0D\x00\x00\x00\x00\x8B", "xx????x" ); 91 | 92 | if ( !presult ) 93 | return false; 94 | 95 | ssdt_service_count = reinterpret_cast< unsigned int* >( presult + *reinterpret_cast< int* >( presult + 0x2 ) + 0x6 ); 96 | 97 | // 98 | // Find number of services (Shadow SSDT). 99 | // 100 | presult = utils::find_pattern_km( L"klhk.sys", ".text", "\x89\x05\x00\x00\x00\x00\x85\xC0", "xx????xx" ); 101 | 102 | if ( !presult ) 103 | return false; 104 | 105 | shadow_ssdt_service_count = reinterpret_cast< unsigned int* >( presult + *reinterpret_cast< int* >( presult + 0x2 ) + 0x6 ); 106 | 107 | // 108 | // Find provider data. 109 | // 110 | presult = utils::find_pattern_km( L"klhk.sys", ".text", "\x39\x1D\x00\x00\x00\x00\x75", "xx????x" ); 111 | 112 | if ( !presult ) 113 | return false; 114 | 115 | provider = reinterpret_cast< unsigned int* >( presult + *reinterpret_cast< int* >( presult + 2 ) + 0x6 ); 116 | return true; 117 | } 118 | 119 | // 120 | // Performs hypervisor initialization. 121 | // 122 | NTSTATUS kaspersky::hvm_init( ) 123 | { 124 | if ( !hvm_thread_object || !( *hvm_thread_object ) || 125 | !hvm_run_requests || !hvm_notification_event || 126 | !hvm_sync_event || !hvm_status || 127 | !provider ) 128 | { 129 | return STATUS_BAD_DATA; 130 | } 131 | 132 | // 133 | // Set provider to random value. 134 | // 135 | *provider = 4; 136 | 137 | // 138 | // Hypervisor initialization. 139 | // 140 | _InterlockedIncrement( hvm_run_requests ); 141 | KeResetEvent( hvm_notification_event ); 142 | KeSetEvent( hvm_sync_event, IO_NO_INCREMENT, FALSE ); 143 | KeWaitForSingleObject( hvm_notification_event, Executive, KernelMode, FALSE, nullptr ); 144 | 145 | // 146 | // Get returned status. 147 | // 148 | return *hvm_status; 149 | } 150 | 151 | // 152 | // Gets the number of services in the SSDT. 153 | // 154 | unsigned int kaspersky::get_svc_count_ssdt( ) 155 | { 156 | return ssdt_service_count ? *ssdt_service_count : 0; 157 | } 158 | 159 | // 160 | // Gets the number of services in the Shadow SSDT. 161 | // 162 | unsigned int kaspersky::get_svc_count_shadow_ssdt( ) 163 | { 164 | return shadow_ssdt_service_count ? *shadow_ssdt_service_count : 0; 165 | } 166 | 167 | // 168 | // Hooks SSDT functions by changing klhk's service table. 169 | // 170 | bool kaspersky::hook_ssdt_routine( unsigned short index, void* dest, void** poriginal ) 171 | { 172 | if ( !system_dispatch_array || !dest || !poriginal ) 173 | return false; 174 | 175 | // 176 | // Get SSDT service count. 177 | // 178 | const auto svc_count = get_svc_count_ssdt( ); 179 | 180 | // 181 | // Kaspersky's SSDT isn't built / invalid index. 182 | // 183 | if ( !svc_count || index >= svc_count ) 184 | return false; 185 | 186 | // 187 | // Swap entry. 188 | // 189 | *poriginal = *system_dispatch_array[ index ]; 190 | *system_dispatch_array[ index ] = dest; 191 | return true; 192 | } 193 | 194 | // 195 | // Unhooks SSDT function. 196 | // 197 | bool kaspersky::unhook_ssdt_routine( unsigned short index, void* original ) 198 | { 199 | if ( !system_dispatch_array || !original ) 200 | return false; 201 | 202 | // 203 | // Get SSDT service count. 204 | // 205 | const auto svc_count = get_svc_count_ssdt( ); 206 | 207 | // 208 | // Kaspersky's SSDT isn't built / invalid index / function not hooked. 209 | // 210 | if ( !svc_count || index >= svc_count || *system_dispatch_array[ index ] == original ) 211 | return false; 212 | 213 | // 214 | // Restore entry. 215 | // 216 | *system_dispatch_array[ index ] = original; 217 | return true; 218 | } 219 | 220 | // 221 | // Hooks Shadow SSDT function. 222 | // 223 | bool kaspersky::hook_shadow_ssdt_routine( unsigned short index, void* dest, void** poriginal ) 224 | { 225 | if ( !system_dispatch_array || !dest || !poriginal ) 226 | return false; 227 | 228 | // 229 | // Get service count for SSDT and Shadow SSDT. 230 | // 231 | const auto svc_count = get_svc_count_ssdt( ), svc_count_shadow_ssdt = get_svc_count_shadow_ssdt( ); 232 | 233 | // 234 | // Failed to obtain service count. 235 | // 236 | if ( !svc_count || !svc_count_shadow_ssdt ) 237 | return false; 238 | 239 | // 240 | // Calculate index for dispatch table 241 | // 242 | const auto index_dispatch_table = ( index - 0x1000 ) + svc_count; 243 | 244 | // 245 | // Get dispatch table limit. 246 | // 247 | const auto dispatch_table_limit = svc_count + svc_count_shadow_ssdt; 248 | 249 | // 250 | // Invalid index. 251 | // 252 | if ( index_dispatch_table >= dispatch_table_limit ) 253 | return false; 254 | 255 | // 256 | // Swap entry. 257 | // 258 | *poriginal = *system_dispatch_array[ index_dispatch_table ]; 259 | *system_dispatch_array[ index_dispatch_table ] = dest; 260 | return true; 261 | } 262 | 263 | // 264 | // Unhooks Shadow SSDT function. 265 | // 266 | bool kaspersky::unhook_shadow_ssdt_routine( unsigned short index, void* original ) 267 | { 268 | if ( !system_dispatch_array || !original ) 269 | return false; 270 | 271 | // 272 | // Get service count for SSDT and Shadow SSDT. 273 | // 274 | const auto svc_count = get_svc_count_ssdt( ), svc_count_shadow_ssdt = get_svc_count_shadow_ssdt( ); 275 | 276 | // 277 | // Failed to obtain service count. 278 | // 279 | if ( !svc_count || !svc_count_shadow_ssdt ) 280 | return false; 281 | 282 | // 283 | // Calculate index for dispatch table. 284 | // 285 | const auto index_dispatch_table = ( index - 0x1000 ) + svc_count; 286 | 287 | // 288 | // Get dispatch table limit. 289 | // 290 | const auto dispatch_table_limit = svc_count + svc_count_shadow_ssdt; 291 | 292 | // 293 | // Invalid index / function not hooked. 294 | // 295 | if ( index_dispatch_table >= dispatch_table_limit || *system_dispatch_array[ index_dispatch_table ] == original ) 296 | return false; 297 | 298 | // 299 | // Restore entry. 300 | // 301 | *system_dispatch_array[ index_dispatch_table ] = original; 302 | return true; 303 | } 304 | 305 | // 306 | // Gets the pointer to a routine in SSDT by its index. 307 | // 308 | void* kaspersky::get_ssdt_routine( unsigned short index ) 309 | { 310 | if ( !system_dispatch_array ) 311 | return nullptr; 312 | 313 | // 314 | // Get SSDT service count. 315 | // 316 | const auto svc_count = get_svc_count_ssdt( ); 317 | 318 | // 319 | // Return the routine's address if the index is valid. 320 | // 321 | return ( svc_count && index < svc_count ) ? *system_dispatch_array[ index ] : nullptr; 322 | } 323 | 324 | // 325 | // Gets the pointer to a routine in Shadow SSDT by its index. 326 | // 327 | void* kaspersky::get_shadow_ssdt_routine( unsigned short index ) 328 | { 329 | if ( !system_dispatch_array ) 330 | return nullptr; 331 | 332 | // 333 | // Get service count for SSDT and Shadow SSDT 334 | // 335 | const auto svc_count = get_svc_count_ssdt( ), svc_count_shadow_ssdt = get_svc_count_shadow_ssdt( ); 336 | 337 | // 338 | // Failed to obtain service count. 339 | // 340 | if ( !svc_count || !svc_count_shadow_ssdt ) 341 | return nullptr; 342 | 343 | // 344 | // Calculate index for dispatch table. 345 | // 346 | const auto index_dispatch_table = ( index - 0x1000 ) + svc_count; 347 | 348 | // 349 | // Get dispatch table limit. 350 | // 351 | const auto dispatch_table_limit = svc_count + svc_count_shadow_ssdt; 352 | 353 | // 354 | // Return the routine's address if the index is valid. 355 | // 356 | return ( index_dispatch_table < dispatch_table_limit ) ? *system_dispatch_array[ index_dispatch_table ] : nullptr; 357 | } -------------------------------------------------------------------------------- /KasperskyHookDrv/kaspersky.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // 7 | // Functions. 8 | // 9 | namespace kaspersky 10 | { 11 | bool is_klhk_loaded ( ); 12 | bool initialize ( ); 13 | NTSTATUS hvm_init ( ); 14 | unsigned int get_svc_count_ssdt ( ); 15 | unsigned int get_svc_count_shadow_ssdt ( ); 16 | bool hook_ssdt_routine ( unsigned short index, void* dest, void** poriginal ); 17 | bool unhook_ssdt_routine ( unsigned short index, void* original ); 18 | bool hook_shadow_ssdt_routine ( unsigned short index, void* dest, void** poriginal ); 19 | bool unhook_shadow_ssdt_routine ( unsigned short index, void* original ); 20 | void* get_ssdt_routine ( unsigned short index ); 21 | void* get_shadow_ssdt_routine ( unsigned short index ); 22 | } -------------------------------------------------------------------------------- /KasperskyHookDrv/kernel_modules.cpp: -------------------------------------------------------------------------------- 1 | #include "kernel_modules.hpp" 2 | 3 | uintptr_t kernel_modules::get_kernel_module_base( const wchar_t* szmodule ) 4 | { 5 | if ( !szmodule || !PsLoadedModuleList || !PsLoadedModuleResource ) 6 | return 0; 7 | 8 | UNICODE_STRING module_name{ }; 9 | RtlInitUnicodeString( &module_name, szmodule ); 10 | 11 | KeEnterCriticalRegion( ); 12 | ExAcquireResourceSharedLite( PsLoadedModuleResource, TRUE ); 13 | 14 | uintptr_t module_base = 0; 15 | 16 | for ( const auto* plist_entry = PsLoadedModuleList->Flink; 17 | plist_entry != PsLoadedModuleList; 18 | plist_entry = plist_entry->Flink ) 19 | { 20 | const auto* pldr_entry = CONTAINING_RECORD( plist_entry, KLDR_DATA_TABLE_ENTRY, InLoadOrderLinks ); 21 | 22 | if ( !RtlCompareUnicodeString( &pldr_entry->BaseDllName, &module_name, TRUE ) ) 23 | { 24 | module_base = reinterpret_cast< uintptr_t >( pldr_entry->DllBase ); 25 | break; 26 | } 27 | } 28 | 29 | ExReleaseResourceLite( PsLoadedModuleResource ); 30 | KeLeaveCriticalRegion( ); 31 | 32 | return module_base; 33 | } -------------------------------------------------------------------------------- /KasperskyHookDrv/kernel_modules.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef struct _KLDR_DATA_TABLE_ENTRY 6 | { 7 | LIST_ENTRY InLoadOrderLinks; 8 | void* ExceptionTable; 9 | unsigned int ExceptionTableSize; 10 | void* GpValue; 11 | void* NonPagedDebugInfo; 12 | void* DllBase; 13 | void* EntryPoint; 14 | unsigned int SizeOfImage; 15 | UNICODE_STRING FullDllName; 16 | UNICODE_STRING BaseDllName; 17 | unsigned int Flags; 18 | unsigned __int16 LoadCount; 19 | unsigned __int16 u1; 20 | void* SectionPointer; 21 | unsigned int CheckSum; 22 | unsigned int CoverageSectionSize; 23 | void* CoverageSection; 24 | void* LoadedImports; 25 | void* Spare; 26 | unsigned int SizeOfImageNotRounded; 27 | unsigned int TimeDateStamp; 28 | } KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY; 29 | 30 | 31 | namespace kernel_modules 32 | { 33 | uintptr_t get_kernel_module_base( const wchar_t* szmodule ); 34 | } 35 | 36 | inline PLIST_ENTRY PsLoadedModuleList = nullptr; 37 | inline PERESOURCE PsLoadedModuleResource = nullptr; -------------------------------------------------------------------------------- /KasperskyHookDrv/pe.cpp: -------------------------------------------------------------------------------- 1 | #include "pe.hpp" 2 | 3 | PIMAGE_SECTION_HEADER pe::get_section_header( const uintptr_t image_base, const char* section_name ) 4 | { 5 | if ( !image_base || !section_name ) 6 | return nullptr; 7 | 8 | const auto pimage_dos_header = reinterpret_cast< PIMAGE_DOS_HEADER >( image_base ); 9 | 10 | if ( pimage_dos_header->e_magic != IMAGE_DOS_SIGNATURE ) 11 | return nullptr; 12 | 13 | const auto pimage_nt_headers = reinterpret_cast< PIMAGE_NT_HEADERS >( image_base + pimage_dos_header->e_lfanew ); 14 | 15 | if ( pimage_nt_headers->Signature != IMAGE_NT_SIGNATURE ) 16 | return nullptr; 17 | 18 | auto psection = IMAGE_FIRST_SECTION( pimage_nt_headers ); 19 | const auto NumberOfSections = pimage_nt_headers->FileHeader.NumberOfSections; 20 | 21 | PIMAGE_SECTION_HEADER psection_hdr = nullptr; 22 | 23 | for ( USHORT i = 0; i < NumberOfSections; ++i ) 24 | { 25 | if ( !_strnicmp( reinterpret_cast< const char* >( &psection->Name[ 0 ] ), section_name, IMAGE_SIZEOF_SHORT_NAME ) ) 26 | { 27 | psection_hdr = psection; 28 | break; 29 | } 30 | 31 | ++psection; 32 | } 33 | 34 | return psection_hdr; 35 | } -------------------------------------------------------------------------------- /KasperskyHookDrv/pe.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace pe 8 | { 9 | PIMAGE_SECTION_HEADER get_section_header( const uintptr_t image_base, const char* section_name ); 10 | } -------------------------------------------------------------------------------- /KasperskyHookDrv/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.hpp" 2 | #include "kernel_modules.hpp" 3 | #include "pe.hpp" 4 | 5 | bool data_compare( const char* pdata, const char* bmask, const char* szmask ) 6 | { 7 | for ( ; *szmask; ++szmask, ++pdata, ++bmask ) 8 | { 9 | if ( *szmask == 'x' && *pdata != *bmask ) 10 | return false; 11 | } 12 | 13 | return !*szmask; 14 | } 15 | 16 | uintptr_t utils::find_pattern( const uintptr_t base, const size_t size, const char* bmask, const char* szmask ) 17 | { 18 | for ( size_t i = 0; i < size; ++i ) 19 | if ( data_compare( reinterpret_cast< const char* >( base + i ), bmask, szmask ) ) 20 | return base + i; 21 | 22 | return 0; 23 | } 24 | 25 | uintptr_t utils::find_pattern_section( const uintptr_t base, const char* szsection, const char* bmask, const char* szmask ) 26 | { 27 | if ( !base || !szsection || !bmask || !szmask ) 28 | return 0; 29 | 30 | const auto* psection = pe::get_section_header( base, szsection ); 31 | return psection ? find_pattern( base + psection->VirtualAddress, psection->SizeOfRawData, bmask, szmask ) : 0; 32 | } 33 | 34 | uintptr_t utils::find_pattern_km( const wchar_t* szmodule, const char* szsection, const char* bmask, const char* szmask ) 35 | { 36 | if ( !szmodule || !szsection || !bmask || !szmask ) 37 | return 0; 38 | 39 | const auto module_base = kernel_modules::get_kernel_module_base( szmodule ); 40 | return module_base ? find_pattern_section( module_base, szsection, bmask, szmask ) : 0; 41 | } 42 | 43 | void* utils::get_system_routine( const wchar_t* szroutine ) 44 | { 45 | if ( !szroutine ) 46 | return nullptr; 47 | 48 | UNICODE_STRING routine { }; 49 | RtlInitUnicodeString( &routine, szroutine ); 50 | 51 | return MmGetSystemRoutineAddress( &routine ); 52 | } 53 | 54 | uintptr_t utils::get_ntos_base( ) 55 | { 56 | using f_RtlPcToFileHeader = PVOID( * )( PVOID PcValue, PVOID* BaseOfImage ); 57 | const auto RtlPcToFileHeader = reinterpret_cast< f_RtlPcToFileHeader >( get_system_routine( L"RtlPcToFileHeader" ) ); 58 | 59 | if ( !RtlPcToFileHeader ) 60 | return 0; 61 | 62 | uintptr_t ntos_base = 0; 63 | RtlPcToFileHeader( RtlPcToFileHeader, reinterpret_cast< void** >( &ntos_base ) ); 64 | 65 | return ntos_base; 66 | } 67 | 68 | bool utils::init( ) 69 | { 70 | const auto ntos_base = get_ntos_base( ); 71 | 72 | if ( !ntos_base ) 73 | return false; 74 | 75 | PsLoadedModuleList = reinterpret_cast< PLIST_ENTRY >( get_system_routine( L"PsLoadedModuleList" ) ); 76 | 77 | if ( !PsLoadedModuleList ) 78 | { 79 | auto result = find_pattern_section 80 | ( 81 | ntos_base, 82 | ".text", 83 | "\xC7\x43\x00\x00\x00\x00\x00\x48\x89\x43\x18\x48\x8D", 84 | "xx?????xxxxxx" 85 | ); 86 | 87 | if ( !result ) 88 | return false; 89 | 90 | result += 0xB; 91 | PsLoadedModuleList = reinterpret_cast< PLIST_ENTRY >( result + *reinterpret_cast< int* >( result + 0x3 ) + 0x7 ); 92 | } 93 | 94 | PsLoadedModuleResource = reinterpret_cast< PERESOURCE >( get_system_routine( L"PsLoadedModuleResource" ) ); 95 | 96 | if ( !PsLoadedModuleResource ) 97 | { 98 | auto result = find_pattern_section 99 | ( 100 | ntos_base, 101 | ".text", 102 | "\x41\x23\xFF\x66", 103 | "xxxx" 104 | ); 105 | 106 | if ( !result ) 107 | return false; 108 | 109 | result += 0xA; 110 | PsLoadedModuleResource = reinterpret_cast< PERESOURCE >( result + *reinterpret_cast< int* >( result + 0x3 ) + 0x7 ); 111 | } 112 | 113 | return PsLoadedModuleList && PsLoadedModuleResource; 114 | } -------------------------------------------------------------------------------- /KasperskyHookDrv/utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // 7 | // For logging stuff. 8 | // 9 | #define log( format, ... ) DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[ KasperskyHook ] " format "\n", ##__VA_ARGS__ ) 10 | 11 | namespace utils 12 | { 13 | uintptr_t find_pattern ( const uintptr_t base, const size_t size, const char* bmask, const char* szmask ); 14 | uintptr_t find_pattern_section ( const uintptr_t base, const char* szsection, const char* bmask, const char* szmask ); 15 | uintptr_t find_pattern_km ( const wchar_t* szmodule, const char* szsection, const char* bmask, const char* szmask ); 16 | void* get_system_routine ( const wchar_t* szroutine ); 17 | uintptr_t get_ntos_base ( ); 18 | bool init ( ); 19 | } -------------------------------------------------------------------------------- /KasperskyHookLoader/KasperskyHookLoader.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 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 16.0 34 | {AC843DC7-AE89-45D5-AD78-EDCB560ACCC3} 35 | Win32Proj 36 | KasperskyHookLoader 37 | 10.0 38 | 39 | 40 | 41 | Application 42 | true 43 | v142 44 | Unicode 45 | 46 | 47 | Application 48 | false 49 | v142 50 | true 51 | Unicode 52 | 53 | 54 | Application 55 | true 56 | v142 57 | Unicode 58 | 59 | 60 | Application 61 | false 62 | v142 63 | true 64 | Unicode 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | false 86 | 87 | 88 | true 89 | 90 | 91 | true 92 | 93 | 94 | false 95 | 96 | 97 | 98 | 99 | 100 | Level3 101 | true 102 | true 103 | true 104 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 105 | true 106 | 107 | 108 | Console 109 | true 110 | true 111 | true 112 | RequireAdministrator 113 | 114 | 115 | 116 | 117 | 118 | 119 | Level3 120 | true 121 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 122 | true 123 | 124 | 125 | Console 126 | true 127 | 128 | 129 | 130 | 131 | 132 | 133 | Level3 134 | true 135 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 136 | true 137 | 138 | 139 | Console 140 | true 141 | RequireAdministrator 142 | 143 | 144 | 145 | 146 | 147 | 148 | Level3 149 | true 150 | true 151 | true 152 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 153 | true 154 | 155 | 156 | Console 157 | true 158 | true 159 | true 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /KasperskyHookLoader/KasperskyHookLoader.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | -------------------------------------------------------------------------------- /KasperskyHookLoader/kasperskyhook.cpp: -------------------------------------------------------------------------------- 1 | #include "kasperskyhook.hpp" 2 | 3 | SC_HANDLE handle_kasperskyhook_svc = nullptr; 4 | 5 | // 6 | // Loads KasperskyHook.sys. 7 | // 8 | bool kasperskyhook::load( ) 9 | { 10 | // 11 | // Get current directory. 12 | // 13 | char buf[ MAX_PATH ]{ }; 14 | GetCurrentDirectoryA( sizeof( buf ), buf ); 15 | 16 | // 17 | // Build KasperskyHook.sys path. 18 | // 19 | const auto path = std::string{ buf } + "\\KasperskyHookDrv.sys"; 20 | 21 | // 22 | // Create KasperskyHook service. 23 | // 24 | handle_kasperskyhook_svc = loader::create_service( "KasperskyHook", "KasperskyHook", path ); 25 | 26 | // 27 | // Load KasperskyHook.sys. 28 | // 29 | return handle_kasperskyhook_svc ? loader::start_service( handle_kasperskyhook_svc ) : false; 30 | } 31 | 32 | // 33 | // Unloads KasperskyHook.sys. 34 | // 35 | bool kasperskyhook::unload( ) 36 | { 37 | SERVICE_STATUS svc_status { }; 38 | 39 | // 40 | // Unload KasperskyHook.sys. 41 | // 42 | auto success = loader::stop_service( handle_kasperskyhook_svc, &svc_status ); 43 | 44 | // 45 | // Service not started. 46 | // 47 | if ( !success && GetLastError( ) == ERROR_SERVICE_NOT_ACTIVE ) 48 | success = true; 49 | 50 | // 51 | // Delete KasperskyHook service on success. 52 | // 53 | return success ? loader::delete_service( handle_kasperskyhook_svc ) : false; 54 | } -------------------------------------------------------------------------------- /KasperskyHookLoader/kasperskyhook.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "loader.hpp" 4 | 5 | // 6 | // Functions for KasperskyHook.sys. 7 | // 8 | namespace kasperskyhook 9 | { 10 | bool load ( ); 11 | bool unload ( ); 12 | } -------------------------------------------------------------------------------- /KasperskyHookLoader/klhk.cpp: -------------------------------------------------------------------------------- 1 | #include "klhk.hpp" 2 | 3 | SC_HANDLE handle_klhk_svc = nullptr; 4 | HKEY hparameters_key = nullptr; 5 | 6 | // 7 | // Loads klhk.sys. 8 | // 9 | bool klhk::load( ) 10 | { 11 | // 12 | // Get system32 directory. 13 | // 14 | char buf[ MAX_PATH ]{ }; 15 | 16 | if ( !GetSystemDirectoryA( buf, sizeof( buf ) ) ) 17 | return false; 18 | 19 | // 20 | // Build klhk.sys path. 21 | // 22 | const auto path = std::string{ buf } + "\\drivers\\klhk.sys"; 23 | 24 | // 25 | // Create klhk service. 26 | // 27 | handle_klhk_svc = loader::create_service( "klhk", 28 | "Kaspersky Lab service driver", 29 | path ); 30 | 31 | // 32 | // Failed to create klhk service. 33 | // 34 | if ( !handle_klhk_svc ) 35 | return false; 36 | 37 | // 38 | // Create Parameters subkey. 39 | // 40 | auto error_code = RegCreateKeyEx( HKEY_LOCAL_MACHINE, 41 | TEXT( "System\\CurrentControlSet\\Services\\klhk\\Parameters" ), 42 | 0, 43 | nullptr, 44 | 0, 45 | KEY_ALL_ACCESS, 46 | nullptr, 47 | &hparameters_key, 48 | nullptr ); 49 | 50 | // 51 | // Failed to create Parameters key. 52 | // 53 | if ( error_code != ERROR_SUCCESS ) 54 | { 55 | // 56 | // Delete klhk service. 57 | // 58 | loader::delete_service( handle_klhk_svc ); 59 | return false; 60 | } 61 | 62 | // 63 | // Setup UseHvm parameter. 64 | // 65 | DWORD use_hvm = 1; 66 | 67 | error_code = RegSetValueEx( hparameters_key, 68 | TEXT( "UseHvm" ), 69 | 0, 70 | REG_DWORD, 71 | reinterpret_cast< const BYTE* >( &use_hvm ), 72 | sizeof( use_hvm ) ); 73 | 74 | // 75 | // Failed to set up parameter. 76 | // 77 | if ( error_code != ERROR_SUCCESS ) 78 | { 79 | // 80 | // Delete Parameters key. 81 | // 82 | RegDeleteKey( HKEY_LOCAL_MACHINE, TEXT( "System\\CurrentControlSet\\Services\\klhk\\Parameters" ) ); 83 | RegCloseKey( hparameters_key ); 84 | 85 | // 86 | // Delete service. 87 | // 88 | loader::delete_service( handle_klhk_svc ); 89 | return false; 90 | } 91 | 92 | // 93 | // Load klhk.sys. 94 | // 95 | const auto success = loader::start_service( handle_klhk_svc ); 96 | 97 | // 98 | // Failed to load klhk.sys. 99 | // 100 | if ( !success ) 101 | { 102 | // 103 | // Delete UseHvm value and Parameters key. 104 | // 105 | RegDeleteValue( hparameters_key, TEXT( "UseHvm" ) ); 106 | RegDeleteKey( HKEY_LOCAL_MACHINE, TEXT( "System\\CurrentControlSet\\Services\\klhk\\Parameters" ) ); 107 | RegCloseKey( hparameters_key ); 108 | 109 | // 110 | // Delete service. 111 | // 112 | loader::delete_service( handle_klhk_svc ); 113 | } 114 | 115 | return success; 116 | } 117 | 118 | // 119 | // Closes handles to resources. 120 | // 121 | void klhk::cleanup( bool delete_service ) 122 | { 123 | if ( hparameters_key ) 124 | { 125 | // 126 | // Close handle to parameters key. 127 | // 128 | RegCloseKey( hparameters_key ); 129 | } 130 | 131 | if ( handle_klhk_svc ) 132 | { 133 | // 134 | // Mark service for deletion. 135 | // 136 | if ( delete_service ) 137 | loader::delete_service( handle_klhk_svc ); 138 | 139 | // 140 | // Close handle to klhk service. 141 | // 142 | CloseServiceHandle( handle_klhk_svc ); 143 | } 144 | } -------------------------------------------------------------------------------- /KasperskyHookLoader/klhk.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "loader.hpp" 4 | 5 | // 6 | // klhk.sys helpers. 7 | // 8 | namespace klhk 9 | { 10 | bool load ( ); 11 | void cleanup ( bool delete_service ); 12 | } -------------------------------------------------------------------------------- /KasperskyHookLoader/loader.cpp: -------------------------------------------------------------------------------- 1 | #include "loader.hpp" 2 | 3 | SC_HANDLE handle_scm = nullptr; 4 | 5 | // 6 | // Opens a handle to SCM. 7 | // 8 | bool loader::open_scm( ) 9 | { 10 | handle_scm = OpenSCManager( nullptr, nullptr, SC_MANAGER_CREATE_SERVICE ); 11 | return handle_scm != nullptr; 12 | } 13 | 14 | // 15 | // Closes handle to SCM. 16 | // 17 | void loader::close_scm( ) 18 | { 19 | CloseServiceHandle( handle_scm ); 20 | } 21 | 22 | // 23 | // Creates / opens a service. 24 | // 25 | SC_HANDLE loader::create_service( const std::string& name, const std::string& display_name, const std::string& path ) 26 | { 27 | // 28 | // Create service. 29 | // 30 | auto hsvc = CreateServiceA( handle_scm, 31 | name.c_str( ), 32 | display_name.c_str( ), 33 | SERVICE_ALL_ACCESS, 34 | SERVICE_KERNEL_DRIVER, 35 | SERVICE_DEMAND_START, 36 | SERVICE_ERROR_NORMAL, 37 | path.c_str( ), 38 | nullptr, 39 | nullptr, 40 | nullptr, 41 | nullptr, 42 | nullptr ); 43 | 44 | // 45 | // Service already exists. 46 | // 47 | if ( !hsvc && GetLastError( ) == ERROR_SERVICE_EXISTS ) 48 | { 49 | // 50 | // Open handle to service. 51 | // 52 | hsvc = OpenServiceA( handle_scm, name.c_str( ), SERVICE_ALL_ACCESS ); 53 | } 54 | 55 | return hsvc; 56 | } 57 | 58 | // 59 | // Deletes a service. 60 | // 61 | bool loader::delete_service( const SC_HANDLE handle_service ) 62 | { 63 | // 64 | // Mark the service for deletion. 65 | // 66 | const auto success = static_cast< bool >( DeleteService( handle_service ) ); 67 | 68 | // 69 | // Invalid handle or access rights. 70 | // 71 | if ( !success && GetLastError( ) != ERROR_SERVICE_MARKED_FOR_DELETE ) 72 | return false; 73 | 74 | // 75 | // Close handle to service. 76 | // 77 | return static_cast< bool >( CloseServiceHandle( handle_service ) ); 78 | } 79 | 80 | // 81 | // Starts a service. 82 | // 83 | bool loader::start_service( const SC_HANDLE handle_service ) 84 | { 85 | // 86 | // Start service. 87 | // 88 | const auto success = static_cast< bool >( StartService( handle_service, 0, nullptr ) ); 89 | 90 | // 91 | // Service was started / already running. 92 | // 93 | return success || GetLastError( ) == ERROR_SERVICE_ALREADY_RUNNING; 94 | } 95 | 96 | // 97 | // Stops a service. 98 | // 99 | bool loader::stop_service( SC_HANDLE handle_service, LPSERVICE_STATUS service_status ) 100 | { 101 | // 102 | // Stop service. 103 | // 104 | return static_cast< bool >( ControlService( handle_service, SERVICE_CONTROL_STOP, service_status ) ); 105 | } -------------------------------------------------------------------------------- /KasperskyHookLoader/loader.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // 7 | // Helpers for loading drivers by interacting with SCM. 8 | // 9 | namespace loader 10 | { 11 | bool open_scm ( ); 12 | void close_scm ( ); 13 | SC_HANDLE create_service ( const std::string& name, const std::string& display_name, const std::string& path ); 14 | bool delete_service ( const SC_HANDLE handle_service ); 15 | bool start_service ( const SC_HANDLE handle_service ); 16 | bool stop_service ( const SC_HANDLE handle_service, LPSERVICE_STATUS service_status ); 17 | } -------------------------------------------------------------------------------- /KasperskyHookLoader/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "klhk.hpp" 3 | #include "kasperskyhook.hpp" 4 | 5 | int main( ) 6 | { 7 | // 8 | // Open handle to SCM. 9 | // 10 | if ( !loader::open_scm( ) ) 11 | { 12 | std::cout << "[-] Failed to open handle to SCM!\n"; 13 | return EXIT_FAILURE; 14 | } 15 | 16 | // 17 | // Load klhk.sys. 18 | // 19 | if ( !klhk::load( ) ) 20 | { 21 | std::cout << "[-] Failed to load klhk.sys!\n"; 22 | 23 | // 24 | // Do cleanup for klhk.sys. 25 | // 26 | klhk::cleanup( true ); 27 | 28 | // 29 | // Close handle to SCM. 30 | // 31 | loader::close_scm( ); 32 | return EXIT_FAILURE; 33 | } 34 | 35 | // 36 | // Just to make sure klhk.sys gets Shadow SSDT information. You can change this to whatever you want. 37 | // 38 | MessageBoxA( nullptr, "Dummy MessageBox", "Dummy MessageBox", MB_OK ); 39 | 40 | // 41 | // Load KasperskyHook.sys. 42 | // 43 | if ( !kasperskyhook::load( ) ) 44 | { 45 | std::cout << "[-] Failed to load KasperskyHook.sys\n"; 46 | 47 | // 48 | // Do cleanup for KasperskyHook.sys. 49 | // 50 | kasperskyhook::unload( ); 51 | 52 | // 53 | // Do cleanup for klhk.sys. 54 | // 55 | klhk::cleanup( false ); 56 | 57 | // 58 | // Close handle to SCM. 59 | // 60 | loader::close_scm( ); 61 | return EXIT_FAILURE; 62 | } 63 | 64 | // 65 | // Log progress. 66 | // 67 | std::cout << "[+] Successfully loaded KasperskyHook! Press END to unload.\n"; 68 | 69 | // 70 | // Wait for user input. 71 | // 72 | while ( !( GetAsyncKeyState( VK_END ) & 1 ) ) 73 | Sleep( 10 ); 74 | 75 | // 76 | // Unload KasperskyHook.sys. 77 | // 78 | if ( !kasperskyhook::unload( ) ) 79 | std::cout << "[-] Failed to unload Kasperskyhook.sys!\n"; 80 | 81 | // 82 | // Do cleanup for klhk.sys. 83 | // 84 | klhk::cleanup( false ); 85 | 86 | // 87 | // Close handle to SCM. 88 | // 89 | loader::close_scm( ); 90 | 91 | // 92 | // Return success. 93 | // 94 | return EXIT_SUCCESS; 95 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 iPower 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KasperskyHook 2 | Hook system calls on Windows by using Kaspersky's hypervisor 3 | 4 | 5 | 6 | ## How does it work? 7 | 8 | Kaspersky utilizes its hypervisor when hardware virtualization is supported for additional protection. It hooks system calls by changing `IA32_LSTAR` to point to its own syscall handler (which is basically a copy of `KiSystemCall64`) so it dispatches system calls to its own handlers (while doing initialization, it builds its own dispatch table). 9 | 10 | This project loads klhk.sys (Kaspersky's hypervisor module) and a custom driver which interfaces with it to subvert the system and hook system calls. 11 | 12 | 13 | 14 | ## Why did you write this? 15 | 16 | While researching Kaspersky components, I thought it was an interesting idea to write a custom project that lets me hook system calls by using Kaspersky's hypervisor to take a closer look at what it is doing. 17 | 18 | 19 | 20 | ## Build steps - how to use it 21 | 22 | * Download [Visual Studio 2019](https://visualstudio.microsoft.com/pt-br/downloads/), [WDK](https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk), clone this repository and build the solution. 23 | * Make sure `KasperskyHook.sys` and `KasperskyHookLoader.exe` are in the same folder. Copy `klhk.sys` to `\Windows\System32\drivers` 24 | * Execute `KasperskyHookLoader.exe` and have fun :D 25 | 26 | 27 | ## Troubleshooting 28 | 29 | If you followed the Build and Testing steps and `kaspersky::hvm_init()` returns `C00000A3` or `C000090B`, try following these steps: 30 | 31 | * Make sure Virtualization (VT-x/AMD-v) is supported and enabled. 32 | * Check if there are any other hypervisors conflicting with klhk (such as other AVs) 33 | * Delete all KasperskyHook-related services, cleanup registry information and reboot 34 | 35 | If it still doesn't work, consider using a newer version of klhk.sys. More information: https://github.com/iPower/KasperskyHook/issues/4 36 | 37 | 38 | **MAKE SURE TO ENABLE TEST MODE TO TEST THIS PROJECT. IF YOU WISH TO USE IT OUTSIDE TEST MODE, USE YOUR CUSTOM DRIVER LOADER OR SIGN THE DRIVER.** 39 | 40 | **NOTE: THIS ISN'T MEANT TO BE AN EASY-TO-PASTE-DETECTION-PROOF PROJECT. I JUST WROTE THIS FOR EDUCATIONAL PURPOSES SO I WON'T BE ADDING ANY HV-HARDENING OR ANTI-DETECTION CODE.** 41 | 42 | 43 | 44 | ## Demo 45 | 46 | ![Demo](demo.gif) 47 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPower/KasperskyHook/238c1b8f376b91b63fbac260d7c6b5fefa76f375/demo.gif -------------------------------------------------------------------------------- /klhk/klhk.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPower/KasperskyHook/238c1b8f376b91b63fbac260d7c6b5fefa76f375/klhk/klhk.sys --------------------------------------------------------------------------------