EDRSnowblast - blizzard on EDR drivers
After the sandstorm it’s time for the blizzard ! The well-known EDRSandblast tool is a fantastic code base for Windows kernel investigating purpose, after several modification I decided to fork this project and wanted to share details about this with the community.
Intro
I love the EDRSandblast tool made by Thomas DIOT (Qazeer) Maxime MEIGNAN (themaks), it’s really amazing. I opened pull requests & issue but I don’t know if the project is maintained which leads me to fork and start my own project named EDRSnowblast in order to fix issues I encounter and implement extra features resulting of successful experiments. This tools helps me at investigating Windows kernel (mostly EDR drivers). Today I want to share information focusing on the tool itself but in the next blogpost I will share technical details on EDR internal communication.
Add new Windows version validation method
About the bug
As you may notice, EDRSandblast
project uses hardcoded offsets in order to reliably perform kernel monitoring bypass operations.
Those offsets are stored in CSV files as shown in the example below :
EDRSandblast
loads this file and the LoadNtoskrnlOffsetsFromFile function checks if ntoskrnlVersion
column contains the current Windows version.
This verification is based on the file version :
But sometimes Microsoft don’t update this value when upating Windows files and some mismatch can happen giving wrong results. It’s a big deal if using kernel RW operation with wrong offsets, it will probably lead to a BSOD (I’ve experienced this bug).
In the following example the ntoskrnl.exe version is 19041.2364 but the current running version is 19045.2364.
One solution could be double checking current Windows version using Windows API (ex: GetVersionEx or RtlGetNtVersionNumbers) but I didn’t take this option.
New Windows version check
I choose to check the current Windows version using SHA256 checksum of the Windows files. I updated Offsets/ExtractOffsets.py
which allows to create new entries in the CSV files (NtoskrnlOffsets.csv, WdigestOffsets.csv, etc) :
As a result EDRSnowblast.exe
check this value using sha256sum, original code left as comments.
Note : only “Manual offset retrieval” method is supported, the “Automatic offsets retrieval and update” method is not implemented.
Add new driver support
I added support for the vulnerable GIGABYTE gdrv.sys Windows driver (CVE-2018-19320, CVE-2018-19322, CVE-2018-19323, CVE-2018-19321) Why doing this ?
First it’s just because I’m used to use this driver I wanted to add support for it :-) The other reason is that driver has a very powerful exploitation primitive : arbitrary physical memory read/write
This is out of the scope of this blogpost but this kind of primitive open new perspectives when facing HVCI / Microsoft VBS protection.
EDRSnowblast.exe audit --kernelmode --driver c:\gdrv.sys --verbose
Add feature : loading unsigned kernel driver
This new feature allows to load unsigned kernel driver, implementing the following commands :
sc create [service name] [binPath=evil.sys]
sc start [service name]
It follows steps described in a previous blogpost, in summary :
- g_CiOptions offset retrieval : using
ExtractOffsets.py
script, new fileCiOffsets.csv
is also available - patching g_CiOptions : in order to disable DSE
- load unsigned kernel driver : creates the new service and starts it
- restore g_CiOptions : to avoid BSOD
The unsigned driver is available until you stop & delete the service (using sc stop
or sc delete
command), as shown below.
Output example (verbose mode) :
EDRSnowblast.exe loadk --kernelmode --loadk-file C:\Users\viking\Desktop\pimpmypid_drv.sys --verbose
Note : the code should have changed since this “happy christmas” 2022 pull request.
Add feature : loading unsigned minifilter driver
Like the previous one, this new feature allows to load unsigned Windows driver but it’s dedicated to minifilter drivers. Indeed it implements the following command :
fltmc load [ driverName ]
It follow the same steps shown above :
- g_CiOptions offset retrieval : using
ExtractOffsets.py
script, new fileCiOffsets.csv
is also available - patch g_CiOptions : in order to disable DSE
- load unsigned minifilter driver : use the Filter Manager Control (fltmc) command in order to load the driver
- restore g_CiOptions : to avoid BSOD
The unsigned driver is available until you use fltmc unload
command.
Output example (verbose mode) :
EDRSnowblast.exe loadk --kernelmode --loadk-file C:\Users\viking\Desktop\pimpmypid_drv.sys --verbose
Add feature “filter-enum” for minifilter enumeration process
It allows to enumerate drivers (filters) which are loaded in the kernel memory, an equivalent of the Windbg !fltkd.frames
command.
EDRSnowblast.exe filter-enum --kernelmode
It is possible to identify index number of the driver. For Windows Defender (WdFilter) is at index n°9 in the above figure.
By using this index it’s possible to retrieve details on the specified filter : MaxConnections & NumberOfConnections are interesting fields.
EDRSnowblast.exe filter-enum --kernelmode --filter-index 9
Add feature “filter-mute” for disabling messages between EDR.sys and EDR.exe
Using this option, you can begin the process of “disabling messages between EDR.sys and EDR.exe”. A dedicated blogpost on this topic will be available soon, but here is an insight.
For example it’s possible to reset WdFilter
MaxConnections field :
EDRSnowblast.exe filter-mute --kernelmode --filter-index 9
When the operation finished, identify the PID of Windows Defender usermode process and kill it :
tasklist | findstr MsMpEng.exe
MsMpEng.exe 2956 Services 0 206,788 K
c:\pimpmypid_clt.exe /kill 2956
Now the new MsMpEng.exe
can’t connect to WdFilter.sys
because MaxConnections (value = 0) is already reached. Without this connection no message can be exchanged between EDR.sys and EDR.exe, impacting the EDR ability to detect & block security threats.
Add new offsets files : updated ExtractOffsets.py
The new features shown in previous sections require building new offsets files : CiOffsets.csv
& FltmgrOffsets.csv
You will find below the process of building required CSV offsets files for a new Windows target.
Generate offsets for a new Windows ci.dll (new file created : CiOffsets.csv)
C:\Users\viking>python .\EDRSnowblast\Offsets\ExtractOffsets.py -i c:\Windows\System32\ci.dll ci
[*] Processing ci version ci_19041-3208.dll (file: c:\Windows\System32\ci.dll)
[+] g_CiOptions = 0x39418
[+] do it : c:\Windows\System32\ci.dll
e246455a03d9113c5dfd597afdd2d6f079d83b5c9bf28d20953ca3e81c1d67a0
[+] Finished processing of ci c:\Windows\System32\ci.dll!
Generate offsets for a new Windows fltmgr.sys (new file created : FltmgrOffsets.csv)
C:\Users\viking>python .\EDRSnowblast\Offsets\ExtractOffsets.py -i c:\Windows\System32\drivers\fltMgr.sys fltmgr
[*] Processing fltmgr version fltmgr_19041-3086.sys (file: c:\Windows\System32\drivers\fltMgr.sys)
[+] FltGlobals = 0x29600
...
[+] do it : c:\Windows\System32\drivers\fltMgr.sys
a74ad4d7624fb741b7008711336b37f3a27d96c3ef6361c107155b3bdfd8592b
[+] Finished processing of fltmgr c:\Windows\System32\drivers\fltMgr.sys!
Generate offsets for a new Windows kernel (new file created : NtoskrnlOffsets.csv)
C:\Users\viking>python .\EDRSnowblast\Offsets\ExtractOffsets.py -i c:\Windows\System32\ntoskrnl.exe ntoskrnl
[*] Processing ntoskrnl version ntoskrnl_19041-3208.exe (file: c:\Windows\System32\ntoskrnl.exe)
[+] PspCreateProcessNotifyRoutine = 0xcec2a0
[+] PspCreateThreadNotifyRoutine = 0xcec0a0
[+] PspLoadImageNotifyRoutine = 0xcec4a0
[+] _PS_PROTECTION Protection = 0x87a
[+] EtwThreatIntProvRegHandle = 0xc19e08
[+] _ETW_GUID_ENTRY* GuidEntry = 0x20
[+] _TRACE_ENABLE_INFO ProviderEnableInfo = 0x60
[+] PsProcessType = 0xcfc410
[+] PsThreadType = 0xcfc440
[+] struct _LIST_ENTRY CallbackList = 0xc8
[+] do it : c:\Windows\System32\ntoskrnl.exe
e8e6040640c9dddc8feeb0a9310bab92e7e422ef469beabdd8b5bb63b7a9dad0
[+] Finished processing of ntoskrnl c:\Windows\System32\ntoskrnl.exe!
Outro
Thanks for reading, feedbacks are welcome !