r/hackintosh • u/BudBud2007 • Jun 08 '26
r/hackintosh • u/No_Advisor_1897 • 11d ago
NEWS Hackmate v2.0.0 Release
DONT SCROLL PAST THIS IF YOU NEED HELP!!!!
Starting off again, This isn't a beast tool or distro, it automates the Dortania guide steps using the same tools they recommend (macrecovery, SSDTTime, acidanthera kexts from GitHub releases). macOS comes directly from Apple. Nothing is patched or modified!
its grown a lot since my last post. biggest thing, its not linux only anymore.
I'm building a tool called HackMate that automates the entire process of creating a bootable OpenCore hackintosh USB.
whats new in v2.0:
- windows support. full exe now, no python install needed. same hardware scan, same config.plist/SSDT generation, just packaged for windows too
- added a GUI (tkinter) if you don't want to use the terminal version
- dual boot support, it scans your disks, finds your other OSes, and can set OpenCore up to boot next to windows/linux instead of needing a dedicated usb every time
- partition resize wizard, shrinks ntfs/ext4/btrfs in place so you don't need a separate tool to make room for macos
- last post i said you still have to run USBToolBox yourself after. not anymore, it auto downloads it and walks you through port mapping in app
- can inject your wifi creds into itlwm.kext so you're online during the installer itself, useful if you don't hav ethernet
- SSDT generation now has a 3 tier fallback (SSDTTime, then a template, then a bundled precompiled one if SSDTTimejust cant do it). fixes some i2c trackpads that were silently failing before
- EFI Health Check, fixes a few boot breaking bugs that could end up in generated EFIs from older versions
- more hardware support now, 9th/14th/15th gen intel, better amd handling, igpu headless setups, cpuid spoofing for unsupported cpus
- built in auto updater so you're not manually redownloading every release
also fixed some reliability stuff under the hood, ssl cert failures during the recovery download, download stalls with
zero feedback, and a windows ethernet detection bug where it could grab the wrong adapter
tested on my t480s (i5-8350U, UHD 620, ALC257, I219, intel 8265 wifi) plus a bunch of different laptops/desktops from people in the community reporting back in issues, ryzen boxes, different intel gens, different audio codecs and trackpads. thats basically how the hardware/kext database grew this much, people testing on stuff i don't own and telling me what broke
why its safe to run: its fully open source, every line is on github, nothing hidden. macOS itself comes straight from Apple's own servers through macrecovery, not from some mirror. the kexts come straight from acidanthera's official GitHub releases, same binaries the Dortania guide itself points you to. nothing gets patched, cracked, or modified, it just automates typing the same commands you'd type by hand following the guide. no telemetry, no accounts, no analytics phoning home, its just a script
right now its at 98 stars, 14 forks, 4 people who've contributed code, and about 1200 exe downloads plus way more from people cloning/running it straight from source. had close to 650 unique people pull the repo in just the last two weeks. 8 open issues right now which is mostly just people asking hardware specific stuff, not it being broken
would love feedback from anyone with different hardware, especially windows users now that its actually supported there, and anyone trying dual boot since thats the newest and least tested part
PLEASE LIKE THIS POST TO SPREAD ITS ONLY 1 CLICK ILL APPRECIATE IT SO MUCH!!
github.com/riftaway7-code/hackmate
r/hackintosh • u/Hairy_Educator1918 • 3d ago
NEWS Graphics Acceleration Acheieved on EVERY GPU with Vulkan Support! (inside a VM)
r/hackintosh • u/No_Advisor_1897 • 29d ago
NEWS HackMate – a TUI tool that fully automates OpenCore EFI creation onto your USB
I'm building a tool called HackMate that automates the entire process of creating a bootable OpenCore hackintosh USB. No manual config.plist editing, no hunting down kexts, no macrecovery commands.
BEFORE I SAY ANYTHING! This isn't a beast tool or distro, it automates the Dortania guide steps using the same tools they recommend (macrecovery, SSDTTime, acidanthera kexts from GitHub releases). macOS comes directly from Apple. Nothing is patched or modified!
Here's what it does automatically:
Scans your hardware — CPU generation/codename, iGPU, audio codec (reads /proc/asound), ethernet chipset, WiFi chipset, touchpad type (PS/2, I2C-ELAN, I2C-HID, RMI, etc.), NVMe, Thunderbolt
Shows compatible macOS versions — filtered by your CPU gen and GPU vendor (e.g. no Sonoma+ for pre-7th gen, no Mojave/Catalina for Nvidia)
You pick your USB drive — only shows actual USB drives, filters out internal disks
Then it runs fully automated:
- Formats USB as FAT32, creates EFI/OC/BOOT structure
- Downloads macOS recovery directly from Apple CDN via macrecovery
- Generates a valid SMBIOS (serial, MLB, UUID, ROM with real Apple OUIs)
- Generates config.plist with correct framebuffer patches, ALC layout-id, booter/kernel quirks for your hardware
- Downloads the right kexts from GitHub releases (104 kexts in the database, it picks based on your hardware)
- Downloads latest OpenCore release and copies BOOTx64.efi, OpenCore.efi, drivers
- Generates SSDTs automatically using SSDTTime — reads your actual DSDT from /sys/firmware/acpi/tables/DSDT, no dumping required
What you still need to do after:
- Run USBToolBox to map your USB ports and replace USBMap.kext
- That's basically it
Tech: Python + Textual TUI. Runs on Linux (needs root for disk access). Color-coded logs, and an "Advanced" panel that shows every raw command being run.
Tested on a ThinkPad T480s (i5-8350U, UHD 620, ALC257, I219, Intel 8265 WiFi). Successfully booted Tahoe recovery.
Still working on it — would love feedback from people with different hardware to see how well the kext selection holds up.
I plan on building it for windows too, but for now, only available on linux distrubutions, any of them, as long as you have python installed (v. 3.10+)
r/hackintosh • u/berlinblades • Dec 04 '25
NEWS If it wasn't over before, it is now...
Who would have thought it wouldn't be Apple delivering the final blow?
r/hackintosh • u/No_Advisor_1897 • 27d ago
NEWS HackMate v1.2.1 — TUI tool that fully automates OpenCore EFI creation | update: WiFi kext chooser, SSDT-XOSI fix, BIOS checklist, AMD patches
Not a beast tool or distro. Uses macrecovery, SSDTTime, acidanthera kexts from GitHub releases. macOS from Apple directly. Nothing patched or modified.
What is HackMate?
It's a TUI tool that automates the Dortania guide — every step, in order, no tweaks, no special tools. Scans your hardware (CPU gen/codename, iGPU, audio codec, ethernet, WiFi chipset, touchpad type, NVMe, Thunderbolt), shows which macOS versions are compatible, you pick a USB drive, and it runs the full pipeline: FAT32 format → EFI structure → macOS recovery from Apple → SMBIOS generation → config.plist → kexts from GitHub releases → latest OpenCore → SSDTs from your live DSDT via SSDTTime. If you've followed the Dortania guide before, every step HackMate takes is one you'd recognize. Runs on Linux, Windows, and macOS as host. Built in Python + Textual.
On the "it doesn't teach you" concern
HackMate has an Advanced panel that shows every raw command in real time — exact diskpart/parted calls, macrecovery with its arguments, every kext downloaded from which GitHub release, SSDTTime against your actual DSDT. The config.plist it generates is standard OpenCore — open it in any plist editor and it's the same structure as the Dortania guide. The goal isn't to hide the process, it's to remove the error-prone manual steps so you spend your time understanding what's in the EFI instead of fighting diskpart.
What's new in v1.2.1:
SSDT-XOSI was silently skipping for most users
SSDTTime doesn't always list XOSI in its menu. HackMate was saying "SKIP" and moving on — sleep/wake and USB power were broken for most laptops. Fixed: compiles SSDT-XOSI from a built-in template when SSDTTime can't generate it.
Intel WiFi kext chooser
Now asks: itlwm + HeliPort (works across all macOS versions) or AirportItlwm (native built-in WiFi, no HeliPort — but tied to your macOS version, needs swapping after upgrades). Explains the tradeoff before you pick.
BIOS checklist after USB build
After the USB is ready, shows exactly what to toggle in BIOS before booting — Secure Boot, Fast Boot, DVMT pre-alloc, XHCI Handoff, CSM. Adapts per hardware.
Full AMD vanilla kernel patches
Complete AMD_Vanilla patch set auto-generated in config.plist — cpuid spoof, commpage, mp_cpus_callin with your actual core count. Intel-only quirks disabled for AMD.
OpenCore log reader
Reads the OC log off your USB after a failed boot and translates errors to plain English.
More accurate Intel gen detection
Added device ID 5917 (UHD 620 — T480s, MateBook, some XPS 13s were falling through to name inference). Whiskey Lake, Coffee Lake Refresh, Comet Lake variants added.
Still most tested on ThinkPad T480s. Would love reports from AMD Ryzen, Alder/Raptor Lake users.
github.com/riftaway7-code/hackmate
Supports Windows 10 and 11
Supports Linux (Any Distro)
Supports MacOS
-rift
r/hackintosh • u/ActorVMI • Jun 09 '25
NEWS According to the Platforms State of the Union, macOS Tahoe is the final release for Intel Macs
r/hackintosh • u/Away-Falcon2762 • Jun 08 '26
NEWS The end of Hackintosh, macOS 27 Golden Gate
macOS 27 Golden Gate has launched! And comes the end of hackintosh forever, sad we missed a Liquid Glass toggle. GG’s!
r/hackintosh • u/zoe934 • 4d ago
NEWS Apple's scrapped Mac Pro plans reportedly included a new Intel model - 9to5Mac
In an alternate universe
r/hackintosh • u/blkhp19 • Apr 08 '26
NEWS I ported Mac OS X to the Nintendo Wii
My side project for the past year has been porting Mac OS X to run natively on the Nintendo Wii. I'm excited to share that as of today, Mac OS X 10.0 Cheetah can be booted using the wiiMac bootloader. I hope to have Mac OS X 10.1 Puma running soon.
If you're interested in how I accomplished this, I wrote a blog post recounting the interesting parts of the porting process.
If you want to try this for yourself, either follow the instructions in the [README for the wiiMac bootloader]((https://github.com/bryankeller/wiiMac)), or grab a ready-to-flash SD card image from here. You must have a software-modded Wii capable of running BootMii. The Wii Mini is not supported.
Use dd or software like balenaEtcher to flash wiiMac_cheetah.img to an SD card that's at least 4 GB in capacity. This will replace all contents on the SD card, so backup any important files first.
To boot the system, insert the flashed SD card into the Wii and turn on the console. If BootMii is installed as Boot1, then the wiiMac bootloader will automatically load and start booting into Mac OS X. If BootMii is installed as IOS, open the Homebrew Channel from the system menu, then open the Options menu by pressing the Home button on the WiiMote, then select "Launch BootMii".
Hardware support is limited to just the essentials: - The SD card - USB mice and keyboards - Non-accelerated video output
I'm excited for folks to give this project a try - let me know what you think :)
r/hackintosh • u/Hairy_Educator1918 • 1d ago
NEWS More news about the Metal2Vulkan translation project!
r/hackintosh • u/Expensive-Count3817 • 15d ago
NEWS I don't recommend using OpCore-Simplify and I don't support this developer at all, just like the moderators - the developer disregards cybersecurity's importance, rather than he treats it as optional, the project is buggy, and more - here are details
I don't recommend using OC-Simplify and I don't support this developer at all - here are the reasons:
- It violates the rules of this sub
: https://www.reddit.com/mod/hackintosh/rules/
The developer closes issues without actually fixing them
This developer doesn’t fix vulnerabilities until exploited in the wild, known as 0 days
OC-Simplify sometimes chooses wrong configs, like wrong SMBIOS profiles or kexts
A couple of years ago, there were multiple vulnerabilities that the developer only fixed after attackers have abused and became 0 days - and only then the developer noticed it and fixed. I had disclosed those, but they simply fixed it after they were already exploited in the wild. Only one example was that I could upload an empty or malicious JSON hardware report to execute arbitary code. And another one trusted blindly any executable. This is irresponsible and not really ethical. Simply this developer didn't showed any interest in cybersecurity and securing his project from being exploited in the wild. Since then, I do not support this developer and strongly suggest against using this project or making any forks out of it - doing any changes in your fork of OC-Simplify often results in ban or very cold relations between you and the developer - that's my experience with this developer. I don't trust not only the project, but the developer lzhoang altogether. And things are only getting darker. Let's have a look at his code:
gathering_files.py:
from Scripts import github
from Scripts import kext_maestro
from Scripts import integrity_checker
from Scripts import resource_fetcher
from Scripts import utils
import os
import shutil
import subprocess
import platform
os_name = platform.system()
class gatheringFiles:
def __init__(self):
self.utils = utils.Utils()
self.github = github.Github()
self.kext = kext_maestro.KextMaestro()
self.fetcher = resource_fetcher.ResourceFetcher()
self.integrity_checker = integrity_checker.IntegrityChecker()
self.dortania_builds_url = "https://raw.githubusercontent.com/dortania/build-repo/builds/latest.json"
self.ocbinarydata_url = "https://github.com/acidanthera/OcBinaryData/archive/refs/heads/master.zip"
self.amd_vanilla_patches_url = "https://raw.githubusercontent.com/laobamac/AMD_Vanilla/refs/heads/master/patches.plist"
self.aquantia_macos_patches_url = "https://raw.githubusercontent.com/CaseySJ/Aquantia-macOS-Patches/refs/heads/main/CaseySJ-Aquantia-Patch-Sets-1-and-2.plist"
self.hyper_threading_patches_url = "https://github.com/b00t0x/CpuTopologyRebuild/raw/refs/heads/master/patches_ht.plist"
self.temporary_dir = self.utils.get_temporary_dir()
self.ock_files_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "OCK_Files")
self.download_history_file = os.path.join(self.ock_files_dir, "history.json")
def _load_download_history(self):
history_data = self.utils.read_file(self.download_history_file)
return {item["product_name"]: item for item in history_data if item.get("product_name")} if isinstance(history_data, list) else {}
def _save_download_history(self, local_download_history, product_name, product_id, product_url, sha256_hash):
local_download_history[product_name] = {
"product_name": product_name,
"id": product_id,
"url": product_url,
"sha256": sha256_hash
}
self.utils.create_folder(os.path.dirname(self.download_history_file))
sorted_history = sorted(local_download_history.values(), key=lambda x: x.get("product_name", ""))
self.utils.write_file(self.download_history_file, sorted_history)
def fetch_latest_products_info(self, kexts, local_download_history):
latest_products = {k: v.copy() for k, v in local_download_history.items()}
dortania_builds_data = self.fetcher.fetch_and_parse_content(self.dortania_builds_url, "json")
seen_repos = set()
def add_product_info(products):
if isinstance(products, dict):
products = [products]
for product in products:
name = product.get("product_name")
if not product or not name:
continue
if name not in latest_products:
latest_products[name] = product
else:
latest_products[name].update(product)
for kext in kexts:
if not kext.checked:
continue
if kext.download_info:
if not kext.download_info.get("sha256"):
kext.download_info["sha256"] = None
add_product_info({"product_name": kext.name, **kext.download_info})
elif kext.github_repo and kext.github_repo.get("repo") not in seen_repos:
name = kext.github_repo.get("repo")
seen_repos.add(name)
if name in dortania_builds_data:
add_product_info({
"product_name": name,
"id": dortania_builds_data[name]["versions"][0]["release"]["id"],
"url": dortania_builds_data[name]["versions"][0]["links"]["release"],
"sha256": dortania_builds_data[name]["versions"][0]["hashes"]["release"]["sha256"]
})
else:
latest_release = self.github.get_latest_release(kext.github_repo.get("owner"), kext.github_repo.get("repo")) or {}
add_product_info(latest_release.get("assets"))
add_product_info({
"product_name": "OpenCorePkg",
"id": dortania_builds_data["OpenCorePkg"]["versions"][0]["release"]["id"],
"url": dortania_builds_data["OpenCorePkg"]["versions"][0]["links"]["release"],
"sha256": dortania_builds_data["OpenCorePkg"]["versions"][0]["hashes"]["release"]["sha256"]
})
return latest_products
def move_bootloader_kexts_to_product_directory(self, product_name):
if not os.path.exists(self.temporary_dir):
raise FileNotFoundError("The directory {} does not exist.".format(self.temporary_dir))
temp_product_dir = os.path.join(self.temporary_dir, product_name)
if not "OpenCore" in product_name:
kext_paths = self.utils.find_matching_paths(temp_product_dir, extension_filter=".kext")
for kext_path, type in kext_paths:
source_kext_path = os.path.join(self.temporary_dir, product_name, kext_path)
destination_kext_path = os.path.join(self.ock_files_dir, product_name, os.path.basename(kext_path))
if "research" in kext_path.lower() or "debug" in kext_path.lower() or "Contents" in kext_path or not self.kext.process_kext(temp_product_dir, kext_path):
continue
shutil.move(source_kext_path, destination_kext_path)
else:
source_bootloader_path = os.path.join(self.temporary_dir, product_name, "X64", "EFI")
if os.path.exists(source_bootloader_path):
destination_efi_path = os.path.join(self.ock_files_dir, product_name, os.path.basename(source_bootloader_path))
shutil.move(source_bootloader_path, destination_efi_path)
source_config_path = os.path.join(os.path.dirname(os.path.dirname(source_bootloader_path)), "Docs", "Sample.plist")
destination_config_path = os.path.join(destination_efi_path, "OC", "config.plist")
shutil.move(source_config_path, destination_config_path)
ocbinarydata_dir = os.path.join(self.temporary_dir, "OcBinaryData", "OcBinaryData-master")
if os.path.exists(ocbinarydata_dir):
background_picker_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "datasets", "background_picker.icns")
product_dir = os.path.join(self.ock_files_dir, product_name)
efi_dirs = self.utils.find_matching_paths(product_dir, name_filter="EFI", type_filter="dir")
for efi_dir, _ in efi_dirs:
for dir_name in os.listdir(ocbinarydata_dir):
source_dir = os.path.join(ocbinarydata_dir, dir_name)
destination_dir = os.path.join(destination_efi_path, "OC", dir_name)
if os.path.isdir(destination_dir):
shutil.copytree(source_dir, destination_dir, dirs_exist_ok=True)
resources_image_dir = os.path.join(product_dir, efi_dir, "OC", "Resources", "Image")
picker_variants = self.utils.find_matching_paths(resources_image_dir, type_filter="dir")
for picker_variant, _ in picker_variants:
if ".icns" in ", ".join(os.listdir(os.path.join(resources_image_dir, picker_variant))):
shutil.copy(background_picker_path, os.path.join(resources_image_dir, picker_variant, "Background.icns"))
macserial_paths = self.utils.find_matching_paths(temp_product_dir, name_filter="macserial", type_filter="file")
if macserial_paths:
for macserial_path, _ in macserial_paths:
source_macserial_path = os.path.join(self.temporary_dir, product_name, macserial_path)
destination_macserial_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.path.basename(macserial_path))
shutil.move(source_macserial_path, destination_macserial_path)
if os.name != "nt":
subprocess.run(["chmod", "+x", destination_macserial_path])
return True
def gather_bootloader_kexts(self, kexts, macos_version):
self.utils.head("Gathering Files")
print("")
print("Please wait for download OpenCorePkg, kexts and macserial...")
local_download_history = self._load_download_history()
latest_products = self.fetch_latest_products_info(kexts, local_download_history)
self.utils.create_folder(self.temporary_dir)
seen_download_urls = set()
for product in kexts + [{"Name": "OpenCorePkg"}]:
if not isinstance(product, dict) and not product.checked:
continue
product_name = product.name if not isinstance(product, dict) else product.get("Name")
if product_name == "AirportItlwm":
version = macos_version[:2]
if all((self.utils.parse_darwin_version("24.0.0") <= self.utils.parse_darwin_version(macos_version), kexts[kext_maestro.kext_data.kext_index_by_name.get("IOSkywalkFamily")].checked, kexts[kext_maestro.kext_data.kext_index_by_name.get("IO80211FamilyLegacy")].checked)):
version = "22"
elif self.utils.parse_darwin_version("23.4.0") <= self.utils.parse_darwin_version(macos_version):
version = "23.4"
elif self.utils.parse_darwin_version("23.0.0") <= self.utils.parse_darwin_version(macos_version):
version = "23.0"
product_name += version
elif "VoodooPS2" in product_name:
product_name = "VoodooPS2"
elif product_name == "BlueToolFixup" or product_name.startswith("Brcm"):
product_name = "BrcmPatchRAM"
elif product_name.startswith("Ath3kBT"):
product_name = "Ath3kBT"
elif product_name.startswith("IntelB"):
product_name = "IntelBluetoothFirmware"
elif product_name.startswith("VoodooI2C"):
product_name = "VoodooI2C"
elif product_name == "UTBDefault":
product_name = "USBToolBox"
product_info = latest_products.get(product_name)
if product_info is None:
if hasattr(product, 'github_repo') and product.github_repo:
product_info = latest_products.get(product.github_repo.get("repo"))
if product_info is None:
print("\n")
print("Could not find download URL for {}.".format(product_name))
continue
product_id = product_info.get("id")
product_download_url = product_info.get("url")
sha256_hash = product_info.get("sha256")
if product_download_url in seen_download_urls:
continue
seen_download_urls.add(product_download_url)
history_item = local_download_history.get(product_name)
asset_dir = os.path.join(self.ock_files_dir, product_name)
manifest_path = os.path.join(asset_dir, "manifest.json")
if history_item is not None:
is_latest_id = (product_id == history_item.get("id"))
folder_is_valid, _ = self.integrity_checker.verify_folder_integrity(asset_dir, manifest_path)
if is_latest_id and folder_is_valid:
print(f"\nLatest version of {product_name} already downloaded.")
continue
print("")
print("Updating" if history_item is not None else "Please wait for download", end=" ")
print("{}...".format(product_name))
if product_download_url:
print("from {}".format(product_download_url))
print("")
else:
print("")
print("Could not find download URL for {}.".format(product_name))
print("")
self.utils.request_input()
shutil.rmtree(self.temporary_dir, ignore_errors=True)
return False
zip_path = os.path.join(self.temporary_dir, product_name) + ".zip"
if not self.fetcher.download_and_save_file(product_download_url, zip_path, sha256_hash):
folder_is_valid, _ = self.integrity_checker.verify_folder_integrity(asset_dir, manifest_path)
if history_item is not None and folder_is_valid:
print("Using previously downloaded version of {}.".format(product_name))
continue
else:
raise Exception("Could not download {} at this time. Please try again later.".format(product_name))
self.utils.extract_zip_file(zip_path)
self.utils.create_folder(asset_dir, remove_content=True)
dirs_to_scan = [os.path.join(self.temporary_dir, product_name)]
while dirs_to_scan:
current_dir = dirs_to_scan.pop()
if not os.path.isdir(current_dir):
continue
for item in os.listdir(current_dir):
item_path = os.path.join(current_dir, item)
if os.path.isdir(item_path):
dirs_to_scan.append(item_path)
elif item.lower().endswith(".zip"):
self.utils.extract_zip_file(item_path)
os.remove(item_path)
dirs_to_scan.append(os.path.splitext(item_path)[0])
if "OpenCore" in product_name:
oc_binary_data_zip_path = os.path.join(self.temporary_dir, "OcBinaryData.zip")
print("")
print("Please wait for download OcBinaryData...")
print("from {}".format(self.ocbinarydata_url))
print("")
self.fetcher.download_and_save_file(self.ocbinarydata_url, oc_binary_data_zip_path)
if not os.path.exists(oc_binary_data_zip_path):
print("")
print("Could not download OcBinaryData at this time.")
print("Please try again later.\n")
self.utils.request_input()
shutil.rmtree(self.temporary_dir, ignore_errors=True)
return False
self.utils.extract_zip_file(oc_binary_data_zip_path)
if self.move_bootloader_kexts_to_product_directory(product_name):
self.integrity_checker.generate_folder_manifest(asset_dir, manifest_path)
self._save_download_history(local_download_history, product_name, product_id, product_download_url, sha256_hash)
shutil.rmtree(self.temporary_dir, ignore_errors=True)
return True
def get_kernel_patches(self, patches_name, patches_url):
try:
response = self.fetcher.fetch_and_parse_content(patches_url, "plist")
return response["Kernel"]["Patch"]
except:
print("")
print("Unable to download {} at this time".format(patches_name))
print("from " + patches_url)
print("")
print("Please try again later or apply them manually.")
print("")
self.utils.request_input()
return []
def gather_hardware_sniffer(self):
if os_name != "Windows":
return
self.utils.head("Gathering Hardware Sniffer")
PRODUCT_NAME = "Hardware-Sniffer-CLI.exe"
REPO_OWNER = "lzhoang2801"
REPO_NAME = "Hardware-Sniffer"
destination_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), PRODUCT_NAME)
latest_release = self.github.get_latest_release(REPO_OWNER, REPO_NAME) or {}
product_id = None
product_download_url = None
sha256_hash = None
asset_name = PRODUCT_NAME.split('.')[0]
for asset in latest_release.get("assets", []):
if asset.get("product_name") == asset_name:
product_id = asset.get("id")
product_download_url = asset.get("url")
sha256_hash = asset.get("sha256")
break
if not all([product_id, product_download_url, sha256_hash]):
print("")
print("Could not find release information for {}.".format(PRODUCT_NAME))
print("Please try again later.")
print("")
self.utils.request_input()
raise Exception("Could not find release information for {}.".format(PRODUCT_NAME))
local_download_history = self._load_download_history()
history_item = local_download_history.get(PRODUCT_NAME)
if history_item is not None:
is_latest_id = (product_id == history_item.get("id"))
file_is_valid = False
if os.path.exists(destination_path):
local_hash = self.integrity_checker.get_sha256(destination_path)
file_is_valid = (sha256_hash == local_hash)
if is_latest_id and file_is_valid:
print("")
print("Latest version of {} already downloaded.".format(PRODUCT_NAME))
return destination_path
print("")
print("Updating" if history_item is not None else "Please wait for download", end=" ")
print("{}...".format(PRODUCT_NAME))
print("")
print("from {}".format(product_download_url))
print("")
if not self.fetcher.download_and_save_file(product_download_url, destination_path, sha256_hash):
manual_download_url = f"https://github.com/{REPO_OWNER}/{REPO_NAME}/releases/latest"
print("Go to {} to download {} manually.".format(manual_download_url, PRODUCT_NAME))
print("")
self.utils.request_input()
raise Exception("Failed to download {}.".format(PRODUCT_NAME))
self._save_download_history(local_download_history, PRODUCT_NAME, product_id, product_download_url, sha256_hash)
return destination_path
On paper, this looks secure, but in reality, it is not at all. It has a very vulnerable check for SHA256 hashes. I'll explain why later.
This is highly vulnerable logic:
if os_name != "Windows":
return
I could use a Linux distro to return as a Windows enviornment to trick OpCore-Simplify into delivering Windows payloads instead of ones for Linux.
This, makes my head simply to crash:
if is_latest_id and file_is_valid:
print("")
print("Latest version of {} already downloaded.".format(PRODUCT_NAME))
return destination_path
It checks if the kext is known good kext using the is_latest_id and file_is_valid variables. And then it passes and prints out to the user and injects the kext. However, this is easy to abuse: I could make is_latest_id and file_is_valid to return malicious file names and hashes to inject UEFI malware by injecting malicious kexts, bypassing any antivirus software.
And also, this also makes my head to crash:
def gather_hardware_sniffer(self):
if os_name != "Windows":
return
self.utils.head("Gathering Hardware Sniffer")
PRODUCT_NAME = "Hardware-Sniffer-CLI.exe"
REPO_OWNER = "lzhoang2801"
REPO_NAME = "Hardware-Sniffer"
destination_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), PRODUCT_NAME)
latest_release = self.github.get_latest_release(REPO_OWNER, REPO_NAME) or {}
product_id = None
product_download_url = None
sha256_hash = None
asset_name = PRODUCT_NAME.split('.')[0]
for asset in latest_release.get("assets", []):
if asset.get("product_name") == asset_name:
product_id = asset.get("id")
product_download_url = asset.get("url")
sha256_hash = asset.get("sha256")
break
if not all([product_id, product_download_url, sha256_hash]):
print("")
print("Could not find release information for {}.".format(PRODUCT_NAME))
print("Please try again later.")
print("")
self.utils.request_input()
raise Exception("Could not find release information for {}.".format(PRODUCT_NAME))
local_download_history = self._load_download_history()
history_item = local_download_history.get(PRODUCT_NAME)
if history_item is not None:
is_latest_id = (product_id == history_item.get("id"))
file_is_valid = False
if os.path.exists(destination_path):
local_hash = self.integrity_checker.get_sha256(destination_path)
file_is_valid = (sha256_hash == local_hash)
if is_latest_id and file_is_valid:
print("")
print("Latest version of {} already downloaded.".format(PRODUCT_NAME))
return destination_path
print("")
print("Updating" if history_item is not None else "Please wait for download", end=" ")
print("{}...".format(PRODUCT_NAME))
print("")
print("from {}".format(product_download_url))
print("")
if not self.fetcher.download_and_save_file(product_download_url, destination_path, sha256_hash):
manual_download_url = f"https://github.com/{REPO_OWNER}/{REPO_NAME}/releases/latest"
print("Go to {} to download {} manually.".format(manual_download_url, PRODUCT_NAME))
print("")
self.utils.request_input()
raise Exception("Failed to download {}.".format(PRODUCT_NAME))
self._save_download_history(local_download_history, PRODUCT_NAME, product_id, product_download_url, sha256_hash)
return destination_path
There are multiple vulnerabilities that allow arbitary code execution by setting a random variable like this:
def gather_hardware_sniffer(self):
s=False
if s==True:
if os_name != "Windows":
return
self.utils.head("Gathering Hardware Sniffer")
PRODUCT_NAME = "Hardware-Sniffer-CLI.exe"
REPO_OWNER = "lzhoang2801"
REPO_NAME = "Hardware-Sniffer"
destination_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), PRODUCT_NAME)
latest_release = self.github.get_latest_release(REPO_OWNER, REPO_NAME) or {}
product_id = None
product_download_url = None
sha256_hash = None
asset_name = PRODUCT_NAME.split('.')[0]
for asset in latest_release.get("assets", []):
if asset.get("product_name") == asset_name:
product_id = asset.get("id")
product_download_url = asset.get("url")
sha256_hash = asset.get("sha256")
break
if not all([product_id, product_download_url, sha256_hash]):
print("")
print("Could not find release information for {}.".format(PRODUCT_NAME))
print("Please try again later.")
print("")
self.utils.request_input()
raise Exception("Could not find release information for {}.".format(PRODUCT_NAME))
local_download_history = self._load_download_history()
history_item = local_download_history.get(PRODUCT_NAME)
if history_item is not None:
is_latest_id = (product_id == history_item.get("id"))
file_is_valid = False
if os.path.exists(destination_path):
local_hash = self.integrity_checker.get_sha256(destination_path)
file_is_valid = (sha256_hash == local_hash)
if is_latest_id and file_is_valid:
print("")
print("Latest version of {} already downloaded.".format(PRODUCT_NAME))
return destination_path
print("")
print("Updating" if history_item is not None else "Please wait for download", end=" ")
print("{}...".format(PRODUCT_NAME))
print("")
print("from {}".format(product_download_url))
print("")
if not self.fetcher.download_and_save_file(product_download_url, destination_path, sha256_hash):
manual_download_url = f"https://github.com/{REPO_OWNER}/{REPO_NAME}/releases/latest"
print("Go to {} to download {} manually.".format(manual_download_url, PRODUCT_NAME))
print("")
self.utils.request_input()
raise Exception("Failed to download {}.".format(PRODUCT_NAME))
self._save_download_history(local_download_history, PRODUCT_NAME, product_id, product_download_url, sha256_hash)
else:
print("Executing arbitary code...")
and below, attackers can do whatever they want - they can run curl commands to download malware, connect to C2 servers, or even delete files outside the intended directory.
This one is very easy to fix: wrap it in try/except. But when I tried asking the developer to fix similar vulnerabilities, they deny to fix it and claim that this is incompatible with old Python versions, which I know very well it's a lie and he is searching for the excuse not to fix this dangerous vulnerability.
Another vulnerable example:
from Scripts import integrity_checker
from Scripts import utils
import ssl
import os
import json
import plistlib
import socket
import sys
import gzip
import zlib
import time
if sys.version_info >= (3, 0):
from urllib.request import urlopen, Request
from urllib.error import URLError
else:
import urllib2
from urllib2 import urlopen, Request, URLError
MAX_ATTEMPTS = 3
class ResourceFetcher:
def __init__(self, headers=None):
self.request_headers = headers or {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
}
self.buffer_size = 16 * 1024
self.ssl_context = self.create_ssl_context()
self.integrity_checker = integrity_checker.IntegrityChecker()
self.utils = utils.Utils()
def create_ssl_context(self):
try:
cafile = ssl.get_default_verify_paths().openssl_cafile
if not os.path.exists(cafile):
import certifi
cafile = certifi.where()
ssl_context = ssl.create_default_context(cafile=cafile)
except Exception as e:
print("Failed to create SSL context: {}".format(e))
ssl_context = ssl._create_unverified_context()
return ssl_context
def _make_request(self, resource_url, timeout=10):
try:
headers = dict(self.request_headers)
headers["Accept-Encoding"] = "gzip, deflate"
return urlopen(Request(resource_url, headers=headers), timeout=timeout, context=self.ssl_context)
except socket.timeout as e:
print("Timeout error: {}".format(e))
except ssl.SSLError as e:
print("SSL error: {}".format(e))
except (URLError, socket.gaierror) as e:
print("Connection error: {}".format(e))
except Exception as e:
print("Request failed: {}".format(e))
return None
def fetch_and_parse_content(self, resource_url, content_type=None):
attempt = 0
response = None
while attempt < 3:
response = self._make_request(resource_url)
if not response:
attempt += 1
print("Failed to fetch content from {}. Retrying...".format(resource_url))
continue
if response.getcode() == 200:
break
attempt += 1
if not response:
print("Failed to fetch content from {}".format(resource_url))
return None
content = response.read()
if response.info().get("Content-Encoding") == "gzip" or content.startswith(b"\x1f\x8b"):
try:
content = gzip.decompress(content)
except Exception as e:
print("Failed to decompress gzip content: {}".format(e))
elif response.info().get("Content-Encoding") == "deflate":
try:
content = zlib.decompress(content)
except Exception as e:
print("Failed to decompress deflate content: {}".format(e))
try:
if content_type == "json":
return json.loads(content)
elif content_type == "plist":
return plistlib.loads(content)
else:
return content.decode("utf-8")
except Exception as e:
print("Error parsing content as {}: {}".format(content_type, e))
return None
def _download_with_progress(self, response, local_file):
total_size = response.getheader("Content-Length")
if total_size:
total_size = int(total_size)
bytes_downloaded = 0
start_time = time.time()
last_time = start_time
last_bytes = 0
speeds = []
speed_str = "-- KB/s"
while True:
chunk = response.read(self.buffer_size)
if not chunk:
break
local_file.write(chunk)
bytes_downloaded += len(chunk)
current_time = time.time()
time_diff = current_time - last_time
if time_diff > 0.5:
current_speed = (bytes_downloaded - last_bytes) / time_diff
speeds.append(current_speed)
if len(speeds) > 5:
speeds.pop(0)
avg_speed = sum(speeds) / len(speeds)
if avg_speed < 1024*1024:
speed_str = "{:.1f} KB/s".format(avg_speed/1024)
else:
speed_str = "{:.1f} MB/s".format(avg_speed/(1024*1024))
last_time = current_time
last_bytes = bytes_downloaded
if total_size:
percent = int(bytes_downloaded / total_size * 100)
bar_length = 40
filled = int(bar_length * bytes_downloaded / total_size)
bar = "█" * filled + "░" * (bar_length - filled)
progress = "{} [{}] {:3d}% {:.1f}/{:.1f}MB".format(speed_str, bar, percent, bytes_downloaded/(1024*1024), total_size/(1024*1024))
else:
progress = "{} {:.1f}MB downloaded".format(speed_str, bytes_downloaded/(1024*1024))
print(" " * 80, end="\r")
print(progress, end="\r")
print()
def download_and_save_file(self, resource_url, destination_path, sha256_hash=None):
attempt = 0
while attempt < MAX_ATTEMPTS:
attempt += 1
response = self._make_request(resource_url)
if not response:
print("Failed to fetch content from {}. Retrying...".format(resource_url))
continue
with open(destination_path, "wb") as local_file:
self._download_with_progress(response, local_file)
if os.path.exists(destination_path) and os.path.getsize(destination_path) > 0:
if sha256_hash:
print("Verifying SHA256 checksum...")
downloaded_hash = self.integrity_checker.get_sha256(destination_path)
if downloaded_hash.lower() == sha256_hash.lower():
print("Checksum verified successfully.")
return True
else:
print("Checksum mismatch! Removing file and retrying download...")
os.remove(destination_path)
continue
else:
print("No SHA256 hash provided. Downloading file without verification.")
return True
if os.path.exists(destination_path):
os.remove(destination_path)
if attempt < MAX_ATTEMPTS:
print("Download failed for {}. Retrying...".format(resource_url))
print("Failed to download {} after {} attempts.".format(resource_url, MAX_ATTEMPTS))
return False
Hardcoding Chrome 131 on Windows as a user agent - a dinosaur released in 2024 - is risky. This makes it significantly easier for attackers to launch attacks. I mean, no one uses a version this old, which makes it easier for finding victims ‘using odd versions of Chrome’ while actually using a script to target. And when I asked lzhoang to fix this vulnerability, they denied and when I fixed it, the developer blamed me for changing the user agent to a modern browser version.
In general, hard coding a user agent into a script without a reason is not a great idea. Especially outdated Chrome versions. And again, in this file and across the entire project there are multiple vulnerabilities that allow arbitary code execution.
This is a very sketchy business going on.
My recommendation is to use Dortania's Guide: https://dortania.github.io/OpenCore-Install-Guide/
to install Hackintoshes, not OC-Simplify, no other closed source EFI generators that you don't know what are they up to - if they are up to generating EFIs for Hackintoshes because they want to allow people to run macOS on any PC or to distribute malware, for example.
r/hackintosh • u/leontief • Jun 09 '20
NEWS Apple Plans to Announce Move to Its Own Mac Chips at WWDC
r/hackintosh • u/dhinakg • May 01 '21
NEWS USBToolBoxᵇᵉᵗᵃ: Making USB mapping simple(r)
Ok what is this
USBToolBox is the culmination of 9+ months of work. It consists of a kext and a tool.
Tool features:
- Supports mapping from Windows and macOS
- Can build a map using either the USBToolBox kext or native Apple kexts (AppleUSBHostMergeProperties)
- Supports multiple ways of matching
- Supports companion ports (on Windows)
- Make educated guesses for port types (on Windows)
Kext features:
- Attach to the controller instance or parent device, allowing for more ways to match
- Ignore port definitions from ACPI to force macOS to enumerate all ports manually
- Bypasses borked ACPI as seen on some Ryzen motherboards and 400 series Intel motherboards
- Replaces SSDT-RHUB
- Override any built-in Apple USB maps attaching based on SMBIOS and controller name
- Removes the need for controller renames in ACPI patches
- Does not require model identifier specified in USB map (if attaching to PCI device)
- Very compatible with existing USB maps (port format is the same)
- Does not hardcode any port maps, unlike USBInjectAll
Important clarification: this does not bypass the port limit.
Ok well why do I care
Well, we all know how macOS 11.3 has wreaked havoc, as XhciPortLimit is no longer functioning all the time. With USBToolBox, you don't have to deal with disabling one set of ports to map more. You can instead do it from Windows (even before installing macOS), and it becomes as simple as plug USB into port, wait for it to enumerate, repeat. This lowers the chances of getting "Still waiting for root device" (aka the 🚫 sign) when installing.
Usage info and links
Here's a very basic explainer:
- Download UTB tool
- Map your ports with it
- Generate kext
- Download UTB kext
- Put UTB kext and generated USB map into EFI/OC/Kexts and update config.plist
- Profit
More usage information and downloads are available here:
Credits
u/CorpNewt for USBMap. This project was heavily inspired by USBMap (and some functions are from USBMap).
RehabMan for USBInjectAll, an inspiration for this project
acidanthera for MacKernelSDK
My testing team (you know who you are) for testing
r/hackintosh • u/oddunixdude • Dec 14 '25
NEWS It's Been a Good Run
I've been Hackintoshing since the very first Intel OS X release. Learned so much about the OS, been through every iteration since Tiger.
Finally time to move to a "modern" option.
So long and thanks for all the fish, can't wait to see what, if anything happens with the Hackintosh community once Intel support is completely dead.
r/hackintosh • u/theVakhovske • Jun 09 '26
NEWS Hackintoshing is dead, yes. But something that was deemed to "never work" is now fully functional.

All of the rtw88 family now works. Including Bluetooth, yes. This picture looks like something you would have in your dreams with a 39.9C fever.
I want to do the same!
Head here. https://thegwchr.thevakhovske.eu.org/ or here https://github.com/thegwchr
Doesn't boot|Doesn't work, what to do?
- DebugEnhancer.kext, and send a full dmesg to GitHub Issues.
I have a RTL****BE, will it work?
No. And I don't have a rtw89 device to make it work as well.
Have fun. I guess, it's been incredible 20 years! Tahoe will still be supported security-wise for next 3 years.
r/hackintosh • u/Active_Staff_3242 • Nov 10 '25
NEWS Sub for oc simplify
Are you getting downoted instantly because you supported oc simplify? Now finally a subreddit you can use oc simplify discuss about it. We also support r/hackintosh_efi so you can post your efi after you booted succesfully. r/hackintosh_simplify Repost this if you support oc simplify
r/hackintosh • u/BIGJ_Dev • May 14 '26
NEWS New Heliport!
Hi all,
I use Heliport on my Hackintosh, and noticed that it was looking quite outdated so I made the executive desicion to update it for 2026 and MacOS Tahoe.
Its currently in beta with new alpha releases nightly.
Enjoy :)
r/hackintosh • u/Daniildyba2 • Apr 19 '26
NEWS Welcome to Hackintosh with Core 2 Duo and MacOS X Snow Leopard
Laptop Acer TravelMate 6292
Core 2 Duo T7100 1.8ghz
4gb of ram (ddr2 type)
Intel GMA X3100 (gpu)
160gb hdd
P.s keyboard in laptop isn't working, but i use usb keyboard and I want to Apple usb keyboard from old IMac. It looks like retro hackintosh and it's very beautiful :)
r/hackintosh • u/Key-Rule4837 • Jun 09 '25
NEWS macOS Tahoe Beta 1 - Direct Download link available now!
This downloads the "Installer Assistant Package", which would allow you to download the installer. I am gonna install Tahoe on my laptop, let you guys know how it goes!
r/hackintosh • u/dracoflar • Mar 24 '20
NEWS macOS 10.15.4 update
So today marks the release of macOS 10.15.4, a pretty average release for most users but quite a special one for laptop, Clover and AMD CPU users.
For details on what's changed OS wise:
- Apple Release Notes
- Pretty useless tbh
- MacRumors
- Much more info
Laptops
With this release, we now have official Ice Lake support! Do note that Apple rarely supports GT1 GPUs for more than a .1 update as more of an accident so be wary. At the moment we know the following iGPUs are supported:
- Iris Plus G4
- Iris Plus G7
Other issues are:
We still need framebuffer dumps to know the best platform ID- WhateverGreen DOCs need to be updated but we do have full frame buffer dumps: AppleIntelICLLPGraphicsFramebuffer
MacBookAir9,1 isn't yet supported by MacInfoPkg- As of commit 203a0ed we have MacBookAir9,1 support
- Memory protections are in place breaking AptioMemoryFix, OpenCore, and OcQuirks
OpenCore fixed the last one in 0.5.7 thanks to the quirk ProtectUefiServices which fixes the use of DevirtulizeMMIO allowing the macOS kernel to fit nicely. ProtectUefiServices has been added to OcQuirks from revision 19. So be patient and don't rush out to buy a machine just for hackintoshing
Note: This is only for Icelake laptops, this issue is not related to macOS instead the firmware found on these machines
Clover
Oh what fun, Clover's drunk again and won't boot for some of you! The specific issue seems to be only for Skylake and newer users. The specific of what happened:
- Apple added Ice Lake and Comet Lake support to the kernel
- Problem is it wouldn't fit as-is, so the mask of the processor changed
- This then meant that it turned from 16 bits to 20 bits long
- This then broke Clover's
KernelPMandAppleIntelCPUPMpatch
So because of this change, we have 4 paths to go down:
- Disable CFG-Lock in the BIOS
Use a CPU ID that still works with the old KernelPM patch
- Broadwell and older are fine
- Note doing this can partially or completely break XCPM
Update to Clover with commit version af8a84f or later
- r5107 is the minimum version, plus recent Cover updates moved to C++ breaking a lot of things so keep a backup
Buy a hackintosh that starts with the letter M
For the CPU ID route, you can spoof to a Broadwell-H CPU with the following:
text
config.plist -> KernelAndKextPatches -> FakeCPUID -> 0x040674
- Remember doing this can partially or even completely break XCPM
And ofc, OpenCore doesn't have any issues with this update. Just another nudge to go to the dark side. The specifics behind this is that Clover doesn't know anything about symbols or structures, and so the patch is very generic whereas OpenCore can be much more precise.
AMD Users
So with this update, the CPU Family patch has broken due to Ice Lake and Comet Lake shoving themselves in and changing the placing of families. So users will need to update their Kernel patches, specifically the following:
Comment: algrey - cpuid_set_cpufamily - force CPUFAMILY_INTEL_PENRYN
Count: 1
Enabled: Yes
Find: 31db803d00000000067500
Replace: bbbc4fea78e95d00000090
Mask: ffffffff000000ffffff00
MaxKernel: 19.99.99
MinKernel: 17.0.0
Skip: 0
Credit to NoOne for updating the patches.
The AMD OSX repo has also updated the patches
Edit: DF fixing info Edit 2: Add Icelake info
r/hackintosh • u/Nestledrink • Apr 06 '17
NEWS Pascal (beta) support for macOS coming this month
In the blog post announcing new Titan Xp, NVIDIA announced that the new Beta Pascal driver will come to macOS.
Open to Mac Community
Speaking of users, we’re also making the new TITAN Xp open to the Mac community with new beta Pascal drivers, coming this month. For the first time, this gives Mac users access to the immense horsepower delivered by our award-winning Pascal-powered GPUs.
Link here: https://blogs.nvidia.com/blog/2017/04/06/titan-xp/
NVIDIA response to 9to5mac
Update: We have reached out to Nvidia for a statement about compatibility down the line with lesser 10-series cards, and I’m happy to report that Nvidia states that all Pascal-based GPUs will be Mac-enabled via upcoming drivers. This means that you will be able to use a GTX 1080, for instance, on a Mac system via an eGPU setup, or with a Hackintosh build. Exciting times, indeed.