SCCM PKI Fun with Certificates

This was fun problem to sort out.  I was asked to jump in and fix a SCCM server already built to work with PKI.  Attempts to get clients registered with the server would end up with bizarre error messages like this:

RegTask: Client is not registered. Sending registration request
RegTask: Reply for registration was empty. Error: 0x8000ffff

I worked on the problem for about 8 hours at work, then went home and setup PKI in my home SCCM lab in about 30 minutes.  I decided I needed to enlist Microsoft PSS on this issue.

After working with Microsoft for about 2.5 hours: they tracked the problem to the certificate on the management point bound to IIS being “too new”.  Essentially, SCCM has legacy code in it that only understands certificates based on the CSP templates (Windows XP/Server 2003) and not KSP/CNG templates (Windows Server 2008 and later).

This is explained in more detail here:

https://www.sevecek.com/EnglishPages/Lists/Posts/Post.aspx?ID=66

The funny part is I was actually using a CA template I had found on the production distribution points that were already up and working, but I guess using the wrong certificate template on DPs doesn’t matter, but using the wrong one on the MP does matter for client registration at least!

I had no access to the CA server, so I couldn’t snoop around on the properties of said certificate templates and they were named “2012 or later IIS”.  Of course the management server is running Windows Server 2012 R2, so why wouldn’t I pick that template?

In the end, you have to use the command line to see the cryptographic provider of the certificates (this doesn’t show up in the GUI):

certutil -repairstore my *

It seems that other people are annoyed by this and according to Microsoft the ability to use CNG or more “modern” certificate templates is coming in a newer build of SCCM:

https://configurationmanager.uservoice.com/forums/300492-ideas/suggestions/17451757-support-v3-and-newer-certificate-templates-for-htt

  • Soli Deo Gloria

Your System Administrator has blocked this Program

This was an interesting one.  I was converting some computers over from an older domain to a new one and was getting this logged in as a non-admin user when trying to change the domain membership:

Attempts to do a runas on Command Prompt ended up with this even more bizarre error message:

At first I thought it was the OS being corrupted on the computer, but I encountered this error on more and more computers.  If I logged in as a user with administrator rights, everything worked fine.

After digging for a while, I figured this had to be a UAC policy as we don’t use AppLocker.

The issue: https://msdn.microsoft.com/en-us/library/cc232762.aspx

ConsentPromptBehaviorUser

Key: SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
Value: “ConsentPromptBehaviorUser”

0x00000000
This option SHOULD be set to ensure that any operation that requires elevation of privilege will fail as a standard user.

0x00000001
This option SHOULD be set to ensure that a standard user that needs to perform an operation that requires elevation of privilege will be prompted for an administrative user name and password. If the user enters valid credentials, the operation will continue with the applicable privilege.

The previous IT staff (who are no longer here) had set a policy disabling UAC elevation.  Doing so causes all kinds of crazy error messages like this one.  Why would they do that?  Well, the one guess I can come up with is that they didn’t want help desk calls from people encountering a UAC prompt. Of course, this also interferes with any IT staff attempting to do any work as all attempts to elevate to admin are blocked.

Some users had admin rights and some didn’t…the ones that didn’t were the ones where this issue was popping up on.  Thankfully, this policy isn’t set in the new domain.

  • Soli Deo Gloria

0x80004005: An error occurred while retrieving policy for this computer

Started a new job recently and one of the techs was having a problem imaging a laptop with a recently replaced motherboard.  We would PXE boot the laptop and then WinPE would bomb out in 10 seconds stating “0x80004005: An error occurred while retrieving policy for this computer”.

Nothing interesting was found on the SCCM side, however when I finally found the SMSTS.LOG in X:\Windows\temp\SMSTSLOG, I didn’t even have to open the file to figure out the problem: it was dated 2016!  Yup: it was a date and time issue.  If your computer skews too far from the current date and time, SCCM won’t talk to your computer.

You can use the commands date and time within cmd (hit the F8 key…you did enable this functionality, right?) to set the correct date and time.

  • Soli Deo Gloria

Create a Custom Installer Using Powershell

We run a program called QATRAX which doesn’t come as a MSI file for installing it.  The program has many sins: one of them being that it can only be installed to C:\program files\traxstar (it’s a x86 program) and it has to have write access to this folder.  Attempts to use a re-packager to convert this to a MSI file have failed, because all repackagers detect it should really go in C:\program files (x86), but of course that won’t work.

The program was made in the 1990s, so figuring out what files it copies to to system is quite easy.  You can use a tracing utility such as Process Monitor to watch for install changes.

# copy qatrax support files
copy-item *.dll C:\windows\syswow64 -Force

We could add registry entries using Powershell code line-by-line, but doing a registry export to a REG file and then import it is far easier in my opinion.

# import qatrax registry settings
regedit /s qatrax.reg

One thing to note is that we need to create an uninstall string manually so it shows up in Programs and Features as being installed.  This will also report back to WMI that the program is really installed to help with software inventory.  You should be able to get this from a system with the software already installed.

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QATrax]
@=""
"DisplayName"="QATrax"
"UninstallString"="C:\\Program Files\\TraxStar\\uninstall.exe TRAXSTAR"

The program also has no native way of switching between dev and prod environments, so I wrote another wrapper that overwrites the values in the registry with certain IP addresses depending on which environment the user wants to be in.

# set everyone full-control to traxstar registry key. this is a hack to allow
# switching between dev and prod environments
$acl = Get-Acl 'HKLM:\SOFTWARE\Wow6432Node\TraxStar Technologies LLC'
$rule = New-Object System.Security.AccessControl.RegistryAccessRule ("Everyone","FullControl","Allow")
$acl.SetAccessRule($rule)
$acl |Set-Acl -Path 'HKLM:\SOFTWARE\Wow6432Node\TraxStar Technologies LLC'

Make a folder in C:\program files

# create install folder (and yes, traxstar has to be in the x64 folder even though it's
# x86 or it will break
mkdir "C:\program files\traxstar\traxclient"

Grant everyone rights to write to this folder

# qatrax requires write access to its own folder
icacls 'C:\program files\traxstar\traxclient' /grant:r everyone:f

Copy files to C:\program files

# copy qatrax files to program install folder
copy-item qatrax.exe "C:\program files\traxstar\traxclient"
copy-item traxlaunch.exe "C:\program files\traxstar\traxclient"
copy-item uninstall.exe "C:\program files\traxstar"
copy-item *.log "C:\program files\traxstar\traxclient"

Build out the start menu

# create start menu items
mkdir "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\QATrax"
icacls *.lnk /grant:r everyone:RX
copy-item *.lnk "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\QATrax"

  • Soli Deo Gloria

PowerShell Code to Find Default Printer

Here’s some code to query what computers have a certain default printer with PowerShell:

$PrinterNameSeek = "\\XXXXXXX01\XX_OFFICE_CLR_01"

$DefaultPrinterObject = Get-WmiObject -Query " SELECT * FROM Win32_Printer WHERE Default=$true"
$DefaultPrinterName = $DefaultPrinterObject.Name.ToUpper()

write-host $DefaultPrinterName

if ($DefaultPrinterName -eq $PrinterNameSeek)

{

write-host $env:COMPUTERNAME
write-host $env:username

out-file \\XXXXXX\logs\$($env:COMPUTERNAME).$($env:username).XX_OFFICE_CLR_01.txt

}

This will need to be run as the end user to use $env:username, but if your ExecutionPolicy doesn’t allow it, you can remove it.

After running this for a few days: you can do a “dir *.* > list.txt” and then import this into an Excel spreadsheet using the import data from text file feature.

  • Soli Deo Gloria

 

 

Creating an Image of a Computer over the Network

This was unique one.  Had a user that kept running out of disk space.  Plan was to image her drive to a bigger drive (150GB SATA to 500GB SATA).  Problem? She works past 5PM, no upcoming vacation.

DISK2VHD to the rescue!  We can use this program to dump a copy of the disk to a VHD file to a network location after hours.  Imaging 109GB over a 1 Gigabit network took about 2 hours.  Note that Windows 7 can mount VHDs, but not VHDXs.  If you are an idiot like me: you can convert a VHDX file back to a VHD file using the command Convert-VHD within PowerShell on Windows 10.

Now we mount the VHD as a drive in Windows using the disk management snap-in (diskmgmt.msc).  Then I used AOMEI’s Backupper to do a disk to disk clone. The resulting copy needed a partition resize to use all available space on the new disk, so I had to blow away the 300MB Bitlocker partition at the end to expand it in disk management (we don’t use Bitlocker on desktops).

Pop in it and boom: works!

This also works for P2P conversions.  I took a guy from an Optiplex 745 to Optiplex 3020 using the same method.  Upon booting Windows, I got the the famous 7B BSOD.  I used the P2P adjust feature from Paragon’s Hard Drive Manager 15 Professional and was up and running after adding the correct drivers.

-Soli Deo Gloria

 

PowerShell Code to Replace Plain Text with in a Group of Files

Here’s some PowerShell code I wrote to replace the license server for Minitab 19:

# Ignore errors

$erroractionpreference = 'Continue'

# Change Minitab

$configFiles = Get-ChildItem "C:\ProgramData\Minitab" -filter *.ini -recurse -exclude *.dll, *.exe

foreach ($file in $configFiles)
{
 (Get-Content $file.PSPath) |
 Foreach-Object { $_ -replace "XXLIC02", "XXLIC09" } |
 Set-Content $file.PSPath
}

– Soli Deo Gloria

GPO: Enable the Policy to Disable the Setting

Got to love Group Policy sometimes.  We wanted to disable the setting “Access data sources across domains” under Internet Explorer>Security>Local intranet>Custom Level.  So of course we set the GPO “Access data sources across domains” to disabled and …it doesn’t work!  Users can still toggle the setting and we are still getting pop-ups in Internet Explorer.  The solution?  Enable the policy so you can disable it.  Yup!  Set it to enabled, then click the dropdown box and pick disabled.

Is this some voodoo Vulcan logic being used here?

– Soli Deo Gloria