5. Analysis of hypervisor crack bypass
Initial load (proxy DLL mechanism)
The bypass uses DLL proxying to inject code without needing any separate injector process, which is quite an elegant, fast and sure-shot approach. In the analyzed sample, the legitimate amd_ags_x64.dll (AMD GPU Services SDK DLL, 176 KB) that the game normally loads is replaced with a custom proxy DLL (167 KB). This proxy exports the same functions as the original, and forwards most calls to the renamed original amd_ags_x64.org. The proxy also loads the main bypass DLL as a static import — which means the Windows loader automatically loads it before the game's entry point is even reached. Hence no separate injector or launcher is needed at all. As per the CrackL@b analysis, this is a clean approach because the game doesn't know anything unusual is happening, as far as it is concerned, it simply loaded its GPU library as expected and everything looks normal.
Hypervisor Backend selection: Intel vs AMD
Once loaded, the bypass DLL reads the CPU vendor string via CPUID leaf 0x0 and picks the appropriate hypervisor kernel driver. The selection logic checks XOR-obfuscated vendor strings (0x444d4163 ^ 0x69746e65 for AMD, 0x6c65746e ^ 0x49656e69 for Intel):

The logic also checks whether another hypervisor is already occupying VT-x or AMD-V, since hardware virtualisation is typically exclusive and two hypervisors cannot both run simultaneously on the same hardware. If Hyper-V or another VMM is already running, the code may stop it first so the chosen driver can properly initialise. Also worth noting here — HyperEvade was additioally used in the sample to further hide the hypervisor from detection. The CPU brand string in the analyzed sample was set to DenuvOwO CPU @ 1337 GHz — which is kind of funny but actually illustrates an important point: the brand string doesn't need
to match any real CPU, it just needs to be consistent with whatever value was used when the Denuvo token was originally generated, because that is what the token is bound to.
This further confirms my gueeess that Denuvo's server does not or tbh CANNOT check the full validation of the hardware information it collects from games, and binds to the token file and gives us back for the game's Denuvo code to run the game.
IAT Hooking and Syscall Number Resolution
With the hypervisor driver running, the bypass DLL performs Import Address Table (IAT) hooking on the game executable. The hooked modules in the analyzed sample are: ntdll.dll, kernel32.dll, kernelbase.dll, and user32.dll. By overwriting IAT entries, calls to specific Windows API functions are redirected through the bypass's handlers without modifying any game code. Additionally, numeric syscall IDs (SSNs) are resolved at runtime directly from ntdll.dll by reading stub code — because syscall numbers change between Windows builds, hardcoding them would be fragile.
Token/license Handlling
Inside the main bypass DLL, two pre-generated Denuvo token blobs are embedded — one per hypervisor backend (one for AMD, one for Intel). On first launch the bypass writes the appropriate token to a .bin or similar file on disk. This token corresponds to a known, fixed hardware profile that the hypervisor is going to be spoofing.
On subsequent launches this pre-generated token is presented to Denuvo as proof of a valid license. Because the hypervisor makes the hardware appear identical to the environment in which the token was originally generated, the validation succeeds — Denuvo basically gets fooled into thinking the hardware matches. Also, Detanup01's GBE fork was used to emulate the Steam API services as well, allowing the game to run without even needing a valid Steam session, as I had said about it above.
CPUID spoofing via HyperDBG
HyperDBG uses the VMCS to enable CPUID exiting. When CPUID executes in the guest, the processor pauses, triggers a VM exit, and the hypervisor handler overwrites the output registers with spoofed values before returning control. The CrackL@b article demonstrates this in detail using an i9-11900K as the target CPU (standard signature: 0x000A0671). Leaf 0x1 sets the processor signature and clears ECX bit 31 (the
hypervisor-present bit). All hypervisor vendor leaves (0x40000000–0x400000FF) are zeroed to hide VMM presence.


KUSER_SHARED_DATA and Build Number spoofing
The NtBuildNumber field at KUSER_SHARED_DATA offset 0x260 is one of the values that Denuvo incorporates into its hardware fingerprint, and hence it needs to be spoofeed correctly. The bypss uses HyperDBG's !epthook command to intercept reads of this field and return the expected spoofed value instead. For example, to spoof the build number to 0x2328 (which is Windows 10 build 9000 in decimal, just
an example value): !epthook 0x7FFE0260 script { @rax = 0x00002328; }
This EPT hook approach is preferred over directly patching the memory page because, as already mentioned earlier, KUSER_SHARED_DATA is not writable on Windows 11 with VBS enabled anyway so directt patching won't work in those cases. HyperHide (github.com/Air14/HyperHide) also covers KUSER_SHARED_DATA spoofing in detail and is a useful additional reference alongside Connor McGarr's blog on Win10 vs Win11 differences.
GPU Vendor ID spoofing
GPU identity is read from PCI Configuration Space — configuration registers exposed by every PCIe device.
The bypass uses EPT hooks on the GPU's MMIO region to intercept reads of these fields and return spoofed
values. In the CrackL@b example, the target was an AMD Radeon RX 6800 XT. Five values are spoofed:

See AMD's PCIe Configuration Space documentation:docs.amd.com/r/en-US/pg343-pcie-versal/Configuration-Space
Storage / Disk Serial spoofing
Disk serials are queried through the NT device I/O control interface via NtDeviceIoControlFile. The relevant IOCTL for serial/model strings is IOCTL_STORAGE_QUERY_PROPERTY with StorageDeviceProperty — this returns a STORAGE_DEVICE_DESCRIPTOR structure containing vendor ID, product ID, revision, and serial number. Note: IOCTL_STORAGE_GET_DEVICE_NUMBER returns only device type and partition number — NOT the serial string. The HyperDBG !syscall command is used to intercept this:
!syscall 0x7 script { if (@rdx == 0x2D1400) { @rax = spoofed_value; } }