# This script is hosted on https://bypassnro.sougen.dev - a public mirror.
# Original: https://w1.zawa-lab.net/w
# Article: https://w1.zawa-lab.net/p/20260728_oobe_bypass/
# License: CC BY-NC-SA 4.0 by zawa-lab (https://w1.zawa-lab.net/)
# Usage: powershell -c "irm bypassnro.sougen.dev|iex"
<#
  oobe-localaccount.ps1  (ASCII only)

  At OOBE, press Shift+F10, then run:
      powershell -c "irm w1.zawa-lab.net/w|iex"

  Prompts for a local account name and password, generates
  unattend.xml, and re-runs OOBE through sysprep.

  Set DRYRUN=1 beforehand to stop just before sysprep:
      set DRYRUN=1
#>

$ErrorActionPreference = 'Stop'

$sysprep = "$env:SystemRoot\System32\Sysprep\sysprep.exe"
if (-not (Test-Path $sysprep)) {
    throw 'sysprep.exe not found. Run this inside OOBE.'
}

# ---- settings (edit to taste) ----
$TimeZone     = 'Tokyo Standard Time'
$InputLocale  = '0411:00000411'
$SystemLocale = 'ja-JP'
$UILanguage   = 'ja-JP'
$UserLocale   = 'ja-JP'
# ----------------------------------

Write-Host ''
Write-Host '=== Create local account ===' -ForegroundColor Cyan
Write-Host ''

# --- account name ---
while ($true) {
    $name = Read-Host 'User name'
    if ($name -notmatch '^[A-Za-z0-9][A-Za-z0-9_.-]{0,19}$') {
        Write-Host '  Letters, digits, _ . - only. Max 20 chars.' -ForegroundColor Yellow
        continue
    }
    if ($name -eq $env:COMPUTERNAME) {
        Write-Host '  Must not match the computer name.' -ForegroundColor Yellow
        continue
    }
    break
}

# --- password ---
function ConvertFrom-Secure([Security.SecureString]$s) {
    $b = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($s)
    try   { [Runtime.InteropServices.Marshal]::PtrToStringUni($b) }
    finally { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($b) }
}

while ($true) {
    $p1 = ConvertFrom-Secure (Read-Host 'Password (blank allowed)' -AsSecureString)
    $p2 = ConvertFrom-Secure (Read-Host 'Password (confirm)'       -AsSecureString)
    if ($p1 -ne $p2) {
        Write-Host '  Mismatch. Try again.' -ForegroundColor Yellow
        continue
    }
    break
}

# unattend expects Base64 of UTF-16LE (plaintext + 'Password')
$pwNode = if ([string]::IsNullOrEmpty($p1)) {
    ''
} else {
    $b64 = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($p1 + 'Password'))
    @"

            
              $b64
              false</PlainText>
            </Password>
"@
}

$xml = @"
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
  <settings pass="oobeSystem">
    <component name="Microsoft-Windows-International-Core"
               processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35"
               language="neutral" versionScope="nonSxS">
      <InputLocale>$InputLocale</InputLocale>
      <SystemLocale>$SystemLocale</SystemLocale>
      <UILanguage>$UILanguage</UILanguage>
      <UserLocale>$UserLocale</UserLocale>
    </component>

    <component name="Microsoft-Windows-Shell-Setup"
               processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35"
               language="neutral" versionScope="nonSxS"
               xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
      <TimeZone>$TimeZone</TimeZone>

      <UserAccounts>
        <LocalAccounts>
          <LocalAccount wcm:action="add">
            <Name>$name</Name>
            <DisplayName>$name</DisplayName>
            <Group>Administrators</Group>$pwNode
          </LocalAccount>
        </LocalAccounts>
      </UserAccounts>

      <OOBE>
        <HideEULAPage>true</HideEULAPage>
        <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
        <HideOnlineAccountScreens>true</HideOnlineAccountScreens>
        <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
        <ProtectYourPC>3</ProtectYourPC>
      </OOBE>

      <FirstLogonCommands>
        <SynchronousCommand wcm:action="add">
          <Order>1</Order>
          <Description>Remove answer files</Description>
          <CommandLine>cmd /c del /f /q "%SystemRoot%\Panther\unattend.xml" "%SystemRoot%\System32\Sysprep\unattend.xml"</CommandLine>
        </SynchronousCommand>
      </FirstLogonCommands>
    </component>
  </settings>
</unattend>
"@

$panther = "$env:SystemRoot\Panther"
$target  = "$panther\unattend.xml"

New-Item -ItemType Directory -Force -Path $panther | Out-Null
[IO.File]::WriteAllText($target, $xml, (New-Object Text.UTF8Encoding $false))
Copy-Item $target "$env:SystemRoot\System32\Sysprep\unattend.xml" -Force

# sanity check
[xml]$check = Get-Content $target
if (-not $check.unattend) { throw 'Generated XML is invalid.' }

Write-Host ''
Write-Host "Account '$name' defined. Answer file written to:" -ForegroundColor Green
Write-Host "  $target"
Write-Host ''

if ($env:DRYRUN -eq '1') {
    Write-Host 'DRYRUN=1 -- sysprep skipped. Nothing was rebooted.' -ForegroundColor Yellow
    exit 0
}

Write-Host 'Running sysprep. The machine will reboot shortly.' -ForegroundColor Green
Start-Sleep -Seconds 3

& $sysprep /oobe /reboot /unattend:$target