-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCameraService.ps1
More file actions
254 lines (229 loc) · 12.1 KB
/
Copy pathCameraService.ps1
File metadata and controls
254 lines (229 loc) · 12.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# Self-elevation if not admin (no #Requires line)
param (
[string]$BackupPath,
[switch]$Force,
[switch]$WhatIf
)
$ErrorActionPreference = "Stop"
# ── Self-elevation if not admin ──────────────────────────────────────────────
if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
$arguments = "-ExecutionPolicy Bypass -File `"" + $MyInvocation.MyCommand.Path + "`""
if ($args) { $arguments += " " + ($args -join " ") }
Start-Process powershell.exe -Verb RunAs -ArgumentList $arguments
exit
}
# ── Neutral window title ─────────────────────────────────────────────────────
$Host.UI.RawUI.WindowTitle = "Windows PowerShell"
# ── Suppress console output if running hidden ────────────────────────────────
$global:ConsoleVisible = $true
if ([Environment]::GetCommandLineArgs() -join ' ' -match '-WindowStyle\s+Hidden') {
$global:ConsoleVisible = $false
}
function Write-Log {
param(
[string]$Message,
[ValidateSet("INFO","WARNING","ERROR","SIMULATION")]
[string]$Level = "INFO"
)
if (-not $global:ConsoleVisible) { return }
$line = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [$Level] $Message"
$color = switch ($Level) {
"ERROR" { "Red" }
"WARNING" { "Yellow" }
"SIMULATION" { "Cyan" }
default { "Gray" }
}
Write-Host $line -ForegroundColor $color
}
# ── Cleanup orphaned temp files from previous aborted runs ───────────────────
function Cleanup-StaleTempFiles {
$tempDir = $env:TEMP
Get-ChildItem -Path $tempDir -File | Where-Object {
$_.Length -eq 0 -and $_.CreationTime -lt (Get-Date).AddHours(-1) -and $_.Name -match '^[a-z0-9]{8}\.[a-z0-9]{3}$'
} | Remove-Item -Force -ErrorAction SilentlyContinue
}
Cleanup-StaleTempFiles
# ── Helper functions ─────────────────────────────────────────────────────────
function Get-BackupFolder {
$seed = $env:COMPUTERNAME + $env:USERNAME + "cam"
$hash = [System.Security.Cryptography.SHA256]::Create().ComputeHash([System.Text.Encoding]::UTF8.GetBytes($seed))
$hex = [System.BitConverter]::ToString($hash[0..15]).Replace('-','').ToLower()
$guid = '{0}-{1}-{2}-{3}-{4}' -f $hex.Substring(0,8), $hex.Substring(8,4), $hex.Substring(12,4), $hex.Substring(16,4), $hex.Substring(20,12)
return "$env:LOCALAPPDATA\Microsoft\Windows\Caches\$guid"
}
function Set-Timestamp {
param([string]$Path)
$ref = Get-Item "$env:SystemRoot\System32\drivers\ntfs.sys" -ErrorAction SilentlyContinue
if (-not $ref) { return }
try {
$item = Get-Item $Path -Force -ErrorAction SilentlyContinue
if ($item) {
$item.CreationTime = $ref.CreationTime
$item.LastWriteTime = $ref.LastWriteTime
$item.LastAccessTime = $ref.LastAccessTime
}
} catch {}
}
if (-not $BackupPath) { $BackupPath = Get-BackupFolder }
if ($WhatIf) {
Write-Log "Simulation mode — no changes will be made." -Level SIMULATION
}
# ── System paths ──────────────────────────────────────────────────────────────
$StoreRepoPath = "$env:SystemRoot\System32\DriverStore\FileRepository"
$RuntimeDriver = "$env:SystemRoot\System32\drivers\usbvideo.sys"
$PnfFile = "$env:SystemRoot\INF\usbvideo.PNF"
$RegPolicyPath = "HKLM:\SOFTWARE\Policies\Microsoft\Camera"
$RegPendPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager"
$RegPendValue = "PendingFileRenameOperations"
# ── Check backup exists (non-critical warning) ────────────────────────────────
if (-not (Test-Path $BackupPath)) {
Write-Log "Backup not found at $BackupPath — restoration may not be possible." -Level WARNING
if (-not $Force) {
$c = Read-Host "Continue without a backup? (Y/N)"
if ($c -ne 'Y') { exit }
}
}
# ── 1. Driver store folder(s) ─────────────────────────────────────────────────
Write-Log "Processing driver store..."
$usbvideoFolders = @(Get-ChildItem -Path $StoreRepoPath -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like "usbvideo.inf_*" })
if ($usbvideoFolders.Count -eq 0) {
Write-Log "No usbvideo.inf_* folder found." -Level WARNING
} else {
foreach ($folder in $usbvideoFolders) {
if ($WhatIf) {
Write-Log "Would corrupt driver store: $($folder.Name)" -Level SIMULATION
continue
}
try {
$acl = Get-Acl $folder.FullName
$acl.SetOwner([Security.Principal.NTAccount]"BUILTIN\Administrators")
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule(
"BUILTIN\Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
$acl.AddAccessRule($ace)
Set-Acl $folder.FullName $acl
Get-ChildItem $folder.FullName -Recurse -Force -ErrorAction SilentlyContinue | ForEach-Object {
try {
$fa = Get-Acl $_.FullName
$fa.SetOwner([Security.Principal.NTAccount]"BUILTIN\Administrators")
Set-Acl $_.FullName $fa
} catch {}
}
Remove-Item "$($folder.FullName)\*" -Recurse -Force -ErrorAction SilentlyContinue
$dummyInf = Join-Path $folder.FullName "usbvideo.inf"
$dummySys = Join-Path $folder.FullName "usbvideo.sys"
New-Item -Path $dummyInf -ItemType File -Force | Out-Null
New-Item -Path $dummySys -ItemType File -Force | Out-Null
Set-Timestamp $dummyInf
Set-Timestamp $dummySys
$folderAcl = Get-Acl $folder.FullName
$folderAcl.SetAccessRuleProtection($true, $false)
$denySystem = New-Object System.Security.AccessControl.FileSystemAccessRule(
"NT AUTHORITY\SYSTEM", "Read", "ContainerInherit,ObjectInherit", "None", "Deny")
$denyTI = New-Object System.Security.AccessControl.FileSystemAccessRule(
"NT SERVICE\TrustedInstaller", "Read", "ContainerInherit,ObjectInherit", "None", "Deny")
$allowAdmin = New-Object System.Security.AccessControl.FileSystemAccessRule(
"BUILTIN\Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow")
$folderAcl.AddAccessRule($denySystem)
$folderAcl.AddAccessRule($denyTI)
$folderAcl.AddAccessRule($allowAdmin)
Set-Acl $folder.FullName $folderAcl
Write-Log "Driver store corrupted: $($folder.Name)"
} catch {
Write-Log "Failed on $($folder.Name): $_" -Level ERROR
}
}
}
# ── 2. PNF file ──────────────────────────────────────────────────────────────
Write-Log "Processing PNF..."
if (Test-Path $PnfFile) {
if ($WhatIf) {
Write-Log "Would zero PNF content: $PnfFile" -Level SIMULATION
} else {
try {
$stream = [System.IO.File]::Open($PnfFile, 'Open', 'Write')
$stream.SetLength(0)
$stream.Close()
Set-Timestamp $PnfFile
Write-Log "PNF content zeroed."
} catch {
Write-Log "Could not zero PNF (may be locked): $_" -Level WARNING
}
}
} else {
Write-Log "PNF not found — skipping."
}
# ── 3. Runtime driver ────────────────────────────────────────────────────────
Write-Log "Processing runtime driver..."
if (Test-Path $RuntimeDriver) {
if ($WhatIf) {
Write-Log "Would corrupt runtime driver: $RuntimeDriver" -Level SIMULATION
} else {
try {
$drvAcl = Get-Acl $RuntimeDriver
$drvAcl.SetOwner([Security.Principal.NTAccount]"BUILTIN\Administrators")
$drvAce = New-Object System.Security.AccessControl.FileSystemAccessRule(
"BUILTIN\Administrators", "FullControl", "None", "None", "Allow")
$drvAcl.AddAccessRule($drvAce)
Set-Acl $RuntimeDriver $drvAcl
$zeroed = $false
try {
$stream = [System.IO.File]::Open($RuntimeDriver, 'Open', 'Write')
$stream.SetLength(0)
$stream.Close()
Set-Timestamp $RuntimeDriver
$zeroed = $true
Write-Log "Runtime driver zeroed."
} catch {
Write-Log "Driver in use — scheduling zero-replace on next reboot." -Level WARNING
$emptyFile = Join-Path $env:TEMP ([System.IO.Path]::GetRandomFileName())
New-Item -Path $emptyFile -ItemType File -Force | Out-Null
$current = (Get-ItemProperty -Path $RegPendPath -Name $RegPendValue -ErrorAction SilentlyContinue).$RegPendValue
$newPair = @("\??\$emptyFile", "\??\$RuntimeDriver")
$merged = if ($current) { $current + $newPair } else { $newPair }
Set-ItemProperty -Path $RegPendPath -Name $RegPendValue -Value $merged -Type MultiString
Write-Log "Pending rename scheduled. Reboot required."
}
# Only apply Deny ACEs if we directly zeroed the file
if ($zeroed) {
$lockAcl = Get-Acl $RuntimeDriver
$lockAcl.SetAccessRuleProtection($true, $false)
$denySysW = New-Object System.Security.AccessControl.FileSystemAccessRule(
"NT AUTHORITY\SYSTEM", "Write", "None", "None", "Deny")
$denyTIW = New-Object System.Security.AccessControl.FileSystemAccessRule(
"NT SERVICE\TrustedInstaller", "Write", "None", "None", "Deny")
$denyAdmW = New-Object System.Security.AccessControl.FileSystemAccessRule(
"BUILTIN\Administrators", "Write", "None", "None", "Deny")
$allowAdmR = New-Object System.Security.AccessControl.FileSystemAccessRule(
"BUILTIN\Administrators", "Read", "None", "None", "Allow")
$lockAcl.AddAccessRule($denySysW)
$lockAcl.AddAccessRule($denyTIW)
$lockAcl.AddAccessRule($denyAdmW)
$lockAcl.AddAccessRule($allowAdmR)
Set-Acl $RuntimeDriver $lockAcl
Write-Log "Write access locked on runtime driver."
} else {
Write-Log "Skipping Deny ACEs because pending rename is active (avoid conflict)."
}
} catch {
Write-Log "Failed on runtime driver: $_" -Level ERROR
}
}
} else {
Write-Log "Runtime driver not found — skipping." -Level WARNING
}
# ── 4. Remove any camera policy flag ──────────────────────────────────────────
if (-not $WhatIf) {
if (Test-Path $RegPolicyPath) {
Remove-ItemProperty -Path $RegPolicyPath -Name "AllowCamera" -Force -ErrorAction SilentlyContinue
Write-Log "Camera policy key cleaned."
}
} else {
Write-Log "Would clean AllowCamera registry value if present." -Level SIMULATION
}
Write-Log "=== Complete. Unplug any webcam and reboot. ==="
if ($global:ConsoleVisible) {
Write-Log ""
Write-Log "TIP: Run from a non-interactive session to avoid PSReadLine history:"
Write-Log " powershell.exe -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -File CameraService.ps1"
}