Content is based on this article on yubico documentation found here:


  • OpenSSH  (v9.4+) found here
  • Git (v2.42+) found here
  • Gitlab account configured (no matter if or if you have CE (community edition) , I used it for proprietary CE  and it worked so it should work with not problem with online version)


On existing reporsitory you need to adjust that SSH will be used instead of PGP

git config gpg.format ssh

Generate new key that supports Yubikey (ECDSA key). During process you will be asked to select device for signing and confirm generation of key with touch on your Yubikey.

ssh-keygen -t ecdsa-sk -f c:\users\yourusername\.ssh\id_ecdsa_sk

Setup to use key for signing

git config user.signingKey c:\users\yourusername\.ssh\id_ecdsa_sk

If you have more ssh keys you should aready have config file here c:\users\yourusername\.ssh\config, add for destination Gitlab server newly created private key, this ensures that our new key will be used.

Copy content of  c:\users\yourusername\.ssh\ to c:\users\yourusername\.ssh\allowed_signers,

Run command to define allowd_signers

git config gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers

Paste public part also to Gitlab account.

And that’s it! If i did not forget on anything, this should be enough and

Powershell commands for fixing WSUS on clients

net stop wuauserv
net stop cryptSvc
net stop bits
net stop msiserver
Ren C:\Windows\SoftwareDistribution SoftwareDistribution.old
Ren C:\Windows\System32\catroot2 Catroot2.old
net start wuauserv
net start cryptSvc
net start bits
net start msiserver


Batch file for fixing  WSUS on client:

@echo off

:: Created by: Shawn Brink
:: Created on: October 1, 2015
:: Updated on: March 8, 2021
:: Tutorial:

:: Prompt to Run as administrator
Set "Variable=0" & if exist "%temp%\getadmin.vbs" del "%temp%\getadmin.vbs"
fsutil dirty query %systemdrive%  >nul 2>&1 && goto :(Privileges_got)
If "%1"=="%Variable%" (echo. &echo. Please right-click on the file and select &echo. "Run as administrator". &echo. Press any key to exit. &pause>nul 2>&1& exit)
cmd /u /c echo Set UAC = CreateObject^("Shell.Application"^) : UAC.ShellExecute "%~0", "%Variable%", "", "runas", 1 > "%temp%\getadmin.vbs"&cscript //nologo "%temp%\getadmin.vbs" & exit

:: Checking and Stopping the Windows Update services
set b=0

set /a b=%b%+1
if %b% equ 3 (
   goto end1
net stop bits
echo Checking the bits service status.
sc query bits | findstr /I /C:"STOPPED" 
if not %errorlevel%==0 ( 
    goto bits 
goto loop2

echo Cannot reset Windows Update since "Background Intelligent Transfer Service" (bits) service failed to stop. Please restart the computer, and try again.
goto Start

set w=0

set /a w=%w%+1
if %w% equ 3 (
   goto end2
net stop wuauserv
echo Checking the wuauserv service status.
sc query wuauserv | findstr /I /C:"STOPPED" 
if not %errorlevel%==0 ( 
    goto wuauserv 
goto loop3

echo Cannot reset Windows Update since "Windows Update" (wuauserv) service failed to stop. Please restart the computer, and try again.
goto Start

set app=0

set /a app=%app%+1
if %app% equ 3 (
   goto end3
net stop appidsvc
echo Checking the appidsvc service status.
sc query appidsvc | findstr /I /C:"STOPPED" 
if not %errorlevel%==0 ( 
    goto appidsvc 
goto loop4

echo Cannot reset Windows Update since "Application Identity" (appidsvc) service failed to stop. Please restart the computer, and try again.
goto Start

set c=0

set /a c=%c%+1
if %c% equ 3 (
   goto end4
net stop cryptsvc
echo Checking the cryptsvc service status.
sc query cryptsvc | findstr /I /C:"STOPPED" 
if not %errorlevel%==0 ( 
    goto cryptsvc 
goto Reset

echo Cannot reset Windows Update since "Cryptographic Services" (cryptsvc) service failed to stop. Please restart the computer, and try again.
goto Start

Ipconfig /flushdns
del /s /q /f "%ALLUSERSPROFILE%\Application Data\Microsoft\Network\Downloader\qmgr*.dat" 
del /s /q /f "%ALLUSERSPROFILE%\Microsoft\Network\Downloader\qmgr*.dat"
del /s /q /f "%SYSTEMROOT%\Logs\WindowsUpdate\*"

if exist "%SYSTEMROOT%\winsxs\pending.xml.bak" del /s /q /f "%SYSTEMROOT%\winsxs\pending.xml.bak" 
if exist "%SYSTEMROOT%\winsxs\pending.xml" ( 
    takeown /f "%SYSTEMROOT%\winsxs\pending.xml" 
    attrib -r -s -h /s /d "%SYSTEMROOT%\winsxs\pending.xml" 
    ren "%SYSTEMROOT%\winsxs\pending.xml" pending.xml.bak 
if exist "%SYSTEMROOT%\SoftwareDistribution.bak" rmdir /s /q "%SYSTEMROOT%\SoftwareDistribution.bak"
if exist "%SYSTEMROOT%\SoftwareDistribution" ( 
    attrib -r -s -h /s /d "%SYSTEMROOT%\SoftwareDistribution" 
    ren "%SYSTEMROOT%\SoftwareDistribution" SoftwareDistribution.bak 
if exist "%SYSTEMROOT%\system32\Catroot2.bak" rmdir /s /q "%SYSTEMROOT%\system32\Catroot2.bak" 
if exist "%SYSTEMROOT%\system32\Catroot2" ( 
    attrib -r -s -h /s /d "%SYSTEMROOT%\system32\Catroot2" 
    ren "%SYSTEMROOT%\system32\Catroot2" Catroot2.bak 

:: Reset Windows Update policies
reg delete "HKCU\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /f
reg delete "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\WindowsUpdate" /f
reg delete "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /f
reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\WindowsUpdate" /f
gpupdate /force

:: Reset the BITS service and the Windows Update service to the default security descriptor


:: Reregister the BITS files and the Windows Update files
cd /d %windir%\system32
regsvr32.exe /s atl.dll 
regsvr32.exe /s urlmon.dll 
regsvr32.exe /s mshtml.dll 
regsvr32.exe /s shdocvw.dll 
regsvr32.exe /s browseui.dll 
regsvr32.exe /s jscript.dll 
regsvr32.exe /s vbscript.dll 
regsvr32.exe /s scrrun.dll 
regsvr32.exe /s msxml.dll 
regsvr32.exe /s msxml3.dll 
regsvr32.exe /s msxml6.dll 
regsvr32.exe /s actxprxy.dll 
regsvr32.exe /s softpub.dll 
regsvr32.exe /s wintrust.dll 
regsvr32.exe /s dssenh.dll 
regsvr32.exe /s rsaenh.dll 
regsvr32.exe /s gpkcsp.dll 
regsvr32.exe /s sccbase.dll 
regsvr32.exe /s slbcsp.dll 
regsvr32.exe /s cryptdlg.dll 
regsvr32.exe /s oleaut32.dll 
regsvr32.exe /s ole32.dll 
regsvr32.exe /s shell32.dll 
regsvr32.exe /s initpki.dll 
regsvr32.exe /s wuapi.dll 
regsvr32.exe /s wuaueng.dll 
regsvr32.exe /s wuaueng1.dll 
regsvr32.exe /s wucltui.dll 
regsvr32.exe /s wups.dll 
regsvr32.exe /s wups2.dll 
regsvr32.exe /s wuweb.dll 
regsvr32.exe /s qmgr.dll 
regsvr32.exe /s qmgrprxy.dll 
regsvr32.exe /s wucltux.dll 
regsvr32.exe /s muweb.dll 
regsvr32.exe /s wuwebv.dll
regsvr32.exe /s wudriver.dll
netsh winsock reset
netsh winsock reset proxy

:: Set the startup type as automatic
sc config wuauserv start= auto
sc config bits start= auto 
sc config DcomLaunch start= auto 

net start bits
net start wuauserv
net start appidsvc
net start cryptsvc

:: Restart computer

This article continues based on prevous article where application principle was used for authentication to AzureAD over powershell module AzureAD.

In order to get it work, module need to be installed. If application was created and working in mentioned article, following set of commands should provide you possibility to use Graph API. In this case list users:

  • replace string YourCertThumprint with the thumbprint of your certificate
  • replace string YourApplicationID with ID of you application used in mentioned article
  • replace string YourTenantID with ID of your tenantID



$cert = Get-ChildItem -Path Cert:LocalMachine\MY | ?{$_.Thumbprint -eq „YourCertThumbprint“ }

$token = Get-MsalToken -ClientId YourApplicationID -ClientCertificate $cert -TenantId YourTenantID

Invoke-RestMethod -Headers @{Authorization = „Bearer $($token.AccessToken)“ } `
-Uri ‚‘ `
-Method Get


This article is just note, but it might be helpful if somebody tries to find the way how to do it. In case that application is not Global Administrators API might need additional permissions in API permissions of your application.

Backup and Restore


From Windows 10 OS, you can do backup with wbadmin command. This is example how perform backup to UNC path  however TargetBackup can be even local USB attached disk.


wbadmin start backup -backupTarget:\\wds1\winback\win10_2 -include:C: -allcritical -quiet


Note: recovery worked only in situation that identical disk has been used, when I used the new one disk it did not work and i tried to use wbadmin start sysrecovery but this did not work either. When i start recovery the error 0x80042308 object not found…So I endup to use WinRE (recovery from original installation media in order do recover system to new disk), where I could use backup from Backup section in this article.

For recovery (clonning) just boot from Windows installation media (important is to have the same installation media architecture and OS to ensure that recovery is possible). In my case i used WinPE if you have (be aware of that backup feature is not possible over WinPE, only partition recovery is possible)

For list of available backup versions run:

wbadmin get versions -backuptarget:\\wds1\winback\win10_2 -machine:DESKTOP-9CL3JDP

Output will show version parameter which needs to be added for recovery:

In this case Version is 07/31/22-08:37 so command for recovery will be:

wbadmin start recovery -version:07/31/2022-08:37 -itemtype:Volume -items:C: -BackupTarget:\\wds1\winback\win10_2 -machine:DESKTOP-9CL3JDP -quiet

After authentication resovery process should b started .


Details about WBAdmin backup and restore are here:

Creation of links

The main reason of doing this is creation of links during computer configuration for end user. It is very boring to do it manually :).

Functions for get and creating code:

function Get-Shortcut {
$path = $null

$obj = New-Object -ComObject WScript.Shell

if ($path -eq $null) {
$pathUser = [System.Environment]::GetFolderPath('StartMenu')
$pathCommon = $obj.SpecialFolders.Item('AllUsersStartMenu')
$path = dir $pathUser, $pathCommon -Filter *.lnk -Recurse 
if ($path -is [string]) {
$path = dir $path -Filter *.lnk
$path | ForEach-Object { 
if ($_ -is [string]) {
$_ = dir $_ -Filter *.lnk
if ($_) {
$link = $obj.CreateShortcut($_.FullName)

$info = @{}
$info.Hotkey = $link.Hotkey
$info.TargetPath = $link.TargetPath
$info.LinkPath = $link.FullName
$info.Arguments = $link.Arguments
$info.Target = try {Split-Path $info.TargetPath -Leaf } catch { 'n/a'}
$info.Link = try { Split-Path $info.LinkPath -Leaf } catch { 'n/a'}
$info.WindowStyle = $link.WindowStyle
$info.IconLocation = $link.IconLocation

New-Object PSObject -Property $info

function Set-Shortcut {
begin {
$shell = New-Object -ComObject WScript.Shell

process {
$link = $shell.CreateShortcut($LinkPath)

$PSCmdlet.MyInvocation.BoundParameters.GetEnumerator() |
Where-Object { $_.key -ne 'LinkPath' } |
ForEach-Object { $link.$($_.key) = $_.value }


Command for creation of icon Google Chat (replace %username% with real username also ensure that data for the specific application exists… in this case application of Google Chat located in folder _crx_mdpkiolbdkhdjpekfbkbmhigcaggjagi ).

Set-Shortcut -LinkPath "C:\Users\%username%\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Google Chat.lnk" -TargetPath "C:\Program Files (x86)\Google\Chrome\Application\chrome_proxy.exe" -IconLocation "C:\Users\%username%\AppData\Local\Google\Chrome\User Data\Default\Web Applications\_crx_mdpkiolbdkhdjpekfbkbmhigcaggjagi\Google Chat.ico,0" -Arguments "--profile-directory=Default --app-id=mdpkiolbdkhdjpekfbkbmhigcaggjagi"


Note that functions are not mine… originally are from:

AD investigation

Here is quick cheatsheet to review configuration of Active Directory.



Net config rdr

 Netdom query fsmo

Nltest /dclist:

Nltest /domain_trusts

Nltest /

(replace with actual domain name)