-
-
Save JamesHopbourn/e3c9dbd265835eeb5ecfd79dc56d3257 to your computer and use it in GitHub Desktop.
Download a Mac OS X 10.9 Mavericks installer image Apple
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
#!/bin/sh | |
# Download script written by Wowfunhappy. Last updated 2025/03/07. | |
# Thank you to Krackers, Jazzzny, and others for helping analyze Apple's download process and debug this script. | |
# Thank you to dosdude1 for donating identifiers from a broken Mac. | |
# Any mistakes are mine alone. | |
BOARD_SERIAL_NUMBER="C0243070168G3M91F" | |
BOARD_ID="Mac-3CBD00234E554E41" | |
ROM="003EE1E6AC14" | |
# Helper functions | |
save_create_bootable_installer_script() { | |
cat << 'EOF' > "$1" | |
#!/bin/sh | |
set -e | |
cd "`dirname "$0"`" | |
asr imagescan --source InstallMacOSXMavericks.dmg | |
did_find_volume="false" | |
while [ $did_find_volume == "false" ] | |
do | |
printf "Please enter the volume name of your USB flash drive: " | |
read target_volname | |
if [ ! -z $target_volname ] && df -l | grep -q "/Volumes/$target_volname" | |
then | |
did_find_volume=true | |
elif [ ! -z $target_volname ] | |
then | |
echo | |
echo "Could not find a volume named $target_volname. Found these volumes:" | |
df -l | awk -F'/Volumes/' '{print $2}' | grep -v '^$' | |
echo | |
fi | |
done | |
printf "WARNING: All data on $target_volname will be erased. Continue? (yes/no) " | |
read confirmation | |
if [ "$confirmation" != "y" ] && [ "$confirmation" != "yes" ] | |
then | |
echo "Exiting. No changes have been made." | |
exit 1 | |
fi | |
disk_identifier=$(diskutil list /Volumes/"$target_volname" | head -n 1) | |
sudo diskutil partitionDisk $disk_identifier GPT jhfs+ "$target_volname" 100% | |
sudo asr restore --source InstallMacOSXMavericks.dmg --noprompt --target /Volumes/"$target_volname" --erase | |
EOF | |
chmod +x "$1" | |
} | |
hex_to_bin() { | |
printf "%s" "$1" | xxd -r -p | |
} | |
check_for_utility() { | |
if ! command -v "$1" > /dev/null | |
then | |
echo "Error: Required utility '$1' is not available on your system." 1>&2 | |
exit 1 | |
fi | |
} | |
# Start here! | |
set -e | |
check_for_utility "hdiutil" | |
check_for_utility "curl" | |
check_for_utility "openssl" | |
if ! openssl dgst -sha256 < /dev/null > /dev/null 2>&1 | |
then | |
echo "Error: The version of OpenSSL on your system does not support SHA-256." 1>&2 | |
exit 1 | |
fi | |
# To retrieve the installation payload from Apple, we must provide: | |
# 1. A server ID, retrieved from osrecovery.apple.com. | |
# 2. A client ID, randomly generated. | |
# 3. The board serial number and matching board id of a Mavericks-era Mac. | |
# 4. A key, a SHA-256 hash derived from: | |
# - The aforementioned client id. | |
# - The aforementioned server id. | |
# - A ROM matching the aforementioned board serial number and board id. | |
# - The SHA-256 hash of the aforementioned board serial number and board id. | |
# 1. Retrieve the server ID from Apple. | |
SERVER_ID=$(curl -fs -c - http://osrecovery.apple.com/ | tail -1 | awk '{print $NF}') | |
# 2. Generate the client ID. | |
CLIENT_ID=$(dd if=/dev/urandom bs=8 count=1 2>/dev/null | od -An -tx1 | tr -d ' \n' | tr '[:lower:]' '[:upper:]') | |
# 4. Generate the key. | |
{ | |
hex_to_bin "$CLIENT_ID" | |
hex_to_bin "$(echo $SERVER_ID | awk -F'~' '{print $2}')" | |
hex_to_bin "$ROM" | |
printf "%s" "${BOARD_SERIAL_NUMBER}${BOARD_ID}" | iconv -t utf-8 | openssl dgst -sha256 -binary | |
printf '\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC' | |
} > key_info | |
# Hash key_info using SHA-256, then convert raw binary output to uppercase hex. | |
KEY=$(openssl dgst -sha256 -binary < key_info | od -An -tx1 | tr -d ' \n' | tr '[:lower:]' '[:upper:]') | |
rm key_info | |
# Finally, retrieve the installation payload, which contains the asset token needed to download InstallESD.dmg. | |
INSTALLATION_PAYLOAD=$(curl -fs 'http://osrecovery.apple.com/InstallationPayload/OSInstaller' -X POST \ | |
-H 'Content-Type: text/plain' \ | |
--cookie "session=$SERVER_ID" \ | |
-d "cid=$CLIENT_ID | |
sn=$BOARD_SERIAL_NUMBER | |
bid=$BOARD_ID | |
k=$KEY") | |
ASSET_URL=$(echo "$INSTALLATION_PAYLOAD" | grep AU | awk -F': ' '{print $2}') | |
ASSET_TOKEN=$(echo "$INSTALLATION_PAYLOAD" | grep AT | awk -F': ' '{print $2}') | |
if [ "$ASSET_URL" != "http://oscdn.apple.com/content/downloads/33/62/031-10295/gho4r94w66f5v4ujm0sz7k1m0hua68i6oo/OSInstaller/InstallESD.dmg" ] | |
then | |
echo "Error: Server did not provide the Mavericks InstallESD URL." 1>&2 | |
exit 1 | |
fi | |
echo "Downloading InstallESD.dmg..." | |
curl --progress-bar "$ASSET_URL" -H "Cookie: AssetToken=$ASSET_TOKEN" > InstallESD.dmg | |
# Verify the checksum of InstallESD.dmg because it was downloaded over unencrypted HTTP. | |
echo "Verifying integrity of InstallESD.dmg..." | |
if [ $(openssl dgst -sha256 InstallESD.dmg | awk -F'= ' '{print $2}') != "c861fd59e82bf777496809a0d2a9b58f66691ee56738031f55874a3fe1d7c3ff" ] | |
then | |
rm InstallESD.dmg | |
echo "Error: Download failed (mismatched checksum)" 1>&2 | |
exit 1 | |
fi | |
echo "Building InstallMacOSXMavericks.dmg..." | |
# Inside InstallESD.dmg is another image, BaseSystem.dmg, which contains a minimal Mac OS X recovery environment. | |
# Additional data from InstallESD.dmg must be copied into BaseSystem.dmg to build a complete Mavericks installer. | |
# Ensure no volumes with these names are already mounted. | |
hdiutil detach "/Volumes/OS X Base System" 2> /dev/null && sleep 2 || true | |
hdiutil detach "/Volumes/OS X Install ESD" 2> /dev/null && sleep 2 || true | |
# Convert BaseSystem.dmg to a modifiable image with sufficient free space for the additional data. | |
hdiutil attach InstallESD.dmg -nobrowse | |
hdiutil convert -ov "/Volumes/OS X Install ESD/BaseSystem.dmg" -format UDSP -o "InstallMacOSXMavericks.sparseimage" | |
hdiutil resize -size 6550020096 "InstallMacOSXMavericks.sparseimage" | |
# Copy additional data into BaseSystem. | |
hdiutil attach "InstallMacOSXMavericks.sparseimage" -nobrowse | |
rm -rf "/Volumes/OS X Base System/System/Installation/Packages" | |
cp -R "/Volumes/OS X Install ESD/Packages" "/Volumes/OS X Base System/System/Installation/" | |
cp "/Volumes/OS X Install ESD/BaseSystem.chunklist" "/Volumes/OS X Base System/System/Installation/" | |
cp "/Volumes/OS X Install ESD/BaseSystem.dmg" "/Volumes/OS X Base System/System/Installation/" | |
hdiutil detach "/Volumes/OS X Base System" | |
hdiutil detach "/Volumes/OS X Install ESD" | |
# Pause before converting so hdiutil won't fail with `hdiutil: convert failed - Resource temporarily unavailable` | |
sleep 2 | |
hdiutil convert -ov "InstallMacOSXMavericks.sparseimage" -format UDZO -o "InstallMacOSXMavericks.dmg" | |
rm InstallMacOSXMavericks.sparseimage | |
rm InstallESD.dmg | |
echo "InstallMacOSXMavericks.dmg successfully created." | |
if [ "$(uname)" = "Darwin" ] | |
then | |
save_create_bootable_installer_script "Create Bootable Installer.command" | |
open -R "InstallMacOSXMavericks.dmg" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment