How to extract NSString value from executable - ios

I'm encrypting data for an iPhone app using the CommonCrypto libraries. The data is local to the application. The encryption key is hardcoded in the code using an NSString.
I wonder if there is a way to access the value of this NSString from the app executable. I know that the code will be in executable form, but at the end an NSString have to store that value in plain text somewhere in the app. Accessing the app folder using iExplorer for example, will give full access to the executable.

Assuming the application was downloaded from the app store onto a device...
Decrypt the binary. This requires a jailbroken device, but it's trivial (there are many, many tools to do this, and tutorials on teh intarwebs)
Move the decrypted binary to a desktop
Run whatever tools you want on it. strings, etc. will all work. IDA Pro or Hopper will disassemble the binary and show not only the C strings in the binary, but the code that accesses it as well.
At this point you have the encryption key that ALL of the users of this application depend on.
...
Profit!
Pulling the C strings out of a binary is one of the first things any attacker will do. It's not recommended to store sensitive information in the binary, such as encryption keys. Unfortunately, there are not many secure ways to get an encryption key to a client. Assess the risks of different approaches and decide what level of exposure you are comfortable with.

Related

iOS obfuscation of supporing files

I have an sqlite table and some audio in my iOS application that I have put a lot of work and effort into, but looking through iFile or any other browser based application I can easily find these files and do whatever I want with them. If I can do this then someone else and more malicious than myself would be able to do the same.
How can I obfuscate my files while keeping them usable?
What you need to do depends on who you are protecting them from.
Using NSData "Data Protection" will protect the file only wheb the iDevice is locked—at best but is a step up.
Another method is to encrypt them with a key which you save in the keychain. on an iPhone 6s can encrypt 1Mb in 6ms, an iPhone 4s in 30 ms (using Common Crypto), so there is really no noticible speed degradation. A good candidate for this is a 3rd party library: RNCryptor, it handes many details needed to do this right. The attacker will have to be more than a cyrious user, this may meet your needs.
You need to define the attacker you are protecting against ranging from a curious kid to a well funded government.
Depending on how hard you want to make it, just hash all filenames so people can't see them. if thats too easy encrypt them ... I have an answer here on SO that details how to do this

How secure is a plist included in my xcode project after compilation?

If I store important values in a plist in xcode, is that less secure than if it was hard coded in a class? Could jail broken devices mess with those values easily? I know there's a certain level of risk with everything, but can someone explain the relative risks of a flat file vs hard coded values (in a MyClass.m file)?
Sub question:
How do you go about storing large amounts of initial data for a game/app to run on? It's fine if the values are readable, I just don't want them easily writable.
as for reading data:
plist data is not secure at all - getting plist content takes virtually no time! (and as the ipa is just a renamed zip you don't even need a device ;))
Extracting compiled code is 'harder' but in case of plain text strings only by a small margin.
(again: no need for a device)
as for writing to it:
data is you deliver is never writable without breaking the code signature. Therefore any method is fine. Often one ships CoreData databases when using CD, but I also use xmld, jsons, plists.. to deliver my content. whatever suits the needs best
note: breaking the code signature makes the app unusable on a stock iOS device but I think It'd remain usable on a jailbroken phone as the kernel doesn't really check the signature there
The values stored in you source files (.m) are safe, it is quite hard to access them. On the other hand accessing an app's plist, image sources, and other files are quite easy, there programs to achieve this (for example: Iexplorer) and it doesn't have to jailbroken at all.
So if you have sensitive information stored in your plist, it worth to encode the file, or store it in your source code.
Anyone can access a .plist file. But if is hard coded in a class is much more secure, use the second option. Nothing is 100% secure, but hard-coded in a class if someone want to access this value, the work is more hard.
You can store your Data into NSDictionary, then convert it to NSData, then do some simple crypto (re-order bytes for ex), then write to you application folder. When you want to read them, just take the content of the file, then decrypt, then re-create NSDictionary.
convert NSDictionary to NSData:
NSData *someDatas = [NSKeyedArchiver archivedDataWithRootObject:aDictionary];
convert NSData to NSDictionary:
NSDictionary *aDictionary = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithData:someDatas];
The data is secure in the way that the user cannot modify the content the right way cause the data won't be valid while application read it.
If you're looking to store sensitive values that you don't want jailbroken devices or reversed engineered app to get access to, you can easily think of using UAObfuscatedString.
As quoted:
When you write code that has a string constant in it, this string is saved in the binary in clear text. A hacker could potentially discover exploits or change the string to affect your app's behavior.
UAObfuscatedString only ever stores single characters in the binary, then combines them at runtime to produce your string. It is highly unlikely that these single letters will be discoverable in the binary as they will be interjected at random places in the compiled code. Thus, they appear to be randomized code to anyone trying to extract strings.
Having values hard coded in code or in a plist file is considered risky for sure.

Encrypting iOS app binary file

I'm building an iOS app but my app binary shows all my NSStrings that I've. Is there a way to encrypt it ?
I want to hide all my NSStrings from my app binary file.
You would not be able to encrypt your app binary in an secure way. You would at least need to pass the key next to the application bundle so the operating system would be able to encrypt the application before running it. And when you pass the key next to the application somebody interested in your application would be able to decrypt it too. So encrypting the whole binary file would be useless.
Do you ship passwords or API keys with your app bundle?
The best deal would be to redesign your application so such stuff isn't needed. You could try to prevent user from reading them directly out of your binary file, but they would always be able to get them. A couple of very smart guys have already tried that and failed, so don't waste your time trying to be better then them. So don't ship passwords or API keys!
If you still want to ship sensitive data in your binary:
You could give the following a try:
NSString *encryptedSensitiveString = #"mysensitivdatapreviosulyencpryted"; // <- this will be stored in your binary since it's a constant string
NSString *sensitiveString = [someHiddenKey decryptString:encryptedSensitiveString];
// Now you can use your sensitive string which is decrypted at runtime
If you are looking for some cryptography library for Objective-C you can use MIHCrypto framework based on OpenSSL.
As someone already stated, building or decrypting the strings dynamically is one choice.
Another is to use a 3rd party app protection system, like Arxan. I have never personally used it so can't really recommend it, but it does all sorts of obfuscation to prevent users from peeking into your app.

Where to store decrypted files?

I am encrypting downloaded files and saving them locally in app's documents directory.
To read them you must decrypt those file and store some where temporarily.
My concerns are:
1.if I store them in doc directory for time they are being used, for that time window one can get those files using tools like iExplorer.
2.My idea is to store them in memory for the time they are being used and flush the vault after use.
This option is good for small files but for large files say 50 MB or video of 100 MB, I am afraid that app will receive memory warning in result will terminate abruptly.
I want to know the best approach for doing this.
There is no perfect security storing local files in a safe way. If a person has full access to the device, he can always find a way to decrypt the files, as long as your application is able to decrypt it.
The only question is: How much effort is necessary to decrypt the files?
If your only concern is that a person may use iExplorer to copy and open these files, a simple local symmetric encryption will do the trick.
Just embed a random symmetric key in your application and encrypt the data block by block while you download it.
You can use the comfortable "Security Transforms" framework to do the symmetric encryption. There are some good examples in the Apple Documentation.
When you load the files, you can use the same key to decrypt them while you load them from the file system.
Just to make things clear: This is not a perfect protection of the files. But to decrypt the files, one has access to your app binary. Analyse this binary in a debugger and searching for the decryption part to extract your symmetric key. This is a lot effort necessary just to decrypt the files.
Split your files into smaller sizes before saving them, then decrypt on load.
Later edit: I noticed this is mentioned in the comments. I agree splitting files isn't the easiest thing in the world, but presumably you'll only need this for video. About 100MB is a lot of text or audio. If your PDF weights as much, it's probably scanned text, and you can change it into a series if images.
And yes, splitting better be done server-side, don't want the user waste battery in video processing.
Decrypt them, obfuscate them with a toy algorithm (e. g. XOR with a constant block), and store them in documents. When needed, load and decrypt.
Since the problem has no solution in theory (a determined enough attacker can read your process memory after all), it's as good a solution as any.

Make it hard to tamper with game data on non-jailbroken devices

We are developing a game where all the game logic is executed locally (no server back-end) and would like to make it difficult to tamper with game data (such as user credits, game settings and so on).
Now, it's even possible on non-jailbroken devices to access the filesystem and change game data - so, for example if user inventory stats are stored in a plist file, it's very easy to edit them.
If we move game settings from plist files to source-code files, such that they get compiled into the binary, it will require at least a modification of the binary to change settings. On non-jailbroken phones - will modified binaries still run, or does the apple codesigning prevent from modifying the binaries in any way?
What are some quick and easy to implement measures to make it a bit harder to tamper with game-data (especially on non-jailbroken phones. Optimally we'd like to provide some kind of security that will at least require a jailbreak to make modifications to the game)?
so - to summarize the questions:
can the binary part of an iOS app be modified and still run on non-jailbroken devices?
what are some quick and easy to implement measures to make it harder to tamper with gamedata on non-jailbroken devices?
You can't modify the binary as it would invalidate the signature. I would just use some sort of encryption on the data you don't want users to modify. You can make this as simple or as complex as you want. I don't think iOS provides any kind of encryption services out of the box, but you don't need to go hog wild with it - a simple ROT13 algorithm would do, since we're not talking about password-level security here. If you want, you can even add a checksum on the encrypted data, then invalidate it if the checksums don't match.
To answer your questions:
No. The application will be required to be signed again.
A simple but not unbreakable measurement is to safe the data in a secure container (key chain for example) or encrypt it yourself before you safe it to disk. An attacker now have to monitor a running app to get to the decrypted data in memory - or need to crack the secure store.
There are a few ways on iOS (and Mac OS X) where you can accomplish to encrypt and decrypt data. One way is pretty nicely described here in the official docs:
Encrypting and Decrypting Data.

Resources