Si quiero que mi aplicación se comporte de manera diferente en un iPhone con jailbreak, ¿cómo podría determinar esto?
Si quiero que mi aplicación se comporte de manera diferente en un iPhone con jailbreak, ¿cómo podría determinar esto?
Respuestas:
Depende de lo que quieras decir con jailbreak. En el caso simple, deberías poder ver si Cydia está instalado y seguirlo, algo así como
NSString *filePath = @"/Applications/Cydia.app";
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
// do something useful
}
Para los núcleos pirateados, es un poco (mucho) más complicado.
fileExistsAtPath:
y hacer que regrese NO
por la ruta específica que verifica.
Este es un código que combina algunas respuestas que encontré para esta necesidad, y le dará una tasa de éxito mucho mayor:
BOOL isJailbroken()
{
#if !(TARGET_IPHONE_SIMULATOR)
if ([[NSFileManager defaultManager] fileExistsAtPath:@"/Applications/Cydia.app"] ||
[[NSFileManager defaultManager] fileExistsAtPath:@"/Library/MobileSubstrate/MobileSubstrate.dylib"] ||
[[NSFileManager defaultManager] fileExistsAtPath:@"/bin/bash"] ||
[[NSFileManager defaultManager] fileExistsAtPath:@"/usr/sbin/sshd"] ||
[[NSFileManager defaultManager] fileExistsAtPath:@"/etc/apt"] ||
[[NSFileManager defaultManager] fileExistsAtPath:@"/private/var/lib/apt/"] ||
[[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://package/com.example.package"]]) {
return YES;
}
FILE *f = NULL ;
if ((f = fopen("/bin/bash", "r")) ||
(f = fopen("/Applications/Cydia.app", "r")) ||
(f = fopen("/Library/MobileSubstrate/MobileSubstrate.dylib", "r")) ||
(f = fopen("/usr/sbin/sshd", "r")) ||
(f = fopen("/etc/apt", "r"))) {
fclose(f);
return YES;
}
fclose(f);
NSError *error;
NSString *stringToBeWritten = @"This is a test.";
[stringToBeWritten writeToFile:@"/private/jailbreak.txt" atomically:YES encoding:NSUTF8StringEncoding error:&error];
[[NSFileManager defaultManager] removeItemAtPath:@"/private/jailbreak.txt" error:nil];
if(error == nil)
{
return YES;
}
#endif
return NO;
}
isJailbroken
+(BOOL)isJailbroken {
NSURL* url = [NSURL URLWithString:@"cydia://package/com.example.package"];
return [[UIApplication sharedApplication] canOpenURL:url];
}
¿Comprobar la ruta del archivo /Applications/Cydia.app
no está permitido en un teléfono normal? Nunca he oído que Apple detecte esto y rechace una aplicación, pero Apple es impredecible. Cydia tiene un esquema de URL cydia: // que se puede verificar legalmente con UIApplicationcanOpenURL:
Comprobar si el núcleo está roto no es TAN mucho más complicado.
El jailbreak hace que la verificación de la firma del núcleo del código firmado siempre informe que el código está firmado correctamente, los teléfonos ininterrumpidos no pueden ejecutar código con una firma incorrecta.
Por lo tanto, incluya un ejecutable separado en la aplicación con una firma incorrecta. Podría ser un programa de 3 líneas que tiene main () y un valor de retorno. Compile el ejecutable sin firmar el código (desactívelo en Configuración del proyecto-> Compilar) y fíjelo con una clave diferente utilizando la utilidad de línea de comandos "codesign".
Haga que su aplicación ejecute el ejecutable separado. Si su programa no puede obtener el valor de retorno cuando ejecuta el ejecutable separado con el signo incorrecto, definitivamente está encarcelado. Si el ejecutable separado devuelve A-OK, el teléfono está definitivamente liberado.
BOOL isJailbroken()
{
#if TARGET_IPHONE_SIMULATOR
return NO;
#else
FILE *f = fopen("/bin/bash", "r");
if (errno == ENOENT)
{
// device is NOT jailbroken
fclose(f);
return NO;
}
else {
// device IS jailbroken
fclose(f);
return YES;
}
#endif
}
Puede detectar si un dispositivo tiene JailBroken o no al verificar lo siguiente:
Hay una biblioteca de código abierto que creé a partir de varios artículos y libros. Pruébalo en GitHub !
Reformé en Swift 2.3 la solución provista por @Yossi
public static func jailbroken(application: UIApplication) -> Bool {
guard let cydiaUrlScheme = NSURL(string: "cydia://package/com.example.package") else { return isJailbroken() }
return application.canOpenURL(cydiaUrlScheme) || isJailbroken()
}
static func isJailbroken() -> Bool {
if isSimulator {
return false
}
let fileManager = NSFileManager.defaultManager()
if fileManager.fileExistsAtPath("/Applications/Cydia.app") ||
fileManager.fileExistsAtPath("/Library/MobileSubstrate/MobileSubstrate.dylib") ||
fileManager.fileExistsAtPath("/bin/bash") ||
fileManager.fileExistsAtPath("/usr/sbin/sshd") ||
fileManager.fileExistsAtPath("/etc/apt") ||
fileManager.fileExistsAtPath("/usr/bin/ssh") {
return true
}
if canOpen("/Applications/Cydia.app") ||
canOpen("/Library/MobileSubstrate/MobileSubstrate.dylib") ||
canOpen("/bin/bash") ||
canOpen("/usr/sbin/sshd") ||
canOpen("/etc/apt") ||
canOpen("/usr/bin/ssh") {
return true
}
let path = "/private/" + NSUUID().UUIDString
do {
try "anyString".writeToFile(path, atomically: true, encoding: NSUTF8StringEncoding)
try fileManager.removeItemAtPath(path)
return true
} catch {
return false
}
}
static func canOpen(path: String) -> Bool {
let file = fopen(path, "r")
guard file != nil else { return false }
fclose(file)
return true
}
El método más sofisticado que conozco es usar la objc_copyImageNames()
función. Devuelve una lista de las bibliotecas cargadas actualmente y dado que la mayoría de las personas tienen MobileSubstrate en dispositivos con jailbreak y la mayoría de las herramientas de crack de iAP dependen de él, al menos aparecerán algunas bibliotecas de MobileSubstrate.
deb
archivo de MobileSubstrate, descomprimirlo y ponerlo en la lista negra (casi) todo .dylib
está empaquetado.
No conozco ninguna "API" que exista para esto. Si lo hubiera, entonces un producto para enmascarar jailbreak los cubriría rápidamente.
Como mucha gente señala, es un juego de gato y ratón. Y después de que ambos jugadores se vuelvan expertos, todo se reduce a quién obtiene el primer movimiento. (Persona que sostiene el dispositivo).
Encontré muchas buenas sugerencias para detectar jailbreak en el nuevo libro de Zdziarski "Hacking and Securing iOS Apps". (Personalmente, pagué más por el libro electrónico O'Reilly porque permiten copiar y pegar).
No, no estoy afiliado a los editores. Pero lo encontré un buen libro. No me gusta publicar solo los errores de los hackers para que puedan solucionarlos, así que pensé en señalar el libro.
Intente ejecutar código sin firmar a través de su aplicación.
Un dispositivo con jailbreak generalmente tiene las siguientes características:
Simplemente verificar la existencia de archivos para la detección de jailbreak está condenado a fallar. Estas comprobaciones son fáciles de evitar.
Algunos archivos comunes para verificar:
/Library/MobileSubstrate/MobileSubstrate.dylib
/Applications/Cydia.app
/var/cache/apt
/var/lib/apt
/var/lib/cydia
/var/log/syslog
/var/tmp/cydia.log
/bin/bash
/bin/sh
/usr/sbin/sshd
/usr/libexec/ssh-keysign
/etc/ssh/sshd_config
/etc/apt
La mayoría busca archivos relacionados con Cydia.
Sugeriría buscar archivos que no están presentes en un iPhone "normal". Todos los kits de jailbreak que he visto instalan ssh. Ese podría ser un buen indicador de un teléfono con jailbreak.
Lo que hicimos es que ya tenemos una fuente RSS para comunicarnos con nuestros usuarios ( Stocks Live ), ponemos una noticia que dice algo como esto:
Algunos dispositivos con jailbreak tienen problemas bla bla bla, hicimos un truco para resolver esos problemas, pero necesitamos saber si este es un dispositivo con jailbreak o no, presione aquí para que la aplicación solucione el problema. Si alguna vez vuelve a la normalidad, es decir, eliminó el jailbreak, presione aquí.
Luego, procesa la interacción del usuario y hace lo apropiado, como comportarse de manera diferente, etc.
Intenta encontrar un archivo creado por Cydia o Jailbreak. O intente escribir en un archivo fuera de la caja negra de la aplicación. Si logra hacerlo, el dispositivo está comprometido / con jailbreak :)
- (BOOL)jailbroken
{
NSFileManager * fileManager = [NSFileManager defaultManager];
return [fileManager fileExistsAtPath:@"/private/var/lib/apt/"];
}
Utilice el siguiente código para Swift 4 y superior: agregue el siguiente código en el appdelegate
private func getJailbrokenStatus() -> Bool {
if TARGET_IPHONE_SIMULATOR != 1 {
// Check 1 : existence of files that are common for jailbroken devices
if FileManager.default.fileExists(atPath: "/Applications/Cydia.app")
|| FileManager.default.fileExists(atPath: "/Library/MobileSubstrate/MobileSubstrate.dylib")
|| FileManager.default.fileExists(atPath: "/bin/bash")
|| FileManager.default.fileExists(atPath: "/usr/sbin/sshd")
|| FileManager.default.fileExists(atPath: "/etc/apt")
|| FileManager.default.fileExists(atPath: "/private/var/lib/apt/")
|| UIApplication.shared.canOpenURL(URL(string:"cydia://package/com.example.package")!) {
return true
}
// Check 2 : Reading and writing in system directories (sandbox violation)
let stringToWrite = "Jailbreak Test"
do {
try stringToWrite.write(toFile:"/private/JailbreakTest.txt", atomically:true, encoding:String.Encoding.utf8)
//Device is jailbroken
return true
} catch {
return false
}
}
else {
return false
}
}
func applicationDidBecomeActive (_ application: UIApplication) {
if getJailbrokenStatus() {
let alert = UIAlertController(title: LocalizedKeys.Errors.jailbreakError, message: LocalizedKeys.Errors.jailbreakErrorMessage, preferredStyle: UIAlertController.Style.alert)
let jailBrokenView = UIViewController()
jailBrokenView.view.frame = UIScreen.main.bounds
jailBrokenView.view.backgroundColor = .white
self.window?.rootViewController = jailBrokenView
jailBrokenView.present(alert, animated: true, completion: nil)
}
if #available(iOS 11.0, *) {
if !UIScreen.main.isCaptured {
DispatchQueue.main.async {
self.blockImageView.removeFromSuperview()
}
}
}
}
Aquí están mis soluciones: Paso 1
extension UIDevice {
func isJailBroken() -> Bool {
let cydiaPath = "/Applications/Cydia.app"
let aptPath = "/private/var/lib/apt/"
if FileManager.default.fileExists(atPath: cydiaPath) || FileManager.default.fileExists(atPath: aptPath) {
return true
}
return false
}
}
Paso 2: llámelo viewDidLoad()
dentro de su controlador de vista de pantalla de inicio (o cualquier VC que esté llamando por primera vez):
// show a blank screen or some other view controller
let viewController = UIDevice.current.isJailBroken() ? JailBrokenViewController() : NextViewController()
self.navigationController?.present(viewController, animated: true, completion:nil)
Intente acceder a /Application/Preferences.app/General.plist. Debería poder hacerlo en un iPhone con jailbreak. En un teléfono que no sea Jb, no podrá acceder a él.