mirror of
https://github.com/StikDebug/StikDebug.git
synced 2026-10-16 04:20:30 +00:00
Merge branch '0-Blu:main' into main
This commit is contained in:
commit
2e00f754d1
17 changed files with 383 additions and 327 deletions
|
|
@ -49,9 +49,22 @@
|
|||
DC6F1D522D94EADF0071B2B6 /* StikJITUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StikJITUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||
1775D3612D9644FD00DFA8E0 /* Exceptions for "StikJIT" folder in "StikJIT" target */ = {
|
||||
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||
membershipExceptions = (
|
||||
Info.plist,
|
||||
);
|
||||
target = DC6F1D362D94EADD0071B2B6 /* StikJIT */;
|
||||
};
|
||||
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||
|
||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||
DC6F1D392D94EADD0071B2B6 /* StikJIT */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
exceptions = (
|
||||
1775D3612D9644FD00DFA8E0 /* Exceptions for "StikJIT" folder in "StikJIT" target */,
|
||||
);
|
||||
path = StikJIT;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
|
@ -429,6 +442,7 @@
|
|||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = StikJIT/Info.plist;
|
||||
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
|
||||
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
|
||||
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
|
||||
|
|
@ -439,6 +453,7 @@
|
|||
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
INFOPLIST_KEY_UISupportsDocumentBrowser = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
|
||||
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
||||
|
|
@ -475,6 +490,7 @@
|
|||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = StikJIT/Info.plist;
|
||||
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
|
||||
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
|
||||
"INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES;
|
||||
|
|
@ -485,6 +501,7 @@
|
|||
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
INFOPLIST_KEY_UISupportsDocumentBrowser = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
|
||||
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
||||
|
|
|
|||
19
StikJIT/Info.plist
Normal file
19
StikJIT/Info.plist
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>com.stik.StikJIT.enableJIT</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>stikjit</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -2,7 +2,5 @@
|
|||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||
//
|
||||
|
||||
#include "idevice.h"
|
||||
#include "heartbeat.h"
|
||||
#include "jit.h"
|
||||
#include "applist.h"
|
||||
#include "idevice/JITEnableContext.h"
|
||||
#include "idevice/idevice.h"
|
||||
|
|
|
|||
|
|
@ -106,8 +106,7 @@ struct HeartbeatApp: App {
|
|||
|
||||
func startHeartbeatInBackground() {
|
||||
let heartBeat = Thread {
|
||||
let cCompletionHandler: @convention(block) (Int32, UnsafePointer<CChar>?) -> Void = { result, messagePointer in
|
||||
let message: String? = messagePointer != nil ? String(cString: messagePointer!) : nil
|
||||
let completionHandler: @convention(block) (Int32, String?) -> Void = { result, message in
|
||||
|
||||
if result == 0 {
|
||||
print("Heartbeat started successfully: \(message ?? "")")
|
||||
|
|
@ -122,7 +121,7 @@ struct HeartbeatApp: App {
|
|||
}
|
||||
}
|
||||
|
||||
startHeartbeat(cCompletionHandler)
|
||||
JITEnableContext.shared().startHeartbeat(completionHandler: completionHandler, logger: nil)
|
||||
}
|
||||
|
||||
heartBeat.qualityOfService = .background
|
||||
|
|
@ -135,8 +134,7 @@ struct HeartbeatApp: App {
|
|||
|
||||
func startHeartbeatInBackground() {
|
||||
let heartBeat = Thread {
|
||||
let cCompletionHandler: @convention(block) (Int32, UnsafePointer<CChar>?) -> Void = { result, messagePointer in
|
||||
let message: String? = messagePointer != nil ? String(cString: messagePointer!) : nil
|
||||
let completionHandler: @convention(block) (Int32, String?) -> Void = { result, message in
|
||||
|
||||
if result == 0 {
|
||||
print("Heartbeat started successfully: \(message ?? "")")
|
||||
|
|
@ -149,7 +147,7 @@ func startHeartbeatInBackground() {
|
|||
}
|
||||
}
|
||||
|
||||
startHeartbeat(cCompletionHandler)
|
||||
JITEnableContext.shared().startHeartbeat(completionHandler: completionHandler, logger: nil)
|
||||
}
|
||||
|
||||
heartBeat.qualityOfService = .background
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ struct HomeView: View {
|
|||
@State private var pairingFileIsValid = false
|
||||
@State private var isImportingFile = false
|
||||
@State private var importProgress: Float = 0.0
|
||||
|
||||
@State private var viewDidAppeared = false
|
||||
@State private var pendingBundleIdToEnableJIT : String? = nil
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
|
|
@ -209,8 +212,33 @@ struct HomeView: View {
|
|||
startJITInBackground(with: selectedBundle)
|
||||
}
|
||||
}
|
||||
.onOpenURL { url in
|
||||
print(url.path())
|
||||
if url.host() != "enable-jit" {
|
||||
return
|
||||
}
|
||||
|
||||
let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
|
||||
if let bundleId = components?.queryItems?.first(where: { $0.name == "bundle-id" })?.value {
|
||||
if viewDidAppeared {
|
||||
startJITInBackground(with: bundleId)
|
||||
} else {
|
||||
pendingBundleIdToEnableJIT = bundleId
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.onAppear() {
|
||||
viewDidAppeared = true
|
||||
if let pendingBundleIdToEnableJIT {
|
||||
startJITInBackground(with: pendingBundleIdToEnableJIT)
|
||||
self.pendingBundleIdToEnableJIT = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private func checkPairingFileExists() {
|
||||
pairingFileExists = FileManager.default.fileExists(atPath: URL.documentsDirectory.appendingPathComponent("pairingFile.plist").path)
|
||||
}
|
||||
|
|
@ -222,14 +250,9 @@ struct HomeView: View {
|
|||
private func startJITInBackground(with bundleID: String) {
|
||||
isProcessing = true
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
guard let cBundleID = strdup(bundleID) else {
|
||||
DispatchQueue.main.async { isProcessing = false }
|
||||
return
|
||||
}
|
||||
|
||||
_ = debug_app(cBundleID)
|
||||
JITEnableContext.shared().debugApp(withBundleID: bundleID, logger: nil)
|
||||
|
||||
free(cBundleID)
|
||||
DispatchQueue.main.async {
|
||||
isProcessing = false
|
||||
}
|
||||
|
|
@ -245,38 +268,13 @@ class InstalledAppsViewModel: ObservableObject {
|
|||
}
|
||||
|
||||
func loadApps() {
|
||||
guard let rawPointer = list_installed_apps() else {
|
||||
self.apps = [:]
|
||||
return
|
||||
}
|
||||
|
||||
let output = String(cString: rawPointer)
|
||||
free(rawPointer)
|
||||
|
||||
guard let jsonData = output.data(using: .utf8) else {
|
||||
print("Error: Failed to convert string to data")
|
||||
self.apps = [:]
|
||||
return
|
||||
}
|
||||
|
||||
print(output)
|
||||
|
||||
// Decode the JSON into a Swift dictionary
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let apps = try decoder.decode([String: String].self, from: jsonData)
|
||||
if let app = apps.first, app.key == "error" {
|
||||
self.apps = [:]
|
||||
} else {
|
||||
self.apps = apps
|
||||
}
|
||||
return
|
||||
self.apps = try JITEnableContext.shared().getAppList()
|
||||
} catch {
|
||||
print("Error: Failed to decode JSON - \(error)")
|
||||
print(error)
|
||||
self.apps = [:]
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ struct InstalledAppsListView: View {
|
|||
NavigationView {
|
||||
ScrollView {
|
||||
LazyVStack(spacing: 0) {
|
||||
ForEach(viewModel.apps.sorted(by: { $0.key < $1.key }), id: \.key) { appName, bundleID in
|
||||
ForEach(viewModel.apps.sorted(by: { $0.key < $1.key }), id: \.key) { bundleID, appName in
|
||||
Button(action: {
|
||||
withAnimation(.spring(response: 0.3, dampingFraction: 0.7)) {
|
||||
onSelectApp(bundleID)
|
||||
|
|
|
|||
|
|
@ -161,6 +161,9 @@ struct SettingsView: View {
|
|||
Text("HugeBlack")
|
||||
.foregroundColor(.primaryText)
|
||||
}
|
||||
}
|
||||
Text("HugeBlack")
|
||||
.foregroundColor(.primaryText)
|
||||
}
|
||||
.listRowBackground(Color.cardBackground)
|
||||
|
||||
|
|
|
|||
20
StikJIT/idevice/JITEnableContext.h
Normal file
20
StikJIT/idevice/JITEnableContext.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// JITEnableContext.h
|
||||
// StikJIT
|
||||
//
|
||||
// Created by s s on 2025/3/28.
|
||||
//
|
||||
@import Foundation;
|
||||
#include "idevice.h"
|
||||
|
||||
typedef void (^HeartbeatCompletionHandler)(int result, NSString *message);
|
||||
typedef void (^LogFuncC)(const char* message, ...);
|
||||
typedef void (^LogFunc)(NSString *message);
|
||||
|
||||
@interface JITEnableContext : NSObject
|
||||
+ (instancetype)shared;
|
||||
- (IdevicePairingFile*)getPairingFileWithError:(NSError**)error;
|
||||
- (void)startHeartbeatWithCompletionHandler:(HeartbeatCompletionHandler)completionHandler logger:(LogFunc)logger;
|
||||
- (void)debugAppWithBundleID:(NSString*)bundleID logger:(LogFunc)logger;
|
||||
- (NSDictionary<NSString*, NSString*>*)getAppListWithError:(NSError**)error;
|
||||
@end
|
||||
125
StikJIT/idevice/JITEnableContext.m
Normal file
125
StikJIT/idevice/JITEnableContext.m
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
//
|
||||
// JITEnableContext.m
|
||||
// StikJIT
|
||||
//
|
||||
// Created by s s on 2025/3/28.
|
||||
//
|
||||
#include "idevice.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "heartbeat.h"
|
||||
#include "jit.h"
|
||||
#include "applist.h"
|
||||
|
||||
#include "JITEnableContext.h"
|
||||
|
||||
JITEnableContext* sharedJITContext = nil;
|
||||
|
||||
@implementation JITEnableContext {
|
||||
int heartbeatSessionId;
|
||||
TcpProviderHandle* provider;
|
||||
}
|
||||
|
||||
+ (instancetype)shared {
|
||||
if(!sharedJITContext) {
|
||||
sharedJITContext = [[JITEnableContext alloc] init];
|
||||
}
|
||||
return sharedJITContext;
|
||||
}
|
||||
|
||||
- (NSError*)errorWithStr:(NSString*)str code:(int)code {
|
||||
return [NSError errorWithDomain:@"StikJIT" code:code userInfo:@{NSLocalizedDescriptionKey: str}];
|
||||
}
|
||||
|
||||
- (LogFuncC)createCLogger:(LogFunc)logger {
|
||||
return ^(const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
NSString* formatStr = [NSString stringWithCString:format encoding:NSASCIIStringEncoding];
|
||||
|
||||
NSString *message = [[NSString alloc] initWithFormat:formatStr arguments:args];
|
||||
NSLog(@"%@", message);
|
||||
|
||||
if(logger) {
|
||||
logger(message);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
};
|
||||
}
|
||||
|
||||
- (IdevicePairingFile*)getPairingFileWithError:(NSError**)error {
|
||||
NSFileManager* fm = [NSFileManager defaultManager];
|
||||
NSURL* docPathUrl = [fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject;
|
||||
NSURL* pairingFileURL = [docPathUrl URLByAppendingPathComponent:@"pairingFile.plist"];
|
||||
if(![fm fileExistsAtPath:pairingFileURL.path]) {
|
||||
NSLog(@"Pairing file not found!");
|
||||
*error = [self errorWithStr:@"Pairing file not found!" code:-17];
|
||||
return false;
|
||||
}
|
||||
|
||||
IdevicePairingFile* pairingFile = NULL;
|
||||
IdeviceErrorCode err = idevice_pairing_file_read(pairingFileURL.fileSystemRepresentation, &pairingFile);
|
||||
if (err != IdeviceSuccess) {
|
||||
*error = [self errorWithStr:@"Failed to read pairing file!" code:err];
|
||||
return nil;
|
||||
}
|
||||
return pairingFile;
|
||||
}
|
||||
|
||||
- (void)startHeartbeatWithCompletionHandler:(HeartbeatCompletionHandler)completionHandler logger:(LogFunc)logger {
|
||||
NSError* err = nil;
|
||||
IdevicePairingFile* pairingFile = [self getPairingFileWithError:&err];
|
||||
if(err) {
|
||||
if(logger) {
|
||||
logger(err.localizedDescription);
|
||||
}
|
||||
|
||||
completionHandler(-17, err.localizedDescription);
|
||||
return;
|
||||
}
|
||||
self->heartbeatSessionId = arc4random();
|
||||
startHeartbeat(pairingFile, &(self->provider), &(self->heartbeatSessionId), ^(int result, const char *message) {
|
||||
completionHandler(result,[NSString stringWithCString:message encoding:NSASCIIStringEncoding]);
|
||||
}, [self createCLogger:logger]);
|
||||
}
|
||||
- (void)debugAppWithBundleID:(NSString*)bundleID logger:(LogFunc)logger {
|
||||
if(!provider) {
|
||||
if(logger) {
|
||||
logger(@"Provider not initialized!");
|
||||
}
|
||||
NSLog(@"Provider not initialized!");
|
||||
return;
|
||||
}
|
||||
|
||||
debug_app(provider, [bundleID UTF8String], [self createCLogger:logger]);
|
||||
}
|
||||
|
||||
|
||||
// apps may have different name, so we must use BnudleId as key. [bundleId:name]
|
||||
- (NSDictionary<NSString*, NSString*>*)getAppListWithError:(NSError**)error {
|
||||
if(!provider) {
|
||||
NSLog(@"Provider not initialized!");
|
||||
*error = [self errorWithStr:@"Provider not initialized!" code:-1];
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString* errorStr = nil;
|
||||
NSDictionary<NSString*, NSString*>* ans = list_installed_apps(provider, &errorStr);
|
||||
if(errorStr){
|
||||
*error = [self errorWithStr:errorStr code:-17];
|
||||
return nil;
|
||||
} else {
|
||||
return ans;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
self->heartbeatSessionId = arc4random();
|
||||
if(provider) {
|
||||
tcp_provider_free(provider);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
//
|
||||
// applist.c
|
||||
// StikJIT
|
||||
//
|
||||
// Created by Stephen on 3/27/25.
|
||||
//
|
||||
|
||||
#include "idevice.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <limits.h>
|
||||
|
||||
char *list_installed_apps() {
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(LOCKDOWN_PORT);
|
||||
if (inet_pton(AF_INET, "10.7.0.1", &addr.sin_addr) <= 0) {
|
||||
return strdup("{\"error\": \"Invalid IP address\"}");
|
||||
}
|
||||
|
||||
char pairingFilePath[1024];
|
||||
CFURLRef url = CFCopyHomeDirectoryURL();
|
||||
if (url) {
|
||||
CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
|
||||
if (path) {
|
||||
CFStringGetCString(path, pairingFilePath, sizeof(pairingFilePath), kCFStringEncodingUTF8);
|
||||
strncat(pairingFilePath, "/Documents/pairingFile.plist", sizeof(pairingFilePath) - strlen(pairingFilePath) - 1);
|
||||
CFRelease(path);
|
||||
}
|
||||
CFRelease(url);
|
||||
}
|
||||
|
||||
IdevicePairingFile *pairing_file = NULL;
|
||||
IdeviceErrorCode err = idevice_pairing_file_read(pairingFilePath, &pairing_file);
|
||||
if (err != IdeviceSuccess) {
|
||||
return strdup("{\"error\": \"Failed to read pairing file\"}");
|
||||
}
|
||||
|
||||
TcpProviderHandle *provider = NULL;
|
||||
err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file, "ExampleProvider", &provider);
|
||||
if (err != IdeviceSuccess) {
|
||||
idevice_pairing_file_free(pairing_file);
|
||||
return strdup("{\"error\": \"Failed to create TCP provider\"}");
|
||||
}
|
||||
|
||||
InstallationProxyClientHandle *client = NULL;
|
||||
err = installation_proxy_connect_tcp(provider, &client);
|
||||
if (err != IdeviceSuccess) {
|
||||
tcp_provider_free(provider);
|
||||
return strdup("{\"error\": \"Failed to connect to installation proxy\"}");
|
||||
}
|
||||
|
||||
void *apps = NULL;
|
||||
size_t apps_len = 0;
|
||||
err = installation_proxy_get_apps(client, NULL, NULL, 0, &apps, &apps_len);
|
||||
if (err != IdeviceSuccess) {
|
||||
installation_proxy_client_free(client);
|
||||
tcp_provider_free(provider);
|
||||
return strdup("{\"error\": \"Failed to get apps\"}");
|
||||
}
|
||||
|
||||
plist_t *app_list = (plist_t *)apps;
|
||||
char *result = malloc(8192); // Allocate memory for output
|
||||
result[0] = '\0';
|
||||
strcat(result, "{\n");
|
||||
|
||||
int first_entry = 1;
|
||||
for (size_t i = 0; i < apps_len; i++) {
|
||||
plist_t app = app_list[i];
|
||||
// Check if the app has an "Entitlements" dictionary.
|
||||
plist_t entitlements = plist_dict_get_item(app, "Entitlements");
|
||||
if (entitlements) {
|
||||
// Look for the "get-task-allow" key.
|
||||
plist_t taskAllowNode = plist_dict_get_item(entitlements, "get-task-allow");
|
||||
if (taskAllowNode) {
|
||||
int isAllowed = 0;
|
||||
plist_get_bool_val(taskAllowNode, &isAllowed);
|
||||
if (isAllowed) {
|
||||
// Retrieve the bundle identifier if the entitlement is true.
|
||||
plist_t bundle_id_node = plist_dict_get_item(app, "CFBundleIdentifier");
|
||||
if (bundle_id_node) {
|
||||
char *bundle_id = NULL;
|
||||
plist_get_string_val(bundle_id_node, &bundle_id);
|
||||
|
||||
// Skip if bundle ID is empty
|
||||
if (bundle_id == NULL || strlen(bundle_id) == 0) {
|
||||
free(bundle_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Retrieve the app name
|
||||
plist_t app_name_node = plist_dict_get_item(app, "CFBundleName");
|
||||
char *app_name = NULL;
|
||||
if (app_name_node) {
|
||||
plist_get_string_val(app_name_node, &app_name);
|
||||
} else {
|
||||
app_name = strdup("Unknown");
|
||||
}
|
||||
|
||||
// Escape special characters in app name and bundle ID
|
||||
char escaped_app_name[1024] = {0};
|
||||
char escaped_bundle_id[1024] = {0};
|
||||
for (int j = 0, k = 0; app_name[j] != '\0'; j++, k++) {
|
||||
if (app_name[j] == '"' || app_name[j] == '\\') {
|
||||
escaped_app_name[k++] = '\\';
|
||||
}
|
||||
escaped_app_name[k] = app_name[j];
|
||||
}
|
||||
for (int j = 0, k = 0; bundle_id[j] != '\0'; j++, k++) {
|
||||
if (bundle_id[j] == '"' || bundle_id[j] == '\\') {
|
||||
escaped_bundle_id[k++] = '\\';
|
||||
}
|
||||
escaped_bundle_id[k] = bundle_id[j];
|
||||
}
|
||||
|
||||
// Add the app name and bundle ID to the result in JSON format
|
||||
if (!first_entry) {
|
||||
strcat(result, ",\n");
|
||||
}
|
||||
strcat(result, " \"");
|
||||
strcat(result, escaped_app_name);
|
||||
strcat(result, "\": \"");
|
||||
strcat(result, escaped_bundle_id);
|
||||
strcat(result, "\"");
|
||||
|
||||
first_entry = 0;
|
||||
free(bundle_id);
|
||||
free(app_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
strcat(result, "\n}\n");
|
||||
|
||||
installation_proxy_client_free(client);
|
||||
tcp_provider_free(provider);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -7,7 +7,8 @@
|
|||
|
||||
#ifndef APPLIST_H
|
||||
#define APPLIST_H
|
||||
@import Foundation;
|
||||
|
||||
char *list_installed_apps(void);
|
||||
NSDictionary<NSString*, NSString*>* list_installed_apps(TcpProviderHandle* provider, NSString** error);
|
||||
|
||||
#endif /* APPLIST_H */
|
||||
|
|
|
|||
86
StikJIT/idevice/applist.m
Normal file
86
StikJIT/idevice/applist.m
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
//
|
||||
// applist.c
|
||||
// StikJIT
|
||||
//
|
||||
// Created by Stephen on 3/27/25.
|
||||
//
|
||||
|
||||
#include "idevice.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "applist.h"
|
||||
|
||||
NSDictionary<NSString*, NSString*>* list_installed_apps(TcpProviderHandle* provider, NSString** error) {
|
||||
IdeviceErrorCode err = IdeviceSuccess;
|
||||
|
||||
InstallationProxyClientHandle *client = NULL;
|
||||
err = installation_proxy_connect_tcp(provider, &client);
|
||||
if (err != IdeviceSuccess) {
|
||||
*error = @"Failed to connect to installation proxy";
|
||||
return nil;
|
||||
}
|
||||
|
||||
void *apps = NULL;
|
||||
size_t apps_len = 0;
|
||||
err = installation_proxy_get_apps(client, NULL, NULL, 0, &apps, &apps_len);
|
||||
if (err != IdeviceSuccess) {
|
||||
installation_proxy_client_free(client);
|
||||
*error = @"Failed to get apps";
|
||||
return nil;
|
||||
}
|
||||
|
||||
plist_t *app_list = (plist_t *)apps;
|
||||
|
||||
NSMutableDictionary<NSString*, NSString*>* ans = [[NSMutableDictionary alloc] init];
|
||||
|
||||
for (size_t i = 0; i < apps_len; i++) {
|
||||
plist_t app = app_list[i];
|
||||
// Check if the app has an "Entitlements" dictionary.
|
||||
plist_t entitlements = plist_dict_get_item(app, "Entitlements");
|
||||
if (entitlements) {
|
||||
// Look for the "get-task-allow" key.
|
||||
plist_t taskAllowNode = plist_dict_get_item(entitlements, "get-task-allow");
|
||||
if (taskAllowNode) {
|
||||
uint8_t isAllowed = 0;
|
||||
plist_get_bool_val(taskAllowNode, &isAllowed);
|
||||
if (isAllowed) {
|
||||
// Retrieve the bundle identifier if the entitlement is true.
|
||||
plist_t bundle_id_node = plist_dict_get_item(app, "CFBundleIdentifier");
|
||||
if (bundle_id_node) {
|
||||
char *bundle_id = NULL;
|
||||
plist_get_string_val(bundle_id_node, &bundle_id);
|
||||
|
||||
// Skip if bundle ID is empty
|
||||
if (bundle_id == NULL || strlen(bundle_id) == 0) {
|
||||
free(bundle_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Retrieve the app name
|
||||
plist_t app_name_node = plist_dict_get_item(app, "CFBundleName");
|
||||
char *app_name = NULL;
|
||||
if (app_name_node) {
|
||||
plist_get_string_val(app_name_node, &app_name);
|
||||
} else {
|
||||
app_name = strdup("Unknown");
|
||||
}
|
||||
|
||||
ans[[NSString stringWithCString:bundle_id encoding:NSASCIIStringEncoding]] = [NSString stringWithCString:app_name encoding:NSASCIIStringEncoding];
|
||||
|
||||
free(bundle_id);
|
||||
free(app_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
installation_proxy_client_free(client);
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
|
@ -9,11 +9,11 @@
|
|||
#include <sys/_types/_u_int64_t.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <limits.h>
|
||||
#include "heartbeat.h"
|
||||
|
||||
typedef void (^HeartbeatCompletionHandler)(int result, const char *message);
|
||||
|
||||
void startHeartbeat(HeartbeatCompletionHandler completion) {
|
||||
printf("DEBUG: Initializing logger...\n");
|
||||
void startHeartbeat(IdevicePairingFile* pairing_file, TcpProviderHandle** provider, int* heartbeatSessionId, HeartbeatCompletionHandlerC completion, LogFuncC logger) {
|
||||
int currentSessionId = *heartbeatSessionId;
|
||||
logger("DEBUG: Initializing logger...");
|
||||
idevice_init_logger(Debug, Disabled, NULL);
|
||||
|
||||
struct sockaddr_in addr;
|
||||
|
|
@ -21,80 +21,59 @@ void startHeartbeat(HeartbeatCompletionHandler completion) {
|
|||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(LOCKDOWN_PORT);
|
||||
if (inet_pton(AF_INET, "10.7.0.1", &addr.sin_addr) <= 0) {
|
||||
fprintf(stderr, "DEBUG: Error converting IP address.\n");
|
||||
logger("DEBUG: Error converting IP address.");
|
||||
return;
|
||||
}
|
||||
printf("DEBUG: Socket address created for IP 10.7.0.1 on port %d.\n", LOCKDOWN_PORT);
|
||||
logger("DEBUG: Socket address created for IP 10.7.0.1 on port %d.", LOCKDOWN_PORT);
|
||||
|
||||
printf("DEBUG: Searching the app bundle for pairing_file.plist...\n");
|
||||
char pairingFilePath[1024];
|
||||
CFURLRef url = CFCopyHomeDirectoryURL();
|
||||
if (url) {
|
||||
CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
|
||||
if (path) {
|
||||
CFStringGetCString(path, pairingFilePath, sizeof(pairingFilePath), kCFStringEncodingUTF8);
|
||||
strncat(pairingFilePath, "/Documents/pairingFile.plist", sizeof(pairingFilePath) - strlen(pairingFilePath) - 1);
|
||||
CFRelease(path);
|
||||
}
|
||||
CFRelease(url);
|
||||
}
|
||||
printf("Pairing file found at path: %s\n", pairingFilePath);
|
||||
IdeviceErrorCode err = IdeviceSuccess;
|
||||
|
||||
printf("DEBUG: Reading pairing file...\n");
|
||||
IdevicePairingFile *pairing_file = NULL;
|
||||
IdeviceErrorCode err = idevice_pairing_file_read(pairingFilePath, &pairing_file);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "DEBUG: Failed to read pairing file: %d\n", err);
|
||||
completion(err, "Failed to read pairing file");
|
||||
return;
|
||||
}
|
||||
printf("DEBUG: Pairing file read successfully.\n");
|
||||
|
||||
printf("DEBUG: Creating TCP provider...\n");
|
||||
TcpProviderHandle *provider = NULL;
|
||||
logger("DEBUG: Creating TCP provider...");
|
||||
err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing_file,
|
||||
"ExampleProvider", &provider);
|
||||
"ExampleProvider", provider);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "DEBUG: Failed to create TCP provider: %d\n", err);
|
||||
idevice_pairing_file_free(pairing_file);
|
||||
logger("DEBUG: Failed to create TCP provider: %d", err);
|
||||
completion(err, "Failed to create TCP provider");
|
||||
return;
|
||||
}
|
||||
printf("DEBUG: TCP provider created successfully.\n");
|
||||
logger("DEBUG: TCP provider created successfully.");
|
||||
|
||||
printf("DEBUG: Connecting to installation proxy...\n");
|
||||
logger("DEBUG: Connecting to installation proxy...");
|
||||
HeartbeatClientHandle *client = NULL;
|
||||
err = heartbeat_connect_tcp(provider, &client);
|
||||
err = heartbeat_connect_tcp(*provider, &client);
|
||||
if (err != IdeviceSuccess) {
|
||||
completion(err, "Failed to connect to Heartbeat");
|
||||
fprintf(stderr, "DEBUG: Failed to connect to installation proxy: %d\n", err);
|
||||
logger("DEBUG: Failed to connect to installation proxy: %d", err);
|
||||
return;
|
||||
}
|
||||
tcp_provider_free(provider);
|
||||
printf("DEBUG: Connected to installation proxy successfully.\n");
|
||||
logger("DEBUG: Connected to installation proxy successfully.");
|
||||
|
||||
completion(0, "Heartbeat Completed");
|
||||
|
||||
u_int64_t current_interval = 15;
|
||||
while (1) {
|
||||
if(*heartbeatSessionId != currentSessionId) {
|
||||
break;
|
||||
}
|
||||
|
||||
u_int64_t new_interval = 0;
|
||||
printf("DEBUG: Sending heartbeat with current interval: %llu seconds...\n", current_interval);
|
||||
logger("DEBUG: Sending heartbeat with current interval: %llu seconds...", current_interval);
|
||||
err = heartbeat_get_marco(client, current_interval, &new_interval);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "DEBUG: Failed to get marco: %d\n", err);
|
||||
logger("DEBUG: Failed to get marco: %d", err);
|
||||
heartbeat_client_free(client);
|
||||
return;
|
||||
}
|
||||
printf("DEBUG: Received new interval: %llu seconds.\n", new_interval);
|
||||
logger("DEBUG: Received new interval: %llu seconds.", new_interval);
|
||||
current_interval = new_interval + 5;
|
||||
|
||||
printf("DEBUG: Sending polo reply...\n");
|
||||
logger("DEBUG: Sending polo reply...");
|
||||
err = heartbeat_send_polo(client);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "DEBUG: Failed to send polo: %d\n", err);
|
||||
logger("DEBUG: Failed to send polo: %d", err);
|
||||
heartbeat_client_free(client);
|
||||
return;
|
||||
}
|
||||
printf("DEBUG: Polo reply sent successfully.\n");
|
||||
logger("DEBUG: Polo reply sent successfully.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@
|
|||
// heartbeat.h
|
||||
#ifndef HEARTBEAT_H
|
||||
#define HEARTBEAT_H
|
||||
#include "idevice.h"
|
||||
|
||||
typedef void (^HeartbeatCompletionHandler)(int result, const char *message);
|
||||
typedef void (^HeartbeatCompletionHandlerC)(int result, const char *message);
|
||||
typedef void (^LogFuncC)(const char* message, ...);
|
||||
|
||||
void startHeartbeat(HeartbeatCompletionHandler completion);
|
||||
void startHeartbeat(IdevicePairingFile* pairintFile, TcpProviderHandle** provider, int* heartbeatSessionId, HeartbeatCompletionHandlerC completion, LogFuncC logger);
|
||||
|
||||
#endif /* HEARTBEAT_H */
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
#include <sys/socket.h>
|
||||
#include "plist.h"
|
||||
|
||||
#ifndef IDEVICE_H
|
||||
#define IDEVICE_H
|
||||
|
||||
#define LOCKDOWN_PORT 62078
|
||||
|
||||
typedef enum IdeviceErrorCode {
|
||||
|
|
@ -1629,3 +1632,5 @@ enum IdeviceErrorCode idevice_usbmuxd_unix_addr_new(const char *addr,
|
|||
* or NULL (in which case this function does nothing)
|
||||
*/
|
||||
void idevice_usbmuxd_addr_free(struct UsbmuxdAddrHandle *usbmuxd_addr);
|
||||
|
||||
#endif /* IDEVICE_H */
|
||||
|
|
|
|||
|
|
@ -17,92 +17,40 @@
|
|||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <limits.h>
|
||||
|
||||
int debug_app(const char *bundle_id) {
|
||||
#include "jit.h"
|
||||
|
||||
int debug_app(TcpProviderHandle* tcp_provider, const char *bundle_id, LogFuncC logger) {
|
||||
// Initialize logger
|
||||
idevice_init_logger(Debug, Disabled, NULL);
|
||||
|
||||
// Hardcode device IP
|
||||
const char *device_ip = "10.7.0.1";
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* Locate pairing file in app bundle
|
||||
*****************************************************************/
|
||||
char pairingFilePath[1024];
|
||||
CFURLRef url = CFCopyHomeDirectoryURL();
|
||||
if (url) {
|
||||
CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
|
||||
if (path) {
|
||||
CFStringGetCString(path, pairingFilePath, sizeof(pairingFilePath), kCFStringEncodingUTF8);
|
||||
strncat(pairingFilePath, "/Documents/pairingFile.plist", sizeof(pairingFilePath) - strlen(pairingFilePath) - 1);
|
||||
CFRelease(path);
|
||||
}
|
||||
CFRelease(url);
|
||||
}
|
||||
printf("Pairing file found at path: %s\n", pairingFilePath);
|
||||
|
||||
/*****************************************************************
|
||||
* CoreDeviceProxy Setup
|
||||
*****************************************************************/
|
||||
printf("=== Setting up CoreDeviceProxy ===\n");
|
||||
|
||||
// Create socket address
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(LOCKDOWN_PORT);
|
||||
if (inet_pton(AF_INET, device_ip, &addr.sin_addr) != 1) {
|
||||
fprintf(stderr, "Invalid IP address\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Read pairing file from the bundle
|
||||
IdevicePairingFile *pairing = NULL;
|
||||
IdeviceErrorCode err = idevice_pairing_file_read(pairingFilePath, &pairing);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to read pairing file: %d\n", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create TCP provider
|
||||
TcpProviderHandle *tcp_provider = NULL;
|
||||
err = idevice_tcp_provider_new((struct sockaddr *)&addr, pairing,
|
||||
"ProcessDebugTest", &tcp_provider);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to create TCP provider: %d\n", err);
|
||||
idevice_pairing_file_free(pairing);
|
||||
return 1;
|
||||
}
|
||||
IdeviceErrorCode err = IdeviceSuccess;
|
||||
|
||||
// Connect to CoreDeviceProxy
|
||||
CoreDeviceProxyHandle *core_device = NULL;
|
||||
err = core_device_proxy_connect_tcp(tcp_provider, &core_device);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to connect to CoreDeviceProxy: %d\n", err);
|
||||
tcp_provider_free(tcp_provider);
|
||||
logger("Failed to connect to CoreDeviceProxy: %d", err);
|
||||
return 1;
|
||||
}
|
||||
tcp_provider_free(tcp_provider);
|
||||
|
||||
// Get server RSD port
|
||||
uint16_t rsd_port;
|
||||
err = core_device_proxy_get_server_rsd_port(core_device, &rsd_port);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to get server RSD port: %d\n", err);
|
||||
logger("Failed to get server RSD port: %d", err);
|
||||
core_device_proxy_free(core_device);
|
||||
return 1;
|
||||
}
|
||||
printf("Server RSD Port: %d\n", rsd_port);
|
||||
logger("Server RSD Port: %d", rsd_port);
|
||||
|
||||
/*****************************************************************
|
||||
* Create TCP Tunnel Adapter
|
||||
*****************************************************************/
|
||||
printf("\n=== Creating TCP Tunnel Adapter ===\n");
|
||||
logger("=== Creating TCP Tunnel Adapter ===");
|
||||
|
||||
AdapterHandle *adapter = NULL;
|
||||
err = core_device_proxy_create_tcp_adapter(core_device, &adapter);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to create TCP adapter: %d\n", err);
|
||||
logger("Failed to create TCP adapter: %d", err);
|
||||
core_device_proxy_free(core_device);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -110,22 +58,22 @@ int debug_app(const char *bundle_id) {
|
|||
// Connect to RSD port
|
||||
err = adapter_connect(adapter, rsd_port);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to connect to RSD port: %d\n", err);
|
||||
logger("Failed to connect to RSD port: %d", err);
|
||||
adapter_free(adapter);
|
||||
core_device_proxy_free(core_device);
|
||||
return 1;
|
||||
}
|
||||
printf("Successfully connected to RSD port\n");
|
||||
logger("Successfully connected to RSD port");
|
||||
|
||||
/*****************************************************************
|
||||
* XPC Device Setup
|
||||
*****************************************************************/
|
||||
printf("\n=== Setting up XPC Device ===\n");
|
||||
logger("=== Setting up XPC Device ===");
|
||||
|
||||
XPCDeviceAdapterHandle *xpc_device = NULL;
|
||||
err = xpc_device_new(adapter, &xpc_device);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to create XPC device: %d\n", err);
|
||||
logger("Failed to create XPC device: %d", err);
|
||||
adapter_free(adapter);
|
||||
core_device_proxy_free(core_device);
|
||||
return 1;
|
||||
|
|
@ -135,7 +83,7 @@ int debug_app(const char *bundle_id) {
|
|||
XPCServiceHandle *debug_service = NULL;
|
||||
err = xpc_device_get_service(xpc_device, "com.apple.internal.dt.remote.debugproxy", &debug_service);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to get debug proxy service: %d\n", err);
|
||||
logger("Failed to get debug proxy service: %d", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -143,7 +91,7 @@ int debug_app(const char *bundle_id) {
|
|||
XPCServiceHandle *pc_service = NULL;
|
||||
err = xpc_device_get_service(xpc_device, "com.apple.instruments.dtservicehub", &pc_service);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to get process control service: %d\n", err);
|
||||
logger("Failed to get process control service: %d", err);
|
||||
xpc_device_free(xpc_device);
|
||||
core_device_proxy_free(core_device);
|
||||
return 1;
|
||||
|
|
@ -152,13 +100,13 @@ int debug_app(const char *bundle_id) {
|
|||
/*****************************************************************
|
||||
* Process Control - Launch App
|
||||
*****************************************************************/
|
||||
printf("\n=== Launching App ===\n");
|
||||
logger("=== Launching App ===");
|
||||
|
||||
// Get the adapter back from the XPC device
|
||||
AdapterHandle *pc_adapter = NULL;
|
||||
err = xpc_device_adapter_into_inner(xpc_device, &pc_adapter);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to extract adapter: %d\n", err);
|
||||
logger("Failed to extract adapter: %d", err);
|
||||
xpc_device_free(xpc_device);
|
||||
core_device_proxy_free(core_device);
|
||||
return 1;
|
||||
|
|
@ -167,19 +115,19 @@ int debug_app(const char *bundle_id) {
|
|||
// Connect to process control port
|
||||
err = adapter_connect(pc_adapter, pc_service->port);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to connect to process control port: %d\n", err);
|
||||
logger("Failed to connect to process control port: %d", err);
|
||||
adapter_free(pc_adapter);
|
||||
xpc_service_free(pc_service);
|
||||
core_device_proxy_free(core_device);
|
||||
return 1;
|
||||
}
|
||||
printf("Successfully connected to process control port\n");
|
||||
logger("Successfully connected to process control port");
|
||||
|
||||
// Create RemoteServerClient
|
||||
RemoteServerAdapterHandle *remote_server = NULL;
|
||||
err = remote_server_adapter_new(pc_adapter, &remote_server);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to create remote server: %d\n", err);
|
||||
logger("Failed to create remote server: %d", err);
|
||||
adapter_free(pc_adapter);
|
||||
xpc_service_free(pc_service);
|
||||
core_device_proxy_free(core_device);
|
||||
|
|
@ -190,7 +138,7 @@ int debug_app(const char *bundle_id) {
|
|||
ProcessControlAdapterHandle *process_control = NULL;
|
||||
err = process_control_new(remote_server, &process_control);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to create process control client: %d\n", err);
|
||||
logger("Failed to create process control client: %d", err);
|
||||
remote_server_free(remote_server);
|
||||
xpc_service_free(pc_service);
|
||||
core_device_proxy_free(core_device);
|
||||
|
|
@ -202,25 +150,25 @@ int debug_app(const char *bundle_id) {
|
|||
err = process_control_launch_app(process_control, bundle_id, NULL, 0, NULL, 0,
|
||||
true, false, &pid);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to launch app: %d\n", err);
|
||||
logger("Failed to launch app: %d", err);
|
||||
process_control_free(process_control);
|
||||
remote_server_free(remote_server);
|
||||
xpc_service_free(pc_service);
|
||||
core_device_proxy_free(core_device);
|
||||
return 1;
|
||||
}
|
||||
printf("Successfully launched app with PID: %" PRIu64 "\n", pid);
|
||||
logger("Successfully launched app with PID: %" PRIu64 "", pid);
|
||||
|
||||
/*****************************************************************
|
||||
* Debug Proxy - Attach to Process
|
||||
*****************************************************************/
|
||||
printf("\n=== Attaching Debugger ===\n");
|
||||
logger("=== Attaching Debugger ===");
|
||||
|
||||
// Get the adapter back from the remote server
|
||||
AdapterHandle *debug_adapter = NULL;
|
||||
err = remote_server_adapter_into_inner(remote_server, &debug_adapter);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to extract adapter: %d\n", err);
|
||||
logger("Failed to extract adapter: %d", err);
|
||||
xpc_service_free(debug_service);
|
||||
process_control_free(process_control);
|
||||
remote_server_free(remote_server);
|
||||
|
|
@ -232,7 +180,7 @@ int debug_app(const char *bundle_id) {
|
|||
// Connect to debug proxy port
|
||||
err = adapter_connect(debug_adapter, debug_service->port);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to connect to debug proxy port: %d\n", err);
|
||||
logger("Failed to connect to debug proxy port: %d", err);
|
||||
adapter_free(debug_adapter);
|
||||
xpc_service_free(debug_service);
|
||||
process_control_free(process_control);
|
||||
|
|
@ -241,13 +189,13 @@ int debug_app(const char *bundle_id) {
|
|||
core_device_proxy_free(core_device);
|
||||
return 1;
|
||||
}
|
||||
printf("Successfully connected to debug proxy port\n");
|
||||
logger("Successfully connected to debug proxy port");
|
||||
|
||||
// Create DebugProxyClient
|
||||
DebugProxyAdapterHandle *debug_proxy = NULL;
|
||||
err = debug_proxy_adapter_new(debug_adapter, &debug_proxy);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to create debug proxy client: %d\n", err);
|
||||
logger("Failed to create debug proxy client: %d", err);
|
||||
adapter_free(debug_adapter);
|
||||
xpc_service_free(debug_service);
|
||||
process_control_free(process_control);
|
||||
|
|
@ -263,7 +211,7 @@ int debug_app(const char *bundle_id) {
|
|||
|
||||
DebugserverCommandHandle *attach_cmd = debugserver_command_new(attach_command, NULL, 0);
|
||||
if (attach_cmd == NULL) {
|
||||
fprintf(stderr, "Failed to create attach command\n");
|
||||
logger("Failed to create attach command");
|
||||
debug_proxy_free(debug_proxy);
|
||||
adapter_free(debug_adapter);
|
||||
xpc_service_free(debug_service);
|
||||
|
|
@ -279,16 +227,16 @@ int debug_app(const char *bundle_id) {
|
|||
debugserver_command_free(attach_cmd);
|
||||
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to attach to process: %d\n", err);
|
||||
logger("Failed to attach to process: %d", err);
|
||||
} else if (attach_response != NULL) {
|
||||
printf("Attach response: %s\n", attach_response);
|
||||
logger("Attach response: %s", attach_response);
|
||||
idevice_string_free(attach_response);
|
||||
}
|
||||
|
||||
// Send detach command
|
||||
DebugserverCommandHandle *detach_cmd = debugserver_command_new("D", NULL, 0);
|
||||
if (detach_cmd == NULL) {
|
||||
fprintf(stderr, "Failed to create detach command\n");
|
||||
logger("Failed to create detach command");
|
||||
} else {
|
||||
char *detach_response = NULL;
|
||||
err = debug_proxy_send_command(debug_proxy, detach_cmd, &detach_response);
|
||||
|
|
@ -297,9 +245,9 @@ int debug_app(const char *bundle_id) {
|
|||
debugserver_command_free(detach_cmd);
|
||||
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "Failed to detach from process: %d\n", err);
|
||||
logger("Failed to detach from process: %d", err);
|
||||
} else if (detach_response != NULL) {
|
||||
printf("Detach response: %s\n", detach_response);
|
||||
logger("Detach response: %s", detach_response);
|
||||
idevice_string_free(detach_response);
|
||||
}
|
||||
}
|
||||
|
|
@ -310,6 +258,6 @@ int debug_app(const char *bundle_id) {
|
|||
debug_proxy_free(debug_proxy);
|
||||
xpc_service_free(debug_service);
|
||||
|
||||
printf("\nDebug session completed\n");
|
||||
logger("Debug session completed");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@
|
|||
// jit.h
|
||||
#ifndef JIT_H
|
||||
#define JIT_H
|
||||
#include "idevice.h"
|
||||
|
||||
int debug_app(const char *bundle_id);
|
||||
typedef void (^LogFuncC)(const char* message, ...);
|
||||
int debug_app(TcpProviderHandle* provider, const char *bundle_id, LogFuncC logger);
|
||||
|
||||
#endif /* JIT_H */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue