mirror of
https://github.com/Lakr233/vphone-cli.git
synced 2026-09-02 02:34:29 +00:00
patcher: Adapt AVPBooter and IBoot to match macOS 27 beta 3+
* fix AVPBooter DGST patch: restrict search to movz/movk instructions The DGST constant search matched any instruction string containing "0x4447", including branch targets like `bl #0x4447c`. On macOS 27 beta 3+ firmware, such a branch appeared before the real DGST movk, causing a false match and subsequent "x0 setter not found" failure. Restrict the search to movz/movk/mov mnemonics only, which are the actual constant-loading instructions. Fixes #373 * fix iBSS JB nonce patch: use tolerance-based ADRP+ADD search findRefsToOffset required exact match between ADRP+ADD computed address and the "boot-nonce" string file offset. On macOS 27 beta 3 firmware, code references a structure header 2 bytes before the string, causing the exact match to fail. Add findRefsNear() which allows up to 16 bytes of negative delta, matching references to the containing structure rather than the string itself. This makes the patch resilient to minor layout changes across firmware versions.
This commit is contained in:
@@ -74,9 +74,13 @@ public final class AVPBooterPatcher: Patcher {
|
||||
throw PatcherError.invalidFormat("AVPBooter: disassembly produced no instructions")
|
||||
}
|
||||
|
||||
// Step 1 — locate the first instruction that references the DGST constant.
|
||||
// Step 1 — locate the first movz/movk instruction that loads the DGST constant.
|
||||
// Only match immediate-loading mnemonics to avoid false positives from branch
|
||||
// targets whose address happens to contain "4447" (e.g. `bl #0x4447c`).
|
||||
guard let hitIdx = insns.firstIndex(where: { insn in
|
||||
"\(insn.mnemonic) \(insn.operandString)".contains(Self.dgstSearch)
|
||||
let mn = insn.mnemonic
|
||||
guard mn == "movz" || mn == "movk" || mn == "mov" else { return false }
|
||||
return insn.operandString.contains(Self.dgstSearch)
|
||||
}) else {
|
||||
throw PatcherError.patchSiteNotFound("AVPBooter DGST: constant 0x4447 not found in binary")
|
||||
}
|
||||
|
||||
@@ -32,9 +32,11 @@ public final class IBootJBPatcher: IBootPatcher {
|
||||
}
|
||||
|
||||
// Collect all ADRP+ADD sites that reference any "boot-nonce" occurrence.
|
||||
// Allow a small negative delta (up to 16 bytes before the string) because
|
||||
// code may reference the containing structure rather than the string itself.
|
||||
var addOffsets: [Int] = []
|
||||
for strOff in stringOffsets {
|
||||
let refs = findRefsToOffset(strOff)
|
||||
let refs = findRefsNear(strOff, tolerance: 16)
|
||||
for (_, addOff) in refs {
|
||||
addOffsets.append(addOff)
|
||||
}
|
||||
@@ -136,6 +138,55 @@ public final class IBootJBPatcher: IBootPatcher {
|
||||
|
||||
// MARK: - Reference Search Helpers
|
||||
|
||||
/// Find all ADRP+ADD pairs that point within `tolerance` bytes before `targetOff`.
|
||||
///
|
||||
/// This handles the common case where code references a structure header
|
||||
/// a few bytes before the actual string (e.g. a length-prefixed property).
|
||||
private func findRefsNear(_ targetOff: Int, tolerance: Int) -> [(adrpOff: Int, addOff: Int)] {
|
||||
let data = buffer.data
|
||||
let size = buffer.count
|
||||
var refs: [(Int, Int)] = []
|
||||
|
||||
var off = 0
|
||||
while off + 8 <= size {
|
||||
guard
|
||||
let a = disasm.disassembleOne(in: data, at: off),
|
||||
let b = disasm.disassembleOne(in: data, at: off + 4)
|
||||
else {
|
||||
off += 4
|
||||
continue
|
||||
}
|
||||
|
||||
guard
|
||||
a.mnemonic == "adrp",
|
||||
b.mnemonic == "add",
|
||||
let detA = a.aarch64,
|
||||
let detB = b.aarch64,
|
||||
detA.operands.count >= 2,
|
||||
detB.operands.count >= 3,
|
||||
detA.operands[0].reg.rawValue == detB.operands[1].reg.rawValue,
|
||||
detA.operands[1].type == AARCH64_OP_IMM,
|
||||
detB.operands[2].type == AARCH64_OP_IMM
|
||||
else {
|
||||
off += 4
|
||||
continue
|
||||
}
|
||||
|
||||
let pageAddr = detA.operands[1].imm
|
||||
let addImm = detB.operands[2].imm
|
||||
let computed = Int(pageAddr + addImm)
|
||||
let delta = targetOff - computed
|
||||
|
||||
if delta >= 0, delta <= tolerance {
|
||||
refs.append((off, off + 4))
|
||||
}
|
||||
|
||||
off += 4
|
||||
}
|
||||
|
||||
return refs
|
||||
}
|
||||
|
||||
/// Find all ADRP+ADD pairs in the binary that point to `targetOff`.
|
||||
///
|
||||
/// Scans the entire buffer in 4-byte steps, checking consecutive instruction
|
||||
|
||||
Reference in New Issue
Block a user