Skip to content

Wack0/bcdeditmod

Repository files navigation

BCDEditMod

This is a mod of bcdedit, allowing for any device to be specified rather than the subset that bcdedit officially supports.

Additionally, another tool called WimOverlayEdit is provided, for editing WimOverlay.dat, as this file contains boot environment device structures within.

Usage

bcdeditmod

Recommended usage is to start all your commands with: bcdeditmod /offline /raw /store file.bcd

Be sure to replace file.bcd with the actual path to your BCD file.

The /offline argument is an underdocumented argument that uses the offline registry library offreg.dll to read and write to the BCD hive, thus not requiring administrator privileges.

The /raw argument prevents bcdedit's own parsing from occuring - the bcdeditmod hooks apply only for devices that bcdedit itself considers unknown, and using /raw means bcdedit will consider all devices unknown.

Additionally, @args.txt syntax is supported like in Microsoft developer tools. This is useful if the value you want to set is too large for the command line. Yes, it happens.

WimOverlayEdit

Usage: WimOverlayEdit setdevice <drive> <device> [--recreate]
Usage: WimOverlayEdit setforcedblockdevice <drive> <device>
Usage: WimOverlayEdit getdevices <drive>
Usage: WimOverlayEdit addreparse <path> <deviceid> <device_file>

setdevice: Writes a custom boot environment device to WimOverlay.dat.
setforcedblockdevice: Writes a custom boot environment device to WimOverlay.dat, using a boot environment exploit to force its type to block io. WimOverlay.dat will be overwritten.
getdevices: Gets all boot environment devices from WimOverlay.dat.
addreparse: Sets reparse data for a given file such that accesses to it from the boot environment will be redirected to that device.

The only use for setforcedblockdevice is to exploit CVE-2024-30865, a now fixed patch-bypass of a dubious disk variant.

To use this, you would use setdevice to set up a redirection device, then addreparse to point a path to a file on that redirection device by its redirection device ID.

This functionality only works inside the boot environment, not in NT - the intended functionality here uses a SHA1 hash in a WIM, not a filename on some other device. Hence, only the root directory is supported for device_file, and only filenames of at most 11 characters (24 bytes = 11 UTF-16LE characters plus null terminator).

Device format

The device format implemented by bcdeditmod always starts with !raw: to mean raw device - anything else will be considered as a standard device type for bcdedit to use.

The syntax here is a custom object notation designed for easy entry in cmd.exe (especially inside double-quotes), in the format of type[param1,param2,...]. The start and end of a string, used for paths, is denoted by colons: :\windows\system32\winload.efi:.

Space characters after commas and close-square-brackets are allowed for readability.

A device or sub-device can potentially be emdedded in another device. To give an example, a valid device is: !raw:block[ram[boot, :\sources\boot.wim:]] - this denotes a block device of sub-type ramdisk, which loads from the boot device using path \sources\boot.wim.

Additionally, after the device there can be up to two extra arguments: a special unknown that takes a path to a file containing binary data to append to the end of the device, and a boot entry GUID used for additional options.

For example:

  • !raw:boot,{00000000-0000-0000-0000-000000000003} denotes a boot device, with additional options GUID of {00000000-0000-0000-0000-000000000003}.
  • !raw:boot,unknown[:file.bin:] denotes a boot device, with the contents of file.bin concatenated to the end.
  • !raw:boot,unknown[:file.bin:],{00000000-0000-0000-0000-000000000003} combines the two above examples.

Where described below, "numeric" means decimal, "hex-encoded" means hex, "GUID" is in the {00000000-0000-0000-0000-000000000000} format, and "path" is a string enclosed by colons as mentioned above.

Device types

The encoded devices generally correspond directly to the underlying boot environment device structures.

Most devices also accept the argument overflow, which contains hex-encoded binary data that is too large to fit into the expected structure size.

unknown

An otherwise unknown device. The first argument is the numeric enumeration type of the device, the second argument is the hex-encoded device body.

Example: !raw:unknown[5,:0000:] is a device with type 5 (this corresponds to DEVICE_TYPE_BOOT), with a two-bye body of all zeroes.

boot

The simplest device type. Has no arguments at all. Used to denote the boot device, that is, the device that bootmgfw.efi or bootmgr.exe loaded from.

serial

Yes, this is a boot environment device for some reason. Only usually used in boot debug scenarios.

Has one argument, which can be one of the following:

  • port - has as sub argument the numeric serial port number (can't remember if this is x86-style I/O port, or 1/2/... for COM1/COM2)
  • uefi - UEFI serial port API. Has no arguments.
  • A valid serial driver built into the boot environment, the names of which follow. Has five sub-arguments: numeric address space ID, numeric bit width, numeric bit offset, numeric access size, and hex-encoded MMIO address.
    • addr
    • max311xe
    • pl011
    • q8x60
    • nvidia
    • omap
    • apm88xxxx
    • q8x74
    • sam5250
    • usif
    • mx6
    • sbsa32
    • sbsa
    • arm_dcc
    • bcm2708
    • sdm845
    • mm16550
    • sdm845v2
    • ialpss

Examples: !raw:serial[port[1]], !raw:serial[uefi], !raw:serial[bcm2708[0,32,0,32,7e201000]]

udp

Used for PXE network boot, and only usable in that scenario.

Has two arguments: numeric HwType and hex-encoded 16-byte HwAddress.

vmbus

Used in Hyper-V VMs.

Has two arguments: GUID InterfaceType and GUID InterfaceInstance.

locate

Specifies a locate-device, used to find an unknown device containing some path.

Has one argument, which can be one of the following:

  • string - contains one sub-argument which is a path.
  • strelem or strelemres - contains one sub-argument which is a hex-encoded BCD element identifier.
    • The difference between the two is strelemres sets a flag introduced in Germanium to not create the device when it is resolved.

Examples: !raw:locate[string[:\setup.exe:]], !raw:locate[strelem[12000002]], !raw:locate[strelemres[12000002]]

uri

Specifies a file downloaded from a remote HTTP server.

Takes a single path string, that of the URI to download.

Currently, the parser automatically skips past a single : character and thus does not support specifying authentication data, or a custom port, or IPv6 addresses. Given a URI device has exactly one form, it can be specified in bcdedit anyway.

Examples: !raw:uri[:https://example.com/winload.efi:]

composite

Specifies a tuple of two devices. When accessing this device, the first device is tried, and if an error occurs, the second device is used.

Has either one or two arguments:

  • If the first argument is needs_creation this denotes the single-argument variant, specifiying that the device is a well-formed device that requires creation. Only supported variant after dubious disk fixes - also requires an additional options GUID.
  • Otherwise, two arguments are specified, both of which being devices themselves.

Examples: !raw:composite[needs_creation], !raw:composite[boot, locate[string[:\setup.exe:]]]

cimfs

Mentioned for completion, but the support is not complete and the functionality in the boot environment is not completetly known yet.

part

Specifies a partition identifier device.

The difference between the non-extended and extended partition devices is that part uses mbrindex and part2 uses mbroffset.

Has several arguments. The first argument is a block device (see below). The remaining arguments determine on the type of the block device:

  • If the block device type is hd or vhd, and its argument is gpt, the second argument must be of type gptsig which takes one argument, the GUID of the partition to access.
  • If the block device type is hd or vhd, and its argument is mbr, the second argument must be of type mbrindex which takes one argument, the numeric partition number to access.
  • Otherwise, the second argument must be of type bootentry, which takes one numeric argument that is completetly unused by the boot environment.

Examples: !raw:part[hd[gpt[{D2E23617-2338-4685-A2D7-F3133312E12E}]],gptsig[{1B85332B-AD73-4D9A-BFC3-B39443D3DFE4}]], !raw:part[optical[0],bootentry[0]], !raw:part[hd[mbr[12345678]],mbrindex[0]]

part2

Specifies an extended partition identifier device.

The difference between the non-extended and extended partition devices is that partition uses mbrindex and partition2 uses mbroffset.

Has several arguments. The first argument is a block device (see below). The remaining arguments determine on the type of the block device:

  • If the block device type is hd or vhd, and its argument is gpt, the second argument must be of type gptsig which takes one argument, the GUID of the partition to access.
  • If the block device type is hd or vhd, and its argument is mbr, the second argument must be of type mbroffset which takes one argument, the hex-encoded offset of the partition.
  • Otherwise, the second argument must be of type bootentry, which takes one numeric argument that is completetly unused by the boot environment (supposed to be the index of an El Torito boot entry).

Examples: !raw:part2[hd[gpt[{D2E23617-2338-4685-A2D7-F3133312E12E}]],gptsig[{1B85332B-AD73-4D9A-BFC3-B39443D3DFE4}]], !raw:part2[optical[0],bootentry[0]], !raw:part2[hd[mbr[12345678]],mbroffset[100000]]

block

Specifies a block device.

The most complex and also most common type of device, there are several sub-types of block device.

hd

Specifies a hard disk. Has a single argument, which can be one of the following:

  • gpt - Disk has a GPT partition table. Contains one sub-argument which is the GUID of the disk identifier.
  • mbr - Disk has an MBR partition table. Contains one sub-argument which is the hex-encoded 32-bit MBR signature.
  • raw - Disk has no partition table. Contains one sub-argument which is the hex-encoded disk number.

Examples: !raw:block[hd[gpt[{D2E23617-2338-4685-A2D7-F3133312E12E}]]], !raw:block[hd[mbr[12345678]]]

vhd

Specifies a VHD file. Has two or three arguments:

  • The first argument is the same as for a hd block device
  • The second argument is the sub-device where the VHD is accessed from (usually a block device of type file).
  • The third argument is optional, and if present must be create to specify that the device needs creation (used for setting up VHD ramdisks where supported).

Examples: !raw:block[vhd[gpt[{D2E23617-2338-4685-A2D7-F3133312E12E}], block[file[boot, :\vhd.vhd:]]]], , !raw:block[vhd[mbr[12345678], block[file[boot, :\vhd.vhd:]], create]]

removable

Specifies a removable disk. Used to specify a floppy disk attached to an internal floppy disk controller. Has a single argument which is the numeric drive number.

Example: !raw:block[floppy[0]]

optical

Specifies an optical drive. Has a single argument which is the numeric disk number. However that argument is completely unused; the boot environment will always use the first found optical drive with inserted media.

Example: !raw:block[optical[0]]

ram_mem

Specifies a ramdisk with internal arguments specified in the BCD, used to exploit dubious disk. Has three arguments:

  • The first argument is the hex-encoded physical address of the ramdisk buffer, which must be page-aligned.
  • The second argument is the hex-encoded offset of the ramdisk buffer past that physical address, which is used if the ramdisk buffer is not page-aligned.
  • The third argument is the hex-encoded length of the ramdisk buffer.

Example: !raw:block[ram_mem[120000, 0, ffffffffffffffff]]

ram

Specifies a sane ramdisk. Has a single argument which is the same as for block device type file (see below).

Example: !raw:block[ram[boot, :\sources\boot.wim:]]

mem_mem

Specifies a memdisk (introduced around Germanium) with internal arguments specified in the BCD, used to exploit dubious disk. Has three arguments:

  • The first argument is the hex-encoded physical address of the memdisk buffer, which must be page-aligned.
  • The second argument is the hex-encoded sector size of the memdisk.
  • The third argument is the hex-encoded length of the memdisk buffer.

Example: !raw:block[mem_mem[120000, 200, ffffffffffffffff]]

mem

Specifies a sane memdisk (introduced around Germanium). The difference between a ramdisk and a memdisk is that a ramdisk is a filesystem image, whereas a memdisk is a disk image (with partition table).

Has a single argument, which is the sub-device which gets read into memory. The boot environment checks the type of this device is either block or cimfs, but any device can be specified here.

Example: !raw:block[mem[block[file[boot, :\hd.img:]]]]

file

Specifies a file on another device. Has two arguments:

  • The first argument is the device to load the file from.
  • The second argument is the path of the file to load from that device.

Example: !raw:block[file[boot, :\fat.img:]]

About

BCD raw device editor: In-memory mod for bcdedit that allows representation of any device.

Topics

Resources

License

Stars

Watchers

Forks