mirror of
https://github.com/Lakr233/vphone-cli.git
synced 2026-04-05 13:09:06 +08:00
122 lines
4.0 KiB
Markdown
122 lines
4.0 KiB
Markdown
# Developer Mode via AMFI XPC
|
|
|
|
How iOS developer mode is enabled programmatically, based on TrollStore's implementation.
|
|
|
|
## XPC Service
|
|
|
|
**Mach service:** `com.apple.amfi.xpc`
|
|
|
|
AMFI (Apple Mobile File Integrity) daemon exposes an XPC endpoint for developer mode control on iOS 16+.
|
|
|
|
## Required Entitlement
|
|
|
|
```
|
|
com.apple.private.amfi.developer-mode-control = true
|
|
```
|
|
|
|
Without this entitlement the XPC connection to amfid is rejected.
|
|
|
|
## Message Protocol
|
|
|
|
Messages are serialized using private CoreFoundation-XPC bridge functions:
|
|
|
|
```objc
|
|
extern xpc_object_t _CFXPCCreateXPCMessageWithCFObject(CFTypeRef obj);
|
|
extern CFTypeRef _CFXPCCreateCFObjectFromXPCMessage(xpc_object_t obj);
|
|
```
|
|
|
|
### Request
|
|
|
|
NSDictionary with a single key:
|
|
|
|
```objc
|
|
@{@"action": @(action)}
|
|
```
|
|
|
|
### Actions
|
|
|
|
| Action | Value | Behavior |
|
|
| -------------------- | ----- | ---------------------------------------------------------------------------- |
|
|
| `kAMFIActionArm` | 0 | Arm developer mode — takes effect on next reboot, user must select "Turn On" |
|
|
| `kAMFIActionDisable` | 1 | Disable developer mode immediately |
|
|
| `kAMFIActionStatus` | 2 | Query current state |
|
|
|
|
### Response
|
|
|
|
XPC reply dict contains a `"cfreply"` key holding the CF-serialized response:
|
|
|
|
```objc
|
|
xpc_object_t cfReply = xpc_dictionary_get_value(reply, "cfreply");
|
|
NSDictionary *dict = _CFXPCCreateCFObjectFromXPCMessage(cfReply);
|
|
```
|
|
|
|
Response fields:
|
|
|
|
| Key | Type | Description |
|
|
| --------- | -------- | ------------------------------------------------ |
|
|
| `success` | BOOL | Whether the XPC call succeeded |
|
|
| `status` | BOOL | Current developer mode state (for Status action) |
|
|
| `armed` | BOOL | Whether armed for reboot (for Arm action) |
|
|
| `error` | NSString | Error description if success is false |
|
|
|
|
## Arming Flow
|
|
|
|
1. Query status (`kAMFIActionStatus`)
|
|
2. If already enabled, done
|
|
3. Send arm (`kAMFIActionArm`)
|
|
4. Device must reboot; user selects "Turn On" in the prompt
|
|
5. Developer mode is now active
|
|
|
|
Arming does **not** enable developer mode immediately. It sets a flag that triggers the enable prompt on the next reboot. Disabling (`kAMFIActionDisable`) takes effect immediately.
|
|
|
|
## TrollStore Reference
|
|
|
|
Source: `references/TrollStore/RootHelper/devmode.m`
|
|
|
|
TrollStore separates privileges: the main app has no AMFI entitlement; all privileged operations go through RootHelper which has `com.apple.private.amfi.developer-mode-control`.
|
|
|
|
Key functions:
|
|
|
|
- `checkDeveloperMode()` — returns current state, YES on iOS <16 (devmode doesn't exist)
|
|
- `armDeveloperMode(BOOL *alreadyEnabled)` — check + arm in one call
|
|
- `startConnection()` — creates and resumes XPC connection to `com.apple.amfi.xpc`
|
|
- `sendXPCRequest()` — CF dict → XPC message → sync reply → CF dict
|
|
|
|
## vphoned Implementation
|
|
|
|
Added as `devmode` capability in vphoned guest agent:
|
|
|
|
### Protocol Messages
|
|
|
|
**Status query:**
|
|
|
|
```json
|
|
{"t": "devmode", "action": "status"}
|
|
→ {"t": "ok", "enabled": true}
|
|
```
|
|
|
|
**Enable (arm):**
|
|
|
|
```json
|
|
{"t": "devmode", "action": "enable"}
|
|
→ {"t": "ok", "already_enabled": false, "msg": "developer mode armed, reboot to activate"}
|
|
```
|
|
|
|
### Entitlements
|
|
|
|
Added to `scripts/vphoned/entitlements.plist`:
|
|
|
|
```xml
|
|
<key>com.apple.private.amfi.developer-mode-control</key>
|
|
<true/>
|
|
```
|
|
|
|
### Host-Side API (VPhoneControl.swift)
|
|
|
|
```swift
|
|
let status = try await control.sendDevModeStatus() // -> DevModeStatus (enabled: Bool)
|
|
let result = try await control.sendDevModeEnable() // -> DevModeEnableResult (alreadyEnabled: Bool, message: String)
|
|
```
|
|
|
|
Both methods use `sendRequest()` with pending request tracking — the response is returned via `async throws`, not logged to console. Callers (e.g. `VPhoneMenuConnect`) display results as `NSAlert` sheets on the VM window.
|