346 lines
15 KiB
Python
346 lines
15 KiB
Python
#!/usr/bin/env python3
|
|
import hivex
|
|
import argparse
|
|
import struct
|
|
|
|
from hivex import Hivex
|
|
from hivex.hive_types import *
|
|
|
|
|
|
# Docs:
|
|
#
|
|
# https://www.geoffchappell.com/notes/windows/boot/bcd/objects.htm
|
|
# https://learn.microsoft.com/en-us/previous-versions/windows/desktop/bcd/bcdbootmgrelementtypes
|
|
|
|
#print(f"Root: {root}")
|
|
|
|
|
|
BCD_Enumerations = {
|
|
"BcdLibraryDevice_ApplicationDevice" : 0x11000001,
|
|
"BcdLibraryString_ApplicationPath" : 0x12000002,
|
|
"BcdLibraryString_Description" : 0x12000004,
|
|
"BcdLibraryString_PreferredLocale" : 0x12000005,
|
|
"BcdLibraryObjectList_InheritedObjects" : 0x14000006,
|
|
"BcdLibraryInteger_TruncatePhysicalMemory" : 0x15000007,
|
|
"BcdLibraryObjectList_RecoverySequence" : 0x14000008,
|
|
"BcdLibraryBoolean_AutoRecoveryEnabled" : 0x16000009,
|
|
"BcdLibraryIntegerList_BadMemoryList" : 0x1700000a,
|
|
"BcdLibraryBoolean_AllowBadMemoryAccess" : 0x1600000b,
|
|
"BcdLibraryInteger_FirstMegabytePolicy" : 0x1500000c,
|
|
"BcdLibraryInteger_RelocatePhysicalMemory" : 0x1500000D,
|
|
"BcdLibraryInteger_AvoidLowPhysicalMemory" : 0x1500000E,
|
|
"BcdLibraryBoolean_DebuggerEnabled" : 0x16000010,
|
|
"BcdLibraryInteger_DebuggerType" : 0x15000011,
|
|
"BcdLibraryInteger_SerialDebuggerPortAddress" : 0x15000012,
|
|
"BcdLibraryInteger_SerialDebuggerPort" : 0x15000013,
|
|
"BcdLibraryInteger_SerialDebuggerBaudRate" : 0x15000014,
|
|
"BcdLibraryInteger_1394DebuggerChannel" : 0x15000015,
|
|
"BcdLibraryString_UsbDebuggerTargetName" : 0x12000016,
|
|
"BcdLibraryBoolean_DebuggerIgnoreUsermodeExceptions" : 0x16000017,
|
|
"BcdLibraryInteger_DebuggerStartPolicy" : 0x15000018,
|
|
"BcdLibraryString_DebuggerBusParameters" : 0x12000019,
|
|
"BcdLibraryInteger_DebuggerNetHostIP" : 0x1500001A,
|
|
"BcdLibraryInteger_DebuggerNetPort" : 0x1500001B,
|
|
"BcdLibraryBoolean_DebuggerNetDhcp" : 0x1600001C,
|
|
"BcdLibraryString_DebuggerNetKey" : 0x1200001D,
|
|
"BcdLibraryBoolean_EmsEnabled" : 0x16000020,
|
|
"BcdLibraryInteger_EmsPort" : 0x15000022,
|
|
"BcdLibraryInteger_EmsBaudRate" : 0x15000023,
|
|
"BcdLibraryString_LoadOptionsString" : 0x12000030,
|
|
"BcdLibraryBoolean_DisplayAdvancedOptions" : 0x16000040,
|
|
"BcdLibraryBoolean_DisplayOptionsEdit" : 0x16000041,
|
|
"BcdLibraryDevice_BsdLogDevice" : 0x11000043,
|
|
"BcdLibraryString_BsdLogPath" : 0x12000044,
|
|
"BcdLibraryBoolean_GraphicsModeDisabled" : 0x16000046,
|
|
"BcdLibraryInteger_ConfigAccessPolicy" : 0x15000047,
|
|
"BcdLibraryBoolean_DisableIntegrityChecks" : 0x16000048,
|
|
"BcdLibraryBoolean_AllowPrereleaseSignatures" : 0x16000049,
|
|
"BcdLibraryString_FontPath" : 0x1200004A,
|
|
"BcdLibraryInteger_SiPolicy" : 0x1500004B,
|
|
"BcdLibraryInteger_FveBandId" : 0x1500004C,
|
|
"BcdLibraryBoolean_ConsoleExtendedInput" : 0x16000050,
|
|
"BcdLibraryInteger_GraphicsResolution" : 0x15000052,
|
|
"BcdLibraryBoolean_RestartOnFailure" : 0x16000053,
|
|
"BcdLibraryBoolean_GraphicsForceHighestMode" : 0x16000054,
|
|
"BcdLibraryBoolean_IsolatedExecutionContext" : 0x16000060,
|
|
"BcdLibraryBoolean_BootUxDisable" : 0x1600006C,
|
|
"BcdLibraryBoolean_BootShutdownDisabled" : 0x16000074,
|
|
"BcdLibraryIntegerList_AllowedInMemorySettings" : 0x17000077,
|
|
"BcdLibraryBoolean_ForceFipsCrypto" : 0x16000079,
|
|
|
|
|
|
"BcdBootMgrObjectList_DisplayOrder" : 0x24000001,
|
|
"BcdBootMgrObjectList_BootSequence" : 0x24000002,
|
|
"BcdBootMgrObject_DefaultObject" : 0x23000003,
|
|
"BcdBootMgrInteger_Timeout" : 0x25000004,
|
|
"BcdBootMgrBoolean_AttemptResume" : 0x26000005,
|
|
"BcdBootMgrObject_ResumeObject" : 0x23000006,
|
|
"BcdBootMgrObjectList_ToolsDisplayOrder" : 0x24000010,
|
|
"BcdBootMgrBoolean_DisplayBootMenu" : 0x26000020,
|
|
"BcdBootMgrBoolean_NoErrorDisplay" : 0x26000021,
|
|
"BcdBootMgrDevice_BcdDevice" : 0x21000022,
|
|
"BcdBootMgrString_BcdFilePath" : 0x22000023,
|
|
"BcdBootMgrBoolean_ProcessCustomActionsFirst" : 0x26000028,
|
|
"BcdBootMgrIntegerList_CustomActionsList" : 0x27000030,
|
|
"BcdBootMgrBoolean_PersistBootSequence" : 0x26000031,
|
|
|
|
"BcdDeviceInteger_RamdiskImageOffset" : 0x35000001,
|
|
"BcdDeviceInteger_TftpClientPort" : 0x35000002,
|
|
"BcdDeviceInteger_SdiDevice" : 0x31000003,
|
|
"BcdDeviceInteger_SdiPath" : 0x32000004,
|
|
"BcdDeviceInteger_RamdiskImageLength" : 0x35000005,
|
|
"BcdDeviceBoolean_RamdiskExportAsCd" : 0x36000006,
|
|
"BcdDeviceInteger_RamdiskTftpBlockSize" : 0x36000007,
|
|
"BcdDeviceInteger_RamdiskTftpWindowSize" : 0x36000008,
|
|
"BcdDeviceBoolean_RamdiskMulticastEnabled" : 0x36000009,
|
|
"BcdDeviceBoolean_RamdiskMulticastTftpFallback" : 0x3600000A,
|
|
"BcdDeviceBoolean_RamdiskTftpVarWindow" : 0x3600000B,
|
|
|
|
"BcdMemDiagInteger_PassCount" : 0x25000001,
|
|
"BcdMemDiagInteger_FailureCount" : 0x25000003,
|
|
|
|
"Reserved1" : 0x21000001,
|
|
"Reserved2" : 0x22000002,
|
|
"BcdResumeBoolean_UseCustomSettings" : 0x26000003,
|
|
"BcdResumeDevice_AssociatedOsDevice" : 0x21000005,
|
|
"BcdResumeBoolean_DebugOptionEnabled" : 0x26000006,
|
|
"BcdResumeInteger_BootMenuPolicy" : 0x25000008,
|
|
|
|
"BcdOSLoaderDevice_OSDevice" : 0x21000001,
|
|
"BcdOSLoaderString_SystemRoot" : 0x22000002,
|
|
"BcdOSLoaderObject_AssociatedResumeObject" : 0x23000003,
|
|
"BcdOSLoaderBoolean_DetectKernelAndHal" : 0x26000010,
|
|
"BcdOSLoaderString_KernelPath" : 0x22000011,
|
|
"BcdOSLoaderString_HalPath" : 0x22000012,
|
|
"BcdOSLoaderString_DbgTransportPath" : 0x22000013,
|
|
"BcdOSLoaderInteger_NxPolicy" : 0x25000020,
|
|
"BcdOSLoaderInteger_PAEPolicy" : 0x25000021,
|
|
"BcdOSLoaderBoolean_WinPEMode" : 0x26000022,
|
|
"BcdOSLoaderBoolean_DisableCrashAutoReboot" : 0x26000024,
|
|
"BcdOSLoaderBoolean_UseLastGoodSettings" : 0x26000025,
|
|
"BcdOSLoaderBoolean_AllowPrereleaseSignatures" : 0x26000027,
|
|
"BcdOSLoaderBoolean_NoLowMemory" : 0x26000030,
|
|
"BcdOSLoaderInteger_RemoveMemory" : 0x25000031,
|
|
"BcdOSLoaderInteger_IncreaseUserVa" : 0x25000032,
|
|
"BcdOSLoaderBoolean_UseVgaDriver" : 0x26000040,
|
|
"BcdOSLoaderBoolean_DisableBootDisplay" : 0x26000041,
|
|
"BcdOSLoaderBoolean_DisableVesaBios" : 0x26000042,
|
|
"BcdOSLoaderBoolean_DisableVgaMode" : 0x26000043,
|
|
"BcdOSLoaderInteger_ClusterModeAddressing" : 0x25000050,
|
|
"BcdOSLoaderBoolean_UsePhysicalDestination" : 0x26000051,
|
|
"BcdOSLoaderInteger_RestrictApicCluster" : 0x25000052,
|
|
"BcdOSLoaderBoolean_UseLegacyApicMode" : 0x26000054,
|
|
"BcdOSLoaderInteger_X2ApicPolicy" : 0x25000055,
|
|
"BcdOSLoaderBoolean_UseBootProcessorOnly" : 0x26000060,
|
|
"BcdOSLoaderInteger_NumberOfProcessors" : 0x25000061,
|
|
"BcdOSLoaderBoolean_ForceMaximumProcessors" : 0x26000062,
|
|
"BcdOSLoaderBoolean_ProcessorConfigurationFlags" : 0x25000063,
|
|
"BcdOSLoaderBoolean_MaximizeGroupsCreated" : 0x26000064,
|
|
"BcdOSLoaderBoolean_ForceGroupAwareness" : 0x26000065,
|
|
"BcdOSLoaderInteger_GroupSize" : 0x25000066,
|
|
"BcdOSLoaderInteger_UseFirmwarePciSettings" : 0x26000070,
|
|
"BcdOSLoaderInteger_MsiPolicy" : 0x25000071,
|
|
"BcdOSLoaderInteger_SafeBoot" : 0x25000080,
|
|
"BcdOSLoaderBoolean_SafeBootAlternateShell" : 0x26000081,
|
|
"BcdOSLoaderBoolean_BootLogInitialization" : 0x26000090,
|
|
"BcdOSLoaderBoolean_VerboseObjectLoadMode" : 0x26000091,
|
|
"BcdOSLoaderBoolean_KernelDebuggerEnabled" : 0x260000a0,
|
|
"BcdOSLoaderBoolean_DebuggerHalBreakpoint" : 0x260000a1,
|
|
"BcdOSLoaderBoolean_UsePlatformClock" : 0x260000A2,
|
|
"BcdOSLoaderBoolean_ForceLegacyPlatform" : 0x260000A3,
|
|
"BcdOSLoaderInteger_TscSyncPolicy" : 0x250000A6,
|
|
"BcdOSLoaderBoolean_EmsEnabled" : 0x260000b0,
|
|
"BcdOSLoaderInteger_DriverLoadFailurePolicy" : 0x250000c1,
|
|
"BcdOSLoaderInteger_BootMenuPolicy" : 0x250000C2,
|
|
"BcdOSLoaderBoolean_AdvancedOptionsOneTime" : 0x260000C3,
|
|
"BcdOSLoaderInteger_BootStatusPolicy" : 0x250000E0,
|
|
"BcdOSLoaderBoolean_DisableElamDrivers" : 0x260000E1,
|
|
"BcdOSLoaderInteger_HypervisorLaunchType" : 0x250000F0,
|
|
"BcdOSLoaderBoolean_HypervisorDebuggerEnabled" : 0x260000F2,
|
|
"BcdOSLoaderInteger_HypervisorDebuggerType" : 0x250000F3,
|
|
"BcdOSLoaderInteger_HypervisorDebuggerPortNumber" : 0x250000F4,
|
|
"BcdOSLoaderInteger_HypervisorDebuggerBaudrate" : 0x250000F5,
|
|
"BcdOSLoaderInteger_HypervisorDebugger1394Channel" : 0x250000F6,
|
|
"BcdOSLoaderInteger_BootUxPolicy" : 0x250000F7,
|
|
"BcdOSLoaderString_HypervisorDebuggerBusParams" : 0x220000F9,
|
|
"BcdOSLoaderInteger_HypervisorNumProc" : 0x250000FA,
|
|
"BcdOSLoaderInteger_HypervisorRootProcPerNode" : 0x250000FB,
|
|
"BcdOSLoaderBoolean_HypervisorUseLargeVTlb" : 0x260000FC,
|
|
"BcdOSLoaderInteger_HypervisorDebuggerNetHostIp" : 0x250000FD,
|
|
"BcdOSLoaderInteger_HypervisorDebuggerNetHostPort" : 0x250000FE,
|
|
"BcdOSLoaderInteger_TpmBootEntropyPolicy" : 0x25000100,
|
|
"BcdOSLoaderString_HypervisorDebuggerNetKey" : 0x22000110,
|
|
"BcdOSLoaderBoolean_HypervisorDebuggerNetDhcp" : 0x26000114,
|
|
"BcdOSLoaderInteger_HypervisorIommuPolicy" : 0x25000115,
|
|
"BcdOSLoaderInteger_XSaveDisable" : 0x2500012b
|
|
}
|
|
|
|
|
|
def format_value(bcd, bcd_value):
|
|
|
|
name = bcd.value_key(bcd_value)
|
|
(type, length) = bcd.value_type(bcd_value)
|
|
|
|
typename = ""
|
|
str_value = ""
|
|
if type == REG_SZ:
|
|
typename = "SZ"
|
|
str_value = bcd.value_string(bcd_value)
|
|
elif type == REG_DWORD:
|
|
typename = "DWORD"
|
|
dval = bcd.value_dword(bcd_value)
|
|
|
|
str_value = hex(dval) + " (" + str(bcd.value_dword(bcd_value)) + ")"
|
|
elif type == REG_BINARY:
|
|
typename = "BIN"
|
|
(length, value) = bcd.value_value(bcd_value)
|
|
str_value = value.hex()
|
|
elif type == REG_DWORD_BIG_ENDIAN:
|
|
typename = "DWORD_BE"
|
|
elif type == REG_EXPAND_SZ:
|
|
typename = "EXPAND SZ"
|
|
elif type == REG_FULL_RESOURCE_DESCRIPTOR:
|
|
typename = "RES DESC"
|
|
elif type == REG_LINK:
|
|
typename = "LINK"
|
|
elif type == REG_MULTI_SZ:
|
|
typename = "MULTISZ"
|
|
(length, str_value) = bcd.value_value(bcd_value)
|
|
str_value = str_value.decode('utf-16le')
|
|
str_value = str_value.replace("\0", ";")
|
|
#value = ";".join("\0".split(value))
|
|
elif type == REG_NONE:
|
|
typename = "NONE"
|
|
elif type == REG_QWORD:
|
|
typename = "QWORD"
|
|
elif type == REG_RESOURCE_LIST:
|
|
typename = "RES LIST"
|
|
elif type == REG_RESOURCE_REQUIREMENTS_LIST:
|
|
typename = "REQ LIST"
|
|
else:
|
|
typename = str(type)
|
|
str_value = "???"
|
|
|
|
|
|
return (typename, length, str_value)
|
|
|
|
def dump_all(root, depth = 0):
|
|
|
|
padding = "\t" * depth
|
|
|
|
children = bcd.node_children(root)
|
|
|
|
if len(children) > 0:
|
|
|
|
for child in children:
|
|
name = bcd.node_name(child)
|
|
print(f"{padding}{name}")
|
|
|
|
dump_all(child, depth + 1)
|
|
# print(f"Child: {child}")
|
|
|
|
#print(f"Values: {num_vals}")
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
values = bcd.node_values(root)
|
|
#print(f"Value list: {values}")
|
|
|
|
for v in values:
|
|
(type_name, length, str_value) = format_value(bcd, v)
|
|
name = bcd.value_key(v)
|
|
|
|
print(f"{padding}{name: <16}: [{type_name: <10}]; ({length: < 4}) {str_value}")
|
|
|
|
|
|
class WindowsBCD:
|
|
def __init__(self, filename):
|
|
self.filename = filename
|
|
self.bcd = Hivex(filename)
|
|
|
|
def dump(self, root=None, depth = 0):
|
|
padding = "\t" * depth
|
|
|
|
if root is None:
|
|
root = self.bcd.root()
|
|
|
|
children = self.bcd.node_children(root)
|
|
|
|
if len(children) > 0:
|
|
for child in children:
|
|
name = self.bcd.node_name(child)
|
|
print(f"{padding}{name}")
|
|
|
|
self.dump(child, depth + 1)
|
|
return
|
|
|
|
values = self.bcd.node_values(root)
|
|
|
|
for v in values:
|
|
(type_name, length, str_value) = format_value(self.bcd, v)
|
|
name = self.bcd.value_key(v)
|
|
|
|
print(f"{padding}{name: <16}: [{type_name: <10}]; ({length: < 4}) {str_value}")
|
|
|
|
def list(self):
|
|
root = self.bcd.root()
|
|
objects = self.bcd.node_get_child(root, "Objects")
|
|
|
|
for child in self.bcd.node_children(objects):
|
|
entry_id = self.bcd.node_name(child)
|
|
|
|
elements = self.bcd.node_get_child(child, "Elements")
|
|
description_entry = self.bcd.node_get_child(elements, "12000004")
|
|
|
|
if description_entry:
|
|
values = self.bcd.node_values(description_entry)
|
|
if values:
|
|
(type_name, length, str_value) = format_value(self.bcd, values[0])
|
|
print(f"{entry_id}: {str_value}")
|
|
else:
|
|
print(f"{entry_id}: [no description value!?]")
|
|
|
|
|
|
appdevice_entry = self.bcd.node_get_child(elements, "11000001")
|
|
|
|
if appdevice_entry:
|
|
values = self.bcd.node_values(appdevice_entry)
|
|
(length, data) = self.bcd.value_value(values[0])
|
|
hex = data.hex()
|
|
print(f"LEN: {length}, HEX: {hex}, RAW: {data}")
|
|
if len(data) > 10:
|
|
etype = struct.unpack_from('<I', data, offset = 16)
|
|
print(f"Type: {etype}")
|
|
|
|
|
|
|
|
else:
|
|
print(f"{entry_id}: [no description entry 12000004]")
|
|
|
|
|
|
parser = argparse.ArgumentParser(
|
|
prog="Windows BCD parser",
|
|
description="Parses the BCD",
|
|
)
|
|
|
|
parser.add_argument("--db", type=str, metavar='BCD file', help="Database to use")
|
|
parser.add_argument("--dump", action='store_true', help="Dumps the specified database")
|
|
parser.add_argument("--list", action='store_true', help="Lists boot entries in the specified database")
|
|
|
|
args = parser.parse_args()
|
|
|
|
bcdobj = WindowsBCD(args.db)
|
|
|
|
if args.dump:
|
|
# "/home/vadim/opengnsys/winboot/boot-copy/EFI/Microsoft/Boot/BCD"
|
|
#bcd = Hivex(args.dump)
|
|
|
|
#root = bcd.root()
|
|
#dump_all(root)
|
|
bcdobj.dump()
|
|
elif args.list:
|
|
bcdobj.list()
|