Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 326 lines (254 sloc) 9.603 kb
4abd836 Rafael Rivera Initial import
authored
1 #requires -Version 3.0
2
3 function Suspend-CertifiedDeviceChecks
4 {
5 $_unwind = New-Object Collections.Stack
6
7 function Add-ToUnwind()
8 {
9 param([Parameter(Mandatory = $true)][ScriptBlock]$Code)
10
11 $_unwind.Push($Code)
12 }
13
14 function Invoke-Unwind()
15 {
16 if($_unwind.Count -gt 0) {
17 $_unwind | % { $_.Invoke() | Out-Null }
18 }
19
20 $_unwind.Clear()
21 }
22
23 function Test-Administrator()
24 {
25 $user = [Security.Principal.WindowsIdentity]::GetCurrent()
26 (New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
27 }
28
29 if(!(Test-Administrator)) {
30 Write-Error "Elevated permissions are required to run this script."
31 return
32 }
33
34 if(![Environment]::Is64BitProcess) {
35 Write-Error "Script requires a 64-bit operating system."
36 return
37 }
38
39 Add-Type -Name Win32 -Namespace $Null -PassThru -MemberDefinition @"
40 [DllImport("kernel32")]
41 [return: MarshalAs(UnmanagedType.Bool)]
42 public static extern bool WriteProcessMemory(
43 IntPtr hProcess,
44 IntPtr lpBaseAddress,
45 byte[] lpBuffer,
46 uint nSize,
47 IntPtr lpNumberOfBytesWritten);
48
49 [Flags]
50 public enum ProcessAccessFlags
51 {
52 // ...
53 All = 0x001F0FFF
54 // ...
55 }
56
57 [DllImport("kernel32")]
58 public static extern IntPtr OpenProcess(
59 uint dwDesiredAccess,
60 [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
61 uint dwProcessId);
62
63 [DllImport("kernel32")]
64 [return: MarshalAs(UnmanagedType.Bool)]
65 public static extern bool CloseHandle(
66 IntPtr hObject);
67
68 [Flags]
69 public enum CreationFlags : uint
70 {
71 None = 0
72 }
73
74 [DllImport("kernel32")]
75 public static extern IntPtr CreateRemoteThread(
76 IntPtr hProcess,
77 IntPtr lpThreadAttributes,
78 uint dwStackSize,
79 IntPtr lpStartAddress,
80 IntPtr lpParameter,
81 uint dwCreationFlags,
82 IntPtr lpThreadId);
83
84 [Flags]
85 public enum AllocationType
86 {
87 Commit = 0x1000,
88 Reserve = 0x2000,
89 Decommit = 0x4000,
90 Release = 0x8000,
91 // ...
92 }
93
94 [Flags]
95 public enum MemoryProtection
96 {
97 // ...
98 ExecuteReadWrite = 0x40,
99 ExecuteWriteCopy = 0x80,
100 // ...
101 }
102
103 [DllImport("kernel32")]
104 public static extern IntPtr VirtualAllocEx(
105 IntPtr hProcess,
106 IntPtr lpAddress,
107 uint dwSize,
108 uint flAllocationType,
109 uint flProtect);
110
111 [DllImport("kernel32", EntryPoint="GetModuleHandleW")]
112 public static extern IntPtr GetModuleHandle(
113 [MarshalAs(UnmanagedType.LPWStr)] string lpModuleName);
114
115 [DllImport("kernel32")]
116 public static extern IntPtr GetProcAddress(
117 IntPtr hModule,
118 [MarshalAs(UnmanagedType.LPStr)] string lpProcName);
119
120 [DllImport("kernel32")]
121 public static extern uint GetLastError();
122
123 public enum WaitResult
124 {
125 // ...
126 WaitObject0 = 0x0
127 // ...
128 }
129
130 [DllImport("kernel32")]
131 public static extern uint WaitForSingleObject(
132 IntPtr hHandle, uint dwMilliseconds);
133
134 [DllImport("kernel32")]
135 [return: MarshalAs(UnmanagedType.Bool)]
136 public static extern bool VirtualFreeEx(
137 IntPtr hProcess,
138 IntPtr lpAddress,
139 uint dwSize,
140 uint dwFreeType);
141 "@ | Out-Null
142
143 #
144 # Find the Device Setup Manager service
145 #
146
147 Start-Service DsmSvc
148
149 $svcpid = Get-WmiObject Win32_Service | ? { $_.Name -eq "DsmSvc" } | Select -ExpandProperty ProcessId
150
151 if(!$svcpid) {
152 Write-Error "Failed to latch onto the Device Setup Manager service. Is it disabled?"
153 return
154 }
155
156 $svchandle = [Win32]::OpenProcess([Win32+ProcessAccessFlags]::All, $false, $svcpid)
157
158 if(!$svchandle) {
159 Write-Error "Failed to open svchost process."
160 return
161 }
162
163 Add-ToUnwind { [Win32]::CloseHandle($svchandle) }
164
165 #
166 # Load DevPropMgr.dll (and leave it loaded)
167 #
168
169 $dll = [Text.Encoding]::Unicode.GetBytes("DevPropMgr.dll")
170 $mem = [Win32]::VirtualAllocEx($svchandle, [IntPtr]::Zero, $dll.Length, ([Win32+AllocationType]::Reserve -bor [Win32+AllocationType]::Commit),
171 [Win32+MemoryProtection]::ExecuteReadWrite)
172
173 if(!$mem) {
174 Write-Error "Failed to allocate a chunk of memory in svchost."
175 Invoke-Unwind
176 return
177 }
178
179 Add-ToUnwind { [Win32]::VirtualFreeEx($svchandle, $mem, 0, [Win32]::AllocationType::Release) }
180
181 if(![Win32]::WriteProcessMemory($svchandle, $mem, $dll, $dll.Length, [IntPtr]::Zero)) {
182 Write-Error "Failed to write to allocated memory in svchost."
183 Invoke-Unwind
184 return
185 }
186
187 $loadlibrary = [Win32]::GetProcAddress([Win32]::GetModuleHandle("kernel32"), "LoadLibraryW")
188
189 if(!$loadlibrary) {
190 Write-Error "Failed to locate kernel32!LoadLibraryW, is this a supported OS?"
191 Invoke-Unwind
192 return
193 }
194
195 $thread = [Win32]::CreateRemoteThread($svchandle, [IntPtr]::Zero, 0, $loadlibrary, $mem, [Win32+CreationFlags]::None, [IntPtr]::Zero)
196
197 if(!$thread) {
198 Write-Error "Failed to create remote thread."
199 Invoke-Unwind
200 return
201 }
202
203 if([Win32]::WaitForSingleObject($thread, [TimeSpan]::FromSeconds(10).Milliseconds) -ne [Win32+WaitResult]::WaitObject0) {
204 Write-Warning "Remote thread terminated unexpectedly, strangeness may follow."
205 }
206
207 #
208 # Patch DevPropMgr!_CheckSignature
209 #
210
211 $addr = Get-Process -Id $svcpid | Select -ExpandProperty Modules | ? { $_.ModuleName -eq "DevPropMgr.dll" } | Select -ExpandProperty BaseAddress
212
213 if(!$addr) {
214 Write-Error "Failed to locate DevPropMgr.dll module in svchost."
215 Invoke-Unwind
216 return
217 }
218
219 # Shelved patch for Windows RT
220 # $patchbytes = [Byte[]](0x00, 0x25) # armasm: movs r5, #0
221 # [Win32]::WriteProcessMemory($svchandle, [IntPtr]::Add($addr, 0xEABC), $patchbytes, $patchbytes.Length, [IntPtr]::Zero)
222
223 # Patch for Windows 8 x64
224 $patchbytes = [Byte[]](0x33, 0xDB, 0x85, 0xDB) # x86-64 asm: xor ebx,ebx | test ebx, ebx
225 if(![Win32]::WriteProcessMemory($svchandle, [IntPtr]::Add($addr, 0x1466B), $patchbytes, $patchbytes.Length, [IntPtr]::Zero)) {
226 Write-Error "Failed to fiddle with svchost memory."
227 Invoke-Unwind
228 return
229 }
230
231 #
232 # Cleanup
233 #
234
235 Invoke-Unwind
236 Write-Host "OK."
237 }
238
239 function Get-MediaRenderers()
240 {
241 Get-WmiObject Win32_PnPEntity | ? { $_.HardwareID -Like "*MediaRenderer*" } | Select Name, HardwareID
242 }
243
244 function New-DeviceMetadata()
245 {
246
247 param(
248 [Parameter(ValueFromPipeline = $true, Mandatory = $true)]
249 [String]$DeviceId,
250
251 [Switch]$Install
252 )
253
254 $device = Get-WmiObject Win32_PnPEntity | ? { $_.HardwareID -Contains $DeviceId } | Select Name, Manufacturer, HardwareID
255
256 if(!$device)
257 {
258 Write-Error "Failed to locate device with specified hardware ID. Is the device on?"
259 return
260 }
261
262 $scratch = "$(([Guid]::NewGuid() | Select -exp Guid).Remove(23))-00000ca710af"
263
264 New-Item $scratch -ItemType Directory | Out-Null
265 Copy-Item .\template\* $scratch -Recurse -Force
266
267 $pkginfo = "$scratch\PackageInfo.xml"
268
269 (Get-Content $pkginfo | ForEach {
270 $buffer = $_ -replace "{hwid}", "DOID:$($device.HardwareID[0])"
271 $buffer = $buffer -replace "{lastmodified}", ([DateTime]::UtcNow.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"))
272 $buffer -replace "{experienceid}", $scratch }) | Out-File $pkginfo -Encoding utf8
273
274 $devinfo = "$scratch\DeviceInfo\DeviceInfo.xml"
275
276 (Get-Content $devinfo | ForEach {
277 $buffer = $_ -replace "{model}", $device.Name
278 $buffer -replace "{manufacturer}", $device.Manufacturer }) | Out-File $devinfo -Encoding utf8
279
280 Get-Item -Path $scratch | New-Cab | Move-Item -Destination ".\$scratch.devicemetadata-ms"
281
282 if($Install) {
283 Copy-Item "$scratch.devicemetadata-ms" "$env:ProgramData\Microsoft\Windows\DeviceMetadataStore\en-US" -Force
284 }
285
286 Remove-Item $scratch -Force -Recurse
287
288 Write-Host "OK."
289 }
290
291 function New-Cab()
292 {
293 param(
294 [Parameter(ValueFromPipeline=$True, Mandatory=$True)]
295 [IO.DirectoryInfo]$Directory,
296
297 [ValidateSet("MSZIP", "LZX")]
298 [String]$Algorithm = "MSZIP"
299 )
300
301 $uri = New-Object Uri ("$($Directory.FullName)\", [UriKind]::Absolute)
302 $files = $Directory.GetFiles("*.*", [IO.SearchOption]::AllDirectories) | % {
303
304 # Each file entry must appear as so: <outside cab path> <inside cab path>
305 $entry = $($uri.MakeRelativeUri($_.FullName).OriginalString) -replace "/", "\"
306 "`"$($_.FullName)`" `"$entry`"`n"
307 }
308
309 $guid = "$([Guid]::NewGuid() | Select -exp Guid)"
310 $ddf = "$env:Temp\$guid.ddf"
311
312 "
313 .Set CabinetNameTemplate=`"$guid.cab`"
314 .Set DiskDirectoryTemplate=`"$env:Temp`"
315 .Set RptFileName=`"$ddf`:rpt`"
316 .Set InfFileName=`"$ddf`:inf`"
317 .Set CompressionType=$Algorithm
318 $files
319 " | New-Item -ItemType File $ddf | Out-Null
320
321 MakeCab /F "$ddf" | Out-Null
322 Remove-Item $ddf -Force | Out-Null
323
324 New-Object IO.FileInfo "$env:Temp\$guid.cab"
325 }
Something went wrong with that request. Please try again.