Files
vphone-cli/AGENTS.md
2026-03-04 13:34:02 +08:00

29 KiB

vphone-cli

Virtual iPhone boot tool using Apple's Virtualization.framework with PCC research VMs.

Quick Reference

  • Build: make build
  • Boot (GUI): make boot
  • Boot (DFU): make boot_dfu
  • All targets: make help
  • Python venv: make setup_venv (installs to .venv/, activate with source .venv/bin/activate)
  • Platform: macOS 15+ (Sequoia), SIP/AMFI disabled
  • Language: Swift 6.0 (SwiftPM), private APIs via Dynamic
  • Python deps: capstone, keystone-engine, pyimg4 (see requirements.txt)

Workflow Rules

  • Always read /TODO.md before starting any substantial work.
  • Always update /TODO.md when plan, progress, assumptions, blockers, or open questions change.
  • If blocked or waiting on user input, write the exact blocker and next action in /TODO.md.
  • If not exists, continue existing work until complete. If exists, follow /TODO.md instructions.

Project Overview

CLI tool that boots virtual iPhones (PV=3) via Apple's Virtualization.framework, targeting Private Cloud Compute (PCC) research VMs. Used for iOS security research — firmware patching, boot chain modification, and runtime instrumentation.

Architecture

Makefile                          # Single entry point — run `make help`

sources/
├── vphone.entitlements               # Private API entitlements (5 keys)
└── vphone-cli/                       # Swift 6.0 executable (pure Swift, no ObjC)
    ├── main.swift                    # Entry point — NSApplication + AppDelegate
    ├── VPhoneAppDelegate.swift       # App lifecycle, SIGINT, VM start/stop
    ├── VPhoneCLI.swift               # ArgumentParser options (no execution logic)
    ├── VPhoneBuildInfo.swift         # Auto-generated build-time commit hash
    │
    │   # VM core
    ├── VPhoneVirtualMachine.swift    # @MainActor VM configuration and lifecycle
    ├── VPhoneHardwareModel.swift     # PV=3 hardware model via Dynamic
    ├── VPhoneVirtualMachineView.swift # Touch-enabled VZVirtualMachineView + helpers
    ├── VPhoneError.swift             # Error types
    │
    │   # Guest daemon client (vsock)
    ├── VPhoneControl.swift           # Host-side vsock client for vphoned (length-prefixed JSON)
    │
    │   # Window & UI
    ├── VPhoneWindowController.swift  # @MainActor VM window management + toolbar
    ├── VPhoneKeyHelper.swift         # Keyboard/hardware key event dispatch to VM
    ├── VPhoneLocationProvider.swift  # CoreLocation → guest forwarding over vsock
    │
    │   # Menu bar (extensions on VPhoneMenuController)
    ├── VPhoneMenuController.swift    # Menu bar controller (builds Keys, Type, Location, Connect)
    ├── VPhoneMenuKeys.swift          # Keys menu — home, power, volume, spotlight buttons
    ├── VPhoneMenuType.swift          # Type menu — paste ASCII text to guest
    ├── VPhoneMenuLocation.swift      # Location menu — host location sync toggle
    ├── VPhoneMenuConnect.swift       # Connect menu — devmode, ping, version, file browser
    │
    │   # File browser (SwiftUI)
    ├── VPhoneFileWindowController.swift # File browser window (NSHostingController)
    ├── VPhoneFileBrowserView.swift   # SwiftUI file browser with search + drag-drop
    ├── VPhoneFileBrowserModel.swift  # @Observable file browser state + transfers
    └── VPhoneRemoteFile.swift        # Remote file data model (path, size, permissions)

scripts/
├── vphoned/                      # Guest daemon (Objective-C, runs inside iOS VM)
│   ├── vphoned.m                 # Main — vsock listener, message dispatch, auto-update
│   ├── vphoned_protocol.{h,m}   # Length-prefixed JSON framing (shared with host)
│   ├── vphoned_hid.{h,m}        # HID event injection (IOHIDEvent)
│   ├── vphoned_devmode.{h,m}    # Developer Mode query/enable via XPC
│   ├── vphoned_location.{h,m}   # CLLocationManager spoofing
│   ├── vphoned_files.{h,m}      # File operations (list, get, put, mkdir, delete, rename)
│   ├── vphoned.plist             # LaunchDaemon plist
│   ├── entitlements.plist        # Guest entitlements
│   └── signcert.p12              # Signing certificate for re-signing
├── patchers/                     # Python patcher package
│   ├── iboot.py                  # Dynamic iBoot patcher (iBSS/iBEC/LLB)
│   ├── iboot_jb.py               # JB extension iBoot patcher (nonce skip)
│   ├── kernel.py                 # Dynamic kernel patcher (25 patches)
│   ├── kernel_jb.py              # JB extension kernel patcher (~34 patches)
│   ├── txm.py                    # Dynamic TXM patcher
│   ├── txm_jb.py                 # JB extension TXM patcher (~13 patches)
│   └── cfw.py                    # CFW binary patcher (base + JB jetsam)
├── resources/                    # Resource archives
│   ├── cfw_input.tar.zst
│   ├── cfw_jb_input.tar.zst      # JB: procursus bootstrap + Sileo
│   └── ramdisk_input.tar.zst
├── fw_prepare.sh                 # Downloads IPSWs, merges cloudOS into iPhone
├── fw_manifest.py                # Generates hybrid BuildManifest.plist & Restore.plist
├── fw_patch.py                   # Patches 6 boot-chain components (41+ modifications)
├── fw_patch_jb.py                # Runs fw_patch + JB extension patches (iBSS/TXM/kernel)
├── ramdisk_build.py              # Builds SSH ramdisk with trustcache
├── ramdisk_send.sh               # Sends ramdisk to device via irecovery
├── cfw_install.sh                # Installs custom firmware to VM disk
├── cfw_install_jb.sh             # Wrapper: cfw_install with JB phases enabled
├── vm_create.sh                  # Creates VM directory (disk, SEP storage, ROMs)
├── setup_venv.sh                 # Creates Python venv with native keystone dylib
└── setup_libimobiledevice.sh     # Builds libimobiledevice toolchain from source

research/
├── patch_comparison_all_variants.md  # Regular/Dev/JB patch comparison table
└── ...                               # Component analysis and architecture docs

Key Patterns

  • Private API access: Private Virtualization.framework APIs are called via the Dynamic library (runtime method dispatch from pure Swift). No ObjC bridge needed.
  • App lifecycle: Explicit main.swift creates NSApplication + VPhoneAppDelegate. CLI args parsed before the run loop starts. AppDelegate drives VM start, window, and shutdown.
  • Configuration: CLI options parsed via ArgumentParser, converted to VPhoneVirtualMachine.Options struct, then used to build VZVirtualMachineConfiguration.
  • Error handling: VPhoneError enum with CustomStringConvertible for user-facing messages.
  • Window management: VPhoneWindowController wraps NSWindow + VZVirtualMachineView. Window size derived from configurable screen dimensions and scale factor. Touch input translated from mouse events to multi-touch via VPhoneVirtualMachineView.
  • Guest daemon (vphoned): ObjC daemon running inside the iOS VM as a LaunchDaemon. Communicates with host over vsock port 1337 using length-prefixed JSON ([uint32 BE length][UTF-8 JSON]). Handles HID injection, developer mode, location spoofing, and file operations. Host side is VPhoneControl which auto-reconnects and supports binary auto-update on connect.
  • Control protocol: All commands use async request-response via VPhoneControl.sendRequest() with pending request tracking. Menu actions (VPhoneMenuConnect) await responses and show results as NSAlert sheets on the VM window.
  • Menu system: VPhoneMenuController owns the menu bar, built from extensions in separate files per menu (Keys, Type, Location, Connect). Each extension has its own build*Menu() method.
  • File browser: SwiftUI-based (VPhoneFileBrowserView + VPhoneFileBrowserModel) hosted in a separate NSWindow via NSHostingController. Supports search, sort, upload/download, drag-drop. File operations go through VPhoneControl async APIs.
  • Location sync: VPhoneLocationProvider wraps CLLocationManager, forwards host Mac's GPS coordinates to the guest over vsock when toggled from the Location menu.

Firmware Assembly Pipeline

The firmware is a PCC/iPhone hybrid — PCC boot infrastructure wrapping iPhone iOS userland.

Pipeline Stages

1. make fw_prepare          Download iPhone + cloudOS IPSWs, merge, generate hybrid plists
        ↓
2. make fw_patch            Patch 6 boot-chain components for signature bypass + debug
   OR  make fw_patch_jb     Base patches + JB extensions (iBSS nonce, TXM CS, kernel JB)
        ↓
3. make ramdisk_build       Build SSH ramdisk from SHSH blob, inject tools, sign with IM4M
        ↓
4. make vm_new              Create VM directory (sparse disk, SEP storage, copy ROMs)
        ↓
5. make boot_dfu            Boot VM in DFU mode
        ↓
6. make ramdisk_send        Load boot chain + ramdisk via irecovery
        ↓
7. make cfw_install         Mount Cryptex, patch userland, install base tools
   OR  make cfw_install_jb  Base CFW + JB phases (jetsam patch, procursus bootstrap)

Component Origins

The firmware merges two Apple IPSWs:

  • iPhone IPSW: iPhone17,3_26.1_23B85_Restore.ipsw (d47ap)
  • cloudOS IPSW: PCC vresearch101ap IPSW (CDN hash URL)

fw_prepare.sh extracts both, then copies cloudOS boot chain into the iPhone restore directory (kernelcache.*, Firmware/{agx,all_flash,ane,dfu,pmp}/*, Firmware/*.im4p). The cloudOS extract is deleted after merge.

Boot Chain — from PCC (cloudOS / vresearch101ap)

Component File Patched Patch Purpose
AVPBooter AVPBooter.vresearch1.bin Yes (1) DGST signature validation bypass
LLB Firmware/all_flash/LLB.vresearch101.RELEASE.im4p Yes (6) Serial + image4 bypass + boot-args + rootfs + panic
iBSS Firmware/dfu/iBSS.vresearch101.RELEASE.im4p Yes (2) Serial labels + image4 callback bypass
iBEC Firmware/dfu/iBEC.vresearch101.RELEASE.im4p Yes (3) Serial + image4 bypass + boot-args
SPTM Firmware/all_flash/sptm.vresearch1.release.im4p No
TXM Firmware/txm.iphoneos.research.im4p Yes (1) Trustcache validation bypass
SEP Firmware Firmware/all_flash/sep-firmware.vresearch101.RELEASE.im4p No
DeviceTree Firmware/all_flash/DeviceTree.vphone600ap.im4p No
KernelCache kernelcache.release.vphone600 Yes (25) APFS, MAC, debugger, launch constraints, etc.
GPU/ANE/PMP Firmware/{agx,ane,pmp}/* No

TXM filename says "iphoneos" but is copied from cloudOS IPSW (fw_prepare.sh line 81).

OS / Filesystem — from iPhone (iPhone17,3)

Component Notes
OS iPhone OS image
SystemVolume System partition
StaticTrustCache Static trust cache
Ap,SystemVolumeCanonicalMetadata System volume metadata

Cryptex1 components (SystemOS/AppOS DMGs) are not included in the BuildManifest. They are only needed by cfw_install.sh which reads paths from the original iPhone manifest separately.

Build Identity

fw_manifest.py generates a single DFU erase-install identity (20 components). The VM always boots via DFU restore, so only one identity is needed.

Variant Boot Chain Ramdisk
Darwin Cloud Customer Erase Install (IPSW) PCC RELEASE (LLB/iBSS/iBEC) + RESEARCH (iBoot/TXM) PCC erase

idevicerestore selects this identity by partial-matching Info.Variant against "Erase Install (IPSW)" while excluding "Research".

Patched Components Summary

Boot chain patches (fw_patch.py) — all 6 targets from PCC:

Component Patches Technique
AVPBooter 1 mov x0, #0 (DGST bypass)
iBSS 2 Dynamic via patchers/iboot.py (string anchors, instruction patterns)
iBEC 3 Dynamic via patchers/iboot.py (string anchors, instruction patterns)
LLB 6 Dynamic via patchers/iboot.py (string anchors, instruction patterns)
TXM 1 Dynamic via patchers/txm.py (trustcache hash lookup bypass)
KernelCache 25 Dynamic via patchers/kernel.py (string anchors, ADRP+ADD xrefs, BL frequency)

JB extension patches (fw_patch_jb.py) — runs base patches first, then adds:

Component JB Patches Technique
iBSS +1 patchers/iboot_jb.py (skip nonce generation)
TXM +13 patchers/txm_jb.py (CS validation bypass, get-task-allow, debugger ent, dev mode)
KernelCache +34 patchers/kernel_jb.py (trustcache, execve, sandbox, task/VM, kcall10)

CFW patches (patchers/cfw.py / cfw_install.sh) — targets from iPhone Cryptex SystemOS:

Binary Technique Purpose Mode
seputil String patch (/%s.gl/AA.gl) Gigalocker UUID fix Base
launchd_cache_loader NOP (disassembly-anchored) Bypass cache validation Base
mobileactivationd Return true (disassembly-anchored) Skip activation check Base
launchd.plist Plist injection Add bash/dropbear/trollvnc daemons Base
launchd Branch (skip jetsam guard) + LC_LOAD_DYLIB injection Prevent jetsam panic + load launchdhook.dylib JB

JB install phases (cfw_install_jb.shcfw_install.sh with CFW_JB_MODE=1):

Phase Action
JB-1 Patch /mnt1/sbin/launchd: inject launchdhook.dylib LC_LOAD_DYLIB + jetsam guard bypass
JB-2 Install procursus bootstrap to /mnt5/<hash>/jb-vphone/procursus
JB-3 Deploy BaseBin hooks (systemhook.dylib, launchdhook.dylib, libellekit.dylib) to /mnt1/cores/

Boot Flow

Base (fw_patch + cfw_install):

AVPBooter (ROM, PCC)
  → LLB (PCC, patched)
    → iBSS (PCC, patched, DFU)
      → iBEC (PCC, patched, DFU)
        → SPTM + TXM (PCC, TXM patched)
          → KernelCache (PCC, 25 patches)
            → Ramdisk (PCC or iPhone, SSH-injected)
              → iOS userland (iPhone, CFW-patched)

Jailbreak (fw_patch_jb + cfw_install_jb):

AVPBooter (ROM, PCC)
  → LLB (PCC, patched)
    → iBSS (PCC, patched + nonce skip)
      → iBEC (PCC, patched, DFU)
        → SPTM + TXM (PCC, TXM patched + CS/ent/devmode bypass)
          → KernelCache (PCC, 25 base + ~34 JB patches)
            → Ramdisk (SSH-injected)
              → iOS userland (CFW + jetsam fix + procursus)

Ramdisk Build (ramdisk_build.py)

  1. Extract IM4M from SHSH blob
  2. Process 8 components: iBSS, iBEC, SPTM, DeviceTree, SEP, TXM, KernelCache, Ramdisk+Trustcache
  3. For ramdisk: extract base DMG → create 254 MB APFS volume → mount → inject SSH tools from resources/ramdisk_input.tar.zst → re-sign Mach-Os with ldid + signcert.p12 → build trustcache
  4. Sign all components with IM4M manifest → output to Ramdisk/ directory as IMG4 files

CFW Installation (cfw_install.sh)

7 phases (+ 2 JB phases), safe to re-run (idempotent):

  1. Decrypt/mount Cryptex SystemOS and AppOS DMGs (ipsw + aea)
  2. Patch seputil (gigalocker UUID)
  3. Install GPU driver (AppleParavirtGPUMetalIOGPUFamily)
  4. Install iosbinpack64 (jailbreak tools)
  5. Patch launchd_cache_loader (NOP cache validation)
  6. Patch mobileactivationd (activation bypass)
  7. Install LaunchDaemons (bash, dropbear SSH, trollvnc)

JB-only phases (enabled via make cfw_install_jb or CFW_JB_MODE=1):

  • JB-1: Patch launchd jetsam guard (prevents jetsam panic on boot)
  • JB-2: Install procursus bootstrap + optional Sileo to /mnt5/<hash>/jb-vphone/

Coding Conventions

Swift

  • Language: Swift 6.0 (strict concurrency).
  • Style: Pragmatic, minimal. No unnecessary abstractions.
  • Sections: Use // MARK: - to organize code within files.
  • Access control: Default (internal). Only mark private when needed for clarity.
  • Concurrency: @MainActor for VM and UI classes. nonisolated delegate methods use MainActor.isolated {} to hop back safely.
  • Naming: Types are VPhone-prefixed (VPhoneVirtualMachine, VPhoneWindowController). Match Apple framework conventions.
  • Private APIs: Use Dynamic() for runtime method dispatch. Touch objects use NSClassFromString + KVC to avoid designated initializer crashes.
  • NSWindow isReleasedWhenClosed: Always set window.isReleasedWhenClosed = false for programmatically created windows managed by an NSWindowController. The default is true, which causes the window to be released on close while NSWindowController and _NSWindowTransformAnimation still hold references — objc_release crashes on a dangling pointer during CA transaction commit. Nib-loaded windows handled by NSWindowController get this set automatically, but programmatic windows do not.

Shell Scripts

  • Use zsh with set -euo pipefail.
  • Scripts resolve their own directory via ${0:a:h} or $(cd "$(dirname "$0")" && pwd).
  • Build uses make build which handles compilation and entitlement signing.

Python Scripts

  • Firmware patching uses capstone (disassembly), keystone-engine (assembly), and pyimg4 (IM4P handling).
  • patchers/kernel.py uses dynamic pattern finding (string anchors, ADRP+ADD xrefs, BL frequency analysis) — nothing is hardcoded to specific offsets.
  • Each patch is logged with offset and before/after state.
  • Scripts operate on a VM directory and auto-discover the *Restore* subdirectory.
  • Environment: Use the project venv (source .venv/bin/activate). Create with make setup_venv. All deps in requirements.txt: capstone, keystone-engine, pyimg4.

Build & Sign

The binary requires private entitlements to use PV=3 virtualization:

  • com.apple.private.virtualization
  • com.apple.private.virtualization.security-research
  • com.apple.security.virtualization
  • com.apple.vm.networking
  • com.apple.security.get-task-allow

Always use make build — never swift build alone, as the unsigned binary will fail at runtime.

VM Creation (make vm_new)

Creates a VM directory with:

  • Sparse disk image (default 64 GB)
  • SEP storage (512 KB flat file)
  • AVPBooter + AVPSEPBooter ROMs (copied from /System/Library/Frameworks/Virtualization.framework/)
  • machineIdentifier (created on first boot if missing, persisted for stable ECID)
  • NVRAM (created/overwritten each boot)

All paths are passed explicitly via CLI (--rom, --disk, --nvram, --machine-id, --sep-storage, --sep-rom). SEP coprocessor is always enabled.

Display is configurable via --screen-width, --screen-height, --screen-ppi, --screen-scale (defaults: 1290x2796 @ 460 PPI, scale 3.0).

Override defaults: make vm_new VM_DIR=myvm DISK_SIZE=32.

Design System

Intent

Who: Security researchers working with Apple firmware and virtual devices. Technical, patient, comfortable in terminals. Likely running alongside GDB, serial consoles, and SSH sessions.

Task: Boot, configure, and interact with virtual iPhones for firmware research. Monitor boot state, capture serial output, debug at the firmware level.

Feel: Like a research instrument. Precise, informative, honest about internal state. No decoration — every pixel earns its place.

Palette

  • Background: Dark neutral (#1a1a1a — near-black, low blue to reduce eye strain during long sessions)
  • Surface: #242424 (elevated panels), #2e2e2e (interactive elements)
  • Text primary: #e0e0e0 (high contrast without being pure white)
  • Text secondary: #888888 (labels, metadata)
  • Accent — status green: #4ade80 (VM running, boot success)
  • Accent — amber: #fbbf24 (DFU mode, warnings, in-progress states)
  • Accent — red: #f87171 (errors, VM stopped with error)
  • Accent — blue: #60a5fa (informational, links, interactive highlights)

Rationale: Dark surfaces match the terminal-adjacent workflow. Status colors borrow from oscilloscope/JTAG tooling — green for good, amber for attention, red for fault. No brand colors — this is a tool, not a product.

Typography

  • UI font: System monospace (SF Mono / Menlo). Everything in this tool is technical — monospace respects the content.
  • Headings: System sans (SF Pro) semibold, used sparingly for section labels only.
  • Serial/log output: Monospace, #e0e0e0 on dark background. No syntax highlighting — raw output, exactly as received.

Depth

  • Approach: Flat with subtle 1px borders (#333333). No shadows, no blur. Depth through color difference only.
  • Rationale: Shadows suggest consumer software. Borders suggest instrument panels. This is an instrument.

Spacing

  • Base unit: 8px
  • Component padding: 12px (1.5 units)
  • Section gaps: 16px (2 units)
  • Window margins: 16px

Components

  • Status indicator: Small circle (8px) with color fill + label. No animation — state changes are instantaneous.
  • VM display: Full-bleed within its container. No rounded corners on the display itself.
  • Log output: Scrolling monospace region, bottom-anchored (newest at bottom). No line numbers unless requested.
  • Toolbar (if present): Icon-only, 32px touch targets, subtle hover state (#2e2e2e -> #3a3a3a).

JB Kernel Patcher Status (patches-jb branch)

Branch is 8 commits ahead of main. All changes are additive — non-JB code paths are unaffected.

Diff vs Main

File Change Impact on non-JB
kernel.py +1 line: self.patches = [] reset in find_all() None (harmless init)
cfw.py +patch-launchd-jetsam, +inject-dylib commands None (new commands only)
kernel_jb.py New file — 2128 lines N/A
txm_jb.py New file — 335 lines N/A
iboot_jb.py New file — 105 lines N/A
fw_patch_jb.py New file — 115 lines (WIP) N/A
cfw_install_jb.sh New file — 214 lines N/A
cfw_jb_input.tar.zst New file — JB resources N/A
Makefile +JB targets (fw_patch_jb, cfw_install_jb) None (additive)
AGENTS.md Documentation updates N/A

Patch Counts

Base patcher (kernel.py): 25 patches — verified identical to main.

JB patcher (kernel_jb.py): 160 patches from 22 methods:

  • 19 of 22 PASSING — Groups A (sandbox hooks, AMFI, execve), B (string-anchored), C (shellcode)
  • 3 FAILING — see below

3 Remaining Failures

Patch Upstream Offset Root Cause Proposed Strategy
patch_nvram_verify_permission NOP BL at 0x1234034 332 identical IOKit methods match structural filter; "krn." string leads to wrong function Find via "IONVRAMController" string → metaclass ctor → PAC disc #0xcda1 → search __DATA_CONST vtable entries (first entry after 3 nulls) with matching PAC disc + BL to memmove
patch_thid_should_crash Zero 0x67EB50 String in __PRELINK_INFO plist (no code refs); value already 0x00000000 in PCC kernel Safe to return True (no-op); or find via sysctl_oid struct search in __DATA
patch_hook_cred_label_update_execve Shellcode at 0xAB17D8 + ops table at 0xA54518 Needs _vfs_context_current (0xCC5EAC) and _vnode_getattr (0xCC91C0) — 0 symbols available Find via sandbox ops table → original hook func → BL targets by caller count (vfs_context_current = highest, vnode_getattr = near mov wN, #0x380)

Key Findings (from research/kernel_jb_patch_notes.md)

All offsets in kernel.py are file offsetsbl_callers dict, _is_bl(), _disas_at(), find_string_refs() all use file offsets, not VAs.

IONVRAMController vtable discovery chain:

"IONVRAMController" string @ 0xA2FEB
  → ADRP+ADD refs → metaclass ctor @ 0x125D2C0
    → PAC discriminator: movk x17, #0xcda1, lsl #48
    → instance size: mov w3, #0x88
  → class vtable in __DATA_CONST @ 0x7410B8 (preceded by 3 null entries)
    → vtable[0] = 0x1233E40 = verifyPermission
      → BL to memmove (3114 callers) at +0x1F4 = 0x1234034 ← NOP this

vfs_context_current / vnode_getattr resolution:

sandbox ops table → entry[16] = original hook @ 0x239A0B4
  → disassemble hook → find BL targets:
    - _vfs_context_current: BL target with >1000 callers, short function
    - _vnode_getattr: BL target near "mov wN, #0x380", moderate callers

Upstream Reference Offsets (iPhone17,3 26.1)

Symbol File Offset Notes
kern_text 0xA740000x24B0000
base_va 0xFFFFFE0007004000
verifyPermission func 0x1233E40 vtable @ 0x7410B8
verifyPermission patch 0x1234034 NOP BL to memmove
_thid_should_crash var 0x67EB50 already 0
_vfs_context_current 0xCC5EAC from BL encoding
_vnode_getattr 0xCC91C0 from BL encoding
hook_cred_label orig 0x239A0B4 from B encoding
sandbox ops entry 0xA54518 index 16
OSMetaClass::OSMetaClass() 0x10EA790 5236 callers
memmove 0x12CB0D0 3114 callers