Skip to content

Repository files navigation

mapped_explorer

Platform Driver Toolchain Status

An unfinished Windows kernel research prototype for identifying executable code present in physical memory but outside the address ranges of loaded kernel modules.

The experiment walks physical memory, looks for FF 25 indirect jumps, resolves their targets, and compares source and destination addresses with SystemModuleInformation. A source outside every known module that resolves into the kernel can be a useful triage lead for manually mapped code or another unusual executable allocation.

Warning

The detector path is disabled in the checked-in source. The current driver initializes its debugger logger and returns success. This repository documents an approach under investigation, not a working detector.

Contents

Research question

Windows reports loaded kernel images through SystemModuleInformation. The prototype asks whether physical-memory inspection can surface code that does not belong to one of those reported ranges but still transfers control into ntoskrnl.

Signal Prototype check Interpretation
Candidate source FF 25 bytes in a copied physical page Possible RIP-relative indirect jump
Resolved destination Address falls inside the first reported module Possible transfer into ntoskrnl
Source ownership Address falls outside every reported module Candidate unbacked or manually mapped code

This is a triage heuristic. Raw opcode matching is not instruction decoding, module membership does not prove page executability, and an address outside a loaded module is not automatically malicious.

Current behavior

Component Checked-in state Runtime effect
Kernel logger Active Writes a DriverEntry message to the kernel debugger
Module enumeration Commented out SystemModules remains null
Physical-range walk Implemented in MemoryScan() Not reached because the call is commented out
FF 25 candidate scan Commented out No instructions are classified
Result transport Not implemented No findings leave the driver
Unload and cancellation Not implemented The active entry path simply returns

Re-enabling only the inner scan is unsafe and incomplete. Detector::IsValidKernel() and Detector::IsValidAny() require a populated SystemModules buffer, and the physical-to-virtual assumptions need separate validation.

Detection model

The diagram below shows the intended experiment. Dashed nodes represent disabled or missing stages in the current source.

flowchart LR
    A[DriverEntry] --> B[Initialize debugger logger]
    B -. disabled .-> C[Query loaded kernel modules]
    C -. disabled .-> D[Walk physical memory ranges]
    D -. disabled .-> E[Copy one page at a time]
    E -. disabled .-> F[Find FF 25 byte pairs]
    F -. disabled .-> G[Resolve candidate target]
    G -. disabled .-> H{Target in kernel and source outside modules?}
    H -. yes .-> I[Record triage finding]
Loading

Several conditions can create findings that do not fit a simple loaded-module model, including firmware mappings, hypervisors, crash facilities, and security products. A future classifier should preserve enough context for an analyst to distinguish those cases.

Build

Requirements:

  • Windows 10 or newer development host
  • Visual Studio 2022 with Desktop development with C++
  • Windows Driver Kit
  • An x64 disposable virtual machine for any runtime experiment

Open mapped_explorer.sln, select Debug | x64 or Release | x64, and build. From a Visual Studio Developer PowerShell prompt, the equivalent command is:

msbuild .\mapped_explorer.sln /m /p:Configuration=Debug /p:Platform=x64

The project contains ARM64 configurations inherited from its template, but the implementation has only been considered as an x64 experiment. Do not treat ARM64 as a supported target.

Caution

Use a disposable VM with test signing and kernel debugging enabled. Physical-memory code running in kernel mode can crash or corrupt the guest. No driver binary or loading utility is included.

Observed output

With the checked-in path, WinDbg receives one line from DriverEntry:

[mapped_explorer][info][DriverEntry] DriverEntry called . . .

No scan result follows because module enumeration and MemoryScan() are disabled. Any output claiming detected addresses does not come from the repository in its current state.

Source map

entry.cpp       Driver entry point and disabled module-enumeration path
detector.cpp    Physical-range walk and disabled candidate scan
detector.hpp    Detector declarations and shared state
defs.hpp        Native structures and system-information declarations
utils.cpp       Physical-to-virtual and guarded copy helpers
klog.hpp        Kernel debugger logger

Research roadmap

A defensible next iteration should separate collection from classification:

  1. Bound and snapshot candidate physical ranges explicitly.
  2. Decode instructions instead of searching for two raw bytes.
  3. Isolate loaded-image enumeration behind a carefully validated compatibility layer.
  4. Record page protections and allocation ownership where Windows exposes them.
  5. Send structured findings to a user-mode viewer for filtering and export.
  6. Test classification against synthetic ranges before any kernel run.

Even with those stages in place, the output should remain an analyst triage signal rather than a verdict.

About

Research prototype for classifying executable code outside loaded Windows kernel modules

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages