Update Readme

Update Readme
This commit is contained in:
Vixx
2025-03-20 23:40:44 +02:00
parent cfb99f2309
commit 3a6e729326
25 changed files with 80 additions and 4 deletions
+4
View File
@@ -180,6 +180,10 @@ fffff806`8f8803a6 <mark>488be9</mark> mov rbp,rcx
fffff806`8f8803a9 4d85d2 test r10,r10
</pre>
<pre>
const uint8_t patternEtwThreatIntProvRegHandle[] = { 0x45, 0x8b, 0xe9, 0x48, 0x8b, 0xe9 };
</pre>
and so now, we need to do a binary search to find the handle, and for the binary search we can use the opcode highlighed (458be9 and 488be9) and start the search for the exported function `nt!KeInsertQueueApc`.
After getting the address of the handle, we just use our Read / Write primitive to enumerate the field and overwrite it.
@@ -99,8 +99,14 @@ fffff800`350c9104 4c8b154d10fdff mov r10,qword ptr [FLTMGR!_imp_ExAcquireFa
fffff800`350c910b e820da146e call nt!ExAcquireFastResourceShared (fffff800`a3216b30)
</pre>
<pre>
const uint8_t patternFltGlobals[] = { 0x48, 0x8d, 0x0d, 0x58 };
</pre>
So the function `ResolveFltmgrGlobals` will resolve the address of `FLTMGR!FltGlobals` by loading `FLTMGR.sys` to the usermode process and using a binary search, by searching for `lea rcx` opcodes and calculate the offset of `FLTMGR!FltGlobals` and use that on the real driver base address of `FLTMGR.sys` to get the kernel address of `FLTMGR!FltGlobals` .
**Note:** we need to subtract 0x58 from the address we will get because as you can see from the snipped above, what we will get is `FLTMGR!FltGlobals+0x58`.
### GetFilterByName Function
Next step is to get the frame, in latest versions of windows only 1 Frame exist.
+35 -4
View File
@@ -189,11 +189,11 @@ fffff800`365780bd 0f57c0 xorps xmm0,xmm0
</pre>
`NETIO!FeInitCalloutTable` is not an exported function, so we cannot get the address of the function directly in our c code.
We need to start the byte search using a function that is exported and close to `NETIO!FeInitCalloutTable`.
We need to start the binary search using a function that is exported and close to `NETIO!FeInitCalloutTable`.
the functions needs to be exported to be able to use `GetProcAddress` and `GetModuleHandle` on them and get the function address.
So To find the closest exported functions (start and end) to use in our code as a starting point for the byte search, we can use IDA.
So To find the closest exported functions (start and end) to use in our code as a starting point for the binary search, we can use IDA.
First let's get the offset to the function from the nt base
@@ -216,7 +216,7 @@ Note: It will take some time for the addresses in the export table to be refresh
And then you have to pick 2 functions where `000580b0` which is the address of `NETIO!FeInitCalloutTable` is between them.
As you can, from the screenshot `FeGetWfpGlobalPtr` and `KfdDeRefCallout` are the start and end functions that i will be using as `NETIO!FeInitCalloutTable` falls in between, so i can use `FeGetWfpGlobalPtr` as the start of the byte search.
As you can, from the screenshot `FeGetWfpGlobalPtr` and `KfdDeRefCallout` are the start and end functions that i will be using as `NETIO!FeInitCalloutTable` falls in between, so i can use `FeGetWfpGlobalPtr` as the start of the binary search.
![Export Table](./screenshots/ExportTable.png)
@@ -254,11 +254,34 @@ lkd> dqs ffff8088`65705010 + 0x198 + 0x08 L1
ffff8088`657051b0 ffff8088`6819a000
</pre>
<pre>
const uint8_t patterngWfpGlobal[] = { 0x4C, 0x8B, 0x05, 0x49, 0x81, 0xC0 };
</pre>
we need to pick bytes that are static and doesnt change between reboot. I highlighed what I will be searching for in my code (4c8b05 and 4981c0). and after finding the address in our code. we will get `fffff80626a980d1`.
After that we can calculate the global structure address and the offset in our code.
I used as well the function `InitDefaultCallout` to get the structure size of each network callout entry (0x60 in our case) using binary search by searching for `b9` and reading the structure size after the address is found.
Next we will use another binary search to find the function address of `InitDefaultCallout`, because we will use to extract the callout structure size dynamicaly.
<pre>
lkd> u
NETIO!FeInitCalloutTable+0x4b:
fffff807`211e80fb 488b89a0010000 mov rcx,qword ptr [rcx+1A0h]
fffff807`211e8102 e839cc0100 call NETIO!_memset_spec_ermsb (fffff807`21204d40)
fffff807`211e8107 488b05728a0300 mov rax,qword ptr [NETIO!gWfpGlobal (fffff807`21220b80)]
fffff807`211e810e c7809801000000040000 mov dword ptr [rax+198h],400h
<mark>fffff807`211e8118 e827000000 call NETIO!InitDefaultCallout (fffff807`211e8144)</mark>
fffff807`211e811d <mark>488bd8</mark> mov rbx,rax
fffff807`211e8120 <mark>4885db</mark> test rbx,rbx
fffff807`211e8123 740f je NETIO!FeInitCalloutTable+0x84 (fffff807`211e8134)
</pre>
<pre>
const uint8_t patterngInitDefaultCallout[] = { 0x48, 0x8B, 0xd8, 0x48, 0x85, 0xdb };
</pre>
I will use the function `InitDefaultCallout` to get the structure size of each network callout entry (0x60 in our case) using binary search by searching for `b9` and reading the structure size after the address is found.
<pre>
lkd> u NETIO!InitDefaultCallout
@@ -271,6 +294,10 @@ fffff806`26a98156 <mark>b9</mark>60000000 mov ecx,60h
fffff806`26a9815b e8a0befbff call NETIO!WfpPoolAllocNonPaged (fffff806`26a54000)
</pre>
<pre>
const uint8_t patterngCalloutStructureSize[] = { 0xb9 };
</pre>
At this point we were able to extract
- Number of entries => NETIO!gWfpGlobal + 0x198
- Pointer to array of callout structure => NETIO!gWfpGlobal + 0x1A0
@@ -319,6 +346,10 @@ fffff801`63968181 <mark>488d05</mark>28ebfdff lea rax,[NETIO!FeDefaultClass
fffff801`63968188 <mark>c70104</mark>000000 mov dword ptr [rcx],4
</pre>
<pre>
const uint8_t patterngFeDefaultClassifyCallback[] = { 0x48, 0x8d, 0x05, 0xc7, 0x01 };
</pre>
`InitDefaultCallout` is not an exported function, so we need to find first an exported function close to `InitDefaultCallout` for our binary search.
<pre>
@@ -0,0 +1,4 @@
C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass\notifyRoutine.cpp;C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass\x64\Release\notifyRoutine.obj
C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass\MemHandler.cpp;C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass\x64\Release\MemHandler.obj
C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass\memory.cpp;C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass\x64\Release\memory.obj
C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass.cpp;C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass\x64\Release\NotifyRoutineKernelBypass.obj
@@ -0,0 +1,2 @@
PlatformToolSet=v143:VCToolArchitecture=Native64Bit:VCToolsVersion=14.42.34433:TargetPlatformVersion=10.0.26100.0:
Release|x64|C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\|
@@ -0,0 +1,3 @@
^C:\GITHUB-VIXX\KERNEL-CALLBACK-REMOVAL\NOTIFYROUTINEKERNELBYPASS\NOTIFYROUTINEKERNELBYPASS\X64\RELEASE\MEMHANDLER.OBJ|C:\GITHUB-VIXX\KERNEL-CALLBACK-REMOVAL\NOTIFYROUTINEKERNELBYPASS\NOTIFYROUTINEKERNELBYPASS\X64\RELEASE\MEMORY.OBJ|C:\GITHUB-VIXX\KERNEL-CALLBACK-REMOVAL\NOTIFYROUTINEKERNELBYPASS\NOTIFYROUTINEKERNELBYPASS\X64\RELEASE\NOTIFYROUTINE.OBJ|C:\GITHUB-VIXX\KERNEL-CALLBACK-REMOVAL\NOTIFYROUTINEKERNELBYPASS\NOTIFYROUTINEKERNELBYPASS\X64\RELEASE\NOTIFYROUTINEKERNELBYPASS.OBJ
C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass\x64\Release\NotifyRoutineKernelBypass.IPDB
C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass\x64\Release\NotifyRoutineKernelBypass.iobj
@@ -0,0 +1,2 @@
c:\github-vixx\kernel-callback-removal\notifyroutinekernelbypass\x64\release\notifyroutinekernelbypass.pdb
c:\github-vixx\kernel-callback-removal\notifyroutinekernelbypass\x64\release\notifyroutinekernelbypass.exe
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ProjectOutputs>
<ProjectOutput>
<FullPath>C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\x64\Release\NotifyRoutineKernelBypass.exe</FullPath>
</ProjectOutput>
</ProjectOutputs>
<ContentFiles />
<SatelliteDlls />
<NonRecipeFileRefs />
</Project>
@@ -0,0 +1,13 @@
notifyRoutine.cpp
C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass\notifyRoutine.cpp(78,12): warning C4244: 'initializing': conversion from 'DWORD64' to 'int', possible loss of data
C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass\notifyRoutine.cpp(191,14): warning C4101: 'pEntry': unreferenced local variable
C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass\notifyRoutine.cpp(263,14): warning C4101: 'pEntry': unreferenced local variable
MemHandler.cpp
memory.cpp
C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\NotifyRoutineKernelBypass\memory.cpp(78,29): warning C4267: 'initializing': conversion from 'size_t' to 'DWORD', possible loss of data
NotifyRoutineKernelBypass.cpp
Generating code
Previous IPDB not found, fall back to full compilation.
All 224 functions were compiled because no usable IPDB/IOBJ from previous compilation was found.
Finished generating code
NotifyRoutineKernelBypass.vcxproj -> C:\Github-Vixx\kernel-callback-removal\NotifyRoutineKernelBypass\x64\Release\NotifyRoutineKernelBypass.exe