Kernel hardware access driver system based on signature-verified script virtual machine
By using a signature verification script virtual machine's kernel hardware access driver system, the driver functionality is moved from the executable binary image to the signed script bytecode. This solves the problems of rapid iteration and dynamic access to ARM64 registers in Windows kernel hardware access drivers under code integrity mechanisms, enabling rapid response to feature iterations and dynamic access to ARM64 registers, and resisting timing side-channel attacks.
Patent Information
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- JIANGXIA INFORMATION TECH (HUIZHOU) CO LTD
- Filing Date
- 2026-04-17
- Publication Date
- 2026-07-10
AI Technical Summary
Existing Windows kernel hardware access driver solutions cannot achieve rapid iteration of driver functions, resistance to timing side channels during bytecode loading, and runtime dynamic access to arbitrary system registers under the hypervisor-protected code integrity mechanism.
A kernel hardware access driver system based on a signature-verified script virtual machine is adopted. The driver function carrier is moved from the executable binary image to the signed script bytecode. The dynamic assets of the ARM64 arbitrary system register access path and the C-to-script bidirectional callback path are moved forward to the compile-time constant expansion. The kernel hardware access driver system based on the signature-verified script virtual machine includes a driver framework module, a script virtual machine module, a hardware access primitive module, and a bytecode integrity verification module, which realizes read-only and write operations on the underlying hardware resources.
It enables the addition, deletion, and replacement of feature sets without unloading the driver image, shortens the feature iteration latency from minutes to minutes, resists timing side-channel attacks, enables runtime dynamic access to arbitrary ARM64 system registers, and provides near-infinite scalability.
Smart Images

Figure REF-OBJ-1776411861680-000052 
Figure REF-OBJ-1776411861680-000053 
Figure REF-OBJ-1776411861680-000054
Abstract
Description
Technical Field
[0001] This invention relates to the field of Windows kernel driver technology, and more specifically to a low-level hardware resource access driver system deployed in the operating system kernel space, based on a signature verification script virtual machine architecture. Background Technology
[0002] With the increasing demand for computer hardware monitoring, firmware debugging, and low-level system analysis, software developers, hardware manufacturers, and system security researchers are increasingly needing to read and write to low-level hardware resources at the Windows operating system kernel level. These resources include physical memory, virtual memory, model-specific registers, peripheral interconnect standard configuration space, input / output ports, control registers, debug registers, and processor identification information. To meet these needs, general-purpose kernel hardware access driver tools such as WinRing0 and RWEverything have emerged. These tools provide a fixed set of input / output control interfaces to the outside world through a signed kernel driver binary image for user-mode applications to call. However, with Windows 11's mandatory implementation of hypervisor-based code integrity mechanisms and the increasingly stringent certification requirements of Microsoft Hardware Quality Labs, existing solutions are revealing increasingly significant structural bottlenecks in terms of functional scalability, runtime security, and cross-instruction set architecture adaptability.
[0003] US Patent Application No. US6092147A discloses a virtual machine system entitled "Virtual Machine with Securely Distributed Bytecode Verification." This system employs a remote computing device that generates bytecode and transmits it to the virtual machine via a network channel. Before executing the bytecode, the virtual machine uses a predetermined cryptographic algorithm (including one-way hashing, message authentication codes based on block ciphers, or digital signatures based on asymmetric algorithms) to calculate an authentication certificate for the received bytecode. This certificate is then compared with the authentication certificate attached by the bytecode generator. Only after a successful comparison is the virtual machine allowed to interpret and execute the corresponding bytecode. While this scheme introduces a cryptographic signature verification mechanism into the loading stage of a bytecode virtual machine for the first time, the envisioned virtual machine is always deployed in user mode or a restricted execution environment such as a smart card. Its entire authentication and execution loop does not touch the hardware resource access path of the operating system kernel mode, nor does it address the adaptation to the non-writable and executable memory protection constraints enforced by the hypervisor-based code integrity mechanism. Therefore, it cannot be directly used in application scenarios that require access to arbitrary hardware registers in kernel mode.
[0004] US Patent Application Publication No. US20160043869A1 discloses a system entitled Secure remote kernel module signing. This scheme is based on the Unified Extensible Firmware Interface Secure Boot Framework, which uses the machine owner key to remotely sign the binary image of the entire kernel module or kernel driver, and verifies the signature when the operating system loads the kernel module. The kernel module is only allowed to be loaded into the kernel address space for execution if the signature is valid. The claims of this scheme also include the case where the script is compiled into a kernel module or kernel driver within the scope of protection. However, the security granularity of this scheme remains at the level of the entire kernel image. Whenever any functional modification or extension to the kernel-mode functionality is required, it must go through the complete compilation, signing, hardware quality laboratory certification, and distribution process again, which usually takes several weeks or even months. This cannot support hardware monitoring scenarios with rapid iteration. More importantly, on Windows devices targeting the ARM64 architecture, any runtime scheme that requires dynamically specifying the target system register cannot be accommodated by the aforementioned whole-machine signing framework because the ARM64 system register read and write instructions require the target register encoding to be hard-coded in the instruction word in the form of immediate values, and the code integrity mechanism protected by the hypervisor prohibits all runtime code generation and code modification.
[0005] In summary, existing kernel hardware access driver solutions, under the constraints of being writable and executable due to the code integrity mechanism protected by the hypervisor, cannot simultaneously support rapid iteration of driver function sets, resistance to timing-side channels during bytecode loading, and runtime dynamic access to arbitrary system registers under the ARM64 architecture. The fundamental reason is that existing technologies always equate dynamic behavior with runtime dynamic code generation or modification, without realizing that such dynamic behavior can be completely eliminated by moving it forward as a whole through a path that combines compile-time static assets with load-time signature verification. This is precisely the core technical problem that this invention aims to solve. Summary of the Invention
[0006] To address the core bottleneck in existing technologies where Windows kernel hardware access drivers cannot simultaneously achieve rapid driver function iteration, bytecode loading resistance to timing side-channeling, and runtime dynamic access to arbitrary system registers in the ARM64 architecture due to the mandatory non-writable and executable memory protection constraints imposed by the hypervisor-based code integrity mechanism, this invention provides a kernel hardware access driver system based on a signature-verified script virtual machine. By sinking the driver function carrier from the executable binary image to the signed script bytecode and moving all dynamic assets required for the ARM64 arbitrary system register access path and the C-to-script bidirectional callback path forward to compile-time constant expansion, this system achieves compliant and unified support for the three types of dynamic behaviors at the principle level of memory protection mechanisms and instruction set encoding bit fields, without performing any write operations on its own executable section at any runtime after the driver system image is loaded.
[0007] The technical solution of this invention is as follows: a kernel hardware access driver system based on a signature verification script virtual machine, comprising a driver framework module deployed in the operating system kernel mode, a script virtual machine module embedded within the driver framework module, a hardware access primitive module registered to the script virtual machine module, and a bytecode integrity verification module that runs through the first three. The driver framework module receives bytecode with a signature header submitted by the user mode via an input / output control channel and transfers the received bytecode to the bytecode integrity verification module. The bytecode integrity verification module recalculates the message authentication code on the bytecode data using an embedded key, and performs a byte-by-byte constant-duration comparison between the calculated message authentication code and the signature field attached to the bytecode header. The bytecode is allowed to be loaded by the script virtual machine module only when the comparison result indicates that all bytes are equal. The script virtual machine module concurrently executes the allowed bytecode using an instance-independent mutex lock approach, and performs read-only and write operations on the underlying hardware resources through the hardware access primitive module. The hardware access primitive module contains a set of assets generated during compilation and placed in the read-only executable section of the driver system image. The assets include a first stub array and a second stub array for the ARM64 architecture, as well as a callback slot array consisting of a set of fixed-address C function symbols generated by expanding the index sequence template. The assets are directly indexed and called at runtime via instruction encoding bit field offset or slot subscript.
[0008] The beneficial effects of this invention are as follows. First, the driver system of this invention can complete the addition, deletion, and replacement of the function set without unloading the driver image itself. The mechanism is that the combined features of the signature bytecode, virtual machine multi-instance context, and input / output control channel loading interface described in claims 1 and 2 sink the business function carrier from the compiled driver binary image to the user-space script bytecode that can be independently signed and distributed. Compared with the whole-machine signature scheme disclosed in the prior art US20160043869A1, which forces every function fine-tuning into the complete cycle of hardware quality laboratory certification, this invention compresses the end-to-end latency of function iteration from a unit of measurement in weeks to a unit of measurement in minutes. Second, the bytecode loading stage of this invention has a natural resistance to timing side-channel attacks. The mechanism is that the constant duration comparison feature of XOR accumulation and traversal number independent of intermediate comparison results described in claim 3 eliminates the impact of signature verification from the time dimension of the execution path. Regarding any observable correlation between latency and signature content, compared to the scheme disclosed in prior art US6092147A, which calls general signature verification before bytecode execution but does not constrain the timing behavior of the verification path, this invention, while maintaining the same cryptographic strength, additionally blocks the timing side channel—a aspect completely ignored by the aforementioned prior art; third, this invention, for the first time, achieves runtime dynamic access to arbitrary ARM64 system registers under the condition of complying with the non-writable and executable memory protection constraints. Its mechanism lies in: the two-level cooperative feature described in claims 4 and 5—compilation-time full coverage expansion of the system register encoding bit fields into a stub array and runtime direct array indexing using a bit field right-shift mask—reverses the hard constraint that the ARM64 instruction set must embed the target register encoding in immediate form into the instruction word, transforming it into a natural continuous index space. Compared to existing approaches based on runtime dynamic code generation or lookup table backfilling in Windows... 11. Given the current situation where all code integrity mechanisms protected by the hypervisor fail, this invention fills the technical gap in dynamic access to arbitrary system registers under the ARM64 Windows kernel mode; Fourth, the three types of features described in this invention work together to produce a system-level effect that significantly exceeds the simple superposition of the individual contributions of each feature. The mechanism is as follows: the bytecode hot replacement feature allows the dynamic instruction construction logic carried by the hardware access primitive module to continuously evolve through the user-mode signature script, while the compile-time stub array and the compile-time callback slot array, in turn, provide a runtime call base for bytecode hot replacement that is completely transparent to the underlying hardware resources and fully compliant with the memory protection mechanism. The three support each other to form a closed-loop collaboration, enabling the entire driver system to obtain a near-infinite scalability space after a single hardware quality laboratory certification. Attached Figure Description
[0009] Figure 1This is an overall architecture diagram of the kernel hardware access driver system based on the signature verification script virtual machine of this invention; Figure 2 This is a detailed structural diagram of the driving framework module 1 described in this invention; Figure 3 This is a detailed structural diagram of the bytecode integrity verification module 2 described in this invention; Figure 4 This is a detailed structural diagram of the script virtual machine module 3 described in this invention; Figure 5 This is a schematic diagram of the compile-time stub array generation and runtime indexing principle of the ARM64 submodule in the hardware access primitive module 4 of the present invention; Figure 6 This is a schematic diagram of the compile-time slot expansion and atomic binding principle of the bidirectional callback submodule in the hardware access primitive module 4 of the present invention. Detailed Implementation
[0010] The specific embodiments of the present invention will be described in further detail below with reference to the accompanying drawings. It should be understood that the embodiments described below are for illustration and explanation only and are not intended to limit the present invention.
[0011] Reference Figure 1 This embodiment provides a kernel hardware access driver system based on a signature verification script virtual machine. This driver system is deployed in the kernel address space of the Windows operating system as a single driver image file. Externally, it carries all low-level hardware resource access capabilities; internally, it uses script bytecode as the business logic unit to complete functional expression. Structurally, the driver system consists of four mutually coupled core modules: driver framework module 1, bytecode integrity verification module 2, script virtual machine module 3, and hardware access primitive module 4. These four modules form a top-down, three-layer closed-loop pipeline: Driver Framework Module 1 is located at the top layer, responsible for input / output control communication with user-mode applications and handling device object registration and lifecycle management; Bytecode Integrity Verification Module 2 is inserted between Driver Framework Module 1 and Script Virtual Machine Module 3, acting as the sole security gatekeeper for bytecode entering kernel mode; Script Virtual Machine Module 3 is located in the middle layer of the driver system, carrying one or more concurrently executing bytecode execution contexts, responsible for interpreting and executing verified script bytecode and calling hardware access primitives as needed; Hardware Access Primitive Module 4 is located at the bottom layer, directly interacting with hardware resources such as the central processing unit, physical memory, peripheral interconnect standard devices, and input / output ports, and exposing all its capabilities to Script Virtual Machine Module 3 through a fixed function registry.
[0012] In this embodiment, the entire driver system image is organized in a portable executable format. During compilation, two binary images—one for the x86-64 architecture and one for the ARM64 architecture—are generated based on the same set of source code using predefined architecture macros. Both images share all the code of the driver framework module 1, bytecode integrity verification module 2, and script virtual machine module 3. Conditional compilation is performed only in the hardware access primitive module 4 according to the architecture macros to enable either the x86-64 or ARM64 submodule, respectively. After compilation and certification by the hardware quality laboratory, the driver system image remains unchanged throughout its deployment lifecycle. All subsequent feature extensions, parameter adjustments, and algorithm upgrades are completed through hot-swapping of the signed script bytecode.
[0013] Regarding input / output control channel planning, the driver framework module 1 in this embodiment exposes four input / output control codes, used for health checks, bytecode loading, bytecode function execution, and driver version query, respectively. All input / output control codes use the METHOD_BUFFERED method to pass the user-mode buffer, ensuring that the data exchange path from user mode to kernel mode remains compliant with security checks covered by the hardware quality laboratory test. The health check input / output control code is designed to pass the smoke test of the hardware quality laboratory toolkit, used for a quick self-check of the driver loading status on the target host before large-scale deployment; the bytecode loading input / output control code is used to trigger the signature verification process of the bytecode integrity verification module 2 and, after successful verification, transfers the bytecode to the script virtual machine module 3; the bytecode function execution input / output control code is used to request the script virtual machine module 3 to call a named script function in a specified virtual machine context; and the driver version query input / output control code is used to return the version identifier of the current driver system image to user mode.
[0014] In terms of runtime data flow throughout the driver system, a typical end-to-end request is organized as follows: The user-space application constructs a bytecode buffer carrying a signature header and initiates a request by loading input / output control codes via the DeviceIoControl interface; Driver framework module 1 extracts the user-space buffer pointer and length from the input / output request packet, performs basic lower bound checks, and then transfers the buffer to bytecode integrity verification module 2; Bytecode integrity verification module 2 parses the signature field at the beginning of the buffer, calls the embedded message authentication code calculation routine to recalculate the message authentication code on the bytecode data at the end of the buffer, and performs a constant duration... The byte-by-byte comparison is performed. If the comparison passes, a new virtual machine context is requested from the script virtual machine module 3, and the bytecode data is written into the code segment of that context. When a subsequent bytecode function execution request arrives, the script virtual machine module 3 uses its internal fast mutex to lock the context, and then interprets and executes the requested script function. During the execution of the script function, if a call to a hardware access primitive is encountered, the corresponding primitive function is found through the registry and execution is jumped to. After the hardware access primitive is executed, its return value is passed back layer by layer to the script function, the script virtual machine module 3, and the driver framework module 1, and finally returned to the user-space application through the same input / output request packet.
[0015] Reference Figure 2 In this embodiment, the driver framework module 1 is implemented based on the Windows driver model. During the initialization phase, it simultaneously registers a plug-and-play functional device object and an independent control device object to balance the requirements of Windows hardware quality laboratory testing for plug-and-play topology and the demands of utility applications for stable control interfaces. The plug-and-play functional device object completes standard start, stop, and deletion processes upon receiving the corresponding plug-and-play request packet. The control device object, as the primary business carrier, resides throughout the entire loading cycle of the driver system image. Both types of device objects share the same set of input / output control distribution routines to ensure consistent processing results regardless of which device path the user initiates the request through.
[0016] Considering the varying availability of secure device creation interfaces across different Windows versions, driver framework module 1 in this embodiment dynamically obtains the address of the secure device creation function during the initialization phase using a kernel-mode symbol lookup interface. Based on the obtained address, it selects the device creation path: when the secure device creation function exists in the target system, driver framework module 1 calls the function to explicitly limit access permissions to the controlled device object using a security descriptor; when the secure device creation function does not exist in the target system, driver framework module 1 automatically falls back to the normal device creation interface to maintain backward compatibility. This dynamic acquisition and fallback mechanism uses a function pointer wrapper to shield external call points from underlying differences, eliminating the need for the upper-layer business code of driver framework module 1 to maintain branch logic for different Windows versions.
[0017] The input / output control dispatch routine of driver framework module 1 adopts a jump dispatch structure based on control code values. For each arriving input / output request packet, the following processing is performed sequentially: extract the input / output control code and its corresponding user-mode input and output buffers from the input / output request packet; find the corresponding processing routine based on the input / output control code; call the processing routine and pass the user-mode buffer pointer, input buffer length, and output buffer length as parameters; after the processing routine is executed, fill its return status code into the status field of the input / output request packet and finally complete the input / output request packet. Before calling the processing routine, driver framework module 1 performs strict lower bound checks on the input buffer length and output buffer length. Any request whose length is insufficient to support subsequent field parsing will be rejected in advance with the status code STATUS_BUFFER_TOO_SMALL to prevent subsequent processing routines from accessing out-of-bounds memory without verification.
[0018] Regarding the numerical layout of the input / output control codes, this embodiment assigns a unique device type number to the entire driver system and constructs four distinct input / output control codes based on this device type number. The device type number is 41394, and the function numbers of the four input / output control codes are 0x811, 0x821, 0x841, and 0x861, respectively, used for health checks, bytecode loading, bytecode function execution, and driver version lookup. All four input / output control codes are configured with a METHOD_BUFFERED pass mode and either read-only or read-write access permissions, enabling the Windows kernel to automatically copy the buffer from user mode to kernel mode for the driver system, avoiding the access violation risks caused by kernel mode code directly manipulating user mode virtual addresses.
[0019] The driver framework module 1 also assumes the static responsibility of holding a set of fixed-address C function symbols required by the bidirectional callback submodule described in this invention. The callback slot array, as an asset in the read-only executable section of the driver system image, is generated recursively by expanding a C++ index sequence template in the translation unit of the driver framework module 1. After the driver system image is loaded, it resides in memory at a fixed relative virtual address and does not undergo any location changes.
[0020] Reference Figure 3 In this embodiment, the bytecode integrity verification module 2 acts as the security gatekeeper for the entire driver system. Any bytecode entering the kernel mode from user mode must undergo signature verification by this module before being allowed to enter the execution path of the script virtual machine module 3. The bytecode integrity verification module 2 exposes a unified loading verification entry point. This entry point receives the bytecode buffer pointer and length transferred by the driver framework module 1. Internally, it sequentially completes three stages: header parsing, message authentication code recalculation, and constant duration comparison. If any stage fails, it immediately returns control to the driver framework module 1 with the corresponding status code.
[0021] During the header parsing phase, the bytecode integrity verification module 2 assumes that the first four bytes of the input buffer are the signature length field encoded in little-endian byte order, followed by a fixed-length byte field as the signature data field, and the remaining bytes are the bytecode data to be verified. In this embodiment, the message authentication code algorithm is selected as a hash message authentication code based on SHA-256, thus fixing the length of the signature data field to 32 bytes, and correspondingly setting the lower bound of the input buffer length to 36 bytes. Any input request shorter than 36 bytes will directly return the status code STATUS_BUFFER_TOO_SMALL. After the length verification passes, the bytecode integrity verification module 2 parses the signature data start pointer and bytecode data start pointer according to the above format, and passes them along with the bytecode data length to the message authentication code recalculation phase.
[0022] During the message authentication code recalculation phase, bytecode integrity verification module 2 obtains an algorithm handle identifying the SHA-256-based hash message authentication code algorithm through the encryption algorithm interface of the encryption service provider exported by the Windows kernel. Then, using the key byte array fixed in the driver system image as the key, it calls the hash object creation interface to obtain a hash object handle. Next, it calls the hash update interface to feed bytecode data into the hash object. Finally, it calls the hash completion interface to retrieve the 32-byte locally calculated message authentication code from the hash object. The return status of all the above calls is checked one by one; any failure will cause bytecode integrity verification module 2 to immediately release the allocated resources and return the original error status code.
[0023] During the constant-duration comparison phase, bytecode integrity verification module 2 compares the locally calculated message authentication code with the signature data field obtained from the header parsing phase byte by byte. To fundamentally eliminate the timing-side channel exposed by traditional library functions returning immediately at the first unequal byte, this embodiment employs a cumulative XOR constant-duration comparison mechanism, the core calculation of which is expressed as follows: , in: The accumulated difference value is a scalar unsigned 8-bit integer, ranging from 0 to 255, calculated by this formula. It characterizes whether there is a difference in any byte bits between the locally calculated message authentication code and the signature field provided by the user space, if and only if... When taking a zero value, it is assumed that the two are completely equal byte by byte and the corresponding bytecode is allowed to pass; The message authentication code is a fixed-length scalar positive integer with a value of [value missing]. The unit is bytes, which is determined by the SHA-256-based hash message authentication code algorithm specification; This is a byte traversal index variable, a scalar non-negative integer, with a value range of 1. to The closed interval is , dimensionless, generated by the incrementing of the cyclic counter; For the locally calculated message authentication code One byte, a scalar unsigned 8-bit integer, with a value range of 0 to 255, in bytes, is retrieved from the hash object by the hash completion interface; The first signature field provided for user space One byte, a scalar unsigned 8-bit integer, with a value range of 0 to 255, in bytes, extracted from the input buffer during the header parsing stage; This is the bitwise XOR operator. The semantics of this operator are to perform a bitwise XOR operation on two unsigned integers of the same length. A zero bit in the result indicates that the two operands are equal at that bit, and a one bit in the result indicates that the two operands are not equal at that bit. The bitwise OR accumulator operator is semantically equivalent to performing a bitwise OR operation on a single-byte accumulator initialized to zero with each subsequent operand, and the final accumulator value retains information from any non-zero bit in all operands.
[0024] The calculation process specified by the above formula is implemented in the form of a fixed number of loops, the number of loops being strictly equal to... Furthermore, independent of any intermediate comparison results, the loop will not exit prematurely even if a difference is detected in the first byte, but will continue to complete the entire loop. The decision to allow or reject a request is made only after the XOR and bitwise OR accumulation operations are performed, based on the final value of the accumulator. The criterion is: if... If the value equals zero, a status code STATUS_SUCCESS is returned to the driver framework module 1, and the bytecode integrity verification module 2 further drives the bytecode loading process of the script virtual machine module 3; if... If the value is not equal to zero, return the status code STATUS_INVALID_SIGNATURE to the driver framework module 1 and immediately terminate the current loading request.
[0025] With the constant-duration comparison mechanism described above, there is no longer an observable correlation between the response latency distribution of the bytecode integrity verification module 2 for any input signature and the actual content of the signature. Even if an attacker can measure the response latency of the bytecode loading input / output control codes with microsecond or even nanosecond precision, they will not be able to deduce the embedded key or any byte of the correct signature from it. In this embodiment, the embedded key is placed in the read-only data section of the driver system image in the form of a 32-byte read-only array. When the key is rotated, only this array needs to be updated and all script bytecode distributed with the driver needs to be re-signed; the signature of the driver system image itself is not affected.
[0026] Reference Figure 4 In this embodiment, the script virtual machine module 3 is a 64-bit bytecode virtual machine deployed in kernel mode, employing the Harvard architecture memory model. Its data segment and code segment are isolated from each other and addressed independently. The script virtual machine module 3 allocates an independent virtual machine context in the kernel's non-paged pool for each bytecode that passes the bytecode integrity verification module 2, in a runtime routine manner. The virtual machine context includes a bytecode loader instance, a private copy of the bytecode data, a set of native function registry handles, and a fast mutex. The bytecode loader instance is responsible for parsing the bytecode data into contiguous code segments and page-organized data segments and establishing a symbol table internally. The native function registry handles are injected item by item during the bytecode loading phase, used to resolve symbolic references to hardware access primitives in the bytecode to the entry addresses of the corresponding primitives in the hardware access primitive module 4 at runtime. The fast mutex is used to ensure the integrity of its internal state when multiple threads concurrently access the same virtual machine context.
[0027] The script virtual machine module 3 in this embodiment supports multi-instance concurrency, meaning that multiple independent virtual machine contexts can exist simultaneously within the same driver system instance. Each virtual machine context has its own independent code segment, data segment, native function registry, and fast mutex lock. This multi-instance concurrency capability allows user-mode applications to load multiple script bytecodes with different functions sequentially within the same driver session. For example, one bytecode focuses on physical memory reading, another on model-specific register polling, and yet another on peripheral interconnect standard bus enumeration. These three virtual machine contexts are completely decoupled in their lifecycles; the loading, execution, error handling, and destruction of any one context will not affect the others.
[0028] When the bytecode function execution input / output control codes arrive, the script virtual machine module 3 locates the target virtual machine context during the context lookup phase based on the handle field attached to the user-mode request. It then performs a locking operation on the fast mutex lock of that context to prevent concurrent execution conflicts. After successful locking, it searches for the script function symbol to be executed in the Native function registry according to the request field and enters the execution loop of that function through the bytecode interpreter's call interface. During execution, the bytecode interpreter fetches, decodes, and dispatches instructions to the corresponding processing logic one by one according to the predefined bytecode instruction set. Execution may be interrupted due to the script function actively calling hardware access primitives, triggering out-of-bounds access, integer division by zero, or triggering other runtime exceptions. For hardware access primitive calls, the bytecode interpreter pushes the call parameters onto the Native call stack according to the convention and jumps to the corresponding entry point of the hardware access primitive module 4. For runtime exceptions, the bytecode interpreter captures the exception status through a pre-set structured exception handler and fills the return value field of this request in the form of an error code. After execution, the script virtual machine module 3 performs an unlocking operation on the fast mutex and sends the result back to the user space via the driver framework module 1.
[0029] When the virtual machine destruction interface exposed by the script virtual machine module 3 is called, it first removes the target virtual machine context from the context table, then sequentially releases the bytecode data copy it holds, the native function registry, and the kernel non-paged pool occupied by the code segment and data segment, and finally returns the memory occupied by the virtual machine context itself. The destruction interface checks whether the current context is still held by another thread for each release operation; if so, the memory return is only completed after the last holder leaves. This design allows the driver system to safely add, delete, or replace loaded script bytecode at any time without causing memory release contention.
[0030] In this embodiment, the x86-64 submodule of the hardware access primitive module 4 is enabled when the compile-time architecture macro is x86-64. It registers more than 60 hardware access primitives with the Native function registry of the script virtual machine module 3. These primitives cover reading and writing of 1-byte, 2-byte, 4-byte, and 8-byte physical memory, atomic compare-and-swap operations of virtual memory, reading and writing of model-specific registers, reading and writing of peripheral interconnect standard configuration space, input and output of input / output ports, reading and writing of control registers, debug registers, and extended control registers, processor identifier lookup, timestamp counter reading, fast transition back buffer invalidation, performance counter reading, and hardware random number generation, etc.
[0031] Most of the primitives mentioned above can be implemented directly using privileged instructions provided by the CPU under the x86-64 architecture. For example, regarding model-specific register access, the RDMSR and WRMSR instructions in the x86-64 instruction set allow the target register number to be dynamically passed through the general-purpose register ECX. Therefore, a specific model-specific register read / write operation can be completed using a simple parameterized function. For physical memory access, the x86-64 submodule first maps the target physical address to a kernel virtual address using the memory mapping interface exported by the Windows kernel. Then, it executes ordinary memory read / write instructions on that virtual address and unmaps it after the operation is complete. For input / output port access, the x86-64 submodule directly uses the IN and OUT instructions, which can be executed without privilege traps in kernel mode. For processor ID lookup, the x86-64 submodule obtains the register value under the corresponding function number using the CPUID instruction and returns it in a structured manner.
[0032] Since the aforementioned primitives are not directly accessible to user space, all their call paths are indirectly exposed to the script bytecode through the Native function registry of the script virtual machine module 3. When the script bytecode needs to access a specific hardware resource, it only needs to call the corresponding Native symbol in its own code. The script virtual machine module 3 will automatically map the call to the primitive entry point in the x86-64 submodule and complete the parameter passing and return value writing.
[0033] Reference Figure 5 In this embodiment, the ARM64 submodule of the hardware access primitive module 4 is enabled when the compile-time architecture macro is set to ARM64. It undertakes the hardware access capabilities equivalent to the x86-64 submodule under the ARM64 architecture, and provides a compliant dynamic access solution specifically for the immediate value encoding constraints of ARM64 system register read and write instructions and the non-writable and executable memory protection constraints enforced by the code integrity mechanism based on the hypervisor protection of Windows 11.
[0034] The system register read and write instructions in the ARM64 instruction set have a significant unique coding structure: of the 32-bit instruction word, bits 5 to 19 (a total of 15 bits) are used to hard-code the target system register number in immediate value form, while the remaining bits are fixed values after the instruction type is given. This coding feature means that for any specific system register, the corresponding read / write instruction must be determined at compile time and cannot be parameterized at runtime by passing the register number in a general-purpose register. On systems without hypervisor-based code integrity protection, one possible workaround is to dynamically generate an instruction sequence containing the target system register number at runtime and write it to a writable and executable memory page, then jump to that page for execution; however, once this mechanism is enabled, all write operations to executable memory pages will be blocked, and the above workaround immediately becomes invalid. Another possible workaround is to modify an existing instruction sequence at runtime to replace the immediate value field; however, this also constitutes a write operation to executable memory pages, which is also not allowed under the aforementioned mechanism.
[0035] To address the aforementioned challenges, the ARM64 submodule in this embodiment proposes a stub array scheme based on C++20 compile-time constant expression functions. This scheme performs a full enumeration of the 15-bit encoded bit fields in system register read and write instructions during compile time. For each valid 15-bit encoded value, an 8-byte stub is generated: the first 4 bytes of the stub represent the corresponding system register read or write instruction, with its destination register number field being exactly the 15-bit encoded value; the last 4 bytes represent the ARM64 return instruction. These stubs are arranged in ascending order of their 15-bit encoded values into a continuous array, with the index of each stub in the array exactly equal to its corresponding system register encoded value. The array corresponding to system register read instructions is named the first stub array, and the array corresponding to system register write instructions is named the second stub array; both arrays have a length of 32768.
[0036] The compile-time generation of the two stub arrays is expressed using the following operations: , , in: The first stub array is the first Each element is a scalar unsigned 64-bit integer, with a value range of 0 to 1. The formula is calculated at compile time, and its lower 32 bits represent a complete ARM64 system register read instruction and its higher 32 bits represent a complete ARM64 return instruction. For the second stub array Each element, and Having the same type and value range, it is calculated by this formula at compile time. Its lower 32 bits represent a complete ARM64 system register write instruction, and its higher 32 bits represent a complete ARM64 return instruction. This is the index of the stub in the array, and also the 15-bit value of the corresponding system register encoding field. It is a non-negative scalar integer with a value range of [value missing]. to The closed interval is , dimensionless, generated by the iteration variables of the loop during compile-time expansion; The opcode base value for the ARM64 system register read instruction, a scalar unsigned 32-bit integer, with the following values: Dimensionless, determined by the system register read instruction encoding as defined in the ARM64 instruction set architecture specification; The opcode base value of the instruction to write to the ARM64 system register is a scalar unsigned 32-bit integer, and its value is... Dimensionless, determined by the system register write instruction encoding as defined in the ARM64 instruction set architecture specification; For ARM64 return instructions, the complete 32-bit encoding is provided; the scalar unsigned 32-bit integer has the following value: Dimensionless, determined by the return instruction encoding as defined in the ARM64 instruction set architecture specification; This is the bitwise OR operator, which performs a logical OR operation on two unsigned integers of the same length. This is a left shift operator, where the left operand is the unsigned integer to be shifted, and the right operand is the non-negative number of bits to shift.
[0037] After being generated during compilation, the two stub arrays are placed in a read-only executable section of the driver system image via preprocessing instructions. The memory protection attributes of this section are set to read-only and executable, and it does not have a writable attribute. After the driver system image is loaded, the two arrays reside in memory with these attributes, and are legally and continuously available for jump calls under the code integrity mechanism protected by the hypervisor, while no runtime write operations are allowed to occur on them.
[0038] The ARM64 submodule of hardware access primitive module 4 registers two key primitives with the Native function registry of script virtual machine module 3: an arbitrary ARM64 system register read primitive and an arbitrary ARM64 system register write primitive. Both primitives take a complete 32-bit ARM64 instruction word as their sole input parameter, and their runtime call paths use the following index mapping: , in: The index of the target stub in the first or second stub array is a non-negative integer scalar with a value range of 1. to The closed interval is calculated by this formula at runtime and is directly used as the array index of one of the two stub arrays to obtain the entry address of the corresponding stub function; This is a complete 32-bit ARM64 system register read or write instruction word passed by the user-mode script through the Native call interface. It is a scalar unsigned 32-bit integer with a value range of [value range missing]. to , dimensionless, constructed from script bytecode; This is a right shift operator, where the left operand is the unsigned integer to be shifted, and the right operand is the non-negative number of bits to shift. This is the bitwise AND operator; It is a bitmask constant, and its value is equal to This is used to retain only the lower 15 bits after a right shift to precisely align the value space of the system register's encoded bit field.
[0039] Obtain Subsequently, the ARM64 submodule of hardware access primitive module 4 uses this address as an array index to read the entry address of the corresponding stub from either the first or second stub array, and uses this address as the indirect jump target to complete a function call. For the system register read primitive, this function call has no parameters and returns an unsigned integer result, which is the current value of the target system register. For the system register write primitive, this function call takes the value to be written as the only parameter and has no return value. After the call is completed, the content of the target system register is updated to the parameter value. To prevent the Windows kernel's control flow protection mechanism from identifying the above indirect jumps to stub functions as illegal indirect call targets, the function declarations of both primitives are marked with an attribute that informs the control flow protection mechanism that such indirect calls are allowed, thus remaining usable even on systems with strict control flow protection enabled.
[0040] Based on the aforementioned two-level collaborative mechanism, the user-mode bytecode loaded by script virtual machine module 3 can construct any valid ARM64 system register read or write instruction word within the script function and pass it as a parameter to the two primitives mentioned above, thereby enabling runtime read and write operations on any ARM64 system register. Throughout the entire read and write process, the executable section of the driver system image itself does not undergo any write operations, fully complying with the writable and executable memory protection constraints.
[0041] Reference Figure 6The hardware access primitive module 4 described in this embodiment also includes a bidirectional callback submodule. This submodule is used to establish a call channel between the external C code and the bytecode loaded in the script virtual machine module 3, which can be triggered by the C code in reverse. The channel enables the driver system to not only accept script execution under user-mode requests, but also to respond to events generated by other execution paths in the kernel and synchronously execute a predefined script function when the event arrives.
[0042] The bidirectional callback submodule embeds a callback slot array of length 256 within the driver framework module 1. Each slot in this array consists of two items: a virtual machine context pointer, used to mark the virtual machine context of the script bound to that slot; and a script function address, used to mark the entry offset of the script function bound to that slot in the bytecode segment. In conjunction with this, the bidirectional callback submodule recursively generates a set of 256 independent C function symbols within the same translation unit using C++ index sequence templates. Each C function symbol is assigned a corresponding slot index at compile time and accesses the callback slot array using that index in its function body. After compilation, this set of C function symbols resides at a fixed address in the read-only executable section of the driver system image; its address itself is also determined at compile time.
[0043] The core value of the above structure lies in the fact that when external C code needs to hold a script function as a callback target, it does not directly hold a piece of runtime-generated machine code, but holds the address of one of the above set of fixed C function symbols. Therefore, the driver system does not need to generate any new executable code at runtime to provide external code with the ability to call script functions in the form of ordinary function pointers. This capability is fully compliant under the code integrity mechanism based on hypervisor protection.
[0044] The bidirectional callback submodule exposes two native primitives: a callback allocation primitive and a callback release primitive. When the script bytecode needs to register one of its functions as a target for C code callbacks, it first calls the callback allocation primitive, passing the address of the script function to be registered as a parameter. The bidirectional callback submodule then scans the first free slot in the callback slot array and uses an atomic comparison-swap operation to attempt to update the script function address field of that slot from null to the requested script function address, while recording the current virtual machine context pointer. The use of atomic comparison-swap operations ensures that each slot is successfully bound by at most one thread in the case of concurrent calls to the callback allocation primitive. After successful binding, the callback allocation primitive returns the address of the C function symbol corresponding to that slot to the script bytecode. The script bytecode can then pass this address to external C code through other native primitives or by directly writing it into a kernel-mode memory structure. When the script bytecode no longer needs the callback binding, it calls the callback release primitive and passes the previously obtained C function symbol address as a parameter. The bidirectional callback submodule uses this to reverse locate the corresponding slot index and clear the slot, thereby allowing subsequent callback allocation primitives to reuse the slot.
[0045] When the symbolic address of a C function held by external C code is invoked, control is transferred to the compile-time expansion function corresponding to the slot. This expansion function accesses the corresponding slot within its function body and retrieves the bound virtual machine context pointer and script function address. It then locks the fast mutex of the virtual machine context, calls the function call interface of script virtual machine module 3 to execute the script function within that context, and unlocks the mutex after the script function finishes execution, returning the script function's return value as the C function's return value back to the external C code. Throughout this process, the external C code only sees a normal C function pointer call, while the script function receives the correct execution context and concurrency protection in the kernel-mode virtual machine. The bridge between the two is entirely handled by static assets determined at compile time, without undergoing any runtime code generation or runtime memory modification.
[0046] In summary, the kernel hardware access driver system based on the signature verification script virtual machine described in this invention, through deep coupling and closed-loop collaboration of the driver framework module 1, bytecode integrity verification module 2, script virtual machine module 3, and hardware access primitive module 4, fully supports three types of dynamic behaviors—rapid iteration of driver functions, anti-timing side-channel bytecode loading, and dynamic access to arbitrary system registers of ARM64—under the constraints of being unwritable and executable under the code integrity mechanism protected by the hypervisor. Simultaneously, it retains a unified input / output control interface and all formal compliance requirements of hardware quality laboratory certification, demonstrating broad prospects for industrial application.
[0047] The above description is merely a preferred embodiment of the present invention and is not intended to limit the invention. Various modifications and variations can be made to the invention by those skilled in the art. Any modifications, equivalent substitutions, and improvements made within the spirit and principles of the invention should be included within the scope of protection of the invention.
Claims
1. A kernel hardware access driver system based on a signature verification script virtual machine, characterized in that, The system includes a driver framework module deployed in the operating system kernel, a script virtual machine module embedded within the driver framework module, a hardware access primitive module registered with the script virtual machine module, and a bytecode integrity verification module that runs through the first three. The driver framework module receives bytecode with a signed header submitted by the user space via an IOCTL channel and forwards it to the bytecode integrity verification module. The bytecode integrity verification module performs a byte-by-byte constant-duration comparison between the signature field at the bytecode terminal and the message authentication code recalculated from the bytecode data using an embedded key. The bytecode is allowed to be loaded by the script virtual machine module only when the comparison result indicates that all bytes are equal. The script virtual machine module concurrently executes the allowed bytecode using an instance-independent mutex lock method and accesses the underlying hardware resources through the hardware access primitive module. The hardware access primitive module includes a set of assets generated and embedded in the read-only executable section of the driver system image during compilation. These assets are directly indexed and invoked at runtime through instruction encoding bit fields, so that the driver system image does not perform any write operations on its own executable section at any runtime after loading.
2. The kernel hardware access driver system based on a signature verification script virtual machine according to claim 1, characterized in that, The script virtual machine module is configured to accept sequential loading requests for multiple different script bytecodes from user space via the bytecode loading control code exposed by the driver framework module. Each script bytecode uses an independent message authentication code corresponding to its own data as a release credential. The script virtual machine module allocates an independent virtual machine context for each script bytecode released by the bytecode integrity verification module. The virtual machine context is dynamically allocated from the kernel non-paged pool and its lifecycle is terminated by an explicit release interface, enabling the driver system to complete the addition, deletion, and replacement of the function set without unloading the driver system image itself.
3. The kernel hardware access driver system based on a signature verification script virtual machine according to claim 2, characterized in that, The byte-by-byte constant duration comparison configuration in the bytecode integrity verification module is as follows: perform an XOR operation on each byte corresponding to the signature field and the recalculated message authentication code, and accumulate all XOR results bitwise into a single-byte accumulator. The number of times the operation is performed is equal to the fixed byte length of the message authentication code and is independent of any intermediate comparison results. After all bytes have been traversed, whether the value of the accumulator is zero is used as the sole criterion for allowing or rejecting the operation, thereby ensuring that the response delay distribution of the bytecode loading control code to any signature input is constant.
4. The kernel hardware access driver system based on a signature verification script virtual machine according to claim 3, characterized in that, When the hardware access primitive module is compiled for the ARM64 instruction set architecture, the assets embedded in the read-only executable section include a first stub array and a second stub array: each stub in the first stub array is composed of a system register read instruction from the target ARM64 system register to a general-purpose register and a return instruction concatenated in sequence; each stub in the second stub array is composed of a system register write instruction from a general-purpose register to the target ARM64 system register and a return instruction concatenated in sequence; the number of stubs in the first stub array and the second stub array is equal to the size of the value space of the system register encoding bit field in the system register read instruction and write instruction; both the first stub array and the second stub array are generated by expanding the value space during the compilation stage using a C++ compile-time constant expression function and are embedded in the read-only executable section; after the driver system image is loaded, it neither performs any write operations on the sections containing the two stub arrays nor generates any new executable code at runtime.
5. The kernel hardware access driver system based on a signature verification script virtual machine according to claim 4, characterized in that, The arbitrary ARM64 system register read primitive and arbitrary ARM64 system register write primitive registered by the hardware access primitive module to the script virtual machine module are each configured to receive a complete 32-bit ARM64 instruction word as input parameters, and use the offset obtained by fixed right shift and bitmasking operation of the system register encoded bit field in the instruction word as the index of the first stub array or the second stub array, and use the stub function address corresponding to the index as the indirect jump target to complete a function jump call. The indirect jump explicitly informs the operating system's control flow protection mechanism that the call is legitimate. The user-mode bytecode loaded by the script virtual machine module can thus achieve runtime read and write operations on any ARM64 system register by constructing and passing any valid ARM64 system register read or write instruction word. The driver system image does not participate in any write operations on its own executable section during the entire read and write process.
6. The kernel hardware access driver system based on a signature verification script virtual machine according to claim 5, characterized in that, The driving framework module also contains a callback slot array generated recursively by the C++ index sequence template during the compilation phase. Each slot in the callback slot array corresponds to an independent C function symbol whose address is determined during the compilation phase. When each C function symbol is called, a tuple consisting of a virtual machine context pointer and a script function address is retrieved from its corresponding slot, and the tuple is used to drive the script virtual machine module to lock and execute the script function. The hardware access primitive module registers a callback allocation primitive and a callback release primitive with the script virtual machine module. The callback allocation primitive binds an empty slot to the tuple through an atomic comparison swap operation and then returns the address of the C function symbol corresponding to the slot to the script virtual machine module. The address is held by the external C code as a normal C function pointer and is subsequently used to call back the script function in a normal function call manner. The driver system image does not generate any new C jump code during the entire binding and callback process.
7. The kernel hardware access driver system based on a signature verification script virtual machine according to claim 1, characterized in that, The driver framework module exposes at least four control codes through the IOCTL channel, which are used for health checks, bytecode loading, bytecode function execution, and driver version query, respectively. The health check control code is compatible with Windows Hardware Labs Toolkit testing. The bytecode loading control code and the bytecode function execution control code both pass the user-mode buffer in the METHOD_BUFFERED mode. When processing each control code request, the driver framework module performs a lower bound check on the length of the user-mode buffer before handing it over to the corresponding processing routine.
8. The kernel hardware access driver system based on a signature verification script virtual machine according to claim 1, characterized in that, The driver framework module is configured to register a plug-and-play functional device object and an independent control device object simultaneously. During the initialization phase, the driver framework module dynamically obtains the address of the secure device creation function exported by the operating system kernel. When the address is unavailable, it automatically falls back to call the ordinary device creation function to complete the creation of the control device object. The plug-and-play functional device object and the control device object share the same set of IOCTL control code distribution routines.
9. The kernel hardware access driver system based on a signature verification script virtual machine according to claim 1, characterized in that, The primitives registered by the hardware access primitive module to the script virtual machine module cover at least one of the following groups: one-byte, two-byte, four-byte, and eight-byte read / write of physical memory; atomic compare-and-swap operations of virtual memory; read and write of model-specific registers; read and write of peripheral interconnect standard configuration space; input and output of input / output ports; read and write of control registers, debug registers, and extended control registers; processor identifier lookup; fast transition back buffer invalidation; performance counter read; and hardware random number generation.
10. The kernel hardware access driver system based on a signature verification script virtual machine according to claim 1, characterized in that, The hardware access primitive module distinguishes between x86-64 architecture compilation paths and ARM64 architecture compilation paths based on compile-time architecture macros. In the x86-64 architecture compilation path, x86-64 architecture-specific primitives such as processor identifier query instructions, timestamp counter reading, control register and debug register operations, input / output port reading and writing, and local descriptor table and global descriptor table operations are retained. In the ARM64 architecture compilation path, the x86-64 architecture-specific primitives are automatically removed, and the compile-time stubs and compile-time callback slot assets as described in claims 4 to 6 are enabled, so that the source code of the driver system maintains a consistent external interface structure under both architectures.
Citation Information
Patent Citations
Secure remote kernel module signing
US20160043869A1
Virtual machine with securely distributed bytecode verification
US6092147A