Si je veux que mon application se comporte différemment sur un iPhone jailbreaké, comment pourrais-je déterminer cela?
Cela dépend de ce que vous entendez par jailbreak. Dans le cas simple, vous devriez être capable de voir si Cydia est installé et aller par là - quelque chose comme
NSString *filePath = @"/Applications/Cydia.app";
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
// do something useful
}
Pour les noyaux piratés, c'est un peu plus impliqué.
+(BOOL)isJailbroken {
NSURL* url = [NSURL URLWithString:@"cydia://package/com.example.package"];
return [[UIApplication sharedApplication] canOpenURL:url];
}
Vérifier le chemin du fichier /Applications/Cydia.app
n'est pas autorisé sur un téléphone normal? Je n'ai jamais entendu parler d'Apple avoir détecté cela et rejeté une application, mais Apple est imprévisible. Cydia a un schéma d'URL cydia: // qui peut être vérifié légalement avec UIApplication canOpenURL:
Vérifier si le noyau est cassé n'est pas beaucoup plus compliqué.
Jailbreaking fait que la vérification de la signature du code signé par le noyau indique toujours que le code est signé correctement, les téléphones non cassés ne peuvent pas exécuter de code avec une signature incorrecte.
Donc, inclure un exécutable séparé dans l'application avec une mauvaise signature. Ce pourrait être juste un programme de 3 lignes qui a main () et une valeur de retour. Compilez l'exécutable sans signer de code (désactivez-le dans Paramètres du projet -> Construire) et signez-le avec une clé différente à l'aide de l'utilitaire de ligne de commande "codesign".
Demandez à votre application d'exécuter l'exécutable séparé. Si votre programme ne peut pas obtenir la valeur de retour lors de l'exécution de l'exécutable séparé avec la mauvaise signature, il est définitivement jailed. Si l'exécutable séparé renvoie A-OK, le téléphone est définitivement jailbreaké.
C’est un code qui combine certaines des réponses que j’ai trouvées pour répondre à ce besoin et qui vous donnera un taux de réussite beaucoup plus élevé:
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;
}
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
}
Vous pouvez détecter si un périphérique est bloqué ou non en vérifiant les éléments suivants:
J'ai créé une bibliothèque open source à partir de divers articles et livres. Essayez-le sur GitHub !
J'ai retravaillé dans Swift 2.3 la solution fournie par @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
}
La méthode la plus sophistiquée que je connaisse utilise la fonction objc_copyImageNames()
. Il retourne une liste des bibliothèques actuellement chargées et, comme la plupart des gens utilisent MobileSubstrate sur des périphériques jailbreakés et que la plupart des outils de crack iAP en dépendent, au moins certaines bibliothèques MobileSubstrate s'afficheront.
Essayez d’exécuter du code non signé via votre application.
Un appareil jailbreaké a généralement les caractéristiques suivantes:
Le simple fait de vérifier l’existence d’un fichier pour la détection de jailbreak est voué à l’échec . Ces contrôles sont faciles à contourner.
Ce que nous avons fait est que nous avons déjà un flux RSS pour communiquer avec nos utilisateurs ( Stocks Live ), nous avons mis une nouvelle qui indique quelque chose comme ceci:
Certains appareils jailbreakés ont des problèmes bla bla bla, nous avons fait un bidouillage pour résoudre ces problèmes, mais nous devons savoir s'il s'agit d'un appareil jailbreaké ou non, appuyez ici pour que l'application corrige le problème. Si vous revenez à la normale, c’est-à-dire que vous avez supprimé le jailbreak, appuyez ici.
Ensuite, vous traitez l’interaction de l’utilisateur et faites ce qui est approprié, comme se comporter différemment, etc.
Essayez de trouver un fichier créé par cydia ou un périphérique jailbreaké. Ou essayez d'écrire dans un fichier en dehors de la boîte noire de l'application. Si vous réussissez à faire cela, l'appareil est compromis/jailbreaké :)
- (BOOL)jailbroken
{
NSFileManager * fileManager = [NSFileManager defaultManager];
return [fileManager fileExistsAtPath:@"/private/var/lib/apt/"];
}
Je ne suis au courant d'aucune "API" qui existe pour cela. S'il en existait, un produit masquant le jailbreak les recouvrirait rapidement.
Comme beaucoup de gens le soulignent, il s’agit d’un jeu de chat et de souris. Et après que les deux joueurs deviennent experts, tout se résume à qui obtient le premier coup. (Personne qui tient l'appareil.)
J'ai trouvé beaucoup de bonnes suggestions pour détecter le jailbreak dans le nouveau livre de Zdziarski "Piratage et sécurisation d'applications iOS". (Personnellement, j'ai payé plus pour le livre électronique O'Reilly, car ils autorisent le copier-coller.)
Non, je ne suis pas affilié aux éditeurs. Mais j'ai trouvé un bon livre. Je n'aime pas simplement publier les erreurs des pirates pour qu'ils puissent les réparer, alors j'ai pensé pointer vers le livre.
Quelques fichiers courants à vérifier: /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 plupart vérifie les fichiers liés à Cydia.
Je suggérerais de rechercher des fichiers qui ne sont pas présents sur un iPhone "Vanilla". Tous les kits de jailbreak que j'ai vus installent ssh. Cela pourrait être un bon indicateur d'un téléphone jailbreaké.
Vous allez suivre une cible en mouvement, mais vous pouvez essayer de suivre la progression de ces ressources pour voir l'efficacité de votre technique:
Heres mes solutions:
extension UIDevice {
func isJailBroken() -> Bool {
var jailBroken = false
let cydiaPath = "/Applications/Cydia.app"
let aptPath = "/private/var/lib/apt/"
if FileManager.default.fileExists(atPath: cydiaPath) {
jailBroken = true
}
if FileManager.default.fileExists(atPath: aptPath) {
jailBroken = true
}
return jailBroken
}
}
et appelez-le dans viewDidLoad()
dans votre contrôleur de vue d'écran de lancement (ou le VC vous appelez pour la première fois):
if UIDevice.current.isJailBroken() {
// show a blank screen or some other view controller
let jailbreakVC = JailBrokenViewController()
self.navigationController?.present(jailbreakVC, animated: true, completion:nil)
} else {
// continue executing your next View controller
let nextVC = NextViewController()
self.navigationController?.present(nextVC, animated: true, completion:nil)
}