106 lines
4.3 KiB
PowerShell
106 lines
4.3 KiB
PowerShell
# =============================
|
|
# General MSIX / APPX / Bundle Auto Re-Sign Script
|
|
# =============================
|
|
|
|
param(
|
|
[Parameter(Mandatory=$true)]
|
|
[string]$PackagePath, # Input MSIX/APPX/BUNDLE
|
|
|
|
[string]$CertificateThumbprint = "", # Optional: Store cert thumbprint
|
|
[string]$PfxPath = "", # Optional: PFX file path
|
|
[string]$PfxPassword = "", # Optional: PFX password
|
|
[string]$OutputFolder = "" # Optional: output folder
|
|
)
|
|
|
|
# -----------------------------
|
|
# 1. Validate paths
|
|
# -----------------------------
|
|
if(-not (Test-Path $PackagePath)){ throw "Package file not found." }
|
|
$PackageExt = [IO.Path]::GetExtension($PackagePath).ToLower()
|
|
if($OutputFolder -eq ""){ $OutputFolder = Join-Path (Split-Path $PackagePath) "Resigned" }
|
|
if(-not (Test-Path $OutputFolder)){ New-Item -ItemType Directory -Path $OutputFolder | Out-Null }
|
|
|
|
# Detect SignTool.exe
|
|
$SignToolPaths = @(
|
|
"$env:ProgramFiles(x86)\Windows Kits\10\bin",
|
|
"$env:ProgramFiles\Windows Kits\10\bin",
|
|
"$env:ProgramFiles(x86)\Windows Kits\11\bin",
|
|
"$env:ProgramFiles\Windows Kits\11\bin"
|
|
)
|
|
$SignTool = $null
|
|
foreach($p in $SignToolPaths){
|
|
$st = Get-ChildItem -Path $p -Recurse -Filter "signtool.exe" -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
if($st){ $SignTool = $st.FullName; break }
|
|
}
|
|
if(-not $SignTool){ throw "SignTool.exe not found. Install Windows 10/11 SDK." }
|
|
Write-Host "Using SignTool: $SignTool"
|
|
|
|
# -----------------------------
|
|
# 2. Prepare temp folder
|
|
# -----------------------------
|
|
$TempDir = Join-Path $env:TEMP "Package_ReSign"
|
|
if(Test-Path $TempDir){ Remove-Item $TempDir -Recurse -Force }
|
|
New-Item -ItemType Directory -Path $TempDir | Out-Null
|
|
|
|
# -----------------------------
|
|
# 3. Handle single package vs bundle
|
|
# -----------------------------
|
|
$PackagesToSign = @()
|
|
switch($PackageExt){
|
|
".appx" { Copy-Item $PackagePath $OutputFolder; $PackagesToSign += Join-Path $OutputFolder (Split-Path $PackagePath -Leaf) }
|
|
".msix" { Copy-Item $PackagePath $OutputFolder; $PackagesToSign += Join-Path $OutputFolder (Split-Path $PackagePath -Leaf) }
|
|
".appxbundle" { makeappx unbundle /p $PackagePath /d $TempDir; $PackagesToSign += Get-ChildItem $TempDir -Recurse -Include *.appx | Select-Object -ExpandProperty FullName }
|
|
".msixbundle" { makeappx unbundle /p $PackagePath /d $TempDir; $PackagesToSign += Get-ChildItem $TempDir -Recurse -Include *.msix | Select-Object -ExpandProperty FullName }
|
|
default { throw "Unsupported package type: $PackageExt" }
|
|
}
|
|
|
|
# -----------------------------
|
|
# 4. Re-sign each package
|
|
# -----------------------------
|
|
# Get publisher string
|
|
if($CertificateThumbprint){
|
|
$Cert = Get-ChildItem Cert:\LocalMachine\My\$CertificateThumbprint
|
|
if(-not $Cert){ throw "Certificate not found in store." }
|
|
$NewPublisher = "CN=$($Cert.Subject -replace '^.*?=','')"
|
|
} elseif($PfxPath){
|
|
if(-not (Test-Path $PfxPath)){ throw "PFX file not found." }
|
|
$Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($PfxPath, $PfxPassword)
|
|
$NewPublisher = "CN=$($Cert.Subject -replace '^.*?=','')"
|
|
} else {
|
|
throw "Provide CertificateThumbprint or PfxPath"
|
|
}
|
|
|
|
Write-Host "Publisher to use: $NewPublisher"
|
|
|
|
foreach($pkg in $PackagesToSign){
|
|
Write-Host "Processing $pkg ..."
|
|
|
|
# Unpack individual package
|
|
$PkgTemp = Join-Path $TempDir ([IO.Path]::GetFileNameWithoutExtension($pkg))
|
|
if(-not (Test-Path $PkgTemp)){ New-Item -ItemType Directory -Path $PkgTemp | Out-Null }
|
|
makeappx unbundle /p $pkg /d $PkgTemp
|
|
|
|
# Update AppxManifest.xml
|
|
$Manifest = Join-Path $PkgTemp "AppxManifest.xml"
|
|
if(Test-Path $Manifest){
|
|
[xml]$Xml = Get-Content $Manifest
|
|
$Xml.Package.Identity.Publisher = $NewPublisher
|
|
$Xml.Save($Manifest)
|
|
}
|
|
|
|
# Repack package
|
|
$Ext = [IO.Path]::GetExtension($pkg)
|
|
$OutPkg = Join-Path $OutputFolder ((Split-Path $pkg -LeafBase) + "_Resigned" + $Ext)
|
|
makeappx bundle /d $PkgTemp /p $OutPkg
|
|
|
|
# Sign package
|
|
if($CertificateThumbprint){
|
|
& $SignTool sign /fd SHA256 /a /f "$($Cert.Thumbprint)" $OutPkg
|
|
} else {
|
|
& $SignTool sign /fd SHA256 /f $PfxPath /p $PfxPassword $OutPkg
|
|
}
|
|
|
|
Write-Host "Resigned package saved: $OutPkg"
|
|
}
|
|
|
|
Write-Host "All packages processed. Output folder: $OutputFolder" |