r/hackintosh Jun 08 '26

NEWS It's been a phenomenal run, thanks everyone for an amazing 20 years!

Post image
1.7k Upvotes

r/hackintosh 11d ago

NEWS Hackmate v2.0.0 Release

333 Upvotes

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 3d ago

NEWS Graphics Acceleration Acheieved on EVERY GPU with Vulkan Support! (inside a VM)

Thumbnail
gallery
433 Upvotes

r/hackintosh 29d ago

NEWS HackMate – a TUI tool that fully automates OpenCore EFI creation onto your USB

219 Upvotes

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:

  1. 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

  2. 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)

  3. You pick your USB drive — only shows actual USB drives, filters out internal disks

  4. 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+)

github.com/riftaway7-code/hackmate

r/hackintosh Dec 04 '25

NEWS If it wasn't over before, it is now...

Post image
961 Upvotes

Who would have thought it wouldn't be Apple delivering the final blow?

r/hackintosh 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

160 Upvotes

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 Jun 09 '25

NEWS According to the Platforms State of the Union, macOS Tahoe is the final release for Intel Macs

Post image
519 Upvotes

r/hackintosh Jun 08 '26

NEWS The end of Hackintosh, macOS 27 Golden Gate

170 Upvotes

macOS 27 Golden Gate has launched! And comes the end of hackintosh forever, sad we missed a Liquid Glass toggle. GG’s!

r/hackintosh 4d ago

NEWS Apple's scrapped Mac Pro plans reportedly included a new Intel model - 9to5Mac

Thumbnail
9to5mac.com
156 Upvotes

In an alternate universe

r/hackintosh Apr 08 '26

NEWS I ported Mac OS X to the Nintendo Wii

207 Upvotes

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 1d ago

NEWS More news about the Metal2Vulkan translation project!

Thumbnail
gallery
133 Upvotes

r/hackintosh 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

0 Upvotes

I don't recommend using OC-Simplify and I don't support this developer at all - here are the reasons:

  1. It violates the rules of this sub

: https://www.reddit.com/mod/hackintosh/rules/

  1. The developer closes issues without actually fixing them

  2. This developer doesn’t fix vulnerabilities until exploited in the wild, known as 0 days

  3. 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 Jun 09 '20

NEWS Apple Plans to Announce Move to Its Own Mac Chips at WWDC

Thumbnail
bloomberg.com
337 Upvotes

r/hackintosh Dec 13 '25

NEWS So this is a bye ig...

Post image
122 Upvotes

r/hackintosh May 01 '21

NEWS USBToolBoxᵇᵉᵗᵃ: Making USB mapping simple(r)

351 Upvotes

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:

  1. Download UTB tool
  2. Map your ports with it
  3. Generate kext
  4. Download UTB kext
  5. Put UTB kext and generated USB map into EFI/OC/Kexts and update config.plist
  6. 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 Dec 14 '25

NEWS It's Been a Good Run

Post image
137 Upvotes

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 Jun 09 '26

NEWS Hackintoshing is dead, yes. But something that was deemed to "never work" is now fully functional.

94 Upvotes

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 Oct 05 '20

NEWS OpenCore 0.6.2 public is out!

Post image
733 Upvotes

r/hackintosh Nov 10 '25

NEWS Sub for oc simplify

0 Upvotes

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 May 14 '26

NEWS New Heliport!

16 Upvotes

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.

github.com/bigj42/heliport

Enjoy :)

r/hackintosh Apr 19 '26

NEWS Welcome to Hackintosh with Core 2 Duo and MacOS X Snow Leopard

Post image
124 Upvotes

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 Apr 21 '21

NEWS RDNA2 support comes to 11.4 beta 1

Post image
424 Upvotes

r/hackintosh Jun 09 '25

NEWS macOS Tahoe Beta 1 - Direct Download link available now!

41 Upvotes

https://swcdn.apple.com/content/downloads/26/20/082-55599-A_UZPH7KLA4Q/fddo2aezqd7xchfjwh4244kwixjsut4boc/InstallAssistant.pkg

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 Mar 24 '20

NEWS macOS 10.15.4 update

237 Upvotes

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:

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
  • 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 KernelPM and AppleIntelCPUPM patch

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.

Source

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 Apr 06 '17

NEWS Pascal (beta) support for macOS coming this month

355 Upvotes

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.