polish: UTF-8 batch scripts, drop redundant set-vnc-password, robust vnc password probe
- run.bat / open-firewall.bat: UTF-8 (no BOM) + chcp 65001 instead of cp866/chcp 866. - scripts/set-vnc-password.bat: removed (run.bat syncs the UltraVNC password via ensure-vnc-password.ps1). - scripts/ensure-vnc-password.ps1: use a real RFB VNC-Auth probe to 127.0.0.1:5900 to decide if the password already matches (no UAC when it does); set via createpassword/setpasswd + service restart only when it differs. Works for any password length (no stored-password encoding assumptions). - AGENTS.md: .bat encoding convention updated to UTF-8/chcp 65001; drop set-vnc-password refs.
This commit is contained in:
@@ -1,59 +1,71 @@
|
||||
# ensure-vnc-password.ps1 - keep the UltraVNC service VNC password in sync
|
||||
# with the password the user types in run.bat. Called from run.bat.
|
||||
# ensure-vnc-password.ps1 - keep the UltraVNC VNC password in sync with the
|
||||
# password the user types in run.bat. Called from run.bat.
|
||||
#
|
||||
# It only WRITES when the password actually differs (so a normal launch with
|
||||
# the same password does nothing and asks for NO admin rights). When it must
|
||||
# change the password it re-launches itself elevated (one UAC prompt) and
|
||||
# restarts the uvnc_service so the new password takes effect.
|
||||
# It checks whether the running VNC server already ACCEPTS the given password
|
||||
# (a real RFB VNC-Auth handshake against 127.0.0.1:5900 - the same mechanism
|
||||
# noVNC uses). If it does, nothing happens and NO admin rights are needed.
|
||||
# If it does not (or no server is up), it sets the UltraVNC service password
|
||||
# to the given value (one UAC prompt) and restarts uvnc_service so it reloads.
|
||||
#
|
||||
# Usage: powershell -NoProfile -ExecutionPolicy Bypass -File ensure-vnc-password.ps1 -Password "<pw>"
|
||||
# Exit codes: 0 = password matches (or was set OK); 1 = could not set it.
|
||||
# Exit codes: 0 = password already accepted (or set OK); 1 = could not set it.
|
||||
|
||||
param([Parameter(Mandatory=$true)][string]$Password)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ini = Join-Path $env:ProgramData "UltraVNC\ultravnc.ini"
|
||||
|
||||
function Write-Info($m){ Write-Host "ensure-vnc-password: $m" }
|
||||
|
||||
if (-not (Test-Path $ini)) {
|
||||
# No installed UltraVNC service config (e.g. portable copy / TightVNC) - nothing to sync.
|
||||
Write-Info "no %ProgramData%\UltraVNC\ultravnc.ini - nothing to sync."
|
||||
exit 0
|
||||
}
|
||||
|
||||
# --- VNC password obfuscation: DES-ECB(key=bitrev([23,82,107,6,35,78,88,7]), pw8) + 1-byte checksum ---
|
||||
# ---- bit-reverse a byte (VNC key bytes are bit-reversed) ----
|
||||
function Invoke-BitRev([byte]$b){ $r=0; for($i=0;$i -lt 8;$i++){ $r = $r -bor ((($b -shr $i) -band 1) -shl (7-$i)) }; return [byte]$r }
|
||||
function Get-ExpectedPasswd([string]$pw){
|
||||
$fixedkey = [byte[]](23,82,107,6,35,78,88,7)
|
||||
$kr = New-Object byte[] 8; for($i=0;$i -lt 8;$i++){ $kr[$i] = Invoke-BitRev $fixedkey[$i] }
|
||||
$pb = [System.Text.Encoding]::ASCII.GetBytes($pw)
|
||||
if ($pb.Length -gt 8) { $pb = $pb[0..7] }
|
||||
$plain = New-Object byte[] 8; for($i=0;$i -lt 8;$i++){ if($i -lt $pb.Length){ $plain[$i] = $pb[$i] } }
|
||||
$des = New-Object System.Security.Cryptography.DESCryptoServiceProvider
|
||||
$des.Mode = [System.Security.Cryptography.CipherMode]::ECB
|
||||
$des.Padding = [System.Security.Cryptography.PaddingMode]::None
|
||||
$des.Key = $kr
|
||||
$cipher = $des.CreateEncryptor().TransformFinalBlock($plain,0,8)
|
||||
$sum = 0; foreach($b in $cipher){ $sum = ($sum + $b) -band 0xFF }
|
||||
$h = ($cipher | ForEach-Object { $_.ToString("X2") }) -join ""
|
||||
return $h + $sum.ToString("X2")
|
||||
|
||||
# ---- real RFB VNC-Auth probe. Returns 'ok','rejected','unreachable','noserver' ----
|
||||
function Test-VncAuth([string]$pw,[string]$target,[int]$port){
|
||||
$c = New-Object System.Net.Sockets.TcpClient
|
||||
try { $c.Connect($target,$port) } catch { return 'unreachable' }
|
||||
try {
|
||||
$s = $c.GetStream(); $s.ReadTimeout = 8000; $s.WriteTimeout = 8000
|
||||
$rb = New-Object byte[] 64
|
||||
$got = 0
|
||||
while($got -lt 12){ $n = $s.Read($rb,$got,12-$got); if($n -le 0){ return 'unreachable' }; $got += $n }
|
||||
if (-not ([System.Text.Encoding]::ASCII.GetString($rb,0,12).StartsWith("RFB "))) { return 'noserver' }
|
||||
$s.Write([System.Text.Encoding]::ASCII.GetBytes("RFB 003.008`n"),0,12)
|
||||
$n = $s.Read($rb,0,64); if($n -lt 1){ return 'unreachable' }
|
||||
$numTypes = $rb[0]
|
||||
if($numTypes -eq 0 -or $n -lt (1+$numTypes)){ return 'noserver' }
|
||||
$types = $rb[1..($numTypes)]
|
||||
if(-not ($types -contains 2)){ return 'noserver' } # VNC-Auth not offered (e.g. MS-Logon only)
|
||||
$s.Write([byte[]](2),0,1) # choose VNC-Auth
|
||||
$got = 0
|
||||
while($got -lt 16){ $n = $s.Read($rb,$got,16-$got); if($n -le 0){ return 'unreachable' }; $got += $n }
|
||||
$challenge = $rb[0..15]
|
||||
$pb = [System.Text.Encoding]::ASCII.GetBytes($pw)
|
||||
if($pb.Length -gt 8){ $pb = $pb[0..7] }
|
||||
$key = New-Object byte[] 8
|
||||
for($i=0;$i -lt 8;$i++){ $kb = if($i -lt $pb.Length){[int]$pb[$i]}else{0}; $key[$i] = Invoke-BitRev ([byte]$kb) }
|
||||
$des = New-Object System.Security.Cryptography.DESCryptoServiceProvider
|
||||
$des.Mode = [System.Security.Cryptography.CipherMode]::ECB
|
||||
$des.Padding = [System.Security.Cryptography.PaddingMode]::None
|
||||
$des.Key = $key
|
||||
$resp = $des.CreateEncryptor().TransformFinalBlock($challenge,0,16)
|
||||
$s.Write($resp,0,16)
|
||||
$n = $s.Read($rb,0,4); if($n -lt 4){ return 'rejected' }
|
||||
$status = ($rb[0]*16777216)+($rb[1]*65536)+($rb[2]*256)+$rb[3]
|
||||
if($status -eq 0){ return 'ok' } else { return 'rejected' }
|
||||
} finally { $c.Close() }
|
||||
}
|
||||
|
||||
function Get-CurrentPasswd{
|
||||
$line = Get-Content $ini -ErrorAction SilentlyContinue | Where-Object { $_ -match '^\s*passwd\s*=' -and $_ -notmatch 'passwd2' } | Select-Object -First 1
|
||||
if (-not $line) { return "" }
|
||||
return ($line -split '=',2)[1].Trim()
|
||||
}
|
||||
|
||||
$expected = Get-ExpectedPasswd $Password
|
||||
$current = Get-CurrentPasswd
|
||||
if ($current -ieq $expected) {
|
||||
Write-Info "UltraVNC password already matches - nothing to do."
|
||||
$probe = Test-VncAuth $Password "127.0.0.1" 5900
|
||||
if($probe -eq 'ok'){
|
||||
Write-Info "UltraVNC already accepts this password - nothing to do."
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Info "UltraVNC password differs (ini=$current, expected=$expected). Need to set it (admin required)."
|
||||
Write-Info "UltraVNC password needs setting (probe=$probe). Need admin."
|
||||
|
||||
# Locate UltraVNC install + password tools.
|
||||
$uvncDirs = @(
|
||||
@@ -63,64 +75,56 @@ $uvncDirs = @(
|
||||
"${env:ProgramFiles(x86)}\UltraVNC"
|
||||
)
|
||||
$uvnc = $uvncDirs | Where-Object { Test-Path "$_\winvnc.exe" } | Select-Object -First 1
|
||||
if (-not $uvnc) { Write-Info "UltraVNC install not found - cannot set password."; exit 1 }
|
||||
if(-not $uvnc){ Write-Info "UltraVNC install not found - cannot set password."; exit 1 }
|
||||
|
||||
# Are we admin?
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
|
||||
if (-not $isAdmin) {
|
||||
Write-Info "re-launching elevated to set the password..."
|
||||
$p = Start-Process -FilePath "powershell.exe" -Verb RunAs -Wait -PassThru -ArgumentList @("-NoProfile","-ExecutionPolicy","Bypass","-File","`"$PSCommandPath`"","-Password","`"$Password`"")
|
||||
if ($p.ExitCode -ne 0) { Write-Info "elevated run failed (exit $($p.ExitCode))."; exit 1 }
|
||||
$now = Get-CurrentPasswd
|
||||
if ($now -ieq $expected) { Write-Info "password set OK."; exit 0 }
|
||||
Write-Info "password still not updated after elevated run (ini=$now)."; exit 1
|
||||
function Get-IniPasswd{
|
||||
$line = Get-Content $ini -ErrorAction SilentlyContinue | Where-Object { $_ -match '^\s*passwd\s*=' -and $_ -notmatch 'passwd2' } | Select-Object -First 1
|
||||
if(-not $line){ return "" }
|
||||
return ($line -split '=',2)[1].Trim()
|
||||
}
|
||||
|
||||
# --- admin path: actually set the password ---
|
||||
function Set-Tool{
|
||||
param([string]$exe)
|
||||
if (-not (Test-Path $exe)) { return $false }
|
||||
function Invoke-SetTool([string]$exe,[string]$pw){
|
||||
if(-not (Test-Path $exe)){ return $false }
|
||||
try {
|
||||
$psi = New-Object System.Diagnostics.ProcessStartInfo
|
||||
$psi.FileName = $exe
|
||||
$psi.Arguments = "`"$Password`""
|
||||
$psi.UseShellExecute = $false
|
||||
$psi.FileName = $exe; $psi.Arguments = "`"$pw`""; $psi.UseShellExecute = $false
|
||||
$p = [System.Diagnostics.Process]::Start($psi)
|
||||
if (-not $p.WaitForExit(5000)) { $p.Kill() }
|
||||
if(-not $p.WaitForExit(5000)){ $p.Kill() }
|
||||
return ($p.ExitCode -eq 0)
|
||||
} catch { return $false }
|
||||
}
|
||||
|
||||
$ok = $false
|
||||
if (Set-Tool (Join-Path $uvnc "createpassword.exe")) { $ok = $true }
|
||||
$now = Get-CurrentPasswd
|
||||
if ($now -ine $expected -and (Test-Path (Join-Path $uvnc "setpasswd.exe"))) {
|
||||
# fallback to setpasswd.exe "<pw>"
|
||||
try {
|
||||
$psi = New-Object System.Diagnostics.ProcessStartInfo
|
||||
$psi.FileName = Join-Path $uvnc "setpasswd.exe"
|
||||
$psi.Arguments = "`"$Password`""
|
||||
$psi.UseShellExecute = $false
|
||||
$p = [System.Diagnostics.Process]::Start($psi)
|
||||
if (-not $p.WaitForExit(5000)) { $p.Kill() }
|
||||
} catch {}
|
||||
$now = Get-CurrentPasswd
|
||||
function Do-Set([string]$pw){
|
||||
$before = Get-IniPasswd
|
||||
[void](Invoke-SetTool (Join-Path $uvnc "createpassword.exe") $pw)
|
||||
$after = Get-IniPasswd
|
||||
if($after -ieq $before){
|
||||
[void](Invoke-SetTool (Join-Path $uvnc "setpasswd.exe") $pw)
|
||||
$after = Get-IniPasswd
|
||||
}
|
||||
if($after -ieq $before){ Write-Info "password tools did not change $ini (still $after)."; return $false }
|
||||
# restart the service so the running server reloads (only if it was running)
|
||||
try { $q = (& sc.exe query uvnc_service 2>$null); $running = ($q -match 'RUNNING') } catch { $running = $false }
|
||||
if($running){
|
||||
Write-Info "restarting uvnc_service ..."
|
||||
& net.exe stop uvnc_service 2>$null | Out-Null
|
||||
& net.exe start uvnc_service 2>$null | Out-Null
|
||||
}
|
||||
return $true
|
||||
}
|
||||
|
||||
if ($now -ine $expected) {
|
||||
Write-Info "tools did not update the password (ini=$now). Set it manually via UltraVNC Admin Properties as admin."
|
||||
exit 1
|
||||
}
|
||||
Write-Info "password updated in $ini."
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
|
||||
# Restart the service so it reloads the new password.
|
||||
$svc = "uvnc_service"
|
||||
$svcExists = $false
|
||||
try { $null = (& sc.exe query $svc 2>$null); $svcExists = ($LASTEXITCODE -eq 0) } catch {}
|
||||
if ($svcExists) {
|
||||
Write-Info "restarting service $svc ..."
|
||||
& net.exe stop $svc 2>$null | Out-Null
|
||||
& net.exe start $svc 2>$null | Out-Null
|
||||
if(-not $isAdmin){
|
||||
Write-Info "re-launching elevated to set the password..."
|
||||
$p = Start-Process -FilePath "powershell.exe" -Verb RunAs -Wait -PassThru -ArgumentList @("-NoProfile","-ExecutionPolicy","Bypass","-File","`"$PSCommandPath`"","-Password","`"$Password`"")
|
||||
if($p.ExitCode -ne 0){ Write-Info "elevated run failed (exit $($p.ExitCode))."; exit 1 }
|
||||
# confirm by re-probing (if a server is up now)
|
||||
$again = Test-VncAuth $Password "127.0.0.1" 5900
|
||||
if($again -eq 'ok'){ Write-Info "password set OK."; exit 0 }
|
||||
if($again -eq 'unreachable'){ Write-Info "password written; no server up to verify (will be used on next start)."; exit 0 }
|
||||
Write-Info "password set but server still rejects it (probe=$again)."; exit 1
|
||||
}
|
||||
exit 0
|
||||
|
||||
# admin path
|
||||
if(Do-Set $Password){ Write-Info "password set OK."; exit 0 } else { exit 1 }
|
||||
+12
-12
@@ -1,16 +1,16 @@
|
||||
@echo off
|
||||
REM ============================================================
|
||||
REM open-firewall.bat - ®âªàë¢ ¥â ¯®àâ 8080 ¢ Windows Firewall.
|
||||
REM ‡ ¯ã᪠âì ®â ¨¬¥¨ ¤¬¨¨áâà â®à (®¤¨ à §).
|
||||
REM ‹¨¡® § ¯ãáâ¨â¥ ¤¢ ¦¤ë: ä ©« á ¬ § ¯à®á¨â ¯à ¢ ¤¬¨¨áâà â®à .
|
||||
REM open-firewall.bat - открывает порт 8080 в Windows Firewall.
|
||||
REM Запускать от имени администратора (один раз).
|
||||
REM Либо запустите дважды: файл сам запросит права администратора.
|
||||
REM ============================================================
|
||||
chcp 866 >nul
|
||||
chcp 65001 >nul
|
||||
cd /d "%~dp0"
|
||||
|
||||
REM �஢¥àª ¯à ¢ ¤¬¨¨áâà â®à ¨ ¢â®-¯®¢ë襨¥.
|
||||
REM Проверка прав администратора и авто-повышение.
|
||||
net session >nul 2>nul
|
||||
if errorlevel 1 (
|
||||
echo ‡ ¯à®á ¯à ¢ ¤¬¨¨áâà â®à ...
|
||||
echo Запрос прав администратора ...
|
||||
powershell -Command "Start-Process -FilePath '%~f0' -Verb RunAs"
|
||||
exit /b
|
||||
)
|
||||
@@ -18,20 +18,20 @@ if errorlevel 1 (
|
||||
set PORT=8080
|
||||
set RULE=web-vnc
|
||||
|
||||
echo “¤ «ïî áâ ஥ ¯à ¢¨«® (¥á«¨ ¥áâì) ...
|
||||
echo Удаляю старое правило (если есть) ...
|
||||
netsh advfirewall firewall delete rule name="%RULE%" >nul 2>nul
|
||||
|
||||
echo „®¡ ¢«ïî à §à¥è î饥 ¯à ¢¨«® ¤«ï ¢å®¤ï饣® TCP-âà 䨪 ¯®àâ %PORT% ...
|
||||
echo Добавляю разрешающее правило для входящего TCP-трафика на порт %PORT% ...
|
||||
netsh advfirewall firewall add rule name="%RULE%" dir=in action=allow protocol=TCP localport=%PORT%
|
||||
if errorlevel 1 (
|
||||
echo [®è¨¡ª ] �¥ 㤠«®áì ¤®¡ ¢¨âì ¯à ¢¨«®.
|
||||
echo [ошибка] Не удалось добавить правило.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo ƒ®â®¢®. �®àâ %PORT% ®âªàëâ ¤«ï ¢å®¤ïé¨å ¯®¤ª«î票©.
|
||||
echo ’¥¯¥àì ª web-vnc ¬®¦® ¯®¤ª«îç âìáï á ¤àã£¨å ¬ è¨ á¥â¨ ¯® ¤à¥áã:
|
||||
echo http://IP_�’މ_Œ€˜ˆ�›:%PORT%
|
||||
echo Готово. Порт %PORT% открыт для входящих подключений.
|
||||
echo Теперь к web-vnc можно подключаться с других машин сети по адресу:
|
||||
echo http://IP_ЭТОЙ_МАШИНЫ:%PORT%
|
||||
echo.
|
||||
pause
|
||||
@@ -1,109 +0,0 @@
|
||||
@echo off
|
||||
REM ============================================================
|
||||
REM set-vnc-password.bat - reliably set the UltraVNC VNC password
|
||||
REM for the running service (uvnc_service / LocalSystem), which
|
||||
REM reads %ProgramData%\UltraVNC\ultravnc.ini.
|
||||
REM
|
||||
REM Runs AS ADMINISTRATOR (auto-elevates). It first tries the
|
||||
REM UltraVNC CLI helpers (createpassword.exe / setpasswd.exe) and
|
||||
REM VERIFIES the password actually changed in ultravnc.ini; if they
|
||||
REM fail silently (as they can), it opens the UltraVNC settings GUI
|
||||
REM so you can set "VNC Password" there. Then it restarts the
|
||||
REM service. Use the SAME password in run.bat (ASCII, max 8 chars).
|
||||
REM ============================================================
|
||||
chcp 866 >nul
|
||||
cd /d "%~dp0"
|
||||
|
||||
net session >nul 2>nul
|
||||
if errorlevel 1 (
|
||||
echo Requesting administrator rights ...
|
||||
powershell -Command "Start-Process -FilePath '%~f0' -Verb RunAs"
|
||||
exit /b
|
||||
)
|
||||
|
||||
set "UVNC="
|
||||
for %%P in (
|
||||
"C:\Program Files\uvnc bvba\UltraVNC"
|
||||
"C:\Program Files\UltraVNC"
|
||||
"C:\Program Files (x86)\uvnc bvba\UltraVNC"
|
||||
"C:\Program Files (x86)\UltraVNC"
|
||||
) do (
|
||||
if exist "%%~P\winvnc.exe" if not defined UVNC set "UVNC=%%~P"
|
||||
)
|
||||
if not defined UVNC (
|
||||
echo [error] UltraVNC installation not found.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
echo UltraVNC: %UVNC%
|
||||
set "INI=%ProgramData%\UltraVNC\ultravnc.ini"
|
||||
|
||||
:getpw
|
||||
set "PW="
|
||||
set /p "PW=Enter VNC password (ASCII, max 8 chars): "
|
||||
if "%PW%"=="" ( echo Password cannot be empty. & goto getpw )
|
||||
|
||||
REM record old passwd
|
||||
set "OLDPW="
|
||||
if exist "%INI%" for /f "tokens=2 delims==" %%a in ('findstr /b /i "passwd=" "%INI%" 2^>nul ^| findstr /v /i "passwd2"') do set "OLDPW=%%a"
|
||||
echo Old passwd=%OLDPW%
|
||||
|
||||
REM try CLI helpers, verify after each
|
||||
set "DONE=0"
|
||||
if exist "%UVNC%\createpassword.exe" (
|
||||
echo Trying createpassword.exe ...
|
||||
"%UVNC%\createpassword.exe" "%PW%" >nul 2>nul
|
||||
call :checkchanged
|
||||
)
|
||||
if "%DONE%"=="0" if exist "%UVNC%\setpasswd.exe" (
|
||||
echo Trying setpasswd.exe ...
|
||||
"%UVNC%\setpasswd.exe" "%PW%" "%PW%" >nul 2>nul
|
||||
call :checkchanged
|
||||
)
|
||||
if "%DONE%"=="0" (
|
||||
echo.
|
||||
echo CLI helpers did not change the password file. Opening UltraVNC settings...
|
||||
echo -> right-click the UltraVNC tray icon, choose Admin Properties,
|
||||
echo set the "VNC Password" to: %PW%
|
||||
echo -> close the settings/tray app, then come back here and press a key.
|
||||
echo.
|
||||
start "" "%UVNC%\winvnc.exe"
|
||||
pause
|
||||
call :checkchanged
|
||||
)
|
||||
set "PW="
|
||||
if "%DONE%"=="0" (
|
||||
echo [warn] Password still not changed in %INI%.
|
||||
echo Set it manually in UltraVNC Admin Properties as administrator.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM restart the service so it reloads the password
|
||||
set "SVC=uvnc_service"
|
||||
sc query %SVC% >nul 2>nul
|
||||
if errorlevel 1 (
|
||||
echo [warn] Service '%SVC%' not found; restart winvnc manually if it runs in app mode.
|
||||
goto showini
|
||||
)
|
||||
echo Restarting service %SVC% ...
|
||||
net stop %SVC% >nul 2>nul
|
||||
net start %SVC%
|
||||
|
||||
:showini
|
||||
echo.
|
||||
echo --- %INI% ---
|
||||
if exist "%INI%" type "%INI%"
|
||||
echo.
|
||||
echo Done. Use the SAME password in run.bat, then reconnect in the browser.
|
||||
pause
|
||||
exit /b
|
||||
|
||||
:checkchanged
|
||||
set "NEWPW="
|
||||
if exist "%INI%" for /f "tokens=2 delims==" %%a in ('findstr /b /i "passwd=" "%INI%" 2^>nul ^| findstr /v /i "passwd2"') do set "NEWPW=%%a"
|
||||
if not "%NEWPW%"=="%OLDPW%" (
|
||||
echo Password file updated. New passwd=%NEWPW%
|
||||
set "DONE=1"
|
||||
)
|
||||
goto :eof
|
||||
Reference in New Issue
Block a user