Skip to content

Commit

Permalink
Dev to Main: Refactor script for dynamic settings, registry and oscdi…
Browse files Browse the repository at this point in the history
…mg.exe fix (#12)

Refactor script for dynamic settings and registry fix

- Created wimutil-settings.json to store config for the project.
- Added dynamic loading of settings from wimutil-settings.json.
- Integrated branch-based configuration with fallback to default branch.
- Removed oscdimg.exe signing date function and only check hash value.
- Fixed GUI loading issue by setting the Internet Explorer "DisableFirstRunCustomize" registry entry at script start.
- Added configurl for main and dev branches and comment out the one not being used. (needs more work)
- Detect branch from configurl rather than scripturl
- Update README with new latest version
- Removed " " white space in launch command.
  • Loading branch information
memstechtips authored Nov 17, 2024
1 parent 301cb29 commit 96e6006
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 98 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ Contributions to this project are welcome! However, please understand that I pre
- **Create New ISO File** with [`oscdimg.exe`](https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/oscdimg-command-line-options)

> [!NOTE]
> This tool is currently in alpha (v0.0.1), and it's a work in progress. Any issues can be reported using the Issues tab.
> This tool is currently in alpha, and it's a work in progress. Any issues can be reported using the Issues tab.
### Versions

[![Latest Version](https://img.shields.io/badge/Version-0.0.1Alpha%20Latest-0078D4?style=for-the-badge&logo=github&logoColor=white)](https://github.com/memstechtips/WIMUtil/releases/tag/v0.0.1)
[![Latest Version](https://img.shields.io/badge/Version-0.0.2Alpha%20Latest-0078D4?style=for-the-badge&logo=github&logoColor=white)](https://github.com/memstechtips/WIMUtil/releases/tag/v0.0.2)

### Support the Project

Expand Down Expand Up @@ -46,7 +46,7 @@ To use **WIMUtil**, follow these steps to launch PowerShell as an Administrator
3. **Paste and Run the Command**:
- Copy the following command:
```powershell
irm "https://github.com/memstechtips/WIMUtil/raw/main/src/WIMUtil.ps1" | iex
irm "https://github.com/memstechtips/WIMUtil/raw/main/src/WIMUtil.ps1" | iex
```
- To paste into PowerShell, **Right-Click** or press **Ctrl + V** in the PowerShell or Terminal window. </br> This should automatically paste your copied command.
- Press **Enter** to execute the command.
Expand Down
13 changes: 13 additions & 0 deletions config/wimutil-settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"main": {
"xamlUrl": "https://github.com/memstechtips/WIMUtil/raw/main/xaml/WIMUtilGUI.xaml",
"oscdimgURL": "https://github.com/memstechtips/WIMUtil/raw/main/assets/executables/oscdimg.exe",
"expectedHash": "CACD23ABCD1E1B791F6280D7D86270FF8D4144728FF611033BAF5599D883731B"
},
"dev": {
"xamlUrl": "https://github.com/memstechtips/WIMUtil/raw/dev/xaml/WIMUtilGUI.xaml",
"oscdimgURL": "https://github.com/memstechtips/WIMUtil/raw/dev/assets/executables/oscdimg.exe",
"expectedHash": "CACD23ABCD1E1B791F6280D7D86270FF8D4144728FF611033BAF5599D883731B"
},
"defaultBranch": "main"
}
189 changes: 94 additions & 95 deletions src/WIMUtil.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ If (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]:
Try {
Start-Process PowerShell.exe -ArgumentList ("-NoProfile -ExecutionPolicy Bypass -File `"{0}`"" -f $PSCommandPath) -Verb RunAs
Exit
}
Catch {
Write-Host "Failed to run as Administrator. Please rerun with elevated privileges."
} Catch {
Write-Host "Failed to run as Administrator. Please rerun with elevated privileges." -ForegroundColor Red
Exit
}
}
Expand Down Expand Up @@ -33,13 +32,62 @@ function SetStatusText {

$script:currentScreenIndex = 1

# URL to the XAML file on GitHub
$xamlUrl = "https://github.com/memstechtips/WIMUtil/raw/main/xaml/WIMUtilGUI.xaml"
# Fix Internet Explorer Engine is Missing to Ensure GUI Launches
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Internet Explorer\Main" -Name "DisableFirstRunCustomize" -Value 2 -Force

# Explicitly define the configuration URL for the branch to use (commenting out the one not to use depending on branch)
$configUrl = "https://raw.githubusercontent.com/memstechtips/WIMUtil/main/config/wimutil-settings.json" # Main branch
# $configUrl = "https://raw.githubusercontent.com/memstechtips/WIMUtil/dev/config/wimutil-settings.json" # Dev branch

Write-Host "Using Configuration URL: $configUrl" -ForegroundColor Cyan

# Determine branch from the configuration URL
$currentBranch = "unknown" # Fallback value
if ($configUrl -match "https://raw.githubusercontent.com/memstechtips/WIMUtil/([^/]+)/config/wimutil-settings.json") {
$currentBranch = $matches[1]
Write-Host "Branch detected from Configuration URL: $currentBranch" -ForegroundColor Green
} else {
Write-Host "Unable to detect branch from Configuration URL. Using fallback." -ForegroundColor Yellow
}

# Download and load the XAML content
Write-Host "Using branch: $currentBranch" -ForegroundColor Cyan

# Load the configuration from the specified URL
try {
$config = (Invoke-WebRequest -Uri $configUrl -ErrorAction Stop).Content | ConvertFrom-Json
Write-Host "Configuration loaded successfully from $configUrl" -ForegroundColor Green
} catch {
Write-Host "Failed to load configuration from URL: $configUrl" -ForegroundColor Red
exit 1
}

# Fetch settings for the current branch
$branchConfig = $config.$currentBranch
if (-not $branchConfig) {
Write-Host "Branch $currentBranch not found in configuration file. Exiting script." -ForegroundColor Red
exit 1
}

Write-Host "Branch settings successfully loaded for: $currentBranch" -ForegroundColor Cyan

# Extract configuration settings
$xamlUrl = $branchConfig.xamlUrl
$oscdimgURL = $branchConfig.oscdimgURL
$expectedHash = $branchConfig.expectedHash

# Validate that required keys are present in the configuration
if (-not ($xamlUrl -and $oscdimgURL -and $expectedHash)) {
Write-Host "Configuration file is missing required settings. Exiting script." -ForegroundColor Red
exit 1
}

# Load XAML GUI
try {
if (-not $xamlUrl) {
throw "XAML URL is not set in the configuration."
}
# Download XAML content as a string
$xamlContent = (Invoke-WebRequest -Uri $xamlUrl).Content
$xamlContent = (Invoke-WebRequest -Uri $xamlUrl -ErrorAction Stop).Content

# Load the XAML using XamlReader.Load with a MemoryStream
$encoding = [System.Text.Encoding]::UTF8
Expand All @@ -52,13 +100,12 @@ try {

# Clean up stream
$xamlStream.Close()
}
catch {
Write-Host "XAML GUI loaded successfully." -ForegroundColor Green
} catch {
Write-Host "Error loading XAML from URL: $($_.Exception.Message)" -ForegroundColor Red
$readerOperationSuccessful = $false
exit 1
}


# Define the drag behavior for the window
function Window_MouseLeftButtonDown {
param (
Expand All @@ -80,7 +127,6 @@ function Update-ProgressIndicator {
$ProgressStep4.Fill = if ($currentScreen -ge 4) { "#FFDE00" } else { "#FFEB99" }
}


# Check if XAML loaded successfully
if ($readerOperationSuccessful) {
# Define Controls consistently using $window
Expand Down Expand Up @@ -433,12 +479,6 @@ if ($readerOperationSuccessful) {
[System.Windows.Forms.Application]::DoEvents()
}


# Define expected hash and signing date of oscdimg.exe file to determine if it's been tampered with
# Note: Different versions of oscdimg.exe will have different hashes and signing dates
$expectedHash = "CACD23ABCD1E1B791F6280D7D86270FF8D4144728FF611033BAF5599D883731B"
$expectedSignDate = [datetime]"2023-10-19T21:51:12"

# Function to get the SHA-256 hash of a file
function Get-FileHashValue {
param (
Expand All @@ -455,34 +495,6 @@ if ($readerOperationSuccessful) {
}
}

# Function to get the signing date of a file
function Get-SignatureDate {
param (
[string]$filePath
)

if (Test-Path -Path $filePath) {
try {
$signature = Get-AuthenticodeSignature -FilePath $filePath
if ($signature.Status -eq 'Valid') {
return $signature.SignerCertificate.NotBefore
}
else {
Write-Host "The file's digital signature is not valid."
return $null
}
}
catch {
Write-Host "Error retrieving the signature date: $_"
return $null
}
}
else {
Write-Host "File not found at path: $filePath"
return $null
}
}

# Check if oscdimg exists on the system without checking hash or date
function CheckOscdimg {
$oscdimgPath = "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg\oscdimg.exe"
Expand All @@ -501,62 +513,50 @@ if ($readerOperationSuccessful) {
[System.Windows.Forms.Application]::DoEvents() # Refresh the UI
}

# Function to download and validate oscdimg
function DownloadOscdimg {
SetStatusText -message "Preparing to download oscdimg..." -color $Script:SuccessColor -textBlock ([ref]$CreateISOStatusText)
[System.Windows.Forms.Application]::DoEvents()
# Function to download and validate oscdimg
function DownloadOscdimg {
SetStatusText -message "Preparing to download oscdimg..." -color $Script:SuccessColor -textBlock ([ref]$CreateISOStatusText)
[System.Windows.Forms.Application]::DoEvents()

$oscdimgURL = "https://github.com/memstechtips/WIMUtil/raw/main/assets/executables/oscdimg.exe"
$adkOscdimgPath = "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg"
$oscdimgFullPath = Join-Path -Path $adkOscdimgPath -ChildPath "oscdimg.exe"
$adkOscdimgPath = "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg"
$oscdimgFullPath = Join-Path -Path $adkOscdimgPath -ChildPath "oscdimg.exe"

# Ensure the ADK directory exists
if (!(Test-Path -Path $adkOscdimgPath)) {
New-Item -ItemType Directory -Path $adkOscdimgPath -Force | Out-Null
SetStatusText -message "Created directory for oscdimg at: $adkOscdimgPath" -color $Script:SuccessColor -textBlock ([ref]$CreateISOStatusText)
[System.Windows.Forms.Application]::DoEvents()
}
# Ensure the ADK directory exists
if (!(Test-Path -Path $adkOscdimgPath)) {
New-Item -ItemType Directory -Path $adkOscdimgPath -Force | Out-Null
SetStatusText -message "Created directory for oscdimg at: $adkOscdimgPath" -color $Script:SuccessColor -textBlock ([ref]$CreateISOStatusText)
[System.Windows.Forms.Application]::DoEvents()
}

# Download oscdimg to the ADK path
try {
SetStatusText -message "Downloading oscdimg to $adkOscdimgPath..." -color $Script:SuccessColor -textBlock ([ref]$CreateISOStatusText)
[System.Windows.Forms.Application]::DoEvents()
# Download oscdimg to the ADK path
try {
SetStatusText -message "Downloading oscdimg from: $oscdimgURL" -color $Script:SuccessColor -textBlock ([ref]$CreateISOStatusText)
[System.Windows.Forms.Application]::DoEvents()

(New-Object System.Net.WebClient).DownloadFile($oscdimgURL, $oscdimgFullPath)
SetStatusText -message "oscdimg downloaded successfully." -color $Script:SuccessColor -textBlock ([ref]$CreateISOStatusText)

# Verify the file's hash
$actualHash = Get-FileHashValue -filePath $oscdimgFullPath
if ($actualHash -ne $expectedHash) {
SetStatusText -message "Hash mismatch! oscdimg may not be from Microsoft." -color $Script:ErrorColor -textBlock ([ref]$CreateISOStatusText)
Write-Host "Expected Hash: $expectedHash"
Write-Host "Actual Hash: $actualHash"
Remove-Item -Path $oscdimgFullPath -Force
return
}

# Verify the file's signature date
$actualSignDate = Get-SignatureDate -filePath $oscdimgFullPath
if ($actualSignDate -ne $expectedSignDate) {
SetStatusText -message "Signature date mismatch! oscdimg may not be from Microsoft." -color $Script:ErrorColor -textBlock ([ref]$CreateISOStatusText)
Write-Host "Expected Sign Date: $expectedSignDate"
Write-Host "Actual Sign Date: $actualSignDate"
Remove-Item -Path $oscdimgFullPath -Force
return
}

# File is valid, enable the Create ISO button
SetStatusText -message "oscdimg verified and ready for use." -color $Script:SuccessColor -textBlock ([ref]$CreateISOStatusText)
$GetoscdimgButton.IsEnabled = $false
$CreateISOButton.IsEnabled = $true
}
catch {
SetStatusText -message "Failed to download oscdimg: $($_.Exception.Message)" -color $Script:ErrorColor -textBlock ([ref]$CreateISOStatusText)
Write-Host "oscdimg downloaded successfully from: $oscdimgURL"

# Verify the file's hash
$actualHash = Get-FileHashValue -filePath $oscdimgFullPath
if ($actualHash -ne $expectedHash) {
SetStatusText -message "Hash mismatch! oscdimg may not be from Microsoft." -color $Script:ErrorColor -textBlock ([ref]$CreateISOStatusText)
Write-Host "Expected Hash: $expectedHash"
Write-Host "Actual Hash: $actualHash"
Remove-Item -Path $oscdimgFullPath -Force
return
}

[System.Windows.Forms.Application]::DoEvents()
# File is valid, enable the Create ISO button
SetStatusText -message "oscdimg verified and ready for use." -color $Script:SuccessColor -textBlock ([ref]$CreateISOStatusText)
$GetoscdimgButton.IsEnabled = $false
$CreateISOButton.IsEnabled = $true
} catch {
SetStatusText -message "Failed to download oscdimg: $($_.Exception.Message)" -color $Script:ErrorColor -textBlock ([ref]$CreateISOStatusText)
}

[System.Windows.Forms.Application]::DoEvents()
}

# Define the location selection function
function SelectNewISOLocation {
# Prompt the user for ISO save location
Expand Down Expand Up @@ -619,7 +619,6 @@ if ($readerOperationSuccessful) {
$SelectISOLocationButton.Add_Click({ SelectNewISOLocation })
$CreateISOButton.Add_Click({ CreateISO })


# Event handler for the Next button
# Next button to navigate to the next screen
$NextButton.Add_Click({
Expand Down Expand Up @@ -675,4 +674,4 @@ else {
Write-Host "Failed to load the XAML file. Exiting script." -ForegroundColor Red
Pause
exit 1
}
}

0 comments on commit 96e6006

Please sign in to comment.