From e1332680d6722250d5472d7e55d9d3f6b8fd09d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Tue, 25 Feb 2025 21:09:19 +0100 Subject: [PATCH] Add WinPE based exploitation environment --- .gitignore | 1 + Makefile | 62 +++++++++++++++++++ pxe/smb/winpe/create-bcd-winpe1.bat | 19 ++++++ pxe/smb/winpe/create-bcd-winpe2.bat | 24 ++++++++ pxe/start-pxe-winpe.sh | 46 ++++++++++++++ winpe/build-dislocker-metadata.sh | 93 +++++++++++++++++++++++++++++ winpe/build-search-vmk.sh | 17 ++++++ winpe/download-winpe.sh | 33 ++++++++++ 8 files changed, 295 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 pxe/smb/winpe/create-bcd-winpe1.bat create mode 100644 pxe/smb/winpe/create-bcd-winpe2.bat create mode 100755 pxe/start-pxe-winpe.sh create mode 100755 winpe/build-dislocker-metadata.sh create mode 100755 winpe/build-search-vmk.sh create mode 100755 winpe/download-winpe.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..adb36c8 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.exe \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..109a3dc --- /dev/null +++ b/Makefile @@ -0,0 +1,62 @@ +# Folders +PXE ?= ./pxe +TFTP = ${PXE}/tftp +SMB = ${PXE}/smb + +# Artifacts Linux +INITRAMFS = ${TFTP}/alpine-initrd.xz +KERNEL = ${TFTP}/linux +SHIM = ${TFTP}/shimx64.efi +GRUB = ${TFTP}/grubx64.efi + +# Artifacts WinPE +BOOT_SDI = ${TFTP}/Boot/boot.sdi +BOOT_WIM = ${TFTP}/Boot/boot.wim +DUMPIT_EXE = ${SMB}/winpe/DumpIt.exe +SEARCH_VMK_EXE = ${SMB}/winpe/search-vmk.exe +DISLOCKER_METADATA_EXE = ${SMB}/winpe/dislocker-metadata.exe + +all: linux winpe + +linux: ${SHIM} ${GRUB} ${KERNEL} ${INITRAMFS} + @echo "Building Linux based bitpixie exploitation components..." + +${INITRAMFS} ${KERNEL}: + @echo "Preparing initramfs and kernel..." + linux/initramfs/bitpixie build + linux/initramfs/bitpixie deploy + +${SHIM} ${GRUB}: + @echo "Preparing shim and GRUB..." + docker run --platform linux/amd64 --rm -v "${PWD}/linux/bootloader:/build" -v "${PXE}":/mnt -w /root \ + alpine:3.20.3 "/build/download.sh" + +winpe: ${BOOT_SDI} ${BOOT_WIM} ${DUMPIT_EXE} ${SEARCH_VMK_EXE} ${DISLOCKER_METADATA_EXE} + @echo "Building WinPE based bitpixie exploitation components..." + +${BOOT_SDI} ${BOOT_WIM}: + @echo "Preparing Windows boot.{sdi,wim} files..." + docker run --privileged --platform linux/amd64 --rm -v "${PWD}/winpe:/build" -v "${PXE}":/mnt -w /root \ + alpine:3.20.3 "/build/download-winpe.sh" + +${DUMPIT_EXE}: + @echo "Please download Magnet DumpIt for Windows" + @echo "\n https://www.magnetforensics.com/resources/magnet-dumpit-for-windows/\n" + @echo "And place it into $@\n" + @exit 1 + +${SEARCH_VMK_EXE}: + @echo "Bulding $@..." + docker run --platform linux/amd64 --rm -v "${PWD}/search-vmk:/src" -v "${PWD}/winpe:/build" -v "${PXE}":/mnt -w /root \ + alpine:3.20.3 "/build/build-search-vmk.sh" + +${DISLOCKER_METADATA_EXE}: + @echo "Bulding $@..." + docker run --platform linux/amd64 --rm -v "${PWD}/winpe:/build" -v "${PXE}":/mnt -w /root \ + alpine:3.20.3 "/build/build-dislocker-metadata.sh" + +clean: + @rm -f "${SHIM}" "${GRUB}" "${KERNEL}" "${INITRAMFS}" + @rm -f "${BOOT_SDI}" "${BOOT_WIM}" "${SEARCH_VMK_EXE}" "${DISLOCKER_METADATA_EXE}" + +.PHONY: all linux winpe clean diff --git a/pxe/smb/winpe/create-bcd-winpe1.bat b/pxe/smb/winpe/create-bcd-winpe1.bat new file mode 100644 index 0000000..8fdae58 --- /dev/null +++ b/pxe/smb/winpe/create-bcd-winpe1.bat @@ -0,0 +1,19 @@ +REM @echo off + +bcdedit /export BCD_winpe1 + +bcdedit /store BCD_winpe1 /create /d "softreboot" /application startup > GUID.txt + +for /F "tokens=2 delims={}" %%i in (GUID.txt) do (set REBOOT_GUID=%%i) +del GUID.txt + +bcdedit /store BCD_winpe1 /set {%REBOOT_GUID%} path "\bootmgfw-stage2.efi" +bcdedit /store BCD_winpe1 /set {%REBOOT_GUID%} device boot +bcdedit /store BCD_winpe1 /set {%REBOOT_GUID%} pxesoftreboot yes + +bcdedit /store BCD_winpe1 /set {default} recoveryenabled yes +bcdedit /store BCD_winpe1 /set {default} recoverysequence {%REBOOT_GUID%} +bcdedit /store BCD_winpe1 /set {default} path "\\" +bcdedit /store BCD_winpe1 /set {default} winpe yes + +bcdedit /store BCD_winpe1 /displayorder {%REBOOT_GUID%} /addlast diff --git a/pxe/smb/winpe/create-bcd-winpe2.bat b/pxe/smb/winpe/create-bcd-winpe2.bat new file mode 100644 index 0000000..f368a37 --- /dev/null +++ b/pxe/smb/winpe/create-bcd-winpe2.bat @@ -0,0 +1,24 @@ +REM @echo off + +bcdedit /export BCD_winpe2 + +bcdedit /store BCD_winpe2 /create {ramdiskoptions} /d "Ramdisk options" +bcdedit /store BCD_winpe2 /set {ramdiskoptions} ramdisksdidevice boot +bcdedit /store BCD_winpe2 /set {ramdiskoptions} ramdisksdipath \Boot\boot.sdi + +bcdedit /store BCD_winpe2 /create /d "winpe boot image" /application osloader > GUID.txt + +for /F "tokens=2 delims={}" %%i in (GUID.txt) do (set REBOOT_GUID=%%i) +del GUID.txt + +bcdedit /store BCD_winpe2 /set {%REBOOT_GUID%} device ramdisk=[boot]\Boot\boot.wim,{ramdiskoptions} + +bcdedit /store BCD_winpe2 /set {%REBOOT_GUID%} path \Windows\System32\winload.efi +bcdedit /store BCD_winpe2 /set {%REBOOT_GUID%} osdevice ramdisk=[boot]\Boot\boot.wim,{ramdiskoptions} +bcdedit /store BCD_winpe2 /set {%REBOOT_GUID%} systemroot \Windows +bcdedit /store BCD_winpe2 /set {%REBOOT_GUID%} detecthal yes +bcdedit /store BCD_winpe2 /set {%REBOOT_GUID%} winpe yes + +bcdedit /store BCD_winpe2 /displayorder {%REBOOT_GUID%} /addlast +bcdedit /store BCD_winpe2 /default {%REBOOT_GUID%} +bcdedit /store BCD_winpe2 /set {bootmgr} timeout 0 diff --git a/pxe/start-pxe-winpe.sh b/pxe/start-pxe-winpe.sh new file mode 100755 index 0000000..f1f8f0d --- /dev/null +++ b/pxe/start-pxe-winpe.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +[ $# -eq 0 ] && echo "usage: $0 " && exit 1 + +scriptpath="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +interface=$1 + +#sudo ip a add 10.13.37.100/24 dev $interface + +cat <<'EOF' > "$scriptpath/dnsmasq.winpe.gdb" +set breakpoint pending on +break open +break open +condition 1 $_regex(file, ".*/bootmgfw\\.efi$") +commands 1 + print "Preparing stage 1" + disable 1 + enable 2 + shell ln -sf BCD_winpe1 smb/BCD + continue +end +condition 2 $_regex(file, ".*/bootmgfw-stage2\\.efi$") +commands 2 + print "Preparing stage 2" + disable 2 + # would restore initial state, but might interfere, restart script instead + #enable 1 + shell ln -sf BCD_winpe2 smb/BCD + continue +end +catch load +commands + enable 1 + disable 2 + continue +end +run +EOF + +sudo gdb -x dnsmasq.winpe.gdb --args dnsmasq --no-daemon \ + --interface=$interface \ + --dhcp-range=10.13.37.100,10.13.37.200,255.255.255.0,1h \ + --dhcp-boot=bootmgfw.efi \ + --enable-tftp \ + --tftp-root="$scriptpath/tftp" \ + --log-dhcp diff --git a/winpe/build-dislocker-metadata.sh b/winpe/build-dislocker-metadata.sh new file mode 100755 index 0000000..e0df507 --- /dev/null +++ b/winpe/build-dislocker-metadata.sh @@ -0,0 +1,93 @@ +#!/bin/sh +set -e + +__() { printf "\n\033[1;32m* %s [%s]\033[0m\n" "$1" "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"; } + +__ "Installing required tools" + +apk add make cmake mingw-w64-gcc + +__ "Getting Mbed TLS source" + + +wget "https://github.com/Mbed-TLS/mbedtls/archive/refs/tags/mbedtls-3.6.2.tar.gz" -O mbedtls.tar.gz \ + && echo 'a3c959773bc5d5b22353bc605e96d92fae2eac486dcaf46990412b84a1a0fb5f mbedtls.tar.gz' \ + | sha256sum -c || exit 1 + +export DESTDIR=$(pwd)/build +mkdir -p ${DESTDIR} +tar xf mbedtls.tar.gz && cd mbedtls-* + +__ "Building Mbed TLS" + +make CC=x86_64-w64-mingw32-gcc AR=x86_64-w64-mingw32-ar WINDOWS_BUILD=1 lib + +mkdir -p ${DESTDIR}/include/mbedtls +cp -rp include/mbedtls ${DESTDIR}/include +mkdir -p ${DESTDIR}/include/psa +cp -rp include/psa ${DESTDIR}/include + +mkdir -p ${DESTDIR}/lib +cp -RP library/libmbedtls.* ${DESTDIR}/lib +cp -RP library/libmbedx509.* ${DESTDIR}/lib +cp -RP library/libmbedcrypto.* ${DESTDIR}/lib + +cd - + +__ "Crating CMake toolchain file" + +cat <<'EOF' > mingw-w64-x86_64.cmake +# Sample toolchain file for building for Windows from an Ubuntu Linux system. +# +# Typical usage: +# *) install cross compiler: `sudo apt-get install mingw-w64` +# *) cd build +# *) cmake -DCMAKE_TOOLCHAIN_FILE=~/mingw-w64-x86_64.cmake .. +# This is free and unencumbered software released into the public domain. + +set(CMAKE_SYSTEM_NAME Windows) +set(TOOLCHAIN_PREFIX x86_64-w64-mingw32) + +# cross compilers to use for C, C++ and Fortran +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++) +set(CMAKE_Fortran_COMPILER ${TOOLCHAIN_PREFIX}-gfortran) +set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres) + +# target environment on the build host system +set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX} MBED_TLS_DIR) + +# modify default behavior of FIND_XXX() commands +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +EOF + +sed -i "s,MBED_TLS_DIR,$DESTDIR,g" mingw-w64-x86_64.cmake + +__ "Getting dislocker source" + + +wget https://github.com/martanne/dislocker-metadata-win32/archive/dbb4545a368fc695e3020b149bd0f381234afe0b.tar.gz -O "dislocker.tar.gz" \ + && echo "a55377715ee988df9ef3c60a92eaa704cd2c098b74f1d8c6494fcb098b634be6 dislocker.tar.gz" \ + | sha256sum -c || exit 1 + +tar xf dislocker.tar.gz + +__ "Building dislocker" + + +cd dislocker-* + +cmake -DCMAKE_TOOLCHAIN_FILE=../mingw-w64-x86_64.cmake -DCMAKE_INSTALL_PREFIX=/tmp/dislocker -DWITH_FUSE=OFF -DWITH_RUBY=OFF + +x86_64-w64-mingw32-gcc -I./include -I${DESTDIR}/include -DPROGNAME=\"dislocker-metadata\" \ + -DAUTHOR=\"Romain\ Coltel\" -DVERSION=\"0.7.2-unsupported\" -D__OS=\"Windows\" \ + -D__ARCH=\"x86_64\" src/dislocker-metadata.c src/metadata/*.c src/common.c \ + src/ntfs/clock.c src/ntfs/encoding.c src/encryption/crc32.c src/encryption/aes-xts.c \ + src/encryption/decrypt.c src/encryption/diffuser.c src/xstd/xstdio.c src/xstd/xstdlib.c \ + -L${DESTDIR}/lib -lmbedtls -lmbedcrypto -lmbedx509 -o dislocker-metadata + +__ "Copying artifacts to SMB directory" + +cp dislocker-metadata.exe /mnt/smb/winpe diff --git a/winpe/build-search-vmk.sh b/winpe/build-search-vmk.sh new file mode 100755 index 0000000..95828be --- /dev/null +++ b/winpe/build-search-vmk.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -e + +__() { printf "\n\033[1;32m* %s [%s]\033[0m\n" "$1" "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"; } + +__ "Installing required tools" + +apk add make mingw-w64-gcc + +__ "Building search-vmk" + +cd /src +make windows + +__ "Copying artifacts to SMB directory" + +cp search-vmk.exe /mnt/smb/winpe diff --git a/winpe/download-winpe.sh b/winpe/download-winpe.sh new file mode 100755 index 0000000..198fc31 --- /dev/null +++ b/winpe/download-winpe.sh @@ -0,0 +1,33 @@ +#!/bin/sh +set -e + +__() { printf "\n\033[1;32m* %s [%s]\033[0m\n" "$1" "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"; } + +__ "Installing required tools" + +apk add bash curl uuidgen qemu-img jq wimlib + +__ "Fetching Quickemu" + +wget "https://github.com/quickemu-project/quickemu/archive/refs/tags/4.9.7.tar.gz" -O quickemu.tar.gz \ + && echo '38a93301a2b233bc458c62d1228d310a9c29c63c10d008c2905029ca66188606 quickemu.tar.gz' \ + | sha256sum -c || exit 1 + +tar xzf quickemu.tar.gz + +__ "Fetching Windows 11" + +./quickemu-*/quickget --download windows 11 + +__ "Extracting artifacts from Windows ISO" + +mkdir iso +mount -o loop,ro Win11_24H2_EnglishInternational_x64.iso iso +cp iso/sources/boot.wim . +wiminfo boot.wim 1 --boot +wiminfo boot.wim + +__ "Copying artifacts to TFTP directory" + +cp boot.wim /mnt/tftp/Boot +cp iso/boot/boot.sdi /mnt/tftp/Boot