
Necesitaba crear una máquina virtual con Windows para revisar el proceso de instalación de Autopsy. Por una necesidad similar contaba con un ISO de instalación de Windows y decidí usarlo en UTM. La experiencia sirvió para varias cosas.
La primera de ellas fue ver lo limitado que está UTM en el manejo de la pantalla. Imposible agrandar la ventana sin que se «pixelee». Contrasta mucho con lo que ofrece Parallels, con el que se pueden cambiar las dimensiones de la ventana de la VM sin perder resolución.
En segundo lugar, la instalación de Windows que ofrece Parallels es muy rápida y sin tantas preguntas. Sin duda se trata de una versión curada. En 15 minutos está lista (incluida la descarga), a diferencia de los 45 que me llevó usar la imagen de disco en UTM.

En Parallels, creé una VM de Windows 11 ya activada como un template que clono cada vez que requiero una VM de Windows, que es mucho más rápido de hacer. Esto me evita la molesta ventana de activación y la marca de agua. Una molestia menor, pero que en ciertas ocasiones uno prefiere que no aparezcan. Mientras consideraba mover la licencia de Parallels que tengo (costosa, por cierto, pero que consideré una inversión necesaria en su momento), revisaba los pasos a seguir. Me parecieron demasiados y preferí revisar un «enfoque diferente».
Hace tiempo me topé con un video que explicaba una forma de activar Windows o algo así para uso local. Tomé nota del tema, pero hasta ahí. Así que busqué y encontré algo. No sé si es lo mismo que yo vi; recuerdo que era más «laborioso», pero ha resultado muy práctico. Ya he anotado lo que hice en mi página de notas de administración de Windows. Este fue el tercer punto.

Un último punto ha sido investigar qué hacen las instrucciones y la URL de activación del punto anterior. irm es un alias de Invoke-RestMethod y iex lo es de Invoke-Expression. La URL apunta a este script:
# This script is hosted on https://get.activated.win for https://massgrave.dev
# Having trouble launching this script? Check https://massgrave.dev for help.
if (-not $args) {
Write-Host ''
Write-Host 'Need help? Check our homepage: ' -NoNewline
Write-Host 'https://massgrave.dev' -ForegroundColor Green
Write-Host ''
}
& {
$psv = (Get-Host).Version.Major
$troubleshoot = 'https://massgrave.dev/troubleshoot'
if ($ExecutionContext.SessionState.LanguageMode.value__ -ne 0) {
$ExecutionContext.SessionState.LanguageMode
Write-Host "PowerShell is not running in Full Language Mode."
Write-Host "Help - https://gravesoft.dev/fix_powershell" -ForegroundColor White -BackgroundColor Blue
return
}
try {
[void][System.AppDomain]::CurrentDomain.GetAssemblies(); [void][System.Math]::Sqrt(144)
}
catch {
Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
Write-Host "Powershell failed to load .NET command."
Write-Host "Help - https://gravesoft.dev/in-place_repair_upgrade" -ForegroundColor White -BackgroundColor Blue
return
}
function Check3rdAV {
$cmd = if ($psv -ge 3) { 'Get-CimInstance' } else { 'Get-WmiObject' }
$avList = & $cmd -Namespace root\SecurityCenter2 -Class AntiVirusProduct | Where-Object { $_.displayName -notlike '*windows*' } | Select-Object -ExpandProperty displayName
if ($avList) {
Write-Host '3rd party Antivirus might be blocking the script - ' -ForegroundColor White -BackgroundColor Blue -NoNewline
Write-Host " $($avList -join ', ')" -ForegroundColor DarkRed -BackgroundColor White
}
}
function CheckFile {
param ([string]$FilePath)
if (-not (Test-Path $FilePath)) {
Check3rdAV
Write-Host "Failed to create MAS file in temp folder, aborting!"
Write-Host "Help - $troubleshoot" -ForegroundColor White -BackgroundColor Blue
throw
}
}
try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } catch {}
$URLs = @(
'https://raw.githubusercontent.com/massgravel/Microsoft-Activation-Scripts/ab6b572af940fa0ea4255b327eb6f69a274d6725/MAS/All-In-One-Version-KL/MAS_AIO.cmd',
'https://dev.azure.com/massgrave/Microsoft-Activation-Scripts/_apis/git/repositories/Microsoft-Activation-Scripts/items?path=/MAS/All-In-One-Version-KL/MAS_AIO.cmd&versionType=Commit&version=ab6b572af940fa0ea4255b327eb6f69a274d6725',
'https://git.activated.win/massgrave/Microsoft-Activation-Scripts/raw/commit/ab6b572af940fa0ea4255b327eb6f69a274d6725/MAS/All-In-One-Version-KL/MAS_AIO.cmd'
)
Write-Progress -Activity "Downloading..." -Status "Please wait"
$errors = @()
foreach ($URL in $URLs | Sort-Object { Get-Random }) {
try {
if ($psv -ge 3) {
$response = Invoke-RestMethod $URL
}
else {
$w = New-Object Net.WebClient
$response = $w.DownloadString($URL)
}
break
}
catch {
$errors += $_
}
}
Write-Progress -Activity "Downloading..." -Status "Done" -Completed
if (-not $response) {
Check3rdAV
foreach ($err in $errors) {
Write-Host "Error: $($err.Exception.Message)" -ForegroundColor Red
}
Write-Host "Failed to retrieve MAS from any of the available repositories, aborting!"
Write-Host "Check if antivirus or firewall is blocking the connection."
Write-Host "Help - $troubleshoot" -ForegroundColor White -BackgroundColor Blue
return
}
# Verify script integrity
$releaseHash = 'D60752A27BDED6887C5CEC88503F0F975ACB5BC849673693CA7BA7C95BCB3EF4'
$stream = New-Object IO.MemoryStream
$writer = New-Object IO.StreamWriter $stream
$writer.Write($response)
$writer.Flush()
$stream.Position = 0
$hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($stream)) -replace '-'
if ($hash -ne $releaseHash) {
Write-Warning "Hash ($hash) mismatch, aborting!`nReport this issue at $troubleshoot"
$response = $null
return
}
# Check for AutoRun registry which may create issues with CMD
$paths = "HKCU:\SOFTWARE\Microsoft\Command Processor", "HKLM:\SOFTWARE\Microsoft\Command Processor"
foreach ($path in $paths) {
if (Get-ItemProperty -Path $path -Name "Autorun" -ErrorAction SilentlyContinue) {
Write-Warning "Autorun registry found, CMD may crash! `nManually copy-paste the below command to fix...`nRemove-ItemProperty -Path '$path' -Name 'Autorun'"
}
}
$rand = [Guid]::NewGuid().Guid
$isAdmin = [bool]([Security.Principal.WindowsIdentity]::GetCurrent().Groups -match 'S-1-5-32-544')
$FilePath = if ($isAdmin) { "$env:SystemRoot\Temp\MAS_$rand.cmd" } else { "$env:USERPROFILE\AppData\Local\Temp\MAS_$rand.cmd" }
Set-Content -Path $FilePath -Value "@::: $rand `r`n$response"
CheckFile $FilePath
$env:ComSpec = "$env:SystemRoot\system32\cmd.exe"
$chkcmd = & $env:ComSpec /c "echo CMD is working"
if ($chkcmd -notcontains "CMD is working") {
Write-Warning "cmd.exe is not working.`nReport this issue at $troubleshoot"
}
if ($psv -lt 3) {
if (Test-Path "$env:SystemRoot\Sysnative") {
Write-Warning "Command is running with x86 Powershell, run it with x64 Powershell instead..."
return
}
$p = saps -FilePath $env:ComSpec -ArgumentList "/c """"$FilePath"" -el -qedit $args""" -Verb RunAs -PassThru
$p.WaitForExit()
}
else {
saps -FilePath $env:ComSpec -ArgumentList "/c """"$FilePath"" -el $args""" -Wait -Verb RunAs
}
CheckFile $FilePath
$FilePaths = @("$env:SystemRoot\Temp\MAS*.cmd", "$env:USERPROFILE\AppData\Local\Temp\MAS*.cmd")
foreach ($FilePath in $FilePaths) { Get-Item $FilePath -ErrorAction SilentlyContinue | Remove-Item }
} @args
