I'm trying to put anti-piracy code in my app. The previous answer to this (which I can't link to because of my member status - sucks) can be easily countered, since the "SignerIdentity" string can be looked for and replaced in the binary using a hex editor.
Instead, checking the fileSize of the info.plist file and comparing it to a reference value sounds more solid (since the info.plist is getting modified here and there when cracking the app). How would I do that? I tried the following but it logs 0.
NSBundle *bundle = [NSBundle mainBundle];
NSDictionary *mainDictionary = [bundle infoDictionary];
NSLog(#"%d", [mainDictionary fileSize]);
You might prevent the noobish crackers from finding references to "SignerIdentity" in your code by applying ROT13 or a similar simple obscuring algorithm
http://en.wikipedia.org/wiki/ROT13
After applying ROT13, "SignerIdentity" would become "FvtareVqragvgl".
Anyway, the answer to your question (how you get the size of the Info.plist file):
NSBundle *bundle = [NSBundle mainBundle];
NSString* bundlePath = [bundle bundlePath];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString* path = [NSString stringWithFormat:#"%#/Info.plist", bundlePath ];
NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:path
error:NULL];
if (fileAttributes != nil) {
NSNumber *fileSize;
if (fileSize = [fileAttributes objectForKey:NSFileSize]) {
NSLog(#"File size: %qi\n", [fileSize unsignedLongLongValue]);
}
}
Also keep in mind that the size (in bytes) of the Info.plist in your Xcode project directory and the Info.plist inside the bundle may differ. You probably want to build the game once, then look at the size of <your app bundle.app>/Info.plist and then update your antipiracy code.
I've never programmed for the iPhone, but couldn't you just take a hash of that file and compare it to a reference, possibly salting the hash value to prevent someone just changing the reference hash to the new one?
that code has still many giveaways:
the string Info.plist is easy to find. NSFileSize is also very suspicious....
As said here Determining if an iPhone is Jail broken Programmatically it looks like some of the most recent cracked apps installed via install0us don't have their info.plist modified. (at least the info.plist does not contain any signeridentity key).
How could we detect the crack in such a case ?
Related
I'm trying to access a resource file I added in the app using relative pathing. I've read that I was supposed to use something like this :
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *filePath = [[mainBundle resourcePath] stringByAppendingPathComponent:#"myFile.txt"];
fh = [NSFileHandle fileHandleForReadingAtPath:resourcePath];
Except this isn't working. With NSLog, I am able to confirm mainBundle isn't null and resourcePath returns something like this:
/Users/tom/Library/Developer/CoreSimulator/Devices/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX/data/Containers/Bundle/Application/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX/MyApp_Demo.app/myFile.txt
I've tried many things, such as adding the name of directory where the resource is located, that would be Ressources/myFile, but nothing is yielding any result.
I'm a total beginner with Objective-C but I have to tinker with legacy code and I have to deal with this, so any help is much appreciated.
Side note:
this is what the project structure looks like from Xcode:
Meanwhile, in Finder, the Ressources directory isn't inside the MyApp directory, rather they're on the same level inside the project directory. I wonder if that could be the problem.
Side note 2:
NSString *filePath2 = [[NSBundle mainBundle] pathForResource:#"myFile" ofType:#"txt"];
returns (null) after logging in the console.
It is best to use a simulator for this debugging process
Verification
You should check if the file or Resources folder is actually being copied to the right location or not. If you have added the Resources folder, than check it with the below code
NSString *resourcesFolderPath = [[NSBundle mainBundle] pathForResource:#"Resources" ofType:nil];
NSString *fullFilePath = [NSString pathWithComponents:#[demoToursPath,"filename.txt"]];
NSFileManager *manager=[NSFileManager defaultManager];
NSLog(#"Filepath: %#", fullFilePath);
NSLog(#"File Exist: %#", [manager fileExistsAtPath:fullFilePath]);
Once you have confirmed this, you can update your code to match the location and path it needs to be in order to access the file.
Additional Debug
You can also just print the Document Directory for the application and open a finder window and navigate there to see if the Resources folder is added at the right place (if it was added)
NSString *documentDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]
NSLog(#"Document Directory: %#", documentDir);
If you update the question with more info, I would be able to help you better
I've been using localization in my app, but for some reason, some of the strings (not all of them) won't translate, I see the key instead the value. I've tried to check if the app finds the localization files by doing this:
NSString *enPath = [[NSBundle mainBundle] pathForResource:#"en" ofType:#"lproj"];
NSString *hePath = [[NSBundle mainBundle] pathForResource:#"he" ofType:#"lproj"];
NSString *ruPath = [[NSBundle mainBundle] pathForResource:#"ru" ofType:#"lproj"];
NSString *esPath = [[NSBundle mainBundle] pathForResource:#"es" ofType:#"lproj"];
NSString *frPath = [[NSBundle mainBundle] pathForResource:#"fr" ofType:#"lproj"];
NSString *arPath = [[NSBundle mainBundle] pathForResource:#"ar" ofType:#"lproj"];
And none of them is nil.
I've checked the name of the localization file and it's Localizable.strings as it should be.
Also checked if the key exists inside the Localizable.strings files and it does.
I've also tried:
Empty Cache
Cleaning all targets
Delete Derived Data folder
Restart
Reset simulator
Convert to UTF-16
Remove all localization files and recreate them.
Also tried to do everything that is in this question.
It's important to say that this is not just a Simulator/Cache problem. It's also showing on devices which download the app. (I have Enterprise account).
What more can I do in order to identify nor fix the problem?
So I found the problem, I guess who translated the Localizable.strings files for me is an asshole. In 4 places in my strings file there was a row as followed:
"KEY" ;= "Value"
This line cause some kind of a crash, but let the compiler to build successfully for some reason. That's why I couldn't find the bug, only when I decided to take the last Key and Value which are not translate and move them to the top of the Localizable.strings file. Then I was able to understand and see that the problem is somewhere in the middle of the file and the top Keys and Values are translated fine.
One thing that you can do catch these kind of errors is to make a copy of the strings file, change the extension to plist and try to open it in Xcode. If there is any problem in the strings file it will show in Xcode since the dictionary will contain only the keys till the point where there is an error. You can then do a Find operation and find the error until you are sure that all strings appear in the plist file. You can then rename the file back to .strings
If you specify table:nil, then NSBundle will try to fetch the localization from the default table (the one in SOMELANG.lproj/Localizable.strings). If you have the localization elsewhere, you should explicitly specify the table using table:#"File" (or use the NSLocalizedStringFromTable() macro in a similar manner:
NSString *value = NSLocalizedStringFromTable(#"key", #"File", nil);
Also,
Double check that the Localizable.strings file is being added to
Targets -> BuildPhases -> Copy Bundle Resources
It hadn't been added automatically for me.
Currently using:
NSString* path = [[NSBundle mainBundle] pathForResource:#"filename"
ofType:#"txt"];
This only works however after I manually add the file into the application bundle.
I can use the documents directory but that's even worse.
After resetting the sim, the file goes away. How do I get it to stay?
How would I write out the file from somewhere to there? Like from a file in source? I don't want to alloc a several megabyte NSString object.
Credit goes to Lyle42 on freenode irc (#iphonedev):
I wasn't aware this field even existed. By adding any file into the copy files build phase (under build phases), they persist across builds.
Then this code:
NSString *_filePath = [[NSBundle mainBundle] pathForResource:#"filename" ofType:#"txt"];
NSLog(#"%#",_filePath);
NSData *_binary = [NSData dataWithContentsOfFile:_filePath];
NSString *_fileContents = [[NSString alloc] initWithData:_binary encoding:NSUTF8StringEncoding];
Works just great. (loads contents of file into an NSString).
You can use this to get your path for the file
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [documentPaths objectAtIndex:0];
filePath = [path stringByAppendingPathComponent:file_name];
you can get the file from your app bundle using
NSString *pathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:file_name];
I can use the documents directory but that's even worse.
Not really. The documents directory is persistent, and the recommended directory for essential documents created by your application. In addition, it's backed up by iTunes, and can be specified for iCloud backup. The app bundle just can't compete with that!
After resetting the sim, the file goes away. How do I get it to stay?
You can't, once the simulator has been "reset" (and I mean a hard wipe of all data and apps), nothing is saved. In between test builds, however, data copied out of the app bundle should survive unless you're storing things in /tmp. In addition, objects in the bundle are "refreshed" (recopied) in the build phase, meaning your resource isn't wiped out, merely reset to the one specified in your project.
How would I write out the file from somewhere to there? Like from a
file in source? I don't want to alloc a several megabyte NSString
object.
To read the file into memory, it would have to turn into a "several megabyte NSString" eventually, but if you really want to add a little IO to your plans for a massive string object, have a look at NSFileManager.
I am saving ipa file to.zip and when extracting the zip, I am getting application file, in which I am seeing all resource files. How can I make this it all secure?
Some of my friends are telling me, that someone can crack IPA and distribute it through torrents.
The code looks like the one below. Can any body help me out ?
NSBundle *bundle = [NSBundle mainBundle];
NSDictionary *info = [bundle infoDictionary];
if ([info objectForKey: #"SignerIdentity"] != nil)
{
/* do something */
}
Is there a way to check whether a file from the main bundle or documents directory on the iphone/ipad has been loaded successfully. I want a callback to do some extra things only on load, otherwise they do not execute because they are ahead of the file.
Thanks,
Ashley
EDIT: To avoid confusion, I actually need to run another method or just set some properties as soon as the file has loaded. Is there a completion block for this?
NSFileManager *manager = [[NSFileManager alloc]init];
NSString *filePath = [NSBundle mainBundle] pathForResource:#"Your File Name" ofType:#"YOur FIleTYPE"];
if([ manager fileExistsatPath: filePath])
{
NSLog(#"exist and loaded");
}
[manager release];
This is one way i think will work..there might be some error in the above code..i recommend autocomplete feature of Xcode