mirror of
https://github.com/Lakr233/vphone-cli.git
synced 2026-04-05 13:09:06 +08:00
Old approach patched vnode-type assertion BLs (CBZ→panic). New approach scans backward from function end for the shared MOV W0,#1 kill return before the LDP x29,x30 epilogue and changes it to MOV W0,#0. Single instruction converts all 5+ kill paths to success. Boot-tested OK.
3.5 KiB
3.5 KiB
A2 patch_amfi_execve_kill_path
1) How the Patch Is Applied
- Source implementation:
scripts/patchers/kernel_jb_patch_amfi_execve.py - Match strategy:
- String anchor:
"AMFI: hook..execve() killing"(fallback:"execve() killing"). - Find function containing the string reference.
- Scan backward from function end for
MOV W0, #1(0x52800020) immediately followed byLDP x29, x30, [sp, #imm](epilogue start).
- String anchor:
- Rewrite: replace
MOV W0, #1withMOV W0, #0— converts kill return to allow.
2) Expected Behavior
- All kill paths in the AMFI execve hook converge on a shared
MOV W0, #1before the function epilogue. Changing this single instruction toMOV W0, #0converts every kill path to a success return:- "completely unsigned code" → allowed
- Restricted Execution Mode violations → allowed
- "Legacy VPN Plugin" → allowed
- "dyld signature cannot be verified" → allowed
- Generic
%skill message → allowed
3) Target
- Target function:
sub_FFFFFE000863FC6C(AMFIhook..execve()handler)- Located in
com.apple.driver.AppleMobileFileIntegrity:__text
- Located in
- Target instruction:
MOV W0, #1at0xFFFFFE00086400FC(shared kill return)- Followed by LDP x29,x30 → epilogue → RETAB
4) IDA MCP Binary Evidence
Function structure
- Prologue: PACIBSP + SUB SP + STP register saves
- Assertions (NOT patched): Two vnode type checks at early offsets:
BL sub_0x7CCC40C(checks*(vnode+113) == 1i.e. regular file)BL sub_0x7CCC41C(checks*(vnode+113) == 2i.e. directory)- These branch to assertion panic handlers on failure
- Kill paths: 5+ conditional branches to
B loc_FFFFFE00086400F8(print + kill):0xFE000863FD1C: unsigned code path → B directly to0x86400FC0xFE000863FE00: restricted exec mode = 2 → B0x86400F80xFE000863FE4C: restricted exec mode = 4 → B0x86400F80xFE000863FEBC: Legacy VPN Plugin → B0x86400F80xFE000863FF38: restricted exec mode = 3 → B0x86400F8
- Shared kill epilogue at
0xFE00086400F8:0x86400F8: BL sub_81A1134 ; printf the kill message 0x86400FC: MOV W0, #1 ; ← PATCH TARGET (kill return value) 0x8640100: LDP X29, X30, [SP,#0x80] ... 0x864011C: RETAB
String hits
0xFE00071F71C2: "AMFI: hook..execve() killing %s (pid %u): Attempt to execute completely unsigned code..."0xFE00071F73B8: "...Attempt to execute a Legacy VPN Plugin."0xFE00071F740B: "...dyld signature cannot be verified..."0xFE00071F74DF: "AMFI: hook..execve() killing %s (pid %u): %s\n"
5) Previous Bug (PANIC root cause)
The original implementation searched for BL + CBZ/CBNZ w0 patterns in the
first 0x120 bytes and found the vnode-type assertion BLs:
BL sub_0x7CCC40C+CBZ W0→ checks if vnode is a regular fileBL sub_0x7CCC41C+CBNZ W0→ checks if vnode is a directory
Replacing the first BL with MOV X0, #0 made W0=0, triggering CBZ W0 →
jumped to BL sub_FFFFFE000865A5C4 (assertion panic handler) → kernel panic.
These are precondition assertions, not AMFI kill checks. The actual kill
logic is deeper in the function and uses return 1 via the shared epilogue.
6) Fix Applied
- Replaced the BL+CBZ/CBNZ pattern matching with backward epilogue scan.
- Single-instruction patch:
MOV W0, #1→MOV W0, #0at the shared kill return. - All kill paths now return 0 (allow) instead of 1 (kill).
- Assertion checks remain untouched (they pass naturally for valid executables).