diff --git a/AltServer/Connections/ALTDebugConnection.h b/AltServer/Connections/ALTDebugConnection.h index cc24c652..fba2abd2 100644 --- a/AltServer/Connections/ALTDebugConnection.h +++ b/AltServer/Connections/ALTDebugConnection.h @@ -16,6 +16,7 @@ NS_SWIFT_NAME(DebugConnection) @property (nonatomic, copy, readonly) ALTDevice *device; - (void)enableUnsignedCodeExecutionForProcessWithName:(NSString *)processName completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler; +- (void)enableUnsignedCodeExecutionForProcessWithID:(NSInteger)pid completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler; - (void)disconnect; diff --git a/AltServer/Connections/ALTDebugConnection.mm b/AltServer/Connections/ALTDebugConnection.mm index 46d3ffcf..b94ae8eb 100644 --- a/AltServer/Connections/ALTDebugConnection.mm +++ b/AltServer/Connections/ALTDebugConnection.mm @@ -96,12 +96,36 @@ char *bin2hex(const unsigned char *bin, size_t length) } - (void)enableUnsignedCodeExecutionForProcessWithName:(NSString *)processName completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler +{ + [self _enableUnsignedCodeExecutionForProcessWithName:processName pid:0 completionHandler:completionHandler]; +} + +- (void)enableUnsignedCodeExecutionForProcessWithID:(NSInteger)pid completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler +{ + [self _enableUnsignedCodeExecutionForProcessWithName:nil pid:(int32_t)pid completionHandler:completionHandler]; +} + +- (void)_enableUnsignedCodeExecutionForProcessWithName:(nullable NSString *)processName pid:(int32_t)pid completionHandler:(void (^)(BOOL success, NSError *_Nullable error))completionHandler { dispatch_async(self.connectionQueue, ^{ - NSString *localizedFailure = [NSString stringWithFormat:NSLocalizedString(@"JIT could not be enabled for %@.", comment: @""), processName]; + NSString *name = processName ?: NSLocalizedString(@"this app", @""); + NSString *localizedFailure = [NSString stringWithFormat:NSLocalizedString(@"JIT could not be enabled for %@.", comment: @""), name]; - NSString *encodedName = @(bin2hex((const unsigned char *)processName.UTF8String, (size_t)strlen(processName.UTF8String))); - NSString *attachCommand = [NSString stringWithFormat:@"vAttachName;%@", encodedName]; + NSString *attachCommand = nil; + + if (processName) + { + NSString *encodedName = @(bin2hex((const unsigned char *)processName.UTF8String, (size_t)strlen(processName.UTF8String))); + attachCommand = [NSString stringWithFormat:@"vAttachName;%@", encodedName]; + } + else + { + // Convert to Big-endian. + int32_t rawPID = CFSwapInt32HostToBig(pid); + + NSString *encodedName = @(bin2hex((const unsigned char *)&rawPID, 4)); + attachCommand = [NSString stringWithFormat:@"vAttach;%@", encodedName]; + } NSError *error = nil; if (![self sendCommand:attachCommand arguments:nil error:&error]) diff --git a/AltServer/Connections/RequestHandler.swift b/AltServer/Connections/RequestHandler.swift index 02326f54..0a683a00 100644 --- a/AltServer/Connections/RequestHandler.swift +++ b/AltServer/Connections/RequestHandler.swift @@ -143,6 +143,37 @@ struct ServerRequestHandler: RequestHandler } } } + + func handleEnableUnsignedCodeExecutionRequest(_ request: EnableUnsignedCodeExecutionRequest, for connection: Connection, completionHandler: @escaping (Result) -> Void) + { + guard let device = ALTDeviceManager.shared.availableDevices.first(where: { $0.identifier == request.udid }) else { return completionHandler(.failure(ALTServerError(.deviceNotFound))) } + + ALTDeviceManager.shared.prepare(device) { result in + switch result + { + case .failure(let error): completionHandler(.failure(error)) + case .success: + ALTDeviceManager.shared.startDebugConnection(to: device) { (connection, error) in + guard let connection = connection else { return completionHandler(.failure(error!)) } + + connection.enableUnsignedCodeExecutionForProcess(withID: request.processID) { (success, error) in + if let error = error, !success + { + print("Failed to enable unsigned code execution for process \(request.processID):", error) + completionHandler(.failure(ALTServerError(error))) + } + else + { + print("Enabled unsigned code execution for process:", request.processID) + + let response = EnableUnsignedCodeExecutionResponse() + completionHandler(.success(response)) + } + } + } + } + } + } } private extension RequestHandler diff --git a/Shared/Connections/ConnectionManager.swift b/Shared/Connections/ConnectionManager.swift index 9d3c054b..31dbf810 100644 --- a/Shared/Connections/ConnectionManager.swift +++ b/Shared/Connections/ConnectionManager.swift @@ -20,6 +20,8 @@ public protocol RequestHandler completionHandler: @escaping (Result) -> Void) func handleRemoveAppRequest(_ request: RemoveAppRequest, for connection: Connection, completionHandler: @escaping (Result) -> Void) + + func handleEnableUnsignedCodeExecutionRequest(_ request: EnableUnsignedCodeExecutionRequest, for connection: Connection, completionHandler: @escaping (Result) -> Void) } public protocol ConnectionHandler: AnyObject @@ -152,6 +154,11 @@ private extension ConnectionManager finish(result) } + case .success(.enableUnsignedCodeExecution(let request)): + self.requestHandler.handleEnableUnsignedCodeExecutionRequest(request, for: connection) { (result) in + finish(result) + } + case .success(.unknown): finish(Result.failure(ALTServerError(.unknownRequest))) } diff --git a/Shared/Server Protocol/ServerProtocol.swift b/Shared/Server Protocol/ServerProtocol.swift index dcee3c3b..bf6fcf45 100644 --- a/Shared/Server Protocol/ServerProtocol.swift +++ b/Shared/Server Protocol/ServerProtocol.swift @@ -25,6 +25,7 @@ public enum ServerRequest: Decodable case installProvisioningProfiles(InstallProvisioningProfilesRequest) case removeProvisioningProfiles(RemoveProvisioningProfilesRequest) case removeApp(RemoveAppRequest) + case enableUnsignedCodeExecution(EnableUnsignedCodeExecutionRequest) case unknown(identifier: String, version: Int) var identifier: String { @@ -36,6 +37,7 @@ public enum ServerRequest: Decodable case .installProvisioningProfiles(let request): return request.identifier case .removeProvisioningProfiles(let request): return request.identifier case .removeApp(let request): return request.identifier + case .enableUnsignedCodeExecution(let request): return request.identifier case .unknown(let identifier, _): return identifier } } @@ -49,6 +51,7 @@ public enum ServerRequest: Decodable case .installProvisioningProfiles(let request): return request.version case .removeProvisioningProfiles(let request): return request.version case .removeApp(let request): return request.version + case .enableUnsignedCodeExecution(let request): return request.version case .unknown(_, let version): return version } } @@ -92,6 +95,10 @@ public enum ServerRequest: Decodable let request = try RemoveAppRequest(from: decoder) self = .removeApp(request) + case "EnableUnsignedCodeExecutionRequest": + let request = try EnableUnsignedCodeExecutionRequest(from: decoder) + self = .enableUnsignedCodeExecution(request) + default: self = .unknown(identifier: identifier, version: version) } @@ -105,6 +112,7 @@ public enum ServerResponse: Decodable case installProvisioningProfiles(InstallProvisioningProfilesResponse) case removeProvisioningProfiles(RemoveProvisioningProfilesResponse) case removeApp(RemoveAppResponse) + case enableUnsignedCodeExecution(EnableUnsignedCodeExecutionResponse) case error(ErrorResponse) case unknown(identifier: String, version: Int) @@ -116,6 +124,7 @@ public enum ServerResponse: Decodable case .installProvisioningProfiles(let response): return response.identifier case .removeProvisioningProfiles(let response): return response.identifier case .removeApp(let response): return response.identifier + case .enableUnsignedCodeExecution(let response): return response.identifier case .error(let response): return response.identifier case .unknown(let identifier, _): return identifier } @@ -129,6 +138,7 @@ public enum ServerResponse: Decodable case .installProvisioningProfiles(let response): return response.version case .removeProvisioningProfiles(let response): return response.version case .removeApp(let response): return response.version + case .enableUnsignedCodeExecution(let response): return response.version case .error(let response): return response.version case .unknown(_, let version): return version } @@ -169,6 +179,10 @@ public enum ServerResponse: Decodable let response = try RemoveAppResponse(from: decoder) self = .removeApp(response) + case "EnableUnsignedCodeExecutionResponse": + let response = try EnableUnsignedCodeExecutionResponse(from: decoder) + self = .enableUnsignedCodeExecution(response) + case "ErrorResponse": let response = try ErrorResponse(from: decoder) self = .error(response) @@ -424,3 +438,28 @@ public struct RemoveAppResponse: ServerMessageProtocol { } } + +public struct EnableUnsignedCodeExecutionRequest: ServerMessageProtocol +{ + public var version = 1 + public var identifier = "EnableUnsignedCodeExecutionRequest" + + public var udid: String + public var processID: Int + + public init(udid: String, processID: Int) + { + self.udid = udid + self.processID = processID + } +} + +public struct EnableUnsignedCodeExecutionResponse: ServerMessageProtocol +{ + public var version = 1 + public var identifier = "EnableUnsignedCodeExecutionResponse" + + public init() + { + } +}