我在fffff801`16e00000
上加载了一个模块,希望通过!pte获得它的物理地址,但是windbg说“这个平台没有实现的级别”,这是什么原因呢?
我知道如何手动操作PML4、PDPT、PD和PT,但是为什么这个扩展不能工作呢?我在内核中调试虚拟机
发布于 2022-04-01 08:20:12
我曾多次遇到同样的问题,但我想不出答案。我不知道这是否会对您有所帮助,但是我编写了一个WinDbg JS脚本来再现这个特定情况下的!pte
命令。
它工作在64位,只有4层分页。
"use strict";
const system = x => host.namespace.Debugger.Utility.Control.ExecuteCommand(x);
const log = x => host.diagnostics.debugLog(`${x}\n`);
const convertStrToInt64 = str => host.parseInt64(str);
const replaceString = (string, search, replaceWith) => {
return string.split(search).join(replaceWith);
}
function isBitSet(Nr, Bit)
{
var mask = host.Int64(1).bitwiseShiftLeft(Bit);
return Nr.bitwiseAnd(mask).compareTo(0);
}
class PageEntry
{
constructor(Value)
{
this.present = isBitSet(Value, 0);
this.write = isBitSet(Value, 1);
this.supervisor = isBitSet(Value, 2);
this.access = isBitSet(Value, 5);
this.dirty = isBitSet(Value, 6);
this.largePage = isBitSet(Value, 7);
this.exec = isBitSet(Value, 63) == true ? 0 : 1;
this.value = Value;
var mask = host.Int64(1);
mask = mask.bitwiseShiftLeft(36).subtract(1)
this.pfn = Value.bitwiseShiftRight(12).bitwiseAnd(mask)
}
toString() {
var str = "";
str += "Value = " + this.value.toString() + "\n\t";
str += "P(" + this.present + "), ";
str += "W(" + this.write + "), ";
str += "E(" + this.exec + "), ";
str += "A(" + this.access + "), ";
str += "D(" + this.access + "), ";
str += "Large(" + this.largePage + ")\n\t";
str += "Pfn: " + this.pfn.toString();
return str;
}
}
function getLayerOffset(Adr, Layer)
{
var shift = 0;
switch (Layer)
{
case 4:
shift = 39;
break;
case 3:
shift = 30;
break;
case 2:
shift = 21;
break;
case 1:
shift = 12;
break;
default:
throw EvalError("Invalid layer");
}
return Adr.bitwiseShiftRight(shift).bitwiseAnd(0x1ff);
}
function paFromPfn(Pfn)
{
return Pfn.bitwiseShiftLeft(12)
}
function readDword64FromPa(PhysicalAddress)
{
var out = system("!dq " + PhysicalAddress.toString() + " L1")[0];
// output example: #1234abc 12341234`abcdabcd
// !sometimes the output from !dq has a space after #
out = out.split(" ");
var value = out[out.length - 1]
return convertStrToInt64("0x" + value);
}
function pageWalk(TablePa, Offset, Level)
{
if (Level == 0)
{
return;
}
var entryAdr = TablePa.add(Offset[Level-1].multiply(8));
var entryValue = readDword64FromPa(entryAdr);
var entry = new PageEntry(entryValue);
var nextLayerPa = paFromPfn(entry.pfn)
// print info
log("Level: " + Level.toString() + ", Entry Address: " + entryAdr.toString())
log(entry)
log("")
if (entry.present == 0)
{
log("Next layer not present");
return;
}
if (entry.largePage == 1)
{
log("Large page present");
return;
}
pageWalk(nextLayerPa, Offset, Level-1)
}
function getPml4AddressFromCr3(Cr3)
{
var mask = host.Int64(1);
var mask = mask.bitwiseShiftLeft(36).subtract(1)
var pml4Pfn = Cr3.bitwiseShiftRight(12).bitwiseAnd(mask)
return paFromPfn(pml4Pfn);
}
function translateAddress(VirtualAddress, Cr3Val=NaN)
{
log("Virtual address: " + VirtualAddress.toString())
var lv4 = getLayerOffset(VirtualAddress, 4);
var lv3 = getLayerOffset(VirtualAddress, 3);
var lv2 = getLayerOffset(VirtualAddress, 2);
var lv1 = getLayerOffset(VirtualAddress, 1);
if (isNaN(Cr3Val))
{
Cr3Val = host.currentThread.Registers.Kernel.cr3;
}
var pml4Adr = getPml4AddressFromCr3(Cr3Val);
log("Pml 4 address: " + pml4Adr.toString())
pageWalk(pml4Adr, [lv1, lv2, lv3, lv4], 4)
}
function initializeScript()
{
var app = [new host.apiVersionSupport(1, 7)];
app.push(new host.functionAlias(translateAddress, "pteV2"));
return app;
}
function invokeScript()
{
}
要使用运行.scriptload script.js
的脚本,可以使用!pteV2(Virtual_Address)
或!pteV2(Virtual_Address, Cr3_Value)
而不是!pte
。
我没有使用js的经验,而且脚本没有经过很好的…测试
脚本也在github上。
https://stackoverflow.com/questions/71598671
复制相似问题