mirror of
https://github.com/outbackdingo/OpCore-Simplify.git
synced 2026-01-27 10:19:49 +00:00
Add WiFi profile extraction tool for itlwm users
This commit is contained in:
@@ -66,6 +66,7 @@
|
||||
- Add built-in device property for network devices (fix 'Could not communicate with the server' when using iServices) and storage controllers (fix internal drives shown as external).
|
||||
- Prioritize SMBIOS optimized for both power management and performance.
|
||||
- Re-enable CPU power management on legacy Intel CPUs in macOS Ventura 13 and newer.
|
||||
- Apply WiFi profiles for itlwm kext to enable auto WiFi connections at boot time.
|
||||
|
||||
and more...
|
||||
|
||||
|
||||
@@ -337,7 +337,20 @@ class KextMaestro:
|
||||
try:
|
||||
bundle_info = self.utils.read_file(plist_path)
|
||||
|
||||
if bundle_info.get("IOKitPersonalities").get("VoodooTSCSync"):
|
||||
if bundle_info.get("IOKitPersonalities").get("itlwm").get("WiFiConfig"):
|
||||
from Scripts import wifi_profile_extractor
|
||||
|
||||
wifi_profiles = wifi_profile_extractor.WifiProfileExtractor().get_profiles()
|
||||
|
||||
if wifi_profiles:
|
||||
bundle_info["IOKitPersonalities"]["itlwm"]["WiFiConfig"] = {
|
||||
"WiFi_{}".format(index): {
|
||||
"password": profile[1],
|
||||
"ssid": profile[0]
|
||||
}
|
||||
for index, profile in enumerate(wifi_profiles, start=1)
|
||||
}
|
||||
elif bundle_info.get("IOKitPersonalities").get("VoodooTSCSync"):
|
||||
bundle_info["IOKitPersonalities"]["VoodooTSCSync"]["IOPropertyMatch"]["IOCPUNumber"] = 0 if self.utils.parse_darwin_version(macos_version) >= self.utils.parse_darwin_version("21.0.0") else int(hardware_report["CPU"]["Core Count"]) - 1
|
||||
elif bundle_info.get("IOKitPersonalities").get("AmdTscSync"):
|
||||
bundle_info["IOKitPersonalities"]["AmdTscSync"]["IOPropertyMatch"]["IOCPUNumber"] = 0 if self.utils.parse_darwin_version(macos_version) >= self.utils.parse_darwin_version("21.0.0") else int(hardware_report["CPU"]["Core Count"]) - 1
|
||||
|
||||
279
Scripts/wifi_profile_extractor.py
Normal file
279
Scripts/wifi_profile_extractor.py
Normal file
@@ -0,0 +1,279 @@
|
||||
from Scripts import run
|
||||
from Scripts import utils
|
||||
import platform
|
||||
import json
|
||||
|
||||
os_name = platform.system()
|
||||
|
||||
class WifiProfileExtractor:
|
||||
def __init__(self):
|
||||
self.run = run.Run().run
|
||||
self.utils = utils.Utils()
|
||||
|
||||
def validate_wifi_password(self, password):
|
||||
if not password:
|
||||
return False
|
||||
|
||||
try:
|
||||
password.encode('ascii')
|
||||
except UnicodeEncodeError:
|
||||
return False
|
||||
|
||||
if 8 <= len(password) <= 63 and all(32 <= ord(c) <= 126 for c in password):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def get_wifi_password_macos(self, ssid):
|
||||
output = self.run({
|
||||
"args": ["security", "find-generic-password", "-wa", ssid]
|
||||
})
|
||||
|
||||
if output[-1] != 0:
|
||||
return None
|
||||
|
||||
try:
|
||||
ssid_info = json.loads(output[0].strip())
|
||||
password = ssid_info.get("password")
|
||||
except:
|
||||
password = output[0].strip() if output[0].strip() else None
|
||||
|
||||
if password and self.validate_wifi_password(password):
|
||||
return password
|
||||
|
||||
return None
|
||||
|
||||
def get_wifi_password_windows(self, ssid):
|
||||
output = self.run({
|
||||
"args": ["netsh", "wlan", "show", "profile", ssid, "key=clear"]
|
||||
})
|
||||
|
||||
if output[-1] != 0:
|
||||
return None
|
||||
|
||||
for line in output[0].splitlines():
|
||||
if "Key Content" in line:
|
||||
password = line.split(":")[1].strip()
|
||||
if self.validate_wifi_password(password):
|
||||
return password
|
||||
|
||||
return None
|
||||
|
||||
def ask_network_count(self, total_networks):
|
||||
self.utils.head("WiFi Network Retrieval")
|
||||
print("")
|
||||
print("Found {} WiFi networks on this device.".format(total_networks))
|
||||
print("")
|
||||
print("How many networks would you like to process?")
|
||||
print(" 1-5 - Specific number (default: 5)")
|
||||
print(" A - All available networks")
|
||||
print("")
|
||||
|
||||
num_choice = self.utils.request_input("Enter your choice: ").strip().lower() or "5"
|
||||
|
||||
if num_choice == "a":
|
||||
print("Will process all available networks.")
|
||||
return total_networks
|
||||
else:
|
||||
try:
|
||||
max_networks = min(int(num_choice), total_networks)
|
||||
print("Will process up to {} networks.".format(max_networks))
|
||||
return max_networks
|
||||
except:
|
||||
max_networks = min(5, total_networks)
|
||||
print("Invalid choice. Will process up to {} networks.".format(max_networks))
|
||||
return max_networks
|
||||
|
||||
def process_networks(self, ssid_list, max_networks, get_password_func):
|
||||
networks = []
|
||||
processed_count = 0
|
||||
consecutive_failures = 0
|
||||
max_consecutive_failures = 3
|
||||
|
||||
while len(networks) < max_networks and processed_count < len(ssid_list):
|
||||
ssid = ssid_list[processed_count]
|
||||
|
||||
try:
|
||||
print("")
|
||||
print("Processing {}/{}: {}".format(processed_count + 1, len(ssid_list), ssid))
|
||||
if os_name == "Darwin":
|
||||
print("Please enter your administrator name and password or click 'Deny' to skip this network...")
|
||||
|
||||
password = get_password_func(ssid)
|
||||
if password:
|
||||
if (ssid, password) not in networks:
|
||||
consecutive_failures = 0
|
||||
networks.append((ssid, password))
|
||||
print("Successfully retrieved password for {}".format(ssid))
|
||||
|
||||
if len(networks) == max_networks:
|
||||
break
|
||||
else:
|
||||
consecutive_failures += 1 if os_name == "Darwin" else 0
|
||||
print("Skipped or could not retrieve password for {}".format(ssid))
|
||||
|
||||
if consecutive_failures >= max_consecutive_failures:
|
||||
continue_input = self.utils.request_input("\nUnable to retrieve passwords. Continue trying? (Y/n): ").strip().lower() or "y"
|
||||
|
||||
if continue_input != "y":
|
||||
break
|
||||
|
||||
consecutive_failures = 0
|
||||
except Exception as e:
|
||||
consecutive_failures += 1 if os_name == "Darwin" else 0
|
||||
print("Error processing network '{}': {}".format(ssid, str(e)))
|
||||
|
||||
if consecutive_failures >= max_consecutive_failures:
|
||||
continue_input = self.utils.request_input("\nUnable to retrieve passwords. Continue trying? (Y/n): ").strip().lower() or "y"
|
||||
|
||||
if continue_input != "y":
|
||||
break
|
||||
|
||||
consecutive_failures = 0
|
||||
finally:
|
||||
processed_count += 1
|
||||
|
||||
if processed_count >= max_networks and len(networks) < max_networks and processed_count < len(ssid_list):
|
||||
continue_input = self.utils.request_input("\nOnly retrieved {}/{} networks. Try more to reach your target? (Y/n): ".format(len(networks), max_networks)).strip().lower() or "y"
|
||||
|
||||
if continue_input != "y":
|
||||
break
|
||||
|
||||
consecutive_failures = 0
|
||||
|
||||
return networks
|
||||
|
||||
def get_preferred_networks_macos(self, interface):
|
||||
output = self.run({
|
||||
"args": ["networksetup", "-listpreferredwirelessnetworks", interface]
|
||||
})
|
||||
|
||||
if output[-1] != 0 or "Preferred networks on" not in output[0]:
|
||||
return []
|
||||
|
||||
ssid_list = [network.strip() for network in output[0].splitlines()[1:] if network.strip()]
|
||||
|
||||
if not ssid_list:
|
||||
return []
|
||||
|
||||
max_networks = self.ask_network_count(len(ssid_list))
|
||||
|
||||
self.utils.head("Administrator Authentication Required")
|
||||
print("")
|
||||
print("To retrieve WiFi passwords from the Keychain, macOS will prompt")
|
||||
print("you for administrator credentials for each WiFi network.")
|
||||
|
||||
return self.process_networks(ssid_list, max_networks, self.get_wifi_password_macos)
|
||||
|
||||
def get_preferred_networks_windows(self):
|
||||
output = self.run({
|
||||
"args": ["netsh", "wlan", "show", "profiles"]
|
||||
})
|
||||
|
||||
if output[-1] != 0:
|
||||
return []
|
||||
|
||||
ssid_list = []
|
||||
|
||||
for line in output[0].splitlines():
|
||||
if "All User Profile" in line:
|
||||
try:
|
||||
ssid = line.split(":")[1].strip()
|
||||
if ssid:
|
||||
ssid_list.append(ssid)
|
||||
except:
|
||||
continue
|
||||
|
||||
if not ssid_list:
|
||||
return []
|
||||
|
||||
max_networks = self.ask_network_count(len(ssid_list))
|
||||
|
||||
self.utils.head("WiFi Profile Extractor")
|
||||
print("")
|
||||
print("Ready to retrieve passwords for networks.")
|
||||
|
||||
return self.process_networks(ssid_list, max_networks, self.get_wifi_password_windows)
|
||||
|
||||
def get_wifi_interfaces(self):
|
||||
output = self.run({
|
||||
"args": ["networksetup", "-listallhardwareports"]
|
||||
})
|
||||
|
||||
if output[-1] != 0:
|
||||
return []
|
||||
|
||||
interfaces = []
|
||||
|
||||
for interface_info in output[0].split("\n\n"):
|
||||
if "Device: en" in interface_info:
|
||||
try:
|
||||
interface = "en{}".format(int(interface_info.split("Device: en")[1].split("\n")[0]))
|
||||
|
||||
test_output = self.run({
|
||||
"args": ["networksetup", "-listpreferredwirelessnetworks", interface]
|
||||
})
|
||||
|
||||
if test_output[-1] == 0 and "Preferred networks on" in test_output[0]:
|
||||
interfaces.append(interface)
|
||||
except:
|
||||
continue
|
||||
|
||||
return interfaces
|
||||
|
||||
def get_profiles(self):
|
||||
os_name = platform.system()
|
||||
|
||||
self.utils.head("WiFi Profile Extractor")
|
||||
print("")
|
||||
print("\033[93mNote:\033[0m")
|
||||
print("- When using itlwm kext, WiFi appears as Ethernet in macOS")
|
||||
print("- You'll need Heliport app to manage WiFi connections in macOS")
|
||||
print("- This step will enable auto WiFi connections at boot time")
|
||||
print(" and is useful for users installing macOS via Recovery OS")
|
||||
print("")
|
||||
|
||||
user_input = self.utils.request_input("Would you like to scan for WiFi profiles? (Y/n): ").strip().lower() or "y"
|
||||
if user_input != "y":
|
||||
return []
|
||||
|
||||
profiles = []
|
||||
self.utils.head("Detecting WiFi Profiles")
|
||||
print("")
|
||||
print("Scanning for WiFi profiles...")
|
||||
|
||||
if os_name == "Windows":
|
||||
profiles = self.get_preferred_networks_windows()
|
||||
elif os_name == "Darwin":
|
||||
wifi_interfaces = self.get_wifi_interfaces()
|
||||
|
||||
if wifi_interfaces:
|
||||
for interface in wifi_interfaces:
|
||||
print("Checking interface: {}".format(interface))
|
||||
interface_profiles = self.get_preferred_networks_macos(interface)
|
||||
if interface_profiles:
|
||||
profiles = interface_profiles
|
||||
break
|
||||
else:
|
||||
print("No WiFi interfaces detected.")
|
||||
|
||||
if not profiles:
|
||||
self.utils.head("WiFi Profile Extractor")
|
||||
print("")
|
||||
print("No WiFi profiles with saved passwords were found.")
|
||||
self.utils.request_input()
|
||||
|
||||
self.utils.head("WiFi Profile Extractor")
|
||||
print("")
|
||||
print("Found the following WiFi profiles with saved passwords:")
|
||||
print("")
|
||||
print("Index SSID Password")
|
||||
print("-------------------------------------------------------")
|
||||
for index, (ssid, password) in enumerate(profiles, start=1):
|
||||
print("{:<6} {:<23} {}".format(index, ssid[:23], password))
|
||||
print("")
|
||||
print("Successfully applied {} WiFi profiles.".format(len(profiles)))
|
||||
print("")
|
||||
|
||||
self.utils.request_input()
|
||||
return profiles
|
||||
Reference in New Issue
Block a user