In my app i need to check sometimes if the running device is a jailbreak device or not. This is the most complete method i have found:
BOOL Jail=NO;
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"]]) {
Jail= 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);
Jail= 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)
{
Jail= YES;
}
What i haven't found, it's a clear answer to the question: "Apple will approve this code?" , in guidelines i can read:
"Apps that read or write data outside its designated container area will be rejected".
However it's clear that i'm trying to write or read only to check if the device is jailbroken... So there's someone that have successfully submitted this code to apple?
This is the code of a submitted app
BOOL bash = NO;
FILE *f = fopen("/bin/bash", "r");
if (f != NULL)
{
bash = YES;
}
fclose(f);
return bash;
So, I believe your code will be accepted too
Maybe.
Many developer's have been rejected for including jailbreak checking, and many have not. If you submit with a jailbreak check, you should NOT expect to be approved (although you may get through the review process this time).
App with jailbreak detection rejected by Apple
https://github.com/sat2eesh/ios-jailBroken/issues/4
Related
Following is general knowledge question for my owns awareness, actually I am new to iOS programming, in my very first app I used to save access a json file and photos which I placed in a free webserver, but I am not sure about how many days I can acquire benefits from that feee web server. hence I was planing to purchase a web-domain & web-space, meanwhile I come to know about apple icloud storage, so the question is that can I save same json file & other image files at icloud and can access in same way as I used to save & access at private web server? and also willing to know, how much data can be transfer (total traffic consumption of data on daily basis and monthly basis)?
1)You can access the icloud file :
NSArray *tempArray=[[iCloud sharedCloud] listCloudFiles];
2)To Download :
NSFileManager *fm = [NSFileManager defaultManager];
NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
if (ubiq == nil) {
return NO;
}
NSError *theError = nil;
[fm setUbiquitous:true itemAtURL:backupUrl destinationURL:[[ubiq URLByAppendingPathComponent:#"Documents" isDirectory:true] URLByAppendingPathComponent:backupName] error:&theError];
NSFileManager *fm = [NSFileManager defaultManager];
NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
if (ubiq == nil) {
return NO;
}
NSError *theError = nil;
bool started = [fm startDownloadingUbiquitousItemAtURL:[[ubiq URLByAppendingPathComponent:#"Documents" isDirectory:true] URLByAppendingPathComponent:backupName] error:&theError];
NSLog(#"started download for %# %d", backupName, started);
if (theError != nil) {
NSLog(#"iCloud error: %#", [theError localizedDescription]);
}
I am working on a project (mobile app) where I need to monitor adversary actions. So, my question is how can I make iOS app tamper-evident?
e.g.
Whenever any adversary try to tamper code then system should alert admin for these actions
and block that adversary
If user tries to install app on rooted device then system can detect that.
System should able to monitor adversary actions.
I found solution for android like ProGuard, SafetyNet but did not found anything for iOS.
I've used this JailBreak detection in one of my project.
With this, you can prevent the possibility.
if ([DTTJailbreakDetection isJailbroken]) {
// your custom activity and business logic here
}
Also, In precise you can use the below snippet:
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;
}
Also , Obfuscation in iOS - objective C you can use this open source-library and for Methods & Classes.
Apart from detecting jailbroken device, and obfuscating code (as #itechnician mentioned), you can:
Detect if debugger is attached: https://developer.apple.com/library/content/qa/qa1361/_index.html
Check the load commands in Mach-O header to check if there's anything injected
Check code integrity
Anyway, all of these can be easily bypassed when on jailbroken device (even the check if it's jailbroken). The best way is to use multiple techniques including obfuscation, to make tampering as hard as possible (so it's not worth it). But I'm not sure if you could make fully tamper-proof app.
You might find these links useful:
https://www.coredump.gr/articles/ios-anti-debugging-protections-part-1/
https://www.raywenderlich.com/45645/ios-app-security-analysis-part-1
http://resources.infosecinstitute.com/ios-application-security-part-31-problem-using-third-party-libraries-securing-apps/
This book is a bit old, but still useful: http://shop.oreilly.com/product/0636920023234.do
Here are opensource ObjC obfuscators/string encryptors:
https://github.com/Polidea/ios-class-guard
https://github.com/FutureWorkshops/Objc-Obfuscator
https://github.com/pjebs/Obfuscator-iOS
I think you're looking something like ixguard
I have a following code, which copies folder from the app bundle to the Documents folder.
- (void)moveTessdataToDocumentsDirectoryIfNecessary
{
// Useful paths
NSFileManager *fileManager = [NSFileManager defaultManager];
// Create specified folder in the Documents directory first
if ([fileManager fileExistsAtPath:self.dataPath] == NO) {
[fileManager createDirectoryAtPath:self.dataPath withIntermediateDirectories:YES attributes:nil error:nil];
}
NSString *tessdataFolderName = #"tessdata";
NSString *tessdataPath = [[NSBundle bundleForClass:self.class].resourcePath stringByAppendingPathComponent:tessdataFolderName];
NSString *destinationPath = [self.dataPath stringByAppendingPathComponent:tessdataFolderName];
if([fileManager fileExistsAtPath:destinationPath] == NO && [fileManager fileExistsAtPath:tessdataPath]) {
NSError *error = nil;
NSLog(#"found %#", tessdataPath);
NSLog(#"coping in %#", destinationPath);
BOOL res = [fileManager copyItemAtPath:tessdataPath toPath:destinationPath error:&error];
if (!res) {
NSLog(#"The result of copyItemAtPath == NO");
}
if(error != nil) {
NSLog(#"ERROR! %#", error.description);
}
}
}
It works fine in a sumilator and in a device.
The issue happens when I start unit tests for this function.
The output while unit testing is:
found /Users/kmakankov/Library/Developer/CoreSimulator/Devices/D28F7234-8C28-4325-BE7D-4DF113DF427E/data/Containers/Bundle/Application/EBD5C654-897B-4066-885B-986553D3459F/TestsProject.app/tessdata
coping in /Users/kmakankov/Library/Developer/CoreSimulator/Devices/D28F7234-8C28-4325-BE7D-4DF113DF427E/data/Containers/Data/Application/50D673A6-3F3E-42A1-98A1-DEAF9A4B2FBE/Documents/tes/tessdata
The result of copyItemAtPath == NO
So as you can see the copyItemAtPath return NO, but there is no error message, so I cannot understand what is the reason of the issue.
Furthemore, If I change copyItemAtPath with moveItemAtPath the function correctly moves the folder from the source to the destination during unit testing, so both source and destination paths are correct.
Does anybody knows what's wrong with copyItemAtPath?
Some extra info. I use iOS SDK 8.1.
I want to pre-fill core data from plist. got that sorted. anyway in order to NOT pre fill core data WHEN iCloud has the data allrdy. how do i check for that ?
i'm useing Magical Record to import and handle my Core Data+iCloud and it works
either i miss some step somewhere or i don't know. it imports and checks if there is a value allrdy if there is it doesn't import. i hope
it works in local storage but as soon as i turn on iCloud it gets messy
i found this but it doesn't work for me. i'm not sure it's the right way to do it
.Some how i think i need to first check if iCloud is enabled then if there's content or i'm i totally wrong here ?
NSURL *ubiq = [[NSFileManager defaultManager]
URLForUbiquityContainerIdentifier:nil];
if (ubiq) {
NSLog(#"iCloud access at %#", ubiq);
}
else {
NSlog(#"No iCloud")
}
Check that:
- (BOOL) iCloudCheckContent{
NSString* backupName = #"myBackup";
NSError *error = nil;
NSFileManager *filemanager = [NSFileManager defaultManager];
NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
if (ubiq == nil) {
NSlog(#"No iCloud");
return NO;
}
bool ret = [filemanager startDownloadingUbiquitousItemAtURL:[[ubiq URLByAppendingPathComponent:#"Documents" isDirectory:true] URLByAppendingPathComponent:backupName] error:&error];
NSLog(#"Started for %# %d", backupName, ret);
if (error != nil) {
NSLog(#"iCloud error: %#", [error localizedDescription]);
}
return ret;
}
My app was rejected cause it seems that 7 mb are stored in documents folder and they are automatically send to icloud. So i have looped all files that will be written to documents folder throught this method :
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL {
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
if (&NSURLIsExcludedFromBackupKey == nil) {
// iOS 5.0.1 and lower
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result == 0;
}
else {
// First try and remove the extended attribute if it is present
int result = getxattr(filePath, attrName, NULL, sizeof(u_int8_t), 0, 0);
if (result != -1) {
// The attribute exists, we need to remove it
int removeResult = removexattr(filePath, attrName, 0);
if (removeResult == 0) {
NSLog(#"Removed extended attribute on file %#", URL);
}
}
// Set the new key
NSError *error = nil;
[URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
return error == nil;
}
The version 1.1 of my app was approved after this code implementation. Last week i tried to send the version 1.2 of the same app (nothing has changed in file management, all files that are stored in documents folder are looped through the addSkipBackupAttributeToItemAtURL method). My app was rejected again for the same reason. I can't move my file to temp or cache folder because my app can't completely restore the file (one of this file is a db, restoring db means loose any user inserted data), so this one can't be the solution. Anyway i have found an issue in the code, this is how i call the method :
[self addSkipBackupAttributeToItemAtURL:[NSURL fileURLWithPath:fullPath]];
using [NSURL fileURLWithPath:fullPath] device with ios 5.1 return an error and it seems impossible to create the attribute. If i change the initialization of the nsurl with [NSURL URLWithString:defaultStorePath], device with 5.1 seems to add correctly the attribute.
With ios 5.0.1 all is inverted , [NSURL URLWithString:defaultStorePath] return an error while [NSURL fileURLWithPath:fullPath] works.
Maybe i can check ios version and set an appropriate nsurl initialization, but it still remains a problem. In rejection explanation i read :
In particular, we found that on launch and/or content download, your app stores 7mb. To check how much data your app is storing:
Install and launch your app
Go to Settings > iCloud > Storage & Backup > Manage Storage
If necessary, tap "Show all apps"
Check your app's storage
If i try to check this value i see 7 mb also with the correct nsurl initialization (when all the attributes are set correctly) . What is the correct behaviour? Anyone with this problem? Do I have to do something specific before the app storage check suggested by apple to make it significant?
I think the trick is to add the NSURLIsExcludedFromBackupKey AND make sure the directory is outside the documents directory. I did this by moving my documents to the Library/Application Support folder (since it didn't make sense in the /tmp or /Caches folders):
// store in /Library/Application Support/BUNDLE_IDENTIFIER/Reference
// make sure Application Support folder exists
NSURL *applicationSupportDirectory = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:YES
error:&error];
if (error) {
NSLog(#"KCDM: Could not create application support directory. %#", error);
return nil;
}
NSURL *referenceFolder = [applicationSupportDirectory URLByAppendingPathComponent:#"Reference" isDirectory:YES];
if (![[NSFileManager defaultManager] createDirectoryAtPath:[referenceFolder path]
withIntermediateDirectories:YES
attributes:nil
error:&error]) {
NSLog(#"KCDM: Error creating Reference folder to store model %#: %#", modelName, error);
return nil;
}
BOOL success = [referenceFolder setResourceValue:#YES forKey: NSURLIsExcludedFromBackupKey error: &error];
if(!success){
NSLog(#"KCDM: Error excluding %# from backup %#", referenceFolder, error);
}
I had the same problem as you until I deleted my app from my device, and re-installed. I also had to delete the existing cached data from the iCloud backup by going to Settings->Storage&Backup -> Manage Storage
That seemed to do the trick.
Also, my code to add the skip attribute is a bit different:
Code lifted from this post
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
{
assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);
if (&NSURLIsExcludedFromBackupKey == nil) { // iOS <= 5.0.1
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result == 0;
}
else { // iOS >= 5.1
NSError *error = nil;
[URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
return error == nil;
}
}