Running BadBuilder on macOS — Mac-Only Guide
Running BadBuilder on macOS — Mac-Only Guide
This guide explains how to compile and run Pdawg-bytes/BadBuilder on macOS without Windows, a Windows VM, or a Windows PC.
The current BadBuilder release provides Windows binaries, while the source contains macOS/Linux placeholders for disk handling. The steps below add the small amount of macOS support needed to detect a USB drive and use an already-formatted FAT32 volume.
Tested approach: Apple Silicon Mac, macOS, .NET 10, 15.5 GB FAT32 USB drive.
What this guide does
The macOS build will:
- Detect external USB drives using
diskutil - Display the USB inside BadBuilder's Target Drive menu
- Use an existing FAT32 USB volume
- Download BadUpdate, XeUnshackle, Aurora, XeXMenu, Simple 360 NAND Flasher, and the required Rock Band Blitz files
- Extract and copy the files to the USB
- Avoid the Windows-only formatting code
It does not implement BadBuilder's Windows-specific raw-disk formatting functionality.
1. Install Apple's Command Line Tools
Open Terminal and run:
xcode-select --install
If they are already installed, verify with:
xcode-select -p
You should see:
/Library/Developer/CommandLineTools
2. Install Homebrew
If Homebrew is not already installed, install it from the official Homebrew website.
After installation, make sure Homebrew is available:
brew --version
On Apple Silicon Macs, Homebrew normally installs under:
/opt/homebrew
If Terminal tells you to add Homebrew to your PATH, follow the commands it provides.
3. Install Git and .NET
Run:
brew install git dotnet
Verify both:
git --version
dotnet --version
This guide was tested with .NET 10.
4. Download BadBuilder
Clone the repository:
git clone https://github.com/Pdawg-bytes/BadBuilder.git
Enter the repository:
cd ~/BadBuilder
Verify the files:
ls
You should see something similar to:
BadBuilder
BadBuilder.slnx
LICENSE
README.md
5. Verify the project builds
Run:
dotnet build BadBuilder/BadBuilder.csproj
The original source should build successfully, although you may see warnings related to the Windows-only disk implementation.
6. Add macOS USB-drive detection
The current source calls the Windows disk enumerator on Windows but has no implementation for macOS.
Create a new file:
cat > BadBuilder/Services/Disks/DiskService.MacOS.cs <<'EOF'
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace BadBuilder.Services.Disks;
internal static partial class DiskService
{
private static List<DiskInfo> EnumerateDisksMacOS()
{
string output = RunProcess("diskutil", "list external physical");
var disks = new List<DiskInfo>();
var matches = Regex.Matches(output, @"^/dev/(disk\d+)\s+\(external,\s*physical\):",
RegexOptions.Multiline);
foreach (Match match in matches)
{
string device = match.Groups[1].Value;
string info = RunProcess("diskutil", $"info /dev/{device}");
string name = GetDiskutilValue(info, "Device / Media Name") ?? $"Disk {device}";
string sizeText = GetDiskutilValue(info, "Disk Size") ?? "";
string removable = GetDiskutilValue(info, "Removable Media") ?? "";
string protocol = GetDiskutilValue(info, "Protocol") ?? "";
long size = ParseDiskSize(sizeText);
DriveType type =
removable.Equals("Yes", StringComparison.OrdinalIgnoreCase) ||
protocol.Contains("USB", StringComparison.OrdinalIgnoreCase)
? DriveType.Removable
: DriveType.Fixed;
disks.Add(new DiskInfo(
device,
name.Trim(),
size,
type,
$"/dev/{device}"));
}
return disks;
}
private static string? GetDiskutilValue(string output, string key)
{
foreach (string line in output.Split('\n'))
{
if (line.TrimStart().StartsWith(key + ":", StringComparison.OrdinalIgnoreCase))
return line[(line.IndexOf(':') + 1)..].Trim();
}
return null;
}
private static long ParseDiskSize(string value)
{
Match match = Regex.Match(value, @"([\d.]+)\s*(TB|GB|MB|KB|B)",
RegexOptions.IgnoreCase);
if (!match.Success)
return 0;
double number = double.Parse(match.Groups[1].Value,
System.Globalization.CultureInfo.InvariantCulture);
return match.Groups[2].Value.ToUpperInvariant() switch
{
"TB" => (long)(number * 1024 * 1024 * 1024 * 1024),
"GB" => (long)(number * 1024 * 1024 * 1024),
"MB" => (long)(number * 1024 * 1024),
"KB" => (long)(number * 1024),
_ => (long)number
};
}
}
EOF
7. Tell DiskService to use the macOS implementation
Open:
BadBuilder/Services/Disks/DiskService.cs
Find:
internal static List<DiskInfo> EnumerateDisks() => InvokePlatformAction(EnumerateDisksWindows, null, null);
Change it to:
internal static List<DiskInfo> EnumerateDisks() => InvokePlatformAction(EnumerateDisksWindows, EnumerateDisksMacOS, null);
Build again:
dotnet build BadBuilder/BadBuilder.csproj
A successful build confirms that macOS disk enumeration has been added.
8. Prepare the USB drive
Plug the USB drive into the Mac.
Find the physical disk:
diskutil list
Look for the external physical drive.
For example:
/dev/disk5 (external, physical)
0: FDisk_partition_scheme
1: DOS_FAT_32 BADUPDATE
Do not assume that /dev/disk5 will be the same on another Mac.
Always verify the disk number yourself.
Verify the FAT32 volume
If the physical disk is /dev/disk5, inspect its partition:
diskutil info /dev/disk5s1 | grep -E "Device Node|Volume Name|File System|Mount Point"
You want to see something similar to:
Device Node: /dev/disk5s1
Volume Name: BADUPDATE
Mount Point: /Volumes/BADUPDATE
File System Personality: MS-DOS FAT32
If the volume is already FAT32 and mounted at:
/Volumes/BADUPDATE
you can use it without formatting it again.
9. Modify BadBuilder's macOS install behavior
Open:
BadBuilder/Application/BuilderApp.cs
Inside InstallAsync(), find the existing Windows/macOS formatting block:
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Controls.WriteWarning("Drive formatting is currently only supported on Windows. Please format the drive manually to FAT32 before proceeding.");
Controls.Pause("Press enter after you have formatted the drive.");
}
else
{
...
}
Replace that block with:
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
Config.MountPoint = "/Volumes/BADUPDATE";
if (!Directory.Exists(Config.MountPoint))
throw new InvalidOperationException("The BADUPDATE USB volume is not mounted at /Volumes/BADUPDATE.");
Controls.WriteSuccess($"Using existing FAT32 drive at {Config.MountPoint}.");
}
else if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Controls.WriteWarning("Drive formatting is currently only supported on Windows. Please format the drive manually to FAT32 before proceeding.");
Controls.Pause("Press enter after you have formatted the drive.");
}
else
{
bool format = Controls.Confirm($"Are you sure you would like to format [bold]{Config.TargetDisk.Name}[/]? All data on this drive will be lost.", false, warning: true);
Controls.PadLine();
if (format)
{
Controls.WriteInfo("Formatting drive.");
Config.MountPoint = DiskService.FormatFAT32(Config.TargetDisk);
Controls.WriteSuccess("Drive formatted.");
}
else
return;
}
This tells the macOS build:
The USB is already formatted. Use
/Volumes/BADUPDATEas the installation destination.
10. Build the modified version
Run:
dotnet build BadBuilder/BadBuilder.csproj
You should get:
Build succeeded
The existing Windows-related warnings are not necessarily a problem.
11. Run BadBuilder
Because BadBuilder requests elevated privileges, run:
sudo dotnet run --project BadBuilder/BadBuilder.csproj
Enter your Mac password when prompted.
12. Select the USB
Choose:
Target drive
Your USB should appear as something similar to:
USB DISK 2.0 (15.50 GB) - Removable
Select it.
The main configuration should then show:
Drive USB DISK 2.0
Exploit BadUpdate
Bootstrap XeUnshackle
Homebrew Aurora, XeXMenu, Simple 360 NAND Flasher
13. Install
Choose:
Install
On macOS you should see:
[+] Using existing FAT32 drive at /Volumes/BADUPDATE.
BadBuilder should then:
- Resolve the latest releases
- Download the required files
- Extract the files
- Copy them to the USB
- Report:
[+] Your USB drive is ready for use.
14. Safely eject the USB
After BadBuilder exits, eject the physical disk.
For example, if your USB was /dev/disk5:
diskutil eject /dev/disk5
You should see:
Disk /dev/disk5 ejected
The USB can now be removed from the Mac.
Troubleshooting
BadBuilder crashes with NullReferenceException when selecting Target Drive
If you see an error involving:
DiskService.InvokePlatformAction
and:
EnumerateDisks()
the macOS disk-enumeration patch has not been applied correctly.
Verify that DiskService.cs contains:
internal static List<DiskInfo> EnumerateDisks() => InvokePlatformAction(EnumerateDisksWindows, EnumerateDisksMacOS, null);
USB isn't detected
Run:
diskutil list
Make sure the USB appears under:
external, physical
If it doesn't appear there, BadBuilder won't be able to enumerate it.
USB is detected but /Volumes/BADUPDATE doesn't exist
Check:
diskutil info /dev/diskXs1 | grep -E "Volume Name|Mount Point|File System"
Replace diskXs1 with the actual USB partition.
If the FAT32 volume isn't mounted, macOS can generally mount it with:
diskutil mount /dev/diskXs1
Then check:
ls /Volumes
You should see:
BADUPDATE
BadBuilder says the drive isn't mounted
Verify:
ls -la /Volumes/BADUPDATE
If that directory exists, BadBuilder should be able to use it.
Important Notes
Do not copy the disk number from this guide
The USB may be /dev/disk2, /dev/disk4, /dev/disk5, etc. on another Mac.
Always run:
diskutil list
and identify the correct external physical disk before performing any disk operation.
Formatting is destructive
Although this guide uses an existing FAT32 volume, formatting a USB with diskutil eraseDisk or another disk-formatting command will erase the selected disk.
Never substitute a disk number without verifying it first.
This is a macOS source-code workaround
The official BadBuilder release currently targets Windows. This guide modifies the source so that the parts needed for USB preparation work on macOS.
It does not turn every Windows-specific feature of BadBuilder into a macOS implementation.
Apple Silicon
This approach works with Apple Silicon Macs because BadBuilder is compiled locally with .NET rather than attempting to execute the Windows binary.
Quick version
Once the prerequisites are installed, the normal workflow is:
cd ~/BadBuilder
Verify the USB:
diskutil list
Verify the FAT32 volume:
diskutil info /dev/disk5s1 | grep -E "Device Node|Volume Name|File System|Mount Point"
Build:
dotnet build BadBuilder/BadBuilder.csproj
Run:
sudo dotnet run --project BadBuilder/BadBuilder.csproj
Select the USB → Install → wait for:
[+] Your USB drive is ready for use.
Then:
diskutil eject /dev/disk5
Done.