mirror of
https://github.com/Lakr233/vphone-cli.git
synced 2026-09-05 17:14:28 +00:00
Introduce Patchless Variant
This commit is contained in:
@@ -109,8 +109,12 @@ help:
|
||||
.PHONY: setup_machine setup_tools
|
||||
|
||||
setup_machine:
|
||||
@if [ "$(filter 1 true yes YES TRUE,$(JB))" != "" ] && [ "$(filter 1 true yes YES TRUE,$(DEV))" != "" ]; then \
|
||||
echo "Error: JB=1 and DEV=1 are mutually exclusive"; \
|
||||
@if count=0; \
|
||||
[ -n "$(filter 1 true yes YES TRUE,$(JB))" ] && count=$$((count+1)); \
|
||||
[ -n "$(filter 1 true yes YES TRUE,$(DEV))" ] && count=$$((count+1)); \
|
||||
[ -n "$(filter 1 true yes YES TRUE,$(LESS))" ] && count=$$((count+1)); \
|
||||
[ $$count -gt 1 ]; then \
|
||||
echo "Error: JB=1, DEV=1, and LESS=1 are mutually exclusive"; \
|
||||
exit 1; \
|
||||
fi
|
||||
SUDO_PASSWORD="$(SUDO_PASSWORD)" \
|
||||
@@ -118,6 +122,7 @@ setup_machine:
|
||||
zsh $(SCRIPTS)/setup_machine.sh \
|
||||
$(if $(filter 1 true yes YES TRUE,$(JB)),--jb,) \
|
||||
$(if $(filter 1 true yes YES TRUE,$(DEV)),--dev,) \
|
||||
$(if $(filter 1 true yes YES TRUE,$(LESS)),--less,) \
|
||||
$(if $(filter 1 true yes YES TRUE,$(SKIP_PROJECT_SETUP)),--skip-project-setup,)
|
||||
|
||||
setup_tools:
|
||||
@@ -265,7 +270,7 @@ boot_dfu: build boot_binary_check
|
||||
# Firmware pipeline
|
||||
# ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
.PHONY: fw_prepare fw_patch fw_patch_dev fw_patch_jb
|
||||
.PHONY: fw_prepare fw_patch fw_patch_less fw_patch_dev fw_patch_jb
|
||||
|
||||
fw_prepare:
|
||||
cd $(VM_DIR) && bash "$(CURDIR)/$(SCRIPTS)/fw_prepare.sh"
|
||||
@@ -273,6 +278,13 @@ fw_prepare:
|
||||
fw_patch: patcher_build
|
||||
"$(CURDIR)/$(PATCHER_BINARY)" patch-firmware --vm-directory "$(CURDIR)/$(VM_DIR)" --variant regular
|
||||
|
||||
fw_patch_less: patcher_build
|
||||
@sh -c 'if [ "$$(id -u)" -ne 0 ]; then \
|
||||
echo "fw_patch_less must be run via sudo" >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
"$(CURDIR)/$(PATCHER_BINARY)" patch-firmware --vm-directory "$(CURDIR)/$(VM_DIR)" --variant less'
|
||||
|
||||
fw_patch_dev: patcher_build
|
||||
"$(CURDIR)/$(PATCHER_BINARY)" patch-firmware --vm-directory "$(CURDIR)/$(VM_DIR)" --variant dev
|
||||
|
||||
|
||||
@@ -17,11 +17,12 @@ Boot a virtual iPhone (iOS 26) via Apple's Virtualization.framework using PCC re
|
||||
|
||||
## Firmware Variants
|
||||
|
||||
Three patch variants are available with increasing levels of security bypass:
|
||||
Four patch variants are available with increasing levels of security bypass:
|
||||
|
||||
| Variant | Boot Chain | CFW | Make Targets |
|
||||
| --------------- | :---------: | :-------: | ---------------------------------- |
|
||||
| **Regular** | 1 patch | 10 phases | `fw_patch` + `cfw_install` |
|
||||
| **Patchless** | 2 patches | 2 phases | `fw_patch_less` (sudo) |
|
||||
| **Regular** | 41 patches | 10 phases | `fw_patch` + `cfw_install` |
|
||||
| **Development** | 52 patches | 12 phases | `fw_patch_dev` + `cfw_install_dev` |
|
||||
| **Jailbreak** | 112 patches | 14 phases | `fw_patch_jb` + `cfw_install_jb` |
|
||||
|
||||
@@ -103,6 +104,7 @@ git clone --recurse-submodules https://github.com/Lakr233/vphone-cli.git
|
||||
```bash
|
||||
make setup_machine # full automation through "First Boot" (includes restore/ramdisk/CFW)
|
||||
# options: NONE_INTERACTIVE=1 SUDO_PASSWORD=...
|
||||
# LESS=1 for patchless variant (- AMFI, SSV, Img4, TXM bypasses)
|
||||
# DEV=1 for dev variant (+ TXM entitlement/debug bypasses)
|
||||
# JB=1 for jailbreak variant (+ full security bypass)
|
||||
```
|
||||
@@ -116,6 +118,7 @@ make vm_new # create VM directory with manifest (config.plist)
|
||||
# options: CPU=8 MEMORY=8192 DISK_SIZE=64
|
||||
make fw_prepare # download IPSWs, extract, merge, generate manifest
|
||||
make fw_patch # patch boot chain (regular variant)
|
||||
# or: sudo make fw_patch_less # patchless variant (- AMFI, SSV, Img4, TXM bypasses)
|
||||
# or: make fw_patch_dev # dev variant (+ TXM entitlement/debug bypasses)
|
||||
# or: make fw_patch_jb # jailbreak variant (+ full security bypass)
|
||||
```
|
||||
|
||||
@@ -58,6 +58,7 @@ NONE_INTERACTIVE_RAW="${NONE_INTERACTIVE:-0}"
|
||||
NONE_INTERACTIVE=0
|
||||
JB_MODE=0
|
||||
DEV_MODE=0
|
||||
LESS_MODE=0
|
||||
SKIP_PROJECT_SETUP=0
|
||||
|
||||
die() {
|
||||
@@ -736,6 +737,19 @@ run_make() {
|
||||
make "$@"
|
||||
}
|
||||
|
||||
run_make_sudo() {
|
||||
local label="$1"
|
||||
shift
|
||||
|
||||
echo ""
|
||||
echo "=== ${label} ==="
|
||||
if [[ -n "${SUDO_PASSWORD:-}" ]]; then
|
||||
sudo -A -- make "$@"
|
||||
else
|
||||
sudo -- make "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
start_boot_dfu() {
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
@@ -944,6 +958,9 @@ parse_args() {
|
||||
--dev)
|
||||
DEV_MODE=1
|
||||
;;
|
||||
--less)
|
||||
LESS_MODE=1
|
||||
;;
|
||||
--skip-project-setup)
|
||||
SKIP_PROJECT_SETUP=1
|
||||
;;
|
||||
@@ -954,6 +971,7 @@ Usage: setup_machine.sh [--jb] [--dev] [--skip-project-setup]
|
||||
Options:
|
||||
--jb Use jailbreak firmware patching + jailbreak CFW install.
|
||||
--dev Use dev firmware patching + dev CFW install.
|
||||
--less Use patchless firmware patching + CFW install.
|
||||
--skip-project-setup Skip setup_tools/build stage.
|
||||
|
||||
Environment:
|
||||
@@ -980,8 +998,8 @@ main() {
|
||||
local cfw_install_target="cfw_install"
|
||||
local mode_label="base"
|
||||
|
||||
if [[ "$JB_MODE" -eq 1 && "$DEV_MODE" -eq 1 ]]; then
|
||||
die "--jb and --dev are mutually exclusive"
|
||||
if (( JB_MODE + DEV_MODE + LESS_MODE > 1 )); then
|
||||
die "--jb, --dev, and --less are mutually exclusive"
|
||||
fi
|
||||
|
||||
if [[ "$JB_MODE" -eq 1 ]]; then
|
||||
@@ -992,6 +1010,10 @@ main() {
|
||||
fw_patch_target="fw_patch_dev"
|
||||
cfw_install_target="cfw_install_dev"
|
||||
mode_label="dev"
|
||||
elif [[ "$LESS_MODE" -eq 1 ]]; then
|
||||
fw_patch_target="fw_patch_less"
|
||||
cfw_install_target=""
|
||||
mode_label="less"
|
||||
fi
|
||||
|
||||
echo "[*] setup_machine mode: ${mode_label}, project_setup=$([[ "$SKIP_PROJECT_SETUP" -eq 1 ]] && echo "skip" || echo "run"), non_interactive=${NONE_INTERACTIVE}"
|
||||
@@ -1015,7 +1037,11 @@ main() {
|
||||
|
||||
run_make "Firmware prep" vm_new
|
||||
run_make "Firmware prep" fw_prepare
|
||||
if [[ "$LESS_MODE" -eq 0 ]]; then
|
||||
run_make "Firmware patch" "$fw_patch_target"
|
||||
else
|
||||
run_make_sudo "Firmware patch" "$fw_patch_target"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Restore phase ==="
|
||||
@@ -1026,6 +1052,8 @@ main() {
|
||||
run_make "Restore" restore RESTORE_UDID="$DEVICE_UDID" RESTORE_ECID="0x$DEVICE_ECID"
|
||||
wait_for_post_restore_reboot
|
||||
stop_boot_dfu
|
||||
|
||||
if [[ "$LESS_MODE" -eq 0 ]]; then
|
||||
echo "[*] Waiting ${POST_KILL_SETTLE_DELAY}s for cleanup before ramdisk stage..."
|
||||
sleep "$POST_KILL_SETTLE_DELAY"
|
||||
|
||||
@@ -1070,6 +1098,7 @@ main() {
|
||||
BOOT_FIFO_FD=""
|
||||
rm -f "$BOOT_FIFO" || true
|
||||
BOOT_FIFO=""
|
||||
fi
|
||||
|
||||
if [[ "$JB_MODE" -eq 1 ]]; then
|
||||
echo ""
|
||||
@@ -1084,7 +1113,11 @@ main() {
|
||||
echo "Setup completed."
|
||||
|
||||
echo "=== Boot analysis ==="
|
||||
if [[ "$LESS_MODE" -eq 0 ]]; then
|
||||
run_boot_analysis
|
||||
else
|
||||
run_make "Start VM" boot
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -24,6 +24,7 @@ public final class FirmwarePipeline {
|
||||
// MARK: - Variant
|
||||
|
||||
public enum Variant: String, Sendable {
|
||||
case less
|
||||
case regular
|
||||
case dev
|
||||
case jb
|
||||
@@ -173,7 +174,7 @@ public final class FirmwarePipeline {
|
||||
inRestoreDir: false,
|
||||
searchPatterns: ["AVPBooter*.bin"],
|
||||
patcherFactories: {
|
||||
if variant != .regular {
|
||||
if variant != .less {
|
||||
return [
|
||||
{ data, verbose in
|
||||
AVPBooterPatcher(data: data, verbose: verbose)
|
||||
@@ -191,9 +192,9 @@ public final class FirmwarePipeline {
|
||||
searchPatterns: ["Firmware/dfu/iBSS.vresearch101.RELEASE.im4p"],
|
||||
patcherFactories: {
|
||||
return switch variant {
|
||||
case .regular:
|
||||
case .less:
|
||||
[]
|
||||
case .dev:
|
||||
case .regular, .dev:
|
||||
[{ data, verbose in
|
||||
IBootPatcher(data: data, mode: .ibss, verbose: verbose)
|
||||
}]
|
||||
@@ -210,16 +211,16 @@ public final class FirmwarePipeline {
|
||||
}()
|
||||
))
|
||||
|
||||
// 3. iBEC — The automatic patching is disabled for the regular variant (you can still just place a custom component there).
|
||||
// 3. iBEC — The automatic patching is disabled for the patchless variant (you can still just place a custom component there).
|
||||
components.append(ComponentDescriptor(
|
||||
name: "iBEC",
|
||||
inRestoreDir: true,
|
||||
searchPatterns: ["Firmware/dfu/iBEC.vresearch101.RELEASE.im4p"],
|
||||
patcherFactories: {
|
||||
return switch variant {
|
||||
case .regular:
|
||||
case .less:
|
||||
[]
|
||||
case .dev, .jb:
|
||||
case .regular, .dev, .jb:
|
||||
[{ data, verbose in
|
||||
IBootPatcher(data: data, mode: .ibec, verbose: verbose)
|
||||
}]
|
||||
@@ -227,16 +228,16 @@ public final class FirmwarePipeline {
|
||||
}()
|
||||
))
|
||||
|
||||
// 4. LLB — The automatic patching is disabled for the regular variant (you can still just place a custom component there).
|
||||
// 4. LLB — The automatic patching is disabled for the patchless variant (you can still just place a custom component there).
|
||||
components.append(ComponentDescriptor(
|
||||
name: "LLB",
|
||||
inRestoreDir: true,
|
||||
searchPatterns: ["Firmware/all_flash/LLB.vresearch101.RELEASE.im4p"],
|
||||
patcherFactories: {
|
||||
return switch variant {
|
||||
case .regular:
|
||||
case .less:
|
||||
[]
|
||||
case .dev, .jb:
|
||||
case .regular, .dev, .jb:
|
||||
[{ data, verbose in
|
||||
IBootPatcher(data: data, mode: .llb, verbose: verbose)
|
||||
}]
|
||||
@@ -251,8 +252,12 @@ public final class FirmwarePipeline {
|
||||
searchPatterns: ["Firmware/txm.iphoneos.research.im4p"],
|
||||
patcherFactories: {
|
||||
return switch variant {
|
||||
case .regular:
|
||||
case .less:
|
||||
[]
|
||||
case .regular:
|
||||
[{ data, verbose in
|
||||
TXMPatcher(data: data, verbose: verbose)
|
||||
}]
|
||||
case .dev, .jb:
|
||||
[{ data, verbose in
|
||||
TXMDevPatcher(data: data, verbose: verbose)
|
||||
@@ -268,9 +273,9 @@ public final class FirmwarePipeline {
|
||||
searchPatterns: ["kernelcache.research.vphone600"],
|
||||
patcherFactories: {
|
||||
return switch variant {
|
||||
case .regular:
|
||||
case .less:
|
||||
[]
|
||||
case .dev:
|
||||
case .regular, .dev:
|
||||
[{ data, verbose in
|
||||
KernelPatcher(data: data, verbose: verbose)
|
||||
}]
|
||||
@@ -304,11 +309,11 @@ public final class FirmwarePipeline {
|
||||
searchPatterns: ["BuildManifest.plist"],
|
||||
patcherFactories: {
|
||||
return switch variant {
|
||||
case .regular:
|
||||
case .less:
|
||||
[{ data, verbose in
|
||||
CryptexFilesystemPatcher(buildManiest: data, restoreDir: try! self.findRestoreDirectory(), verbose: verbose)
|
||||
}]
|
||||
case .dev, .jb:
|
||||
case .regular, .dev, .jb:
|
||||
[]
|
||||
}
|
||||
}()
|
||||
@@ -321,11 +326,11 @@ public final class FirmwarePipeline {
|
||||
searchPatterns: ["BuildManifest.plist"],
|
||||
patcherFactories: {
|
||||
return switch variant {
|
||||
case .regular:
|
||||
case .less:
|
||||
[{ data, verbose in
|
||||
ManifestHashPatcher(data: data, restoreDir: try? self.findRestoreDirectory(), verbose: verbose)
|
||||
}]
|
||||
case .dev, .jb:
|
||||
case .regular, .dev, .jb:
|
||||
[]
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -108,12 +108,14 @@ struct VPhoneBootCLI: ParsableCommand {
|
||||
|
||||
struct PatchFirmwareCLI: ParsableCommand {
|
||||
enum VariantOption: String, CaseIterable, ExpressibleByArgument {
|
||||
case less
|
||||
case regular
|
||||
case dev
|
||||
case jb
|
||||
|
||||
var pipelineVariant: FirmwarePipeline.Variant {
|
||||
switch self {
|
||||
case .less: .less
|
||||
case .regular: .regular
|
||||
case .dev: .dev
|
||||
case .jb: .jb
|
||||
|
||||
Reference in New Issue
Block a user