#StackBounty: #linux #windows #iso #disk-image #mkisofs Changing the boot entries of a Windows ISO using mkisofs to use cdboot_noprompt…

Bounty: 50

When you boot a Windows 10 ISO, you will get this misleading prompt:
enter image description here
Why is it misleading? Because this message comes from the Windows ISO itself after you actually already booted from it.
This prompt is a feature that is supposed to prevent you from accidentally booting in your Windows image.

Now I have a very specific use-case in which this prompt makes it impossible for me to automatically create and install a UEFI-based Windows 10 VM.

So I’ve done some digging and on Windows you can create a Windows ISO without the prompt by specifying a noprompt image on the boot entry like so:

$setfsboot="C:1_TEMPISOetfsboot.com"
$sefisys ="C:1_TEMPISOefisys_noprompt.bin"
Oscdimg -bootdata:2#p0,eb$setfsboot#pEF,e,b$sefisys -u1 
-udfver102 C:winpe_amd64media C:winpe_amd64winpeamd64.iso

Quick explanation

-bootdata:2#p0,eb$setfsboot#pEF,e,b$sefisys

  • 2 means there are 2 boot entries
  • # separator
  • p0,eb$setfsboot is the default boot entry (for legacy BIOS boot)
  • # separator
  • pEF,e,b$sefisys is the fallback boot entry (for UEFI boot)

Documentation for OSCdimg

Now I’m trying to achieve the same thing on Linux using mkisofs, which is very tricky because just in order to make a UEFI-bootable Windows ISO, you need the upstream version of mkisofs (see this post by mkey) (Which can be obtained here.) The versions of mkisofs that come with Linux distributions apparently lack some features and have ancient bugs in them that never got fixed.

I’ve tried removing efi/microsoft/boot/cdboot.efi and then renaming efi/microsoft/boot/cdboot_noprompt.efi to efi/microsoft/boot/cdboot.efi in order to trick the ISO, but that didn’t work unfortunately.

At the moment I use this code to extract a boot image from the ISO directly:

BOOT_LOAD_SEG="$(dumpet -i "${WIN10_IMG}" | grep "Media load segment: " | cut -d ':' -f2 | cut -d ' ' -f2)"
BOOT_LOAD_SIZE="$(dumpet -i "${WIN10_IMG}" | grep "Load Sectors: " | grep -o "[^:]*$" | cut -d ' ' -f2 | head -1)"

EFI_STARTING_SECTOR="$(dumpet -i "${WIN10_IMG}" | grep "Load LBA: " | grep -o "[^:]*$" | cut -d ' ' -f2 | tail -1)"
echo "EFI_STARTING_SECTOR: $EFI_STARTING_SECTOR"

sudo dd if="${WIN10_IMG}" of="${TMP}/efi.dmp" bs=2048 count=1 skip="${EFI_STARTING_SECTOR}"
EFI_BOOT_LOAD_SIZE="$(file "${TMP}/efi.dmp" | grep -oP 'sectors (d+)' | cut -d ' ' -f2)"
echo "EFI_BOOT_LOAD_SIZE: ${EFI_BOOT_LOAD_SIZE}"

sudo dd if="${WIN10_IMG}" of="${ISO_FILES}/efi/win_efi_boot.img" bs=2048 count="${EFI_BOOT_LOAD_SIZE}" skip="${EFI_STARTING_SECTOR}"

In the last command above, the extracted image is placed in the folder containing the files extracted from the ISO.

Then using the -eltorito-boot "efi/win_efi_boot.img" flag for mkisofs, I tell it to use that for the boot entry.

I have written a script that automatically sets up everything you need in order to get to the point where I am right now.
If you take a look at STEP 5 in the script you can see my attempt to change the file names, but I think, I may have to change STEP 4 instead, but I just don’t know how.

#!/usr/bin/env bash

#You might have to install a few dependencies for schily tools to compile.
#On Fedora this did the trick for me: `sudo dnf install e2fsprogs-devel imake gcc-c++`

############ STEP 1 download Windows 10 ISO from Microsoft ##############
WIN10_IMG="$(pwd)/windows10.iso" 
WIN10_IMG_ARCH="x64"

if [ ! -f "$WIN10_IMG" ]; then # if the windows10.iso has not been downloaded yet
    if [[ "$WIN10_IMG_ARCH" == "x86" ]] || [[ "$WIN10_IMG_ARCH" == "i386" ]] ; then
        echo "Retrieving the x86 Windows 10 iso URL..."
        WINDOWS_10_ISO_URL=$(curl -LsI -o /dev/null -w %{url_effective} "https://tb.rg-adguard.net/dl.php?go=7e583fea") # This strange looking URL actually redirects to a legit software-download.microsoft.com URL 
    else
        echo "Retrieving the x64 Windows 10 iso URL..."
        WINDOWS_10_ISO_URL=$(curl -LsI -o /dev/null -w %{url_effective} "https://tb.rg-adguard.net/dl.php?go=3dd1ce66") # This strange looking URL actually redirects to a legit software-download.microsoft.com URL 
    fi

    echo "Download URL: $WINDOWS_10_ISO_URL"
    echo "Making sure the URL comes from a trusted Microsoft domain..."
    if [[ $WINDOWS_10_ISO_URL == https://software-download.microsoft.com/* ]] ; then
        echo "Downloading the Windows 10 installation iso..."
        wget "$WINDOWS_10_ISO_URL" -O "$WIN10_IMG"
    else
        echo "URL validation failed. Please download the Windows 10 iso manually."
        exit 1
    fi
fi
#########################################################################


############## STEP 2 download and build the schily tools ###############

SCHILY_VERSION="2021-06-07"
SCHILY_ARCHIVE="schily-${SCHILY_VERSION}.tar.bz2"
SCHILY_DIR="./schily-tools"

if [ ! -f "${SCHILY_DIR}/mkisofs/OBJ/x86_64-linux-gcc/mkisofs" ]; then # if the mkisofs of Schily Tools has not been built yet
    sudo rm -rf "${SCHILY_DIR}"
    wget "https://altushost-swe.dl.sourceforge.net/project/schilytools/${SCHILY_ARCHIVE}" -O "${SCHILY_ARCHIVE}"
    tar -xf "${SCHILY_ARCHIVE}"
    rm "${SCHILY_ARCHIVE}"
    mv "schily-${SCHILY_VERSION}" "${SCHILY_DIR}"
    cd "${SCHILY_DIR}"
    ./Gmake.linux
    cd ..
    if [ ! -f "${SCHILY_DIR}/mkisofs/OBJ/x86_64-linux-gcc/mkisofs" ]; then
        echo "Building Schily Tools failed"
        exit 1
    fi
fi
#########################################################################


################# STEP 3 Extract the files from the ISO #################
TMP="./tmp"
ISO_FILES="${TMP}/iso-files"
ISO_MP="${TMP}/iso-mountpoint"
if [ ! -f "${ISO_FILES}/setup.exe" ]; then # If the Windows ISO hasn't been extracted yet
    sudo rm -rf "${TMP}"
    mkdir -p "${ISO_FILES}"
    mkdir -p "${ISO_MP}"
    sudo mount -t udf "${WIN10_IMG}" "${ISO_MP}"
    sudo cp -Rva ${ISO_MP}/* "${ISO_FILES}"
    sudo umount "${ISO_MP}"
fi
#########################################################################


################## STEP 4 Extract the EFI boot image ####################
# Extract boot load segment address and size
BOOT_LOAD_SEG="$(dumpet -i "${WIN10_IMG}" | grep "Media load segment: " | cut -d ':' -f2 | cut -d ' ' -f2)"
BOOT_LOAD_SIZE="$(dumpet -i "${WIN10_IMG}" | grep "Load Sectors: " | grep -o "[^:]*$" | cut -d ' ' -f2 | head -1)"

EFI_STARTING_SECTOR="$(dumpet -i "${WIN10_IMG}" | grep "Load LBA: " | grep -o "[^:]*$" | cut -d ' ' -f2 | tail -1)"
echo "EFI_STARTING_SECTOR: $EFI_STARTING_SECTOR"

sudo dd if="${WIN10_IMG}" of="${TMP}/efi.dmp" bs=2048 count=1 skip="${EFI_STARTING_SECTOR}"
EFI_BOOT_LOAD_SIZE="$(file "${TMP}/efi.dmp" | grep -oP 'sectors (d+)' | cut -d ' ' -f2)"
echo "EFI_BOOT_LOAD_SIZE: ${EFI_BOOT_LOAD_SIZE}"

sudo dd if="${WIN10_IMG}" of="${ISO_FILES}/efi/win_efi_boot.img" bs=2048 count="${EFI_BOOT_LOAD_SIZE}" skip="${EFI_STARTING_SECTOR}"
#########################################################################


######## STEP 5 Make changes to the files extracted from the ISO ########
# Make some arbitrary changes to the iso files
#sudo rm -rf "${ISO_FILES}/efi/microsoft/boot/cdboot.efi"
#sudo mv "${ISO_FILES}/efi/microsoft/boot/cdboot_noprompt.efi" "${ISO_FILES}/efi/microsoft/boot/cdboot.efi"
#sudo rm -rf "${ISO_FILES}/efi/microsoft/boot/efisys.bin"
#sudo mv "${ISO_FILES}/efi/microsoft/boot/efisys_noprompt.bin" "${ISO_FILES}/efi/microsoft/boot/efisys.bin"
#########################################################################


###### STEP 6 Build a new ISO using the extracted/modified files ########
sudo rm -f "${WIN10_IMG}.tmp.iso"
sudo "${SCHILY_DIR}/mkisofs/OBJ/x86_64-linux-gcc/mkisofs" 
  -no-emul-boot 
  -b boot/etfsboot.com 
  -boot-load-seg "${BOOT_LOAD_SEG}" 
  -boot-load-size "${BOOT_LOAD_SIZE}" 
  -eltorito-alt-boot 
  -no-emul-boot 
  -eltorito-boot "efi/win_efi_boot.img" 
  -boot-load-size 1 
  -iso-level 4 
  -UDF 
  -o "${WIN10_IMG}.tmp.iso" 
  "${ISO_FILES}"
#########################################################################


############ STEP 7 Remove the files exxtracted from the ISO ############
#sudo rm -f "${TMP}"
#########################################################################


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.