Last active
July 14, 2023 02:35
-
-
Save CrCrisan/2e699478ce8063bb11dd69c36daf749a to your computer and use it in GitHub Desktop.
Alternative for WinDbg !pte command
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"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.dirty + "), "; | |
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() | |
{ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
bug in line 44:
str += "D(" + this.access + "), ";
, should be:this.dirty