Skip to content

Blog

Enabling Password Writeback with Azure AD Connect Cloud Sync (can’t find the cmdlet?)

With a relatively recent Azure AD hybrid directory under our belts, we decided at work not to use the older Azure AD Connect tool and instead use the newer Azure AD Connect Cloud Sync. It’s lighter weight, doesn’t require a SQL database β€” lots of reasons to love it.

It does appear that, juuuust in time for our deployment, password writeback is supported, in preview.

However, I struggled to follow the official instructions to enable it, as the cmdlet did not seem to be available after importing the DLL.

Import-Module 'C:\\Program Files\\Microsoft Azure AD Connect Provisioning Agent\\Microsoft.CloudSync.Powershell.dll' 
Set-AADCloudSyncPasswordWritebackConfiguration -Enable $true -Credential $(Get-Credential)
Set-AADCloudSyncPasswordWritebackConfiguration : The term 'Set-AADCloudSyncPasswordWritebackConfiguration' is not
recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if
a path was included, verify that the path is correct and try again.
At line:1 char:1
+ Set-AADCloudSyncPasswordWritebackConfiguration
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Set-AADCloudSyn...ckConfiguration:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

A little bit of investigating revealed that the DLL does indeed export the cmdlet, so what is going on?

I tried to run the above in PowerShell 7. It imported the cmdlet, but hit an issue with running it when importing its required libraries.

My Workaround

My workaround is to use PowerShell 7, but import the module with the -UseWindowsPowershell compatibility switch.

Import-Module "C:\Program Files\Microsoft Azure AD Connect Provisioning Agent\Microsoft.CloudSync.Powershell.dll" -UseWindowsPowerShell 
Set-AADCloudSyncPasswordWritebackConfiguration -Enable $true -Credential $(Get-Credential) 

And with that, password writeback is working on Azure AD Cloud Sync!

Emerging from the Shadows

I have been getting back into the swing of building things just for fun and for exploration. I think a pressure can emerge that the things we create have to mean something, have to hit some mark of quality to be worthy of pursuing at all. I think that is a mistake, especially in that it discourages you from being open to areas where you don’t already have great expertise. So, here I am, putting into practice rejecting that pressure.

Continuing my theme of trying to work with lower-level APIs and with unmanaged languages like C and C++, I have developed a very simple client for Windows’ Volume Shadow Copy service, that allows me to create a shadow copy of a volume, copy some files in a folder to a destination, and then release the shadow copy.

I can see a use for this as part of a very low-tech backup solution where a drive is (most of the time) physically disconnected, and where you want to keep the technology stack as simple as humanly possible for the greatest flexibility in disaster recovery scenarios β€” BitLocker for external drives (compatible even with Windows client systems), and a bunch of VHDX files on an NTFS volume, copied there using VSS so you don’t have to bring your VMs down.

A big disclaimer is prominently offered β€” this is not production quality code. My discipline with the responsibility of memory management and other lower-level concepts is “emerging”, to use a euphemism.

Still, I thoroughly enjoyed this β€” it was challenging for where I currently am, but achievable. You can’t improve at something if you don’t let yourself produce output that wouldn’t perhaps yet meet your highest quality standards. (And goodness knows there is plenty of production code out there that never met those standards before it was relied upon by the world.) The perfect shall not be allowed to be the enemy of personal growth and development.

So, here is ShadowDuplicator, your very untested, extremely rudimentary VSS snapshot based backup client. Even if it’s just a workaround for a lack of vssadmin create shadow on client operating systems, it’s something. πŸ˜‰

DfontSplitter 0.4 for Windows

I’m delighted to announce DfontSplitter 0.4 for Windows. After a nine-year hiatus without software updates, this release has big under-the-bonnet changes!

The application is now built with .NET 4.7.2 and runs on Windows 7 – Windows 10. If you still need support going back as far as Windows 98(!), you can still use the old version.

A new, improved, fondu (which does the bulk of the work) is bundled as a DLL that is Windows-native and no longer requires the Cygwin library. It also includes a number of memory safety improvements.

To fix the long-standing issue where extracted TTFs didn’t quite play nicely with Windows, DfontSplitter 0.4 for Windows embeds functionality from FontForge to do some final conversion work to make your fonts work perfectly with Windows.

Source is available on GitHub (DfontSplitter, fondu-win-dll)

The β€œT with chisel” DfontSplitter icon is licensed under the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. The icon includes a modified version of β€œChisel wood 24mm” by Isabelle Grosjean, which is also licensed as such.

RoslynCodeAnalysisService creating SQLite Databases on C:

I recently opened an old version of my DfontSplitter C# project in Visual Studio 2019. I expected a process would need to be gone through to upgrade the project from its source version (VS2008 I believe) before it could be opened in Visual Studio 2019. Such a process did happen and it completed without errors.

A little later, I noticed something odd. A folder had appeared at the root of my C: drive with the name xyDQ7sfb+k4aZLT8oSso4yqXRQ=.

The unusual looking folder name contained a SQLite database.

Inside, a sqlite3 folder and the usual artifacts that you’d associate with a SQLite database.

At this point of my initial investigation, I hadn’t yet connected my opening of this Visual Studio project with this folder. It looked highly suspicious β€” a name that apparently was encoded and random.

Investigating the database

So, I fired up DB Browser for SQLite and pointed it at the database.

It contained tables including names like SolutionData2, ProjectData2, StringInfo2. Some investigation of the contents of these led me to this recent VS2008 project I’d opened.

I still felt it looked malicious though β€” was this something injecting itself into Visual Studio projects I was building?

Tracking down the source(?)

Some web searching later, I’d discovered a part of Roslyn, the C# compiler, which had references to these _SpellChecker_ entries I’d seen in SolutionData2 and the suggestion that this is dumped to persistent storage.

Catching it in the act

So, I deleted the folder from the C drive and replicated the process. I opened the same project again, but this time running Sysinternals Process Monitor in the background, filtering Path for sqlite or this folder name.

We can see calls to CreateFile (which creates a handle to a file β€” this is usually ‘opening’ the file rather than ‘creating’ it) with the result PATH NOT FOUND. Then, another call to CreateFile (highlighted) that actually creates the directory.

From there, it’s clear that this process, ServiceHub.RoslynCodeAnalysisService32.exe, is responsible for this database and its timing correlated exactly with me upgrading this project from VS2008 to VS2019.

But… what is this? Why?

I posted some Visual Studio Feedback about my observations, although this issue was closed as applying to sqlite, not Visual Studio. I understand that this isn’t high priority, but I disagree with the assessment that the use of SQLite in this case makes it SQLite’s fault!

So I remain curious. Do some code analysis on the solution, sure. But why store results in the root of the C drive? How is the encoded folder’s name decided? Why does this whole thing feel suspicious rather than behaviour I’d expect from an IDE?

And… it’s gone

As of Visual Studio 16.5.3, this appears to be fixed β€” the same filesystem behaviour by RoslynCodeAnalysisService32 is now prefixed with %LOCALAPPDATA%\Microsoft\VisualStudio\Roslyn\Cache\RemoteWorkspace. I guess it was indeed a bug β€” an oversight in actually setting the full path to this database properly.

Idle Lock Lite (Going Lower-Level 2.0)

In this post, I said

Maybe next the whole program should do the workstation locking, warning message and idle detection in one program.

Well, here it is β€” Idle Lock Lite.

It’s a lightweight application designed to run in the background, detecting if the computer is idle (based on keyboard or mouse movement) and presenting a timed warning that the computer will be locked. It then locks the computer if it is still idle once the grace period expires.

Idle Lock Lite

It is functional, but its real world usability isn’t there yet β€” it’s not going to be usable in practice if it isn’t aware of things like playing back video, presentations and other states that are not idle, but don’t involve user input for longer periods of time. It isn’t aware of those things at the time of writing!

However, it has been an enjoyable and informative further exploration of working with the Win32 API directly.

I found myself drawn to working in C/Win32 for this application and its predecessor β€” the result here is less than 50 KiB in size and uses about 1.4 MiB of RAM (Private Bytes). Any similar application you would create in .NET, for example, would be an order of magnitude more demanding in terms of resources, just because of the nature of the framework.

Here’s an explanation of how it works:

  • It accepts two command line arguments β€” the number of seconds before displaying the warning window and the number of grace period seconds while that window is open.
  • It measures the number of GetTickCount64 ticks taken for a SetTimer with 1000 ms to be fired. This is used to calculate idle periods and grace periods in terms of ticks.
  • It sets up two SetWindowsHookEx hooks β€” one for keyboard activity and one for the mouse. These yield execution some of the time to avoid performance issues from the frequency with which they are called. These update our last interaction tick number to indicate the computer is in use.
  • Every ten seconds, a SetTimer-based timer calls a function which evaluates if we’ve reached the idle condition. If so, the warning dialogue is displayed.
  • The warning dialogue counts down the grace period with the progress bar and another SetTimer callback. Upon expiry, LockWorkStation is called to lock the computer.
  • The WM_WTSSESSION_CHANGE window event is listened for β€” we take notice of WTS_SESSION_LOCK and UNLOCK events to ensure that we don’t try to detect idle conditions if the screen is already locked, and that when unlocked, any previous idle period is reset.

Learning about how Windows operates at a lower-level β€” windows, window messages and some of the more primitive operations has been illuminating! This is the perfect bi(y)te-sized project to help me move forward with learning about this!

Extract List of ADFS Failed Logins to CSV

Keeping an eye on failed logins and the user accounts that are being targeted is an important part of being responsible for an Office 365/Azure Active Directory tenant.

If you can afford the higher-level O365/Azure AD plans, there are great tools built in to the Azure Portal that allow useful intelligence into your security posture.

For The Rest of Us(tm), we sometimes need to be a little creative to gather the information needed. For on-premises Active Directory Federation Services (ADFS) servers, I put together a simple, quick and, perhaps slightly hacky script to extract the usernames from recent failed login events from the Windows Event Log and dump them, along with the rest of the Windows Event, to a CSV file for later analysis.

This specifically searches event logs from the past 12 hours (43200000 milliseconds in the $query).

Note that this is heavily dependent upon the format of the event message having the username on the (zero-indexed) line 14. Works for us β€” no warranties, etc. etc.!

Installing RSAT on 1903 from the Features on Demand ISO

Installing the Remote System Administration Tools on a Windows 10 1903 system that uses System Center Configuration Manager to receive Windows updates seems to be challenging. The process of pulling the RSAT bits down from Windows Update in my experience was not succeeding – perhaps because the SCCM WSUS instance did not have them.

The CBS.log showed:

CBS    Exec: Failed to download FOD from WU, retry onece. [HRESULT = 0x800f0954 - CBS_E_INVALID_WINDOWS_UPDATE_COUNT_WSUS]

Some solutions online seemed to suggest temporarily switching the Windows Update source in the registry to Windows Update (online) rather than WSUS, but editing the registry this way and upsetting the software update system seemed… unwise.

I ended up doing it a different way: downloading the Features on Demand DVD ISO from the Volume Licensing Service Center (in my case, SW_DVD9_NTRL_Win_10_1903_64Bit_MultiLang_FOD_1_X22-01658.ISO), mounting the ISO and using this modified version of Martin Bengtsson’s script to install the components from that ISO without contacting Windows Update.

With any luck, this might help someone else.

Going Lower-Level

I just released, on GitHub, IdleTaskTerminatorLite, my first foray into the lower-level world of programming directly with the Win32 API.

We use an old custom shutdown.exe (BeyondLogic Shutdown) to provide a timed screen lock feature, where a user is notified their screen will lock in a period of time and can cancel the locking of the workstation.

Clicking the Cancel button within the time limit, however, seems unnecessary and requires precisely clicking the Cancel button when the user is under time pressure! This is not a good user experience. A simple change to the idle state of the machine (any keypress or mouse movement) should cancel the timed locking of the workstation.

This lightweight background application detects user activity and forcibly kills the beyondlogic.shutdown.exe process, effectively cancelling the locking of the workstation without requiring the user to actually click Cancel.

This is currently rather ‘opinionated’ in that it specifically checks for hard-coded named processes running. It Works for Us(tm), but you may need to modify it for your environment. πŸ˜‰

This whole solution is a little bit hacky, but it works. 😐

I had written something along these lines to terminate this workstation lock program in C#, but as a .NET process running in the background, you were looking at dozens of megabytes of RAM for something always running in the background. It felt thoroughly inefficient and unnecessary for something so simple.

I have always found myself honestly a little frightened of C and C++. Horror stories around coding securely, the undefined behaviour of doing ‘pointer stuff’ yourself… but this little project represented an opportunity to take this relatively rudimentary functionality and learn how to implement it the Win32 API directly in a C program β€” and in doing so, cut resource usage (hopefully) significantly.

So, I did. Using the oft-abused WH_KEYBOARD_LL hook (and its WH_MOUSE_LL cousin), I periodically update a counter as to the user’s last idle time. If the hook is called (i.e. the user is typing or moving the mouse) and it’s been long enough since we last noticed such interaction, I check for the beyondlogic.shutdown.exe process and, if present, kill it.

This began life as whatever Visual Studio template gave me a buildable project that let me work with the right APIs, so there is likely unnecessary stuff still present and it could be more lightweight still. And, there’s a good chance I’ve made mistakes that need correcting, so please do get in contact if you’re willing to educate me in some small (or large) way!

I have tried to be particularly careful with buffers β€” string handling is either done with (I guess, inefficient) fixed-size buffers where I check what I put in will fit first, and I’ve tried to use the ‘safe’ string functions where possible too.

So, it’s a baby step towards working on more low-level projects. But, I’ve taken some action to tackle my pointer anxiety. πŸ™‚

Maybe next the whole program should do the workstation locking, warning message and idle detection in one program.

“File and Printer Sharing Ports Blocked” β€” But Are They?

A recent upgrade to System Center Operations Manager, taking it to the new 2019 release, perhaps combined with an update to the Windows Server management packs, created an interesting issue.

On the management server, an alert was triggered about the management server itself:

Resolution State: New
Alert: Server Service: File and Printer Sharing Ports Blocked
Source: SCOM (SMB)
Path: SCOM.fqdn
Last modified by: System
Last modified time: 3/13/2019 2:14:28 PM
Alert description: Either Windows Firewall is disabled or the firewall inbound rules for TCP ports 445 or 139 are disabled.

Interesting. Did the upgrade to SCOM 2019 or the management pack somehow break Windows File Sharing? And if it did, why hadn’t we noticed more significant issues than just this alert?

Well, no β€” it looks like this alert is actually earlier from March, but perhaps the alert has re-surfaced, post upgrade, as the monitor re-evaluated. What I was sure about, however, was that the file sharing ports were indeed open and that this alert couldn’t be correct!

Right? Right?

To the Firewall!

Investigating all the relevant firewall rules revealed that everything was in order β€” Windows File and Printer Sharing exceptions were allowed, as appropriate, across the board.

File and Printer Sharing rules

What is it Detecting?

So, it was time to dig a little deeper.

I was able to go to the Alert details and click on the Alert Monitor to drill down and find the details of how the monitor was coming to this apparently erroneous conclusion.

I extracted the script and tried running it manually on the server using cscript.

With a few WScript.Echo calls of mine sprinkled in, the relevant part of the VBScript that powered the monitor was as follows:

Dim rule

For Each rule in fwPolicy2.Rules
  If (rule.Protocol = NET_FW_IP_PROTOCOL_TCP) And (rule.LocalPorts = "445") Then
    WScript.Echo("Proto " + CStr(rule.Protocol) + " and port " + rule.LocalPorts + " enabled: " + CStr(rule.Enabled))
    WScript.Echo("rule.Profiles: " + CStr(rule.Profiles) + " and rule.Enabled " + CStr(rule.Enabled))

    If (Not rule.Enabled) And (rule.Profiles And fwCheckProfile )  Then

      WScript.Echo "Setting file sharing ports enabled to true"
      fwFileSharingPortsEnabled = "True"

      Exit For

    End If

  End If
Next

So, let’s go ahead and run this.

The script also checks to see if any non-hidden shares exist on the server and will only put the monitor in an unhealthy state if at least one exists.

It iterates over all the rules for port 445, decides all the rules are enabled, which would allow access to File Sharing, but then ends up with fwFileSharingPortsEnabled still being false.

This propagates to the ultimate script output of a PropertyBag with the value Disabled under PortStatus.

All the rules are enabled, but the result is that it considers the ports not open for business??

Is this Logic?

Is this Logic?

It seems to me that there is a logic error here:

If (Not rule.Enabled) And (rule.Profiles And fwCheckProfile )  Then

Only if the firewall rule is not enabled and the profile matches the current network profile, we consider the port enabled?

Remember that if the rule is not enabled, traffic would be blocked by the Windows Firewall.

It seems that this might be a simple logic error in the management pack. A comment later in the script even states:

‘ Only if regular share exists and port 139/445 are not open will portStatus be returned as “Disabled”

Am I missing something obvious?

I’d Report This…

I cannot figure out where I should report this, if I’m correct in thinking how this should be working. Should I complain on a forum? Is there a System Center Operations Manager support Short-Form “Bird” Social Media Site Before It Went Terrible profile? Product Support?

An Unorthodox Workaround

For now, disabling at least one of the rules for port 445 suppresses this alert. For example, if you don’t need or want Remote Event Log Management, you can disable the Remote Event Log Management (NP-In) rule. This script will then return Enabled and the alert will not be fired.

Any of the port 445 rules being disabled will cause the script to be happy again.


Windows Upgrade Woes β€” 0x8024000d when searching for updates after 1703 upgrade

Windows as a Service.

It sounds like an eminently sensible idea in world where failing to keep software up-to-date, in particular with security fixes, has a tangible negative impact on people. Treating software as a service also provides a healthy ongoing income stream, as well. πŸ˜‰

At work, we had many issues with our first attempt at running an in-place upgrade from Windows 10 1511 to 1607 using ConfigMgr. They were resolved, in the end, but required a lot of effort.

So, naively, I am assuming that we couldn’t possibly quite as unlucky a second time, when testing using the same Windows 10 Servicing method for upgrading 1607 to 1703.

Alas, the upgrade to the new build itself worked without issue, but once booted into the new OS, Configuration Manager-mediated Windows Update scanning now fails.

This, from the WUAHandler.log:

OnSearchComplete - Failed to end search job. Error = 0x8024000d.
Scan failed with error = 0x8024000d.

Digging a little deeper, I’m seeing errors relating to the metadata for the updates.

[metadataintegrity] failed: hr = 0x80245004
[metadataintegrity]GetFragmentSigningConfig failed with 0x80245004. Using default enforcement mode: Audit.

We’re seeing an error relating to missing XML content, which I guess adds up with the suggestion that the metadata integrity is not validating.

0x8024000D WU_E_XML_MISSINGDATA Windows Update Agent could not find required information in the update's XML data.

My searching so far indicates that folks have fixed this with rather significant rebuilds of their WSUS infrastructure. I’d like to avoid that, of course!

It seems that perhaps third-party products being added to WSUS (such as Adobe Flash Player, before it was shipped as part of MS updates from Windows 8 onwards) may be related to the issue.

It is odd, and frustrating, that whatever issue it is only manifests in 1703, and that, once again, the nuclear option of a rebuild of a significant infrastructure piece is the dominant suggested solution.

I will update this post with any success I have resolving the issue without starting afresh with WSUS.