Author: Abhinay Pal · 8 min read
If you’ve ever spent half a workday wrestling with the AzureAD module, downloading Get-WindowsAutoPilotInfo.ps1, exporting a CSV, emailing your Intune admin, and waiting for a portal upload — this tool replaces all of it.
One PowerShell file. Lives on a USB stick. Captures the hardware hash, talks directly to Microsoft Graph, registers the device in Intune Autopilot, and waits until the deployment profile is actually assigned. Under three minutes per device, every time.
Watch the 2-minute demo on YouTube · Download from GitHub · CC BY-NC 4.0
The problem we kept hitting
Every Autopilot registration workflow we’ve seen — at customer sites, in our own deployments, in MSP shops, in enterprise SOEs — has at least one of these problems:
- Module hell. The
AzureADmodule’sCommonLibrary.dllthrows processor-architecture errors on ARM and 32-bit hosts. You get it working on your laptop, install the same version on a spare machine, and it breaks differently. - Portal dependency. The hash is captured, exported to CSV, the tech emails it to the Intune admin, who opens the portal, navigates to Autopilot Devices, uploads the CSV. Forty-five minutes per device. Every time.
- No visibility into profile assignment. The hash is in Intune, but did the deployment profile actually attach? T
I got tired of all four. So built the Autopilot Device Hash Gather Utility, and v2.0 is the first version I’m confident enough about to publish.
What the tool is
Autopilot Device Hash Gather Utility v2.0 is a Windows Presentation Foundation (WPF) PowerShell tool that:
- Reads the device’s Autopilot hardware hash directly from WMI
- Authenticates to Microsoft Graph using an app registration it provisions itself
- Uploads the hash to
importedWindowsAutopilotDeviceIdentities - Polls Intune until the deployment profile is actually assigned — translating Graph status codes into plain English
- Ships as a single
.ps1file on a USB stick that any technician can use
Not-Required:
AzureAD. AzureADPreview. Microsoft.Graph SDK. WindowsAutoPilotIntune. Get-WindowsAutoPilotInfo.ps1. A Modules\ folder. A pre-existing app registration. PowerShell 7. Anything beyond the script itself.
Required: Windows 10 1809+ or Windows 11 (x64 or ARM64), PowerShell 5.1 (ships with Windows), local admin on the target device, and a one-time tenant admin sign-in for the very first run.
How it works — the two parts that matter
There’s a lot going on under the hood — the WPF UI, the runspace worker thread, the WMI hash capture, the Graph polling logic — but if you’re evaluating whether to trust this tool, the two questions you actually care about are:
- How does it sign in to my tenant?
- How does it protect the credentials it stores?
Here’s the answer to both.
1. Authentication — it provisions its own app registration
The first time you run the tool, it does not need a pre-existing app registration. There’s nothing for an Intune admin to set up in advance. There’s no client ID to paste, no secret to share by email.
You click Start. A browser window opens to the Microsoft sign-in page. A tenant admin signs in once.
Behind the scenes, the tool then makes four Graph calls:
| Step | Endpoint | What it does |
|---|---|---|
| 1 | POST /applications | Creates an app registration named PixelTech – Autopilot Hash Upload |
| 2 | POST /servicePrincipals | Creates the service principal that allows the app to act in your tenant |
| 3 | POST /servicePrincipals/{id}/grantConsentForAllUsers | Grants admin consent for two Graph permissions |
| 4 | POST /applications/{id}/addPassword | Mints a client secret valid for two years |
The two permissions it grants are:
DeviceManagementServiceConfig.ReadWrite.All— required to upload an Autopilot hashDeviceManagementManagedDevices.ReadWrite.All— required to read deployment-profile assignment status
That’s it. No Directory.Read.All, no User.Read.All, no overreach. These are the minimum permissions the Microsoft Graph API requires for the operations this tool performs, and you can verify them yourself in the Entra admin portal.
The app registration is fully visible in your tenant. You can audit it, rotate the secret, restrict its scope, or delete it entirely from Entra ID → App registrations → PixelTech – Autopilot Hash Upload. Nothing is hidden.
From the second run onward — same machine or a different one — the tool uses the saved credentials and acquires a token silently via the client-credentials flow. No browser. No sign-in. No portal trip.
2. Encryption — AES-256 with a passphrase that lives in your head
After the app registration is created, but before any credential touches the disk, the tool asks you for a passphrase.
This is the moment most “credential management” stories get awkward. Most tools either:
- Store the secret in plaintext (bad — anyone with the USB has your tenant), or
- Use Windows DPAPI to encrypt it (better, but ties the file to one machine + one user — defeats the whole point of a portable USB tool)
We chose a third path. The client secret is encrypted with AES-256-CBC, the same standard cipher used by banks, governments, and TLS itself. The encryption key is derived from a passphrase you create, using PBKDF2-SHA1 with 200,000 iterations — a deliberately slow hashing step that makes brute-forcing the passphrase impractical even for an attacker with the encrypted file.
Critically, the passphrase never touches disk. It’s entered into a masked password field, held in memory only for the duration of the session, and is never written to the config file, the log file, or anywhere else. The key is regenerated from the passphrase every run.
The on-disk format is:
enc:aes256:v1:<base64 salt>:<base64 iv>:<base64 ciphertext>
Because the encryption is keyed off the passphrase and not the machine, the same USB stick + the same passphrase unlocks the tool on any Windows device. That’s the portability win — and the reason we deliberately did not use DPAPI.
The threat model in one paragraph: if someone steals the USB stick, they have the encrypted secret but not the passphrase — useless. If someone learns the passphrase, they don’t have the encrypted secret — also useless. They’d need both, and even then, you can rotate the secret in Entra ID at any time and the stolen pair becomes worthless.
The user interface
The tool is a single WPF window with three tabs.
Hash Upload tab
- Device info card — name, manufacturer, model, serial, domain — read automatically from WMI on launch.
- Phase stepper — four circles representing Prepare → Authenticate → Upload Hash → Complete. The active phase glows violet with a pulsing animation. Completed phases turn green with a checkmark.
- Console — a live, monospaced log of everything the tool is doing. Auto-scrolls to the bottom.
- Progress bar — pill-shaped, smooth fill animation, ticks live during the run.
- Action buttons — Start (primary), Abort (when running), Close.
Settings tab
- Group Tag — written to the device record in Intune; used by Autopilot deployment profiles to target this device. Picked up live from the textbox at run time, no save required.
- Tenant ID — your Microsoft 365 tenant ID. Auto-populated after the first sign-in.
- Save Settings — persists the values to
AutopilotApp_Config.json. - Reset App Registration — deletes the saved config so the next run does a fresh first-run flow.
About tab
Version, release date, developer, supported platforms, authentication mechanism, secret-storage scheme, and a “What’s new in v2.0” section.
The first-run flow, end to end
- Plug in the USB that contains
Gather Autopilot Hash.WPF.ps1and (optionally)logo.png. - Launch the script: right-click → Run with PowerShell, or open an admin PowerShell prompt and run
powershell -ExecutionPolicy Bypass -File "E:\Gather Autopilot Hash.WPF.ps1". - (Optional) On the Settings tab, type your Group Tag.
- Click Start Autopilot Collection.
- A browser opens. A tenant admin signs in. Behind the scenes the tool creates the app registration, service principal, consent grant, and client secret (~5 seconds).
- The passphrase window appears with two fields — passphrase and confirm. Minimum 8 characters. Type both, click OK.
- The tool encrypts the client secret with the passphrase you just set, writes
AutopilotApp_Config.jsonnext to itself, and proceeds. - The hardware hash is captured from WMI, uploaded to
importedWindowsAutopilotDeviceIdentities, and polled until the import completes. - The tool looks up the device by serial number in
windowsAutopilotDeviceIdentities, then pollsdeploymentProfileAssignmentStatusevery 10 seconds with friendly messages:- “Looking for a matching deployment profile…”
- “Profile scheduled — Intune is applying it now”
- “Profile assigned and in sync — ‘Corp Autopilot’”
- Done. The phase stepper turns all green. The progress bar hits 100%. The tech can move to the next device.
Subsequent runs (same USB, any machine)
- Plug in the USB. Launch the script.
- The passphrase window appears in unlock mode — a single field and the message “Enter the passphrase that was used to encrypt the saved credentials.”
- Type the passphrase, click Start.
- No browser. No sign-in. The tool reads the encrypted secret, decrypts it, acquires a token via client-credentials, and proceeds straight to hash capture and upload.
The whole thing takes under three minutes per device on a well-behaved tenant.
OOBE workflow
The tool also runs during Windows Out-Of-Box Experience (OOBE), which is the most powerful use case for fleet rollouts:
- On the OOBE network screen, connect to Wi-Fi or Ethernet.
- Press Shift+F10 to open a command prompt.
- Run
powershell -ExecutionPolicy Bypass -File "E:\Gather Autopilot Hash.WPF.ps1"(replaceE:with your USB drive letter). - Enter the passphrase when prompted.
- Wait for
[Profile] → Profile assigned and in sync. - Close the tool, run
shutdown /r /t 0, and let the device restart. OOBE picks up the freshly assigned profile on the reboot.
Note: OOBE supports the subsequent-run flow (passphrase only, silent token). The first-ever run requires an interactive browser, which is unreliable inside OOBE. Do the first run on any non-OOBE Windows machine to generate
AutopilotApp_Config.json, then carry that USB to your field devices. From that point on, every machine — including OOBE — needs only the passphrase.
What’s new in v2.0
Legacy plaintext and DPAPI-encrypted configs from earlier builds are automatically migrated on first launch with v2.0 — no manual steps required.
Security posture
| Concern | How v2.0 addresses it |
|---|---|
| Client secret exposure on shared USB | AES-256-CBC + PBKDF2-SHA1 (200k iterations). Passphrase in memory only, never on disk. |
| Replay after USB loss | Rotate the client secret in Entra (single-click in the portal) or delete the app registration entirely to invalidate the stolen pair. |
| Over-scoped app registration | Only two Graph permissions requested, both the minimum required. Auditable in Entra. |
| Tokens in logs | Access tokens are never logged. Logs contain HTTP status codes, device IDs, and state transitions only. |
| Brute-force resistance | PBKDF2-SHA1 at 200k iterations is roughly 400 ms per attempt on modern hardware — enough friction to slow dictionary attacks without being user-hostile. |
| Network in transit | All Graph calls over TLS 1.2+ to graph.microsoft.com and login.microsoftonline.com. No custom endpoints. |
If you’re security-reviewing this for your environment, the entire script is a single .ps1 file under 2,000 lines. Audit it, fork it, change anything you don’t like.
Customization
Replace the header logo: drop a PNG named logo.png next to the script. The tool auto-loads it on launch — recommended size 96×96 or 128×128 px, transparent background.
Change the accent color: the violet #7C3AED accent is defined in one place in the XAML. Search for the hex code and replace with your brand color.
Rebrand the app registration: search for PixelTech - Autopilot Hash Upload in the script and rename it. The tool will create the app under your chosen name on first run.
Change the chrome gradient: the lavender background is a LinearGradientBrush with two stops (#F5F3FF and #EDE9FE). Swap them for any two-tone pair.
Get the tool
| Version | 2.0.0 |
| Released | April 2026 |
| Platform | Windows 10 1809+ / Windows 11 (x64 or ARM64) |
| Runtime | PowerShell 5.1 (no PS7 required) |
| License | Creative Commons Attribution-NonCommercial 4.0 (CC BY-NC 4.0) |
📺 Watch the 2-minute demo →
📥 Download from GitHub →
📖 Read the README →
A note from the author
This tool started as an internal time-saver.
If it saves you an hour, a Tuesday, or a customer relationship — that’s the win. If it doesn’t, tell us what we got wrong on GitHub and we’ll fix it.
— Abhinay Pal



Leave a Comment