Skip to content

wesmar/BootBypass

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BootBypass — Native Boot-Phase DSE/HVCI Bypass utility

Advanced native-mode utility for bypassing Driver Signature Enforcement and Memory Integrity. Implements smart SeCiCallbacks patching and independent management of HVCI settings. Operating as a subsystem:native application, it ensures early-phase control and environment preparation for security research and driver development.

Author Marek Wesołowski (WESMAR) Contact marek@kvc.pl  ·  +48 607 440 283
Year 2026 Domain kvc.pl

Table of Contents

  1. Overview
  2. Architecture
  3. Boot-Phase Execution Context
  4. Resource Embedding — IDR_DRV
  5. Kernel Offset Discovery — SeCiCallbacks Scanner
  6. IOCTL Memory Primitives — RTC_PACKET
  7. DSE Patch/Restore Sequence
  8. HVCI Detection and Hive Patching
  9. Service Name Obfuscation — MmPoolTelemetry
  10. DSE State Persistence
  11. Configuration Reference — drivers.ini
  12. Research Notes — Algorithm Development
  13. Module Reference
  14. Build System
  15. Deployment

1. Overview

BootBypass is a Windows native-subsystem application (/SUBSYSTEM:NATIVE) that executes as a SMSS boot-phase program — before services.exe, before winlogon.exe, and before any antivirus or EDR user-mode component initializes. It delivers a complete, automated pipeline for:

  • DSE bypass — patching SeCiCallbacks in the live kernel to disable Code Integrity validation, loading an unsigned target driver, then restoring the original callback — all within a single atomic boot-phase sequence.
  • HVCI (Memory Integrity) bypass — directly modifying the SYSTEM registry hive on disk, without using any registry API, to clear the HypervisorEnforcedCodeIntegrity\Enabled flag before the next boot.
  • INI-driven operation — all actions declared in C:\Windows\drivers.ini (UTF-16 LE). Supports LOAD, UNLOAD, RENAME, and DELETE operations, executed sequentially.

Secure Boot independence. Secure Boot validates the pre-OS chain — UEFI firmware → boot manager → Windows kernel. That chain is complete and sealed before SMSS launches its first process. bb.exe executes inside an already-running, already-validated kernel session; Secure Boot has no mechanism to inspect or constrain native applications registered in BootExecute. The relevant enforcement boundary at this stage is DSE — which this utility addresses directly.

Archive password: github.com

Demonstrated outcome — unsigned kernel driver loaded and running:

sc query omnidriver

SERVICE_NAME: omnidriver
        TYPE               : 1  KERNEL_DRIVER
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)

2. Architecture

The project is a single native executable compiled from seven C translation units, one MASM module, a shared header, and embedded binary resources.

src/
├── BootBypass.h             Global type definitions, NT API imports, constants
├── BootManager.c/.h         Entry point (NtProcessStartup), privilege setup, main dispatch
├── SecurityPatcher.c/.h     IOCTL read/write primitives, DSE patch/restore, AutoPatch sequence
├── OffsetFinder.c/.h        PE parser, SeCiCallbacks heuristic scanner, ZwFlushInstructionCache locator
├── SetupManager.c/.h        Resource extraction (IDR_DRV), HVCI detect/patch, hive NK/VK walker
├── DriverManager.c/.h       NtLoadDriver, NtUnloadDriver, IsDriverLoaded
├── FileManager.c/.h         NtSetInformationFile rename/delete, recursive directory delete
├── SystemUtils.c/.h         memset, wcslen, wcscpy/wcscat safe ops, NtDisplayString, alloc/free
├── MmPoolTelemetry.asm      Runtime service name decoder (MASM, obfuscated)
├── IDR_DRV                  Embedded driver blob (LZNT1-compressed + XOR-encrypted)
├── drivers.ini              Boot-phase runtime configuration (UTF-16 LE)
└── resource.h / BootBypass.rc

2.1 High-Level Execution Flow

flowchart TD
    A([NtProcessStartup]) --> B[Acquire privileges\nSE_LOAD_DRIVER · SE_BACKUP\nSE_RESTORE · SE_SHUTDOWN]
    B --> C[ReadIniFile + ParseIniFile]
    C --> D{Offsets in INI?}
    D -- No --> E[FindKernelOffsetsLocally\nScan ntoskrnl.exe on disk]
    D -- Yes --> F
    E --> F{HVCI enabled?}
    F -- Yes --> G[PatchSystemHiveHVCI\nDirect NK/VK hive write\nReboot]
    F -- No --> H[For each INI entry]
    H --> I{Action}
    I -- LOAD + AutoPatch --> J[ExecuteAutoPatchLoad]
    I -- LOAD --> K[LoadDriver]
    I -- UNLOAD --> L[UnloadDriver]
    I -- RENAME --> M[NtSetInformationFile]
    I -- DELETE --> N[NtSetInformationFile\nrecursive if set]
    J --> O[ExtractkvcFromResource\nXOR decrypt + LZNT1 decompress\nWrite to Sam.evtx]
    O --> P[LoadDriver under obfuscated name]
    P --> Q[OpenDriverDevice]
    Q --> R[GetNtoskrnlBase\nNtQuerySystemInformation]
    R --> S[ReadMemory64 → save callback\nWriteMemory64 → patch SeCiCallbacks+0x20]
    S --> T[LoadDriver target unsigned driver]
    T --> U[WriteMemory64 → restore callback]
    U --> V[UnloadDriver + Cleanupkvc\nDelete Sam.evtx + registry key]
    V --> W([SUCCESS])
Loading

3. Boot-Phase Execution Context

3.1 Why the SMSS Phase

BootBypass runs as a native application registered in:

HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\BootExecute

The default value is autocheck autochk *. deploy.ps1 appends bb to this multi-string, causing SMSS to launch bb.exe from %SystemRoot%\System32 on the next boot — before any Win32 subsystem process starts.

At this execution stage:

  • No antivirus user-mode threads are alive.
  • No ETW-based kernel callbacks are armed by security software.
  • The kernel and its loaded boot drivers are running; the session manager has control.
  • NtDisplayString writes directly to the boot screen (visible when Verbose=YES).

3.2 Linker and CRT Configuration

#pragma comment(linker,
    "/SUBSYSTEM:NATIVE "
    "/ENTRY:NtProcessStartup "
    "/NODEFAULTLIB "
    "/STACK:0x100000,0x100000")
#pragma comment(lib, "ntdll.lib")
#pragma optimize("", off)
#pragma check_stack(off)
Flag Effect
/SUBSYSTEM:NATIVE Loaded by SMSS; no Win32 initialization
/ENTRY:NtProcessStartup NT native entry point; PEB passed directly by the loader
/NODEFAULTLIB No CRT dependency; all string operations re-implemented in SystemUtils.c
/STACK:0x100000,0x100000 1 MB committed stack; required for in-place LZNT1 decompression buffers
#pragma optimize("", off) Prevents dead-code elimination of deliberate structural sequences
#pragma check_stack(off) Disables /GS stack cookies; consistent with native binary conventions

3.3 Privilege Acquisition

The first action of NtProcessStartup is enabling four privileges via RtlAdjustPrivilege:

Privilege Purpose
SeLoadDriverPrivilege (10) NtLoadDriver / NtUnloadDriver
SeBackupPrivilege (17) Open the SYSTEM hive with backup intent
SeRestorePrivilege (18) Write to the SYSTEM hive
SeShutdownPrivilege (19) NtShutdownSystem after HVCI hive patch

4. Resource Embedding — IDR_DRV

The bypass driver is embedded directly into bb.exe as a RCDATA resource (type 10, ID 101) and never touches disk as a standalone file. It is protected by two layers applied at build time:

4.1 Build Pipeline (compress_idr.ps1)

Input: src\kvc.sys (raw PE, 14024 bytes)
  ↓
RtlCompressBuffer (LZNT1 + COMPRESSION_ENGINE_MAXIMUM)
  → compressed blob (9139 bytes, ~35% reduction)
  ↓
XOR encrypt, key = { 0xA0, 0xE2, 0x80, 0x8B, 0xE2, 0x80, 0x8C } (7-byte rotating)
  → IDR_DRV (final resource blob, 9139 bytes)

The script outputs the constants required in SetupManager.c:

#define kvc_SIZE              9139    // compressed+encrypted size
#define kvc_UNCOMPRESSED_SIZE 14024   // original PE size

These are verified at runtime: if the resource size does not match kvc_SIZE exactly, extraction fails immediately.

4.2 Runtime Extraction — Manual PE Resource Walk

No Win32 resource API is available in the native subsystem. FindResourceData() locates the embedded blob by walking the PE resource directory manually, starting from the image base obtained directly from the PEB:

// x64: PEB at GS:[0x60], ImageBase at PEB+0x10
imageBase = (PVOID)*(ULONGLONG*)((UCHAR*)__readgsqword(0x60) + 0x10);

Walk path through the .rsrc directory tree:

IMAGE_RESOURCE_DIRECTORY (root)
  └─ entry.Id == 10  (RT_RCDATA)
       └─ IMAGE_RESOURCE_DIRECTORY (type level)
            └─ entry.Id == 101  (IDR_DRV)
                 └─ IMAGE_RESOURCE_DIRECTORY (language level)
                      └─ IMAGE_RESOURCE_DATA_ENTRY
                           ├─ OffsetToData  → pointer to encrypted blob
                           └─ Size          → verified against kvc_SIZE

4.3 Pre-Cleanup Before Extraction

Before writing the driver to disk, ExtractkvcFromResource() checks for leftover state from a previous crash or incomplete run:

IsDriverLoaded(driverName)?
  YES → NtUnloadDriver(service path)
      → NtOpenKey(service key) + NtDeleteKey
      → NtOpenFile(Sam.evtx) + FILE_DISPOSITION delete

This ensures idempotent operation regardless of prior crash.

4.4 Decryption and Decompression

// Step 1: XOR decrypt in-place
for (SIZE_T i = 0; i < kvc_SIZE; i++)
    xorBuf[i] = srcData[i] ^ XOR_KEY[i % XOR_KEY_LEN];

// Step 2: LZNT1 decompress via ntdll
RtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1,
    decompBuf, kvc_UNCOMPRESSED_SIZE,
    xorBuf,    kvc_SIZE,
    &finalSize);

If finalSize != kvc_UNCOMPRESSED_SIZE, the extraction is aborted — no partial file is written.

4.5 Temporary Path

The decompressed PE is written to:

\SystemRoot\System32\winevt\Logs\Sam.evtx

This path was chosen because:

  • The Windows Event Log service (EventLog) is not yet running during the SMSS boot phase — no sharing violation.
  • The filename and directory are indistinguishable from legitimate Windows telemetry to a casual observer.
  • The file is deleted by Cleanupkvc() immediately after the bypass driver is unloaded — zero permanent footprint.

4.6 Cleanup

Cleanupkvc() unconditionally:

  1. Opens Sam.evtx with DELETE access and sets FILE_DISPOSITION_INFORMATION.DeleteFile = TRUE.
  2. Opens the service registry key under HKLM\...\Services\<name> and calls NtDeleteKey.

5. Kernel Offset Discovery — SeCiCallbacks Scanner

When Offset_SeCiCallbacks or Offset_SafeFunction are missing from drivers.ini, FindKernelOffsetsLocally() reads ntoskrnl.exe directly from disk and scans it — no PDB download, no network access, no symbols.

5.1 ZwFlushInstructionCache (SafeFunction)

Located by a simple export table name scan. The RVA is read from the export directory:

Export directory → name table → find "ZwFlushInstructionCache" → ordinal → function RVA

This function is used as the patch target: writing its address into SeCiCallbacks+0x20 causes CiValidateImageHeader to immediately return success for all drivers, bypassing signature verification.

5.2 SeCiCallbacks — Heuristic Pattern Scan

SeCiCallbacks is an undocumented kernel global — not exported, not in any public symbol. The scanner finds it by identifying its initialization code in the .text section of ntoskrnl.exe.

Target instruction pattern:

At driver startup, the kernel writes the size of the SeCiCallbacks structure into the struct's first DWORD via a RIP-relative store:

C7 05 <rel32> <imm32>     ; MOV DWORD PTR [rip+disp], <struct_size>

This is a 10-byte instruction (C7 05 form, not the 48 C7 05 QWORD form). The displacement points to a writable data section — SeCiCallbacks itself.

Scoring system: Each candidate instruction is evaluated by a multi-factor scoring algorithm:

Evidence Points
Base score for matching RIP-relative DWORD store to writable data 80
imm32 within expected struct-size range [0x40, 0x4000] (required)
imm32 == 0x108 (known SeCiCallbacks flags value) +12
Preceding RIP-relative LEA points to target+4 in writable data (required)
Zeroing of EDX/R8D (xor edx,edx / xor r8d,r8d) before struct init +1 (per item)
Struct size constant in r8d / r9d (41 B8 or 49 C7 C0, value 0x40–0x400) +1
CALL instruction appears after the zeroing + size sequence +1
Each point from zeroing window multiplied by 12
Nearby QWORD store within 0x20 bytes (48 C7 05 / 48 89) to writable data +8
qword store gap < 24 bytes 30 − gap
struct size matches: qword_target_rva − lea_target_rva == struct_size +18
imm32 == struct_size + 12 (common SeCiCallbacks layout) +18
imm32 == struct_size + 8 or +16 +6
qword_delta == imm32 − 8 (pointer-and-size layout) +20
Distance penalty (LEA distance / 32, max 12) −(0..12)

Minimum qualifying score: 110.

The scanner uses the PE exception directory (.pdata, IMAGE_RUNTIME_FUNCTION_ENTRY) to constrain the backwards search window to the containing function's prologue — reducing false positives and search time significantly.

Callback offset: hardcoded to 0x20 (32 bytes into SeCiCallbacks). This is the slot for CiValidateImageHeader, the callback that validates PE code integrity before loading.

5.3 PE Loading for Offline Scan

ntoskrnl.exe is opened with NtOpenFile + FILE_READ_DATA | SYNCHRONIZE, mapped into user memory via NtAllocateVirtualMemory, and read with NtReadFile. All section boundaries are parsed from the PE header — no kernel mapping, no LoadLibrary.


6. IOCTL Memory Primitives — RTC_PACKET

The bypass driver exposes arbitrary 32-bit kernel virtual memory read and write via a simple IOCTL interface. Communication uses the following structure:

typedef struct _RTC_PACKET {
    UCHAR     pad0[8];     // offset  0  — reserved
    ULONGLONG addr;        // offset  8  — target kernel virtual address
    UCHAR     pad1[8];     // offset 16  — reserved
    ULONG     size;        // offset 24  — transfer size (always 4)
    ULONG     value;       // offset 28  — read result / write value
    UCHAR     pad3[16];    // offset 32  — reserved
} RTC_PACKET;              // total: 48 bytes

Because the IOCTL only supports 32-bit transfers, 64-bit read/write is decomposed into two consecutive 32-bit operations:

// WriteMemory64: low DWORD first, high DWORD at address+4
WriteMemory32(hDriver, address,     (ULONG)(value & 0xFFFFFFFF),        ioctl_write);
WriteMemory32(hDriver, address + 4, (ULONG)((value >> 32) & 0xFFFFFFFF), ioctl_write);

// ReadMemory64: two reads, reassembled
low  = ReadMemory32(hDriver, address,     ioctl_read);
high = ReadMemory32(hDriver, address + 4, ioctl_read);
*value = ((ULONGLONG)high << 32) | low;

The IOCTL codes are read from drivers.ini (IoControlCode_Read, IoControlCode_Write) — no hardcoded constants in the binary.

Kernel device handle is obtained via NtOpenFile on the device path declared in DriverDevice. If the path ends with kvc, it is resolved at runtime to \Device\<MmGetPoolDiagnosticString()> — see §9.


7. DSE Patch/Restore Sequence

ExecuteAutoPatchLoad() performs the complete bypass in five steps:

STEP 1  ExtractkvcFromResource()
        XOR decrypt + LZNT1 decompress IDR_DRV → Sam.evtx
        LoadDriver(obfuscated_name, Sam.evtx, "KERNEL", "SYSTEM")

STEP 2  OpenDriverDevice(\Device\<obfuscated_name>)
        GetNtoskrnlBase (NtQuerySystemInformation class 11)

STEP 3  callbackToPatch = ntBase + Offset_SeCiCallbacks + Offset_Callback (0x20)
        safeFunction    = ntBase + Offset_SafeFunction
        ReadMemory64(callbackToPatch) → save originalCallback + DSE_STATE to drivers.ini
        WriteMemory64(callbackToPatch, safeFunction)   ← DSE disabled

STEP 4  LoadDriver(target_service, target_image_path)  ← unsigned driver loads

STEP 5  WriteMemory64(callbackToPatch, originalCallback) ← DSE restored
        UnloadDriver(obfuscated_name)
        Cleanupkvc()                                   ← Sam.evtx + registry deleted

If any step fails after the patch write (steps 4–5), the original callback is already persisted in [DSE_STATE] — it will be restored on the next boot from the saved value.


8. HVCI Detection and Hive Patching

8.1 Detection

HVCI status is read from the live registry at boot time:

HKLM\SYSTEM\CurrentControlSet\Control\DeviceGuard\
    Scenarios\HypervisorEnforcedCodeIntegrity\Enabled (REG_DWORD)

If Enabled == 1, direct memory patching via IOCTL would fail (HVCI prevents writable kernel code). The tool switches to hive patching mode.

8.2 Offline Hive Patching — Chunked NK/VK Walk

PatchSystemHiveHVCI() opens \SystemRoot\System32\config\SYSTEM directly with FILE_OPEN_FOR_BACKUP_INTENT | FILE_READ_DATA | FILE_WRITE_DATA (requires SeBackupPrivilege + SeRestorePrivilege). It operates entirely without the registry API — reading and modifying the raw binary hive file.

Scan strategy — chunked 1 MB reads with 256-byte overlap:

The hive file is scanned in 1 MB chunks. Each chunk is searched for the 31-byte ASCII literal:

HypervisorEnforcedCodeIntegrity

When the pattern is found at offset p within a chunk, the scanner validates that it belongs to an NK (key) cell — not a value blob — by checking the two-byte signature at p - 0x4C:

chunkBuffer[p - 0x4C] == 0x6E &&   // 'n'
chunkBuffer[p - 0x4C + 1] == 0x6B  // 'k'

The NK cell header layout at p - 0x4C:

Offset Field Verification
+0x00 NK signature 0x6E 0x6B — required
+0x04 values count must be 1–256
+0x08 values list offset raw hive offset
+0x4C key name (ASCII) HypervisorEnforcedCodeIntegrity

Values list walk:

The values list is a flat array of ULONG hive offsets, one per value. Each offset is resolved to an absolute file offset as 0x1000 + cell_offset (skipping the 4 KB hive header). For each VK (value) cell:

VK offset Field Expected
+4 VK signature 0x76 0x6B
+6 name length (USHORT) 7 (ASCII) or 14 (Unicode)
+8 data length 0x80000004 (inline REG_DWORD)
+12 inline data current DWORD value
+16 data type REG_DWORD (4)
+20 flags bit 0 set = ASCII name

Name match: compares 7 bytes "Enabled" in ASCII (flags bit 0 set) or 7 UTF-16 LE codepoints (flags bit 0 clear).

Write and verify:

writeOffset.QuadPart = vkFileOffset + 12;  // inline REG_DWORD payload
NtWriteFile(hFile, ..., &newValue, 4, &writeOffset);

// Immediate read-back verification
NtReadFile(hFile, ..., &verifiedValue, 4, &writeOffset);
assert(verifiedValue == newValue);

After successful patch, NtFlushBuffersFile flushes to physical media. The tool then calls NtShutdownSystem(1) to reboot — the patched hive takes effect on the next boot. On the boot after the reboot, HVCI is no longer active and the DSE bypass proceeds normally.

Windows 10 compatibility: On Windows 10 the VK cell for Enabled can reside megabytes away from its NK cell in the hive file. The 256-byte chunk overlap prevents missing patterns at chunk boundaries; the values-list random-access reads handle distant VK cells regardless of their file position.

8.3 HVCI Restoration

If RestoreHVCI=YES in drivers.ini, after all operations complete PatchSystemHiveHVCI(TRUE) is called to re-enable the hive flag, and SetHVCIRegistryFlag(TRUE) writes Enabled=1 back to the live registry key — so the Windows Security Center shows Memory Integrity as active again.


9. Service Name Obfuscation — MmPoolTelemetry

The service name used for the bypass driver is not stored as a plain string anywhere in bb.exe. It is produced at runtime by MmGetPoolDiagnosticString() — an x64 MASM function in MmPoolTelemetry.asm that assembles the name from encoded immediate values.

The returned name appears in:

  • The service registry key path (HKLM\...\Services\<name>)
  • The device object path (\Device\<name>)
  • NtLoadDriver / NtUnloadDriver calls

Device path resolution: drivers.ini declares DriverDevice=\Device\kvc as a placeholder. At runtime, if the last path component is exactly kvc, ExecuteAutoPatchLoad() replaces it with \Device\<MmGetPoolDiagnosticString()>:

SIZE_T nameStart = find_last_backslash(config->DriverDevice);
if (config->DriverDevice[nameStart] == L'k' &&
    config->DriverDevice[nameStart+1] == L'v' &&
    config->DriverDevice[nameStart+2] == L'c' &&
    config->DriverDevice[nameStart+3] == L'\0') {
    wcscpy_safe(resolved, MAX_PATH_LEN, L"\\Device\\");
    wcscat_safe(resolved, MAX_PATH_LEN, MmGetPoolDiagnosticString());
    devicePath = resolved;
}

This means neither the real driver name nor the device path appear in any string table, import table, or resource of the binary.


10. DSE State Persistence

If the process terminates abnormally between patching and restoring SeCiCallbacks, the original callback value would be lost — leaving DSE permanently disabled until the next kernel load. To prevent this, the original callback is persisted immediately after the read:

SaveStateSection() appends a [DSE_STATE] section to drivers.ini:

[DSE_STATE]
OriginalCallback=0xFFFFF80612345678

On the next boot, LoadStateSection() reads this value before performing any operation. RemoveStateSection() strips the section from the file after a successful restore. Both operations parse and rewrite the UTF-16 LE INI file using only NT file APIs.


11. Configuration Reference — drivers.ini

The configuration file is placed at %SystemRoot%\drivers.ini — decoded by bb.exe as \SystemRoot\drivers.ini. It must be encoded as UTF-16 LE with BOM (written automatically by deploy.ps1).

11.1 [Config] Section

[Config]
Execute=YES                       ; NO = parse file but perform no operations
RestoreHVCI=NO                    ; YES = re-enable HVCI flag in hive after all operations
Verbose=NO                        ; YES = output to boot screen via NtDisplayString; NO = silent

DriverDevice=\Device\kvc          ; Bypass driver device path; "kvc" resolved at runtime
IoControlCode_Read=2147492936     ; 0x80002048
IoControlCode_Write=2147492940    ; 0x8000204C

; Kernel offsets — commented out = auto-scanned at boot from ntoskrnl.exe.
; Fill in known values to skip the scan (faster on repeated runs).
;Offset_SeCiCallbacks=0x0
Offset_Callback=0x20              ; offset within SeCiCallbacks to CiValidateImageHeader
;Offset_SafeFunction=0x0

If both Offset_SeCiCallbacks and Offset_SafeFunction are 0, FindKernelOffsetsLocally() scans ntoskrnl.exe at boot time and populates them automatically. The offsets are not written back to the file — the scan runs on every boot if they are absent.

11.2 Driver Entry — ACTION=LOAD

[Driver0]
Action=LOAD
AutoPatch=YES                     ; YES = full DSE bypass cycle; NO = direct NtLoadDriver
CheckIfLoaded=NO                  ; YES = skip if driver already running
ServiceName=omnidriver            ; SCM service name (registry key)
DisplayName=omnidriver            ; Display label (boot screen only)
ImagePath=\SystemRoot\System32\drivers\omnidriver.sys
DriverType=KERNEL
StartType=SYSTEM

11.3 Driver Entry — ACTION=UNLOAD

[Driver1]
Action=UNLOAD
ServiceName=omnidriver
DisplayName=Unload omnidriver

11.4 File Operations — RENAME and DELETE

Rename/move a file or directory (pre-boot, before any file locks are established):

[Op0]
Action=RENAME
DisplayName=Rename my file
SourcePath=\SystemRoot\System32\oldname.dll
TargetPath=\SystemRoot\System32\newname.dll
ReplaceIfExists=YES

Delete a file or directory tree:

[Op1]
Action=DELETE
DisplayName=Remove temp artifact
DeletePath=\SystemRoot\Temp\artifact.bin
RecursiveDelete=NO

All paths use NT-style format — no drive letters. \SystemRoot is the kernel alias for the Windows installation root, resolved independently of which drive Windows is installed on.

11.5 Multiple Entries

Up to 64 entries (MAX_ENTRIES) are supported per file. Entries are processed sequentially in declaration order. AutoPatch=YES entries extract the bypass driver, use it, and clean up before proceeding to the next entry.

11.6 Complete Reference Example

; ============================================================
; BootBypass Configuration — UTF-16 LE with BOM
; ============================================================

[Config]
Execute=YES
RestoreHVCI=NO
Verbose=NO

DriverDevice=\Device\kvc
IoControlCode_Read=2147492936
IoControlCode_Write=2147492940

; Kernel offsets — commented out = auto-scanned at boot from ntoskrnl.exe.
;Offset_SeCiCallbacks=0x0
Offset_Callback=0x20
;Offset_SafeFunction=0x0

; --- Load unsigned target driver with DSE bypass ---
[Driver0]
Action=LOAD
AutoPatch=YES
CheckIfLoaded=NO
ServiceName=omnidriver
DisplayName=omnidriver
ImagePath=\SystemRoot\System32\drivers\omnidriver.sys
DriverType=KERNEL
StartType=SYSTEM

; --- Rename a file before Windows session starts ---
[Op0]
Action=RENAME
DisplayName=Swap library
SourcePath=\SystemRoot\System32\mylib_new.dll
TargetPath=\SystemRoot\System32\mylib.dll
ReplaceIfExists=YES

; --- Delete a leftover artifact ---
[Op1]
Action=DELETE
DisplayName=Remove temp
DeletePath=\SystemRoot\Temp\setup_artifact.tmp
RecursiveDelete=NO

12. Research Notes — How the Algorithms Were Developed

12.1 HVCI Hive Structure Discovery — Windows 10 vs Windows 11

The HVCI bypass via raw hive patching required understanding a non-obvious structural difference between Windows generations that is not documented anywhere publicly.

Windows 11 — compact hive layout. The HypervisorEnforcedCodeIntegrity NK cell and its Enabled VK cell are stored close together in the hive file — typically within a few kilobytes. A simple forward scan finds the key name and the value data nearby with high reliability.

Windows 10 — scattered layout. Microsoft's registry compaction on Windows 10 places the VK cell for Enabled at a completely unrelated file offset, potentially megabytes away from the NK cell that references it. A naive contiguous scanner finds the key name, reads the values-list offset from the NK header, then must perform an entirely separate random-access read to a distant file position to reach the actual VK cell.

Understanding this required:

  1. Opening raw SYSTEM hive files from both Windows versions in a hex editor.
  2. Manually tracing the NK → values-list → VK chain at the binary level: 4-byte cell sizes, the 0x1000 base offset of the first hive bin, the inline REG_DWORD encoding at VK offset +12.
  3. Confirming that the NK signature (nk = 0x6E 0x6B) appears exactly 0x4C bytes before the key name in the cell, and the VK signature (vk = 0x76 0x6B) at +4 within the value cell.

The implementation handles both layouts via chunked 1 MB reads with 256-byte overlap (preventing missed patterns at chunk boundaries) combined with random-access NtReadFile calls for values-list and VK data regardless of their file position. Write is followed by an immediate read-back verification before NtFlushBuffersFile commits the change to disk.

12.2 SeCiCallbacks Discovery — IDA Reverse Engineering and Python Prototype

Finding SeCiCallbacks without PDB symbols across arbitrary Windows kernel builds required a full reverse engineering process before a single line of C was written.

Goal: Locate two offsets in ntoskrnl.exe at boot time — fully offline, no internet, no symbol server:

  • Offset_SeCiCallbacks — RVA of the undocumented SeCiCallbacks global
  • Offset_SafeFunction — RVA of ZwFlushInstructionCache (patch target to neutralise CI)

Stage 1 — IDA analysis. Loaded ntoskrnl.exe in IDA Pro (x64). Navigated to SepInitializeCodeIntegrity — the function responsible for initialising the Code Integrity subsystem at boot. Observed the following characteristic initialization sequence:

lea     rcx, SeCiCallbacks+4       ; LEA r64, [RIP+rel32] — points to struct+4
xor     edx, edx                   ; zero fill value
mov     r8d, 0FCh                  ; struct size for memset
call    memset
mov     cs:SeCiCallbacks, 108h     ; C7 05 rel32 108h — flags field write
mov     cs:qword_..., 0A000010h    ; 48 C7 05 rel32 ... — nearby qword write

Key insight: the LEA points to SeCiCallbacks + 4 (not the base), so seci_rva = lea_target − 4. The C7 05 store immediately after memset writes the flags field (0x108 on observed builds). A nearby 48 C7 05 (QWORD store) appears within ~0x20 bytes into the same structure.

Stage 2 — Python prototype (find_seci.py). Implemented a complete offline scanner in Python to iterate quickly on heuristics:

# Anchor: find all C7 05 rel32 imm32 instructions in executable sections
# where target RVA lands in a writable, non-executable section
# and imm32 is in [0x40, 0x4000] (plausible struct size/flags)

for file_off in exec_section_range:
    if data[file_off:file_off+2] != b'\xC7\x05':
        continue
    target_rva = compute_rip_relative(file_off, length=10, data=data)
    if not is_writable_data(target_rva, sections):
        continue
    # Search backwards for matching LEA to target_rva + 4
    # Score the candidate by zeroing window, qword proximity, size match

The prototype went through three iterations:

  • v1 — single tight byte pattern near SepInitializeCodeIntegrity. Too brittle across compiler versions.
  • v2 — hybrid: fast path (precise manual decode of C7 05 + nearby 48 C7 05) + structural scan using .pdata RUNTIME_FUNCTION bounds as function delimiters.
  • v3 — scoring system: multiple independent signals weighted by confidence; minimum threshold prevents false positives.

Validated output on a local build:

Offset_SeCiCallbacks = 0xF047A0
Offset_SafeFunction  = 0x6A7760
Offset_Callback      = 0x20

Stage 3 — Port to C (OffsetFinder.c). The Python algorithm was ported to pure C with no CRT dependency, operating directly on a memory-mapped copy of ntoskrnl.exe loaded via NtReadFile. The scoring engine (ScoreZeroingWindow, FindRuntimeFunctionBounds, FindNearbyQwordStore) maps 1:1 to the Python prototype. Minimum score threshold: 110 points. Observed scores on correct candidates: 120–185 points.

The ZwFlushInstructionCache RVA is found by a simple export table name scan — it is a public export, present on all builds, resolved without any heuristic.


13. Module Reference

Module Responsibility
BootManager.c NtProcessStartup entry, privilege setup, INI load, HVCI check gate, entry dispatch loop
SecurityPatcher.c WriteMemory32/64, ReadMemory64, GetNtoskrnlBase, OpenDriverDevice, ExecuteAutoPatchLoad, SaveStateSection, LoadStateSection, RemoveStateSection
OffsetFinder.c PE parser (ParsePe, FindExportRva), heuristic scanner (FindKernelOffsetsLocally), scoring engine (ScoreZeroingWindow), exception directory walker (FindRuntimeFunctionBounds)
SetupManager.c FindResourceData, ExtractkvcFromResource, Cleanupkvc, PatchSystemHiveHVCI, CheckAndDisableHVCI, RestoreHVCI, SetHVCIRegistryFlag
DriverManager.c LoadDriver (registry key creation + NtLoadDriver), UnloadDriver, IsDriverLoaded
FileManager.c ExecuteRename (NtSetInformationFile + FILE_RENAME_INFORMATION), ExecuteDelete (FILE_DISPOSITION_INFORMATION), recursive directory delete
SystemUtils.c memset_impl, wcslen, wcscpy_safe, wcscat_safe, wcscat_check, _wcsicmp_impl, TrimString, ULONGLONGToHexString, StringToULONGLONG, DisplayMessage, DisplayAlwaysMessage, DisplayStatus, AllocateZeroedBuffer, FreeAllocatedBuffer, ReadIniFile, ParseIniFile, FreeIniFileBuffer, QuerySystemModuleInformation
MmPoolTelemetry.asm MmGetPoolDiagnosticString — runtime decoder for bypass driver service name

14. Build System

13.1 Project

Visual Studio 2022, BootBypass.vcxproj. Configuration: Release | x64.

Key project settings:

  • Runtime library: none (/NODEFAULTLIB)
  • Subsystem: Native
  • Entry point: NtProcessStartup
  • Additional dependencies: ntdll.lib
  • Enable assembly: MASM (ml64.exe) for MmPoolTelemetry.asm

13.2 Build Script (build.ps1)

build.ps1 builds the Visual Studio project and copies the output bb.exe to data\. Run from the repo root in an elevated Developer PowerShell:

.\build.ps1

13.3 Driver Resource Preparation (compress_idr.ps1)

Run once whenever kvc.sys changes. Produces src\IDR_DRV and prints the updated #define constants:

.\compress_idr.ps1 -InputSys src\kvc.sys -OutputFile src\IDR_DRV

Output example:

Input  : 14024 bytes  (src\kvc.sys)
Output : 9139 bytes   (src\IDR_DRV)  [-34.8%]

Update SetupManager.c:
#define kvc_SIZE              9139
#define kvc_UNCOMPRESSED_SIZE 14024

Update the constants in SetupManager.c, then rebuild.


15. Deployment

14.1 deploy.ps1

Run from an elevated PowerShell session. The script:

  1. Copies bb.exe to %SystemRoot%\System32\bb.exe.
  2. Reads drivers.ini, optionally replaces ImagePath with the value from -TargetDriverNtPath.
  3. Writes the (possibly modified) INI to %SystemRoot%\drivers.ini as UTF-16 LE.
  4. Appends bb to HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\BootExecute (REG_MULTI_SZ), preserving the existing autocheck autochk * entry.
# Deploy — inject real driver NT path
.\deploy.ps1 -TargetDriverNtPath "\SystemRoot\System32\drivers\omnidriver.sys"

# Deploy with force (no confirmation prompt)
.\deploy.ps1 -TargetDriverNtPath "\SystemRoot\System32\drivers\omnidriver.sys" -Force

# Preview all actions without modifying the system
.\deploy.ps1 -TargetDriverNtPath "\SystemRoot\System32\drivers\omnidriver.sys" -WhatIf

# Remove all traces (BootExecute entry, bb.exe, drivers.ini)
.\deploy.ps1 -Remove

-TargetDriverNtPath must use an NT-style path beginning with \ and without a drive letter.
Example: \SystemRoot\System32\drivers\omnidriver.sys

14.2 Operation Sequence

1. Run deploy.ps1             → installs bb.exe + drivers.ini + BootExecute entry
2. Reboot                     → SMSS executes bb.exe before any Win32 process
3. bb.exe runs:
   a. Read/parse drivers.ini
   b. If offsets missing → scan ntoskrnl.exe
   c. If HVCI enabled → patch SYSTEM hive → reboot (one additional reboot)
   d. Extract bypass driver from IDR_DRV → Sam.evtx
   e. Load bypass driver → patch SeCiCallbacks+0x20
   f. Load unsigned target driver
   g. Restore SeCiCallbacks → unload bypass driver → delete Sam.evtx
4. Windows continues booting  → target driver running
5. Verify: sc query <ServiceName>   → STATE: 4 RUNNING

Responsible Use

This tool is intended exclusively for authorized security research, driver development, and educational purposes in controlled environments. Use only on systems you own or have explicit written permission to test.


© 2026 Marek Wesołowski (WESMAR)

About

Advanced native-mode utility for bypassing DSE and HVCI. Implements smart SeCiCallbacks patching and independent management of Memory Integrity settings. Operating as a subsystem:native app, it ensures early-phase control and environment preparation for security research and driver development.

Topics

Resources

License

Stars

Watchers

Forks

Packages