Created
April 18, 2020 15:45
-
-
Save n4r1b/2d913f50e9de4767df96bf0fc01b757b to your computer and use it in GitHub Desktop.
A js script for windbg to list the registry keys that are being monitored by WdFilter.
This file contains hidden or 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"; | |
// remove [Object object] | |
delete Object.prototype.toString; | |
function add(address, val) | |
{ | |
return host.Int64(address).add(val); | |
} | |
class MpClientValue | |
{ | |
constructor (addr) { | |
this.pMpClientValue = addr != host.Int64(0) ? host.createPointerObject(addr, "nt", "unsigned __int64 *") : host.Int64(0); | |
} | |
get getClientValue() { | |
return this.__create() | |
} | |
toString() { | |
return this.pMpClientValue.address.toString() + " [Type: MP_CLIENT_VALUE *]"; | |
} | |
__create() { | |
if (this.pMpClientValue == host.Int64(0)) { | |
return host.createPointerObject(host.Int64(0), "nt", "unsigned __int64 *"); | |
} | |
var NextClientValue = this.pMpClientValue.isNull ? host.Int64(0) : new MpClientValue(this.pMpClientValue.dereference()); | |
return { | |
NextClientValue, | |
ValueHash : host.memory.readMemoryValues(add(this.pMpClientValue.address, 0x8), 16, 1, false), | |
KeyRules : host.createTypedObject(add(this.pMpClientValue.address, 0x18), "nt", "unsigned __int64") | |
} | |
} | |
} | |
class MpKeyValue | |
{ | |
constructor(addr) { | |
this.pMpKeyValue = addr != host.Int64(0) ? host.createPointerObject(addr, "nt", "unsigned __int64 *") : host.Int64(0); | |
} | |
toString() { | |
return this.pMpKeyValue.address.toString() + " [Type: MP_KEY_VALUE *]"; | |
} | |
get getKeyValue() { | |
return this.__create() | |
} | |
__create() { | |
if (this.pMpKeyValue == host.Int64(0)) { | |
return host.createPointerObject(host.Int64(0), "nt", "unsigned __int64 *"); | |
} | |
var NextKeyValue = this.pMpKeyValue.isNull ? host.Int64(0) : new MpKeyValue(this.pMpKeyValue.dereference()); | |
var ClientValue = this.pMpKeyValue.add(2).isNull ? host.Int64(0) : new KeyIterator(this.pMpKeyValue.add(2).dereference(), "MP_CLIENT_VALUE"); | |
return { | |
NextKeyValue, | |
KeyValueName : host.createPointerObject(this.pMpKeyValue.add(1).dereference(), "nt", "wchar_t *"), | |
ClientValue | |
} | |
} | |
} | |
class MpKeyEntry | |
{ | |
constructor(addr) { | |
this.pMpKeyEntry = addr != host.Int64(0) ? host.createPointerObject(addr, "nt", "unsigned __int64 *") : host.Int64(0); | |
} | |
get getEntry() { | |
return this.__create(); | |
} | |
toString() { | |
if (this.pMpKeyEntry == host.Int64(0)) { | |
return "0x0 [Type: MP_KEY_ENTRY *]" | |
} | |
return this.pMpKeyEntry.address.toString() + " [Type: MP_KEY_ENTRY *]"; | |
} | |
__create() { | |
if (this.pMpKeyEntry == host.Int64(0)) { | |
return host.createPointerObject(host.Int64(0), "nt", "unsigned __int64 *"); | |
} | |
var SubKey = this.pMpKeyEntry.isNull ? null : new MpKeyEntry(this.pMpKeyEntry.dereference()); | |
var NextKey = this.pMpKeyEntry.add(1).isNull ? null : new MpKeyEntry(this.pMpKeyEntry.add(1).dereference()); | |
var ClientList = this.pMpKeyEntry.add(4).isNull ? null : new KeyIterator(this.pMpKeyEntry.add(4).dereference(), "MP_CLIENT_VALUE"); | |
var ValuesList = this.pMpKeyEntry.add(5).isNull ? null : new KeyIterator(this.pMpKeyEntry.add(5).dereference(), "MP_KEY_VALUE"); | |
return { | |
EntryAddr : this.pMpKeyEntry.address, | |
SubKey, | |
NextKey, | |
KeyName : host.createPointerObject(this.pMpKeyEntry.add(2).dereference(), "nt", "wchar_t *"), | |
KeysToSkip : host.createTypedObject(add(this.pMpKeyEntry.address, 0x18), "nt", "unsigned short"), | |
ClientList, | |
ValuesList | |
} | |
} | |
} | |
class MpRegUserData | |
{ | |
constructor(addr) { | |
this.DataSize = host.createTypedObject(addr, "nt", "unsigned int"); | |
this.NumberOfEntries = host.createTypedObject(add(addr, 0x4), "nt", "unsigned int"); | |
this.MonitoredKeysTree = new KeyIterator(host.createPointerObject(add(addr, 0x8), "nt", "unsigned __int64 *").dereference(), "MP_KEY_ENTRY"); | |
this.MonitoredKeysRules = host.createTypedObject(add(addr, 0x10), "nt", "unsigned __int64"); | |
} | |
toString() { | |
return " [Type: MP_REG_USER_DATA *]"; | |
} | |
} | |
class KeyIterator | |
{ | |
constructor (startAddress, type) { | |
this.StartAddress = startAddress; | |
this.Type = type | |
} | |
*[Symbol.iterator]() { | |
var it; | |
switch(this.Type) { | |
case "MP_KEY_ENTRY": | |
it = this.getMpKeyEntries(new MpKeyEntry(this.StartAddress)); | |
break; | |
case "MP_KEY_VALUE": | |
it = this.getMpKeyValues(new MpKeyValue(this.StartAddress)); | |
break; | |
case "MP_CLIENT_VALUE": | |
it = this.getMpClientValues(new MpClientValue(this.StartAddress)); | |
break; | |
} | |
var res = it.next(); | |
while(!res.done) { | |
yield res.value; | |
res = it.next(); | |
} | |
} | |
toString() { | |
return this.StartAddress.toString() + " [Type: " + this.Type + " *]"; | |
} | |
* getMpKeyEntries(keyEntryAddr) { | |
var mpKeyEntry = keyEntryAddr.getEntry; | |
if (mpKeyEntry.isNull) { | |
return; | |
} | |
yield mpKeyEntry; | |
yield * this.getMpKeyEntries(mpKeyEntry.SubKey); | |
yield * this.getMpKeyEntries(mpKeyEntry.NextKey); | |
} | |
* getMpKeyValues(keyValuesAddr) { | |
var mpKeyValues = keyValuesAddr.getKeyValue | |
if (mpKeyValues.isNull) { | |
return; | |
} | |
yield mpKeyValues; | |
yield * this.getMpKeyValues(mpKeyValues.NextKeyValue); | |
} | |
* getMpClientValues(clientValuesAddr) { | |
var mpClientValue = clientValuesAddr.getClientValue | |
if (mpClientValue.isNull) { | |
return; | |
} | |
yield mpClientValue; | |
yield * this.getMpClientValues(mpClientValue.NextClientValue); | |
} | |
} | |
function __DisplayRegUserData() | |
{ | |
let pMpRegData = host.getModuleSymbolAddress("WdFilter", "MpRegData"); | |
if (pMpRegData === null) { | |
throw new Error("Unable to find pointer MpRegData"); | |
} | |
let mpRegData = host.createPointerObject(pMpRegData, "nt", "unsigned __int64 *").dereference(); | |
if (mpRegData == host.Int64(0)) { | |
throw new Error("Unable to get mpRegData"); | |
} | |
let pMpRegUserData = host.createPointerObject(add(mpRegData, 0x10), "nt", "unsigned __int64 *").dereference(); | |
if (pMpRegUserData == host.Int64(0)) { | |
throw new Error("Unable to get MpRegUserData"); | |
} | |
let mpRegUserData = new MpRegUserData(pMpRegUserData); | |
return { MpRegData: mpRegData, MpRegUserData: mpRegUserData }; | |
} | |
class __WdFilterRegData | |
{ | |
RegUserData() { | |
return __DisplayRegUserData(); | |
} | |
CreateInstance(typeName, addrObj) { | |
var name = typeName.toUpperCase(); | |
switch(name) { | |
case "MP_KEY_ENTRY": | |
case "MPKEYENTRY": | |
return new MpKeyEntry(addrObj).getEntry; | |
break; | |
case "MP_KEY_VALUE": | |
case "MPKEYVALUE": | |
return new MpKeyValue(addrObj).getKeyValue; | |
break; | |
case "MP_CLIENT_VALUE": | |
case "MPCLIENTVALUE": | |
return new MpClientValue(addrObj).getClientValue; | |
break; | |
default: | |
throw new Error("Unrecognized type name"); | |
} | |
} | |
get [Symbol.metadataDescriptor]() | |
{ | |
return { | |
RegUserData: { PreferShow: true, | |
Help: "!mpRegUserData - Returns MP_REG_USER_DATA, from here we can obtain a list of all the keys monitored by WdFilter. Remark: It relies on symbol MpRegData, so WdFilter symbols must be loaded" | |
}, | |
CreateInstance: {PreferShow: true, | |
Help: "CreateInstance(typeName, addrObj) - Creates an instance of type MP_KEY_ENTRY, MP_KEY_VALUE or MP_CLIENT_VALUE" | |
} | |
}; | |
} | |
} | |
class __WdFilterExtension | |
{ | |
get WdFilterExtension() | |
{ | |
return new __WdFilterRegData(); | |
} | |
}; | |
function initializeScript() | |
{ | |
return [new host.apiVersionSupport(1, 2), | |
new host.functionAlias(__DisplayRegUserData, "mpRegUserData"), | |
new host.namespacePropertyParent(__WdFilterExtension, "Debugger.Models.Utility", "Debugger.Models.Utility.Analysis", "Analysis")]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For more info check: https://n4r1b.netlify.app/posts/2020/04/dissecting-the-windows-defender-driver-wdfilter-part-4/