Inject Drivers to Windows 10 Install Media

So Windows 10 is here with its second build (9860) in its “Technical Preview”. Since I am an OSD guy, I like to make sure when a system is built all the drivers are there (even for my test machines and ad-hoc builds to “see if it works”). Usually this just entails adding some drivers and–for the most part–plug and play is nice enough to install everything for me. If you’re without MDT and/or SCCM or just like to have a USB installer ready for anything, you don’t have the luxury of a driver package and just want all the drivers to automatically be there when Windows installs.

This process is very common and really, this applies to Windows Vista (and up) but as I went to inject drivers to Windows 10 media from my Windows 8.1 machine I met an old-friend-of-an-error and figured this was worth sharing.

Get the Drivers

First thing’s first. Get the Drivers! For Windows 10, Microsoft has done a great job of letting Windows 7/8.1 drivers install (or attempt to) and maintain a large percentage of support. So, download all the drivers and put them into one directory. Make sure that any downloaded installers are extracted first to where you can see the inf, cat, and sys files. I know Dell and HP both have self extracting executable for most drivers they offer out.

If you’re like me, you’ll have a huge hierarchy of Manufacturer> Model showcasing all the different models that you want to test on and support.

drivers_u

 

Create Your Media

Connect a USB Drive (USB 3.0 is better :)). We’ll need to format the disk…This will remove all of the files so make sure to backup anything.

  1. Open an Administrative Command Prompt
  2. DiskPart <enter>
  3. List Disk <enter>
  4. Locate which disk is the usb drive. Easiest way is to tell by size.
  5. select disk # <enter>  (# is the disk number from previous step)
  6. clean <enter>
  7. create partition primary <enter>
  8. select partition 1 <enter>
  9. format fs=fat32 quick <enter>
  10. active <enter>
  11. assign <enter>
  12. exit <enter>

Now you have a clean and fresh USB drive to use.

Extract the Install Files

With Windows 8+ you can just right-click and select “Mount” on the iso. Copy all of the files to the USB drive.

With Windows 7, you’ll need a program like 7-zip. Open the ISO, and extract all files to the USB drive.

Mount the WIM

There are two WIM’s in your Windows Installer that we’re concerned about: <InstallRoot>\sources\boot.wim and <InstallRoot>\sources\install.wim.

  • The Boot.wim is what gets loaded when you boot to your install media. This is a WinPE image used to apply an OS–MDT/SCCM people will be very familiar with the boot media concept.
  • The install.wim file is the actual sysprepped OS Installation that will get applied to your hard drive. If you mounted this, it will look just like your C drive: Program Files, Windows, Users, etc…

So really we now dive to 2 scenarios:

  1. When you boot to your media, your hard drive (or other device) is not recognized.
  2. When Windows is installed, drivers are missing

Scenario 1 relates to your boot media, scenario 2 relates to the install.wim. A rule of thumb is that your boot.wim only needs essential drivers; eg: storage and network. In this scenario, we’re only concerned about storage, since we’re using USB as our source media. Really though, both processes are the same.

  1. Open an Administrative Command prompt.
  2. Create a directory to mount the WIM file (mkdir c:\mount)
  3. Mount the wim:
dism /mount-wim /wimfile:%PathToWimFile% /Index:1 /mountdir:%ImageMountDir%

Add in the Drivers:

To add the drivers we’ll need to point the command to the folder of drivers we created above.

REMEMBER: only add storage and network to boot.wim. Anything more is just silly.

If you have you install.wim mounted you can point to the top folder that contains all the drivers for your model. Example: c:\drivers\hp\EliteBook800SeriesG1

Add the drivers:

dism /image:%ImageMountDirFromAbove% /add-driver /driver:%PathToDriversFolder% /recurse /forceunsigned

The recurse option will check all sub folders. the forceunsigned will allow unsigned drivers to be added.

On Windows 8.1 while mounting my Windows 10 install.wim i was greeted with an error:

Deployment Image Servicing and Management tool
Version: 6.3.9600.17031
Error: 50

To service this Windows image requires the latest version of the DISM. See http://go.microsoft.com/fwlink/?LinkId=293395 to find the latest version of DISM, and http://go.microsoft.com/fwlink/?LinkId=293394 to learn how to install the latest version of DISM from the ADK on your computer.

The DISM log file can be found at C:\Windows\Logs\DISM\dism.log

We could look at the dism log if we wanted but to me this error is rather self-explanatory. Essentially this is saying that the OS i have mounted is newer than the dism tool i’m using. Dism version: 6.3.9600.17031…Windows 8.1 OS Version is 6.3.9600 (see what they did there?). Think of it this way: Each version supports the corresponding Windows release plus older (Backwards compatible). It cannot work with a newer version since older version doesn’t know what newer version is.

The fix for this is to use the DISM command included in the Windows setup disk. Rerun the dism command above but this time, we’ll need to use the full path to the Windows 10 media:

%PathToWindowsInstallMedia%\Sources\dism.exe  /image:%ImageMountDirFromAbove% /add-driver /driver:%PathToDriversFolder% /recurse /forceunsigned

And voila…now we have drivers added.

Save the Changes

Last thing is to commit the changes we made:

%PathToWindowsInstallMedia%\Sources\dism.exe  /unmount-wim /mountdir:%ImageMountedDir% /commit

Again, this process will really apply to any version of Windows where you’d like to inject drivers within your media!

 

Enjoi!

Advertisements

Get BitLocker Recovery From Active Directory with Powershell

At the company I currently work for we’ve been using BitLocker since Vista (although Vista install base was rather small). Having moved from another “Pretty Good” Disk encryption technology, one thing we struggled with was Recovery information. While the previous solution had its own server to store all recovery keys, BitLocker links these to the Computer Object. When that computer object is deleted, so is the key. This was a battle for us at first since we have automation in place to remove stale AD Accounts, but–at the time–did not have any method to backup that information. We immediately added a table to a database and as part of our cleanup would backup these Keys.

First: Why not MBAM?

I loosely touched on this in another post regarding TPM Backup information in AD and i’ll give the quick summary again. By the time MBAM cam around, we already had our backup system in place. This was added into a global utility that allowed our technicians to perform AD tasks without AD permissions (Create computer, reset, move ou, etc…). MBAM would have just been “another thing” for us to maintain and manage. With our custom tool and SCCM already in place, MBAM did not provide us any additional benefits. For those of you using MBAM, This may not be for you, however this still provides a great way to quickly grab the information for those ad-hoc requests.

As we move to upgrade our various automation from the tried-and-true VBScript to the ever-so-loved Powershell, Obtaining the BitLocker Recovery Information was an odd one. If you use the RSAT tools and pull up details of a computer object there is a “BitLocker Recovery tab”.

RecoveryB

Each BitLocker Recovery password is an object of the computer account object. The odd thing is that by doing a Get-ADComputer, Recovery information is not returned as a “property” like other items–and where I expected it. As usual, first step was to use a search engine and see what others had done. I found a few results that gave me what i wanted (notably this post) but didn’t like the way it was scripted. The snippet that does the work is here:

$objADObject = get-adobject -Filter * | Where-Object {$_.DistinguishedName -match $objComputer.Name -and $_.ObjectClass -eq "msFVE-RecoveryInformation"}

While this gets the job done it is slow and by slow i mean the combination of “-Filter *” and piping to “Where-Object” is looking at everything before seeing if its the item (droid) that I’m looking for. Recovery Key look-up for my system took approximately 15 seconds for the first result, and didnt finish processing until a few seconds after that.

Let’s step back and look at a BitLocker Recovery object (msFVE-RecoveryInformation); really lets justify the filter “$_.DistinguishedName -match $objComputer.Name”.

Each BitLocker Recovery object is of the Object Class: msFVE-RecoveryInformation. If you look at the DistinguishedName of an object we can see it stems from the Distinguished name of the computer object it is attached to:

DistinguishedName : CN=2014-10-20T13:10:38-06:00{E59D69FF-6A3B-42A6-89C0-57A0DA0E302A},CN=WIN7X86PC01,OU=swComputers,DC=swansonglab,DC=com

Unfortunately this is the best way (I’ve found) to tie a recovery object back to the computer account. For those curious, here is what’s contained in a msFVE-RecoveryInformation object:

CanonicalName : swansonglab.com/swComputers/WIN7X86PC01/2014-10-20T13:10:38-06:00{E59D69FF-6A3B-42A6-89C0-57A0DA0E302A}
CN : 2014-10-20T13:10:38-06:00{E59D69FF-6A3B-42A6-89C0-57A0DA0E302A}
Created : 10/20/2014 1:10:55 PM
createTimeStamp : 10/20/2014 1:10:55 PM
Deleted :
Description :
DisplayName :
DistinguishedName : CN=2014-10-20T13:10:38-06:00{E59D69FF-6A3B-42A6-89C0-57A0DA0E302A},CN=WIN7X86PC01,OU=swComputers,DC=swansonglab,DC=com
dSCorePropagationData : {12/31/1600 6:00:00 PM}
instanceType : 4
isDeleted :
LastKnownParent :
Modified : 10/20/2014 1:10:55 PM
modifyTimeStamp : 10/20/2014 1:10:55 PM
msFVE-KeyPackage : {136, 1, 0, 0...}
msFVE-RecoveryGuid : {255, 105, 157, 229...}
msFVE-RecoveryPassword : 465762-121880-049797-598411-533643-549890-128436-549736
msFVE-VolumeGuid : {146, 36, 120, 28...}
Name : 2014-10-20T13:10:38-06:00{E59D69FF-6A3B-42A6-89C0-57A0DA0E302A}
nTSecurityDescriptor : System.DirectoryServices.ActiveDirectorySecurity
ObjectCategory : CN=ms-FVE-RecoveryInformation,CN=Schema,CN=Configuration,DC=swansonglab,DC=com
ObjectClass : msFVE-RecoveryInformation
ObjectGUID : d0a15cc8-5f86-42ed-8942-633cec25b6b1
ProtectedFromAccidentalDeletion : False
sDRightsEffective : 15
showInAdvancedViewOnly : True
uSNChanged : 99936
uSNCreated : 99936
whenChanged : 10/20/2014 1:10:55 PM
whenCreated : 10/20/2014 1:10:55 PM

Remember in most cases getting recovery is searched by the GUID. This can be filtered on using Powershell with no problems or computer object linking. The example I’m looking at is getting all recovery objects attached to a computer account.

So my issues with the snippet above (using “-Filter *” and “Where-Object”), again, was time consuming. Since the Recovery Information objects are attached to a computer object we can simply use the computer account’s Distinguished Name as the search base for the command:

# Get Computer Object
> $computer = Get-ADComputer -Filter {Name -eq 'WIN7X86PC01'}

# Get all BitLocker Recovery Keys for that Computer. Note the 'SearchBase' parameter
> $BitLockerObjects = Get-ADObject -Filter {objectclass -eq 'msFVE-RecoveryInformation'} -SearchBase $computer.DistinguishedName -Properties 'msFVE-RecoveryPassword'

# Output the results!
> $BitLockerObjects
DistinguishedName : CN=2014-10-20T13:10:38-06:00{E59D69FF-6A3B-42A6-89C0-57A0DA0E302A},CN=WIN7X86PC01,OU=swCompute
rs,DC=swansong,DC=com
msFVE-RecoveryPassword : 465762-121880-049797-598411-533643-549890-128436-549736
Name : 2014-10-20T13:10:38-06:00{E59D69FF-6A3B-42A6-89C0-57A0DA0E302A}
ObjectClass : msFVE-RecoveryInformation
ObjectGUID : d0a15cc8-5f86-42ed-8942-633cec25b6b1

DistinguishedName : CN=2014-10-20T13:11:29-06:00{450547C6-675C-4A61-B276-17CC620D3885},CN=WIN7X86PC01,OU=swCompute
rs,DC=swansong,DC=com
msFVE-RecoveryPassword : 632126-201135-053504-485045-151657-139986-094820-137687
Name : 2014-10-20T13:11:29-06:00{450547C6-675C-4A61-B276-17CC620D3885}
ObjectClass : msFVE-RecoveryInformation
ObjectGUID : 8c3963ea-89ec-4b41-934b-ee6023d9d1e9

DistinguishedName : CN=2014-10-20T13:12:03-06:00{A29D2D47-89D6-4459-B106-40B1F62A04EF},CN=WIN7X86PC01,OU=swCompute
rs,DC=swansong,DC=com
msFVE-RecoveryPassword : 497178-478654-023111-302291-606034-162855-504163-720698
Name : 2014-10-20T13:12:03-06:00{A29D2D47-89D6-4459-B106-40B1F62A04EF}
ObjectClass : msFVE-RecoveryInformation
ObjectGUID : 4a72004e-e76e-4cb3-a828-152011b8b541

Hopefully this has provided some additional information on BitLocker Recovery keys and how to obtain them should you ever need to!

Enjoi!