Tuesday, March 21, 2023

Formative Years

    The first game I ever completed was Pokemon Crystal on my brother's Game Boy Color. 
    Some kind soul had gifted it to him for his 9th birthday. It was the purple one. I'm sure the jealous tantrum I was throwing as he unwrapped it wasn't too bad. He had always been gifted the new fancy toys. Not that he didn't deserve them, he was a miracle after all.
    I reflect on (brood about) my childhood pretty often. My oldest brother was the first born grandchild of a huge family, so of course he was spoiled. And then my second brother was the miracle child, surviving a disease that should have killed him, so of course he was spoiled too.
Totodile, Pokemon Crystal 2001
    Then there was me. I think the excitement of kids had likely worn off after the 40th cousin had been born, so needless to say, I didn't get showered with gifts the way my brothers had. I'm sure I expressed my frustration plenty. I'd never complain about it though, really!

    Of course, the upside to my brothers being spoiled rotten was their hand-me-downs. It didn't take long for me to inherit the GameBoy. My mother had bought him Pokemon Crystal at some point, and I happily wrote over his save data with a new game. Totodile was my first starter Pokemon. He helped me beat the game at the humble level of 74, along with the first legendary Pokemon I ever caught, Raiku. I took me 5 or 6 attempts to beat Lance at the end of the game. I may have asked my oldest brother for help once or twice. He did so, begrudgingly.
The Legend of Zelda, A Link to the Past
    The games that I played as a kid were formative to who I am today. The art and stories that draw my eye have their roots in the charm and style of the games of the late 90s and early 2000s. 
    I remember being blown away by the lush nature and open world of A Link to the Past. I recall being entrenched in the stories of Golden Sun and Super Mario Tennis Pro Tour. I remember being charmed by the bright and colorful world of Kirby. I remember learning to manage time and resources with my first Harvest Moon game. Final Fantasy Tactics and Advanced Wars expanded my planning skills, and changed my expectations of the medium forever.
    It did much more than form my preferences though. My brothers and I played everything together. If it was multiplayer, we did our best to wear the contacts out on the game cartridges. We spent hundreds of hours playing Mario Kart and Smash Brothers. In fact, even the single player games, like Pokemon Colosseum, were open to back seat experiences.
     If it wasn't video games, we'd be out on the trampoline together, playing basketball in the backyard, or shooting soda cans with BB guns. They had my back at school and at home.
    Things would change. My oldest brother was nearing adulthood, and the effects of my middle brother's childhood sickness were beginning to manifest in learning difficulties for him.
    When I turned 9 my oldest brother moved to my father's house. When I turned 10, my middle brother was sent to a special education school to learn how to live without hearing. My single mother was now the only company in our home, and she often worked late. I had to learn to be alone.
     It was a melancholy experience. While I was grateful to be alone during my brooding preteen years, I missed the companionship of my brothers. After school, I was just... alone. No brothers to watch my back, no one to jab and sneer, no one to laugh and play with.
     I played Pokemon Emerald that year.
    The opening sequence of the game shows your character biking away from their hometown, the parents, and their best friend. The sun is shining down, the coastline behind them. They're on their way to experience their first journey, all alone.
    But the part that matters to me is the end.
    Your character travels an exotic world, thwarting evil, meeting new friends, facing puzzles and challenges, saves the world, and meets creatures of myth and legend. Your final challenge is the elite four, and the Pokemon champion. Your character faces them all, wins. and becomes the new reigning champion, all by their self. There at the end, having conquered what the world had to throw at you, your best friend arrives to meet you. 
    The final scene of the game shows your character biking back the other way, their journey complete, the world saved. Now, the night has set, the city is behind you, and you are no longer alone.
     The journey ends with you and a companion, headed home. 

 

    I can't say that I ever got used to being alone, or that I learned to be comfortable in that silence. The truth is that, sometimes, childhood ends sooner than we were expecting it to. I'm sure that my brothers felt that way too.
    Sometimes circumstances will leave us stranded. Maybe we're ostracized, left out, ignored, or forgotten... And sometimes we have to go through life that way, fighting our battles alone. If we can stick it out, face those challenges head on, just maybe, at the end, you'll have a companion waiting for you too.  


    I've got a special place in my heart for pixel art styled games. One of my first projects as a Computer Science major was a top down adventure game. It was terrible, of course. The character art was a lame stick figure made in MS Paint, and you couldn't do much more than walk around.
    Years later, I'd like to think that I improved a bit. It wasn't too long ago that I discovered Aseprite, a software specially designed for pixel art creation. Now I'm happily making the same art that kept me company as a kid.
    So, hello from me to you. I hope I can keep you company too.

Gerthew


 

Sunday, March 19, 2023

Cloud Watchers in the Terminal

Where windows tower, streaming light,
where hearts await an inbound flight
and watch the clouds in lofty wonder
above the leagues that split asunder -

they regard above where angels drift,
and those wistful souls that ever shift,
as dancing clouds eternally chase
windy streams in empty space -

those hearts below shall plead to know,
from where shall freedom be bestowed,
within their flights or with the doves,
within the clouds or high above?

















Photo taken over Texas skies, many years ago.

    I've got a special connection with airport terminals. I'd spend a lot of time in them as a kid. For hours, I'd roam an empty terminal. My only company would be an occasional wandering traveler or the janitorial crew passing by. I'd find myself seated in front of a set of windows that towered three stories above me. I'd spend a lot of time reflecting there.
    It was freeing - to be away from family, friends, expectations, to be just another passing stranger to everyone. It was the end of a story, and the beginning of a new one. I knew when I came back through this terminal in a few months, I'd be in a new home, a new school, another new start. For me, it was a place in between, the start and end of a story, the brief respite before the next act.

Saturday, March 18, 2023

Feeling Azure - A PowerShell Deep Dive

 PowerShell Solutions

   So, have you ever tried to join a computer to a domain using PowerShell? It's a simple line or two of code:

$domainName = "yourdomain.local"
$username = "administrator"
$password = "password"
$computerName = "yourcomputername"

$credential = New-Object System.Management.Automation.PSCredential ($username, (ConvertTo-SecureString $password -AsPlainText -Force))

Add-Computer -DomainName $domainName -Credential $credential -ComputerName $computerName -Restart
    Fill in the variables with the correct information and voila, the computer has been registered and joined to your local Active Directory. Hop in the AD tenant and get the computer moved into the right group and you are good to go!
    Currently, I'm employed with a Market Service Provider, which means I've got a lot of different Local AD tenants and several Azure AD tenants to contend with.
    For local AD device joining, I use a similar script during the configuration of a computer. It's an automated process, a "lite-touch" deployment, if you will. Using Windows Deployment Server and Windows Deployment Toolkit, I network boot the machine, select the image for the customer, name it, and let it fly! 10 minutes later and you have a near-fully imaged computer ready to head out the door. Some last minute cleanup includes running any leftover Windows updates and ensuring our RMM tool is installed.
    Unfortunately, for the companies using Azure AD, the process has a hiccup: PowerShell doesn't support joining a device to Azure AD.
    As you can probably tell by the fact that I've written this post, this bugged me. Every so often I'll have to configure a few hundred devices in a weeks time. Between un-packaging all the computers, getting plenty of paper-cuts, and drying my hands out on all of the cardboard, I'd prefer not to manually join each of the devices to Azure AD. I'd like to simplify device configuration as much as possible so I can get back to the rest of my job.
    A few Google searches later and I discovered that the internet had declared my worst fear: making it work with PowerShell is impossible.
    I was crushed.
    But there had to be a workaround.

 

 

Windows Configuration Designer


    It's clunky, but it works. 
    Windows Configuration Designer (WCD) is a Microsoft Store application designed to supposedly simplify workstation deployment. It can be used to name a device, join it WiFi, installWwindows Store applications, and most importantly, join a device to Azure AD or Local AD.
    Of course the only component of this application I was interested in was the Azure AD joining function.
    This article by Anders Ahl was a great starting point for my Azure AD journey. WCD is a pretty simple program. Following Anders' article I was able to plug in the necessary information and get a .ppkg file. The .ppkg is just a package file with an Azure token that can be installed upon applying the package to the device. There's even a handy little line of code within the article for installing the package:
DISM.exe /Image=C:\ /Add-ProvisioningPackage /PackagePath:C:\BulkJoin.ppkg
    After applying the package, the device should be joined to the Azure domain! Simple! Just slap that package and script in the customer image and we're off to the races!
    Except... 
    Six months later, the script broke for each and every customer. I knew it was coming, but its easy to forget about over such a long time period. The token that WCD pulls expires after a maximum of 6 months. Afterwards, the package needs to be rebuilt.
    Not a big deal, just rebuild the packages! But now I have dozens of these scripts, packages and images. To add to the complexity, trying to create more than one package in a day can sometimes result in WCD locking itself to one Azure account. This will force me to wait a day or two for the login to expire, and then I'm free to start working on the next package.
    This was not ideal. So, back to the drawing board.

 

 

Autopilot


    So why is this a problem in the first place? Why not just allow a PowerShell to do the heavy lifting and script its way into an Azure account?
    I've got a theory, and it's pretty universal in the technology sector: monetization.
    Autopilot, in Microsoft's infallible opinion, is the future: grab the hardware hash and hand it over to Microsoft, set up the user's account with an Intune license, and send it off to the user. All the user needs to do is login and wait for the apps and configuration you specified to download. It's that easy!
    ..Sort of.
    There are immediately some issues for my use case. First, many of my customers do not want to pay for the proper licensing to use Intune. Many of our customers are healthcare facilities operating with near destitute equipment budgets. As much as I would love for them to utilize the latest and greatest equipment, the truth is that many of them still have 10 year old Cisco switches in their network racks. In fact, I only have one customer that is currently using Autopilot, a logistics company that insists on being on the cutting edge of technology.
    Second, a user will not always have the necessary bandwidth for the initial deployment of a computer using Autopilot. Many of our customers work in rural areas that don't have the blessing of high speed fiber. An Autopilot deployment in one of these areas could last as long as two days. That is simply unacceptable.
     Third, sometimes Autopilot just doesn't work. The logistics company we support does have the blessing of high-speed fiber internet. Autopilot relies on a callback to Intune to actually configure the device. Sometimes Intune just... decides to take it's time. We've had computers sit in stasis for up to three hours, and some would finish their deployment missing a full half of the applications we'd specified to be installed.
    Fourth, allowing a user to have permissions to join Azure AD is a recipe for disaster. Microsoft wants to push user enrollment to be the solution for joining a device to the company tenant. This way, there's an Intune license, which means more money for Microsoft. Let's look at why user joining is a problem.

 

 

The Vulnerability


    On his website, Dr. Nestori Syynimaa explores an attack called "AAD Kill Chain" wherein a threat actor can exploit the same tokens being pulled by WCD to gain access to a company's Azure AD tenant. This is, of course, a disastrous scenario.
    Details about his discovery of this vulnerability can be read about here. His conclusion: Don't allow users to have permissions to join a device to Azure AD.
    Ironically, this vulnerability also presents me with a convenient opportunity.

 

 

Exploiting BPRT Tokens


    After some fiddling, lots of documentation skimming, and some correspondence with Dr. Nestori, I found a solution.
    First, we need to install some packages. We start with bypassing the execution policy. Next, we install the latest NuGet package, the AzureAD package, and AADInternals, a trusted package developed by Dr. Nestori.
    Next we begin grabbing the information we need. After making some variables for our credentials, we'll reach out to Microsoft's registration service. After touching base and getting an access token to AzureAD, we direct Microsoft to create a user named "BPRT AzureJoinScriptUser." This user exist only to hold the fresh BPRT token we need to join the device to Azure AD. Because the account is brand new, there is no need to worry about token expiration in the future.
    Now we'll use the token to emulate the join process by "joining" a device to Azure AD. We're really just contacting Azure AD to create a corresponding device, transport key (=Certificate) and a Device Object. We'll need all of this pre-made to actually configure the device itself.
    The next step is calling the certificate and using it join the device. 
    Finally, we clean up by deleting the temporary user we needed to host the fresh BPRT token.
    Here's the script when it's all put together:
echo "Setting execution policy."
set-executionpolicy bypass -Force

echo "Installing NuGet latest"
Install-PackageProvider -Name NuGet -Force

echo "Installing AzureAD module."
Install-Module AzureAD -Force

echo "Installing and importing 3rd party module: AADInternals"
Install-Module AADInternals -Force
Import-Module AADInternals -Force

$AdminUserName = "Azure join account username"
$AdminPassword = "Azure join account password"
$SecurePassword = ConvertTo-SecureString $AdminPassword -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential -argumentlist $AdminUserName, $SecurePassword

Get-AADIntAccessTokenForAADGraph -Resource urn:ms-drs:enterpriseregistration.windows.net -Credential $Credential -SaveToCache

$bprt = New-AADIntBulkPRTToken -Name "BPRT AzureJoinScriptUser"

Get-AADIntAccessTokenForAADJoin -BPRT $BPRT -SaveToCache

$compname = hostname
Join-AADIntDeviceToAzureAD -DeviceName $compname
$pfxfile = ".\" + (dir .\ -n *.pfx)

Join-AADIntLocalDeviceToAzureAD -UserPrincipalName $AdminUserName -PfxFileName $pfxfile

Connect-AzureAD -Credential $Credential

echo "Cleaning Up..."
Start-Sleep -Seconds 25
Remove-AzureADUser -ObjectID (Get-AzureADUser | where {$_.DisplayName -eq "BPRT AzureJoinScriptUser"}).UserPrincipalName
echo "Operations complete."
     And there it is! A working script to join devices to an Azure AD tenant. No more rebuilding packages, no more manually entering credentials. Using AADinternals, I've successfully defied what the internet declared: "It's impossible." 
    I'd like to clarify that tools on Dr. Nestori's website aren't really for this purpose. Certainly, they can be used in any way you would like, but AADinternals is closer to a penetration testing tool. Dr. Nestori was kind enough to help me use it for simplifying my workflow. I highly recommend reading through his website. 
 

Friday, March 17, 2023

A blog, from me to you.

Back in the hay-day of Instagram (before Facebook started buying every social media platform) I had built up quite a community of like minded individuals. I trimmed and weeded who I followed thoroughly, leaving only those who regularly published content that I wanted see. 

After Facebook's purchase of Instagram I had to jump ship. Bloated features, a non linear timeline of my feed, double the ads, almost no user posts on my feed anymore - I couldn't take it. 

I do miss it. I was regularly treated to posts from writers, photographers, talented programmers and technology focused individuals. It was a great outlet for me. I published stories and photos myself, found local coffee shops, and made several friends. The biggest find? My wife. 

So here's my goal: To use this blog to share again. I miss writing, taking photos, sharing code, enthusing about coffee.. etc. Even if it's just my wife reading this blog forever.

My first post is for my wife, a poem to reminisce about the first year of our relationship. 

This is my little love letter from me to you, Kate.

Courtship

Oh, how thoughts of her fill your day,
and each sly excuse to walk her way
to see her twist and twirl a lock of hair,
exposing her neck and skin to air,
rewards smiling eyes at her discretion
and a playful smile in your direction.

Oh, how you'll feel at your first embrace,
how her hair will wrap around your face,
the twists and twirls your heart will spin,
the joy your soul will feel within -

Oh, the aches your heart will know,
when receiving texts with undertones.
How you'll yearn to know her shape,
to feel her breath against your face -

Then, one day, caught out in the rain,
You'll both be soaked, and shivering,
she'll be pressed up against you, away from the storm,
and she'll say with you, she's always warm.

Oh, how you'll spend your hours alone together,
hoping it will last forever -
Oh the way her breath will brush your face
as you dance within an empty space,
while watching stars atop a hill,
with fireflies and daffodils,
You'll kiss her.

And it will last forever.

 

A City with Mountains on All Sides

The cities have always been my home. Accessible. Loud. Crowded. A little dirty. I worked there, shopped there, wandered late-night corners a...