Skip to content
This repository has been archived by the owner on Apr 14, 2023. It is now read-only.

Bringing up the emulator

TrungNguyen1909 edited this page Mar 24, 2023 · 31 revisions

This doc details all the steps to build and run the emulator.

Prerequisites

You will need a macOS system for some of the preparation steps.

Getting dependencies

Getting support tools

git clone https://github.com/TrungNguyen1909/qemu-t8030-tools
pip3 install pyasn1

macOS Homebrew

brew install glib libtasn1 meson ninja pixman jtool2 jq coreutils gnutls libgcrypt pkg-config

Linux

sudo apt update
sudo apt install -y git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev libtasn1-dev ninja-build build-essential cmake libgnutls28-dev pkg-config

Get jtool2 from the jtool2's official website.

There is a jtool2.ELF64 inside the package.

Install lzfse

For Linux, follow the step below to install lzfse.

For macOS, you can install lzfse from Homebrew ONLY if you are running an Intel. However, there are some problems building when Homebrew uses /opt prefix (M1 systems).

If you have issues regarding LZFSE, try installing it from sources like below.

git clone https://github.com/lzfse/lzfse
cd lzfse
mkdir build; cd build
cmake ..
make
sudo make install
cd ..

Building QEMU

git clone https://github.com/TrungNguyen1909/qemu-t8030
cd qemu-t8030
mkdir build; cd build
../configure --target-list=aarch64-softmmu,x86_64-softmmu --disable-capstone --enable-lzfse --disable-werror
make -j$(nproc)

S8000 SecureROM Emulation

Continue at here if you want to emulate iPhone 6s SecureROM.

The section following this is for running iOS.

Getting iOS firmware

Download and unzip iPhone11,8,iPhone12,1_14.0_18A5351d_Restore.ipsw

curl -LO https://updates.cdn-apple.com/2020SummerSeed/fullrestores/001-35886/5FE9BE2E-17F8-41C8-96BB-B76E2B225888/iPhone11,8,iPhone12,1_14.0_18A5351d_Restore.ipsw
mkdir iphone; cd iphone
unzip ../iPhone11,8,iPhone12,1_14.0_18A5351d_Restore.ipsw

Getting precompiled system binaries

export STRAP_URL=$(curl https://assets.checkra.in/loader/config.json | jq -r ".core_bootstrap_tar")
curl -LO $STRAP_URL
mkdir strap
tar xf strap.tar.lzma -C strap

Preparing the ramdisk

These steps are only needed if you want to add your own binaries to the ramdisk.

Note that for all the below steps might need to be run on macOS.

Unpacking the ramdisk

python3 qemu-t8030-tools/bootstrap_scripts/asn1rdskdecode.py 038-44087-125.dmg 038-44087-125.dmg.out
# resize
hdiutil resize -size 512M -imagekey diskimage-class=CRawDiskImage 038-44087-125.dmg.out

# mount
hdiutil attach -imagekey diskimage-class=CRawDiskImage 038-44087-125.dmg.out

# enable ownership
sudo diskutil enableownership /Volumes/AzulSeed18A5351d.arm64eUpdateRamDisk

# Copy system binaries
sudo rsync -av strap/ /Volumes/AzulSeed18A5351d.arm64eUpdateRamDisk

# LaunchDaemons
sudo rm /Volumes/AzulSeed18A5351d.arm64eUpdateRamDisk/System/Library/LaunchDaemons/*
sudo cp qemu-t8030/setup-ios/bash.plist /Volumes/AzulSeed18A5351d.arm64eUpdateRamDisk/System/Library/LaunchDaemons/

# unmount
hdiutil detach /Volumes/AzulSeed18A5351d.arm64eUpdateRamDisk

Creating trustcache for the modified ramdisk

This step is no longer needed as we now patch AMFI by default.

Bundled trustcache

python3 qemu-t8030-tools/bootstrap_scripts/asn1trustcachedecode.py Firmware/038-44087-125.dmg.trustcache Firmware/038-44087-125.dmg.trustcache.out
python3 qemu-t8030-tools/bootstrap_scripts/dump_trustcache.py Firmware/038-44087-125.dmg.trustcache.out | grep cdhash | cut -d' ' -f2 > tchashes

System Binaries

for filename in $(find strap/ -type f); do jtool2 --sig $filename 2>/dev/null; done | grep CDHash | cut -d' ' -f6 | cut -c 1-40 >> ./tchashes

Serialize trustcache

python3 qemu-t8030-tools/bootstrap_scripts/create_trustcache.py tchashes static_tc

Creating NVMe namespaces

WARNING: This step can take up to 32GB of hard disk.

The problem we are facing here is that macOS cannot mount a qcow2 disk image, so we have no compression.

In order to modify the disk with the macOS host, we need to use a raw disk image.

./qemu-t8030/build/qemu-img create -f raw nvme.1 32G
./qemu-t8030/build/qemu-img create -f raw nvme.2 8M
./qemu-t8030/build/qemu-img create -f raw nvme.3 128K
./qemu-t8030/build/qemu-img create -f raw nvme.4 8K
./qemu-t8030/build/qemu-img create -f raw nvram  8K
./qemu-t8030/build/qemu-img create -f raw nvme.6 4K
./qemu-t8030/build/qemu-img create -f raw nvme.7 1M

Run

Don't forget that -snapshot can be used to prevent filesystem corruptions on reset.

-smp can be set up to 6 CPUs.

-m can go up to 4GB of RAM.

Adding kaslr-off=true after a comma in the first line will disable KASLR.

Auto boot

This will put the device into Restore mode on the first run and boot to NAND after restore completed

qemu-t8030/build/qemu-system-aarch64 -s -M t8030,trustcache-filename=Firmware/038-44135-124.dmg.trustcache,ticket-filename=root_ticket.der \
-kernel kernelcache.research.iphone12b \
-dtb Firmware/all_flash/DeviceTree.n104ap.im4p \
-append "debug=0x14e kextlog=0xffff serial=3 -v wdt=-1" \
-initrd 038-44135-124.dmg \
-cpu max -smp 4 \
-m 4G -serial mon:stdio \
-drive file=nvme.1,format=raw,if=none,id=drive.1 \
-device nvme-ns,drive=drive.1,bus=nvme-bus.0,nsid=1,nstype=1,logical_block_size=4096,physical_block_size=4096 \
-drive file=nvme.2,format=raw,if=none,id=drive.2 \
-device nvme-ns,drive=drive.2,bus=nvme-bus.0,nsid=2,nstype=2,logical_block_size=4096,physical_block_size=4096 \
-drive file=nvme.3,format=raw,if=none,id=drive.3 \
-device nvme-ns,drive=drive.3,bus=nvme-bus.0,nsid=3,nstype=3,logical_block_size=4096,physical_block_size=4096 \
-drive file=nvme.4,format=raw,if=none,id=drive.4 \
-device nvme-ns,drive=drive.4,bus=nvme-bus.0,nsid=4,nstype=4,logical_block_size=4096,physical_block_size=4096 \
-drive file=nvram,if=none,format=raw,id=nvram \
-device apple-nvram,drive=nvram,bus=nvme-bus.0,nsid=5,nstype=5,id=nvram,logical_block_size=4096,physical_block_size=4096 \
-drive file=nvme.6,format=raw,if=none,id=drive.6 \
-device nvme-ns,drive=drive.6,bus=nvme-bus.0,nsid=6,nstype=6,logical_block_size=4096,physical_block_size=4096 \
-drive file=nvme.7,format=raw,if=none,id=drive.7 \
-device nvme-ns,drive=drive.7,bus=nvme-bus.0,nsid=7,nstype=8,logical_block_size=4096,physical_block_size=4096 \
-monitor telnet:127.0.0.1:1235,server,nowait

Boot from modified Ramdisk/RootFS

Remove rd=md0 boot args from the below commands if you want to boot from NAND instead of ramdisk.

qemu-t8030/build/qemu-system-aarch64 -s -M t8030,trustcache-filename=static_tc,boot-mode=manual,ticket-filename=root_ticket.der \
-kernel kernelcache.research.iphone12b \
-dtb Firmware/all_flash/DeviceTree.n104ap.im4p \
-append "debug=0x14e kextlog=0xffff serial=3 -v rd=md0 wdt=-1" \
-initrd 038-44087-125.dmg.out \
-cpu max -smp 1 \
-m 4G -serial mon:stdio \
-drive file=nvme.1,format=raw,if=none,id=drive.1 \
-device nvme-ns,drive=drive.1,bus=nvme-bus.0,nsid=1,nstype=1,logical_block_size=4096,physical_block_size=4096 \
-drive file=nvram,if=none,format=raw,id=nvram \
-device apple-nvram,drive=nvram,bus=nvme-bus.0,nsid=5,nstype=5,id=nvram,logical_block_size=4096,physical_block_size=4096

Boot S8000 SecureROM

You need to get the SecureROM of the S8000 (production) board from securerom.fun

You will also need its DeviceTree from an iPhone 6s IPSW, I tried this version and it works just fine.

The path to the DeviceTree file in the IPSW is Firmware/all_flash/DeviceTree.n71ap.im4p

Create the NOR image if you haven't done so:

./qemu-t8030/build/qemu-img create -f raw s8000.nor 16M

The command to emulate S8000 SecureROM is below:

qemu-t8030/build/qemu-system-aarch64 -s -M s8000,force-dfu=false \
-bios "s8000/SecureROM for s8000si, iBoot-2234.0.0.3.3" \
-dtb DeviceTree.n71ap.im4p \
-cpu max -smp 1 -nographic \
-d guest_errors \
-m 4G -serial mon:stdio \
-drive file=s8000.nor,format=raw,if=none,id=nor \
-device m25p128,drive=nor,bus=spi0.bus \
-monitor telnet:127.0.0.1:1235,server,nowait

You can assert the FORCE_DFU pin (enter DFU mode automatically without reading NOR) by setting force-dfu=true.

Stop the emulator

If you have a shell, use the command halt to shutdown the device gracefully.

Connect to the monitor at localhost:1235 and use the q command to force quit.

As such, to avoid filesystem corruptions on the NAND, consider using the -snapshot flag to run without saving changes to your disk.