Breaking iOS application. Part 1

Original author: Derek Selander
  • Transfer
  • Tutorial
You did a good job and here is your app on the App Store!

  • Keep user accounts?
  • Using in-app purchases?
  • Do not want to show your know-how?

Reason to think about code and data security! We will look for vulnerabilities in a test application. In this article, we’ll talk about data security, and in the next one , let's move on to the code.


The purpose of this lesson is not to make you a hacker, but to show how attackers can circle you around your finger. The article missed some info needed to crack a real application on the device. We will torture the simulator (by the way, it seems to be even legitimate [citation needed] ).

Disclaimer from the translator: a lot of “water” and references to Hollywood (and so long) were removed from the original text. A number of key clarifications have been added.


No application is safe! If someone really wants to find vulnerabilities in you, then he will find them. There is no guaranteed way to prevent an attack. Unless, release the application. But there are great ways to stop crackers. (According to the author, they will get tired, and they will go to bed to look for easier prey, huh. - Approx. Per. )

Before reading further, you should roughly understand what a terminal is, as well as Objective C and Cocoa (however, too much code will not).

Let's get started

We will need:
1. Utility class-dump-z ;
2. A proxy for debugging over the network, for example, Charles (the trial version is distinguished by annoying messages and works for a maximum of 30 minutes in 1 session). In the comments to the source of the article, they recommend an alternative to Charles - Burpsuite .

To get you creative in the process, I offer you a script. Imagine: a new iPad application has been released - “Meme Collector”. Everyone likes. But you were whispered in your ear that in-app purchases will draw a significant amount of money out of you.

In general, you are planning to get paid content (memes) for free. There are several areas where you can move, we will talk about them - and about the appropriate methods of protection.

Slight simplification
Due to the length of this tutorial, we initially made some simplifications in the test project. For example, the “purchase” of game currency is not a real in-app purchase, but a fake request to StoreKit (everything happens locally on the device).

What is what? "Map" of the application (application mapping)

Take a bird's eye view of the app! What does it do, from the point of view of the user? What is its basic structure?

Open the Meme Collector project in your favorite IDE or in Xcode (no ads).

We will run the application in the Release configuration.
Xcode: Product> Scheme> Edit scheme ... ( ⌘ < ) - select Run ... on the left, Info> Build Configuration: Release tab on the right.
AppCode: Run> Edit configurations ... > Configuration: Release.

Launch the app on the iPad simulator ( ⌘R ). And now forget that you have the source, you are the user. One of two things will open:

Do you have an option on the left?
Is this a habra effect or a connection problem. Memes are taken from the API - check what this url produces {"success":true,"result":[список мемов]}. During the translation of the article, they had problems with the server. If there is a desire to rid the project of dependence on this API, wellcome to github.

This strange interface allows you to "buy" a meme by tap on it, and also shows the number of purchases of this meme and the balance of money in your account. From the translator: by clicking the "Purchase Currency" button, I really thought: did I enter the Apple ID on the simulator?

... but I remembered that my credit card was not tied to the US account. :) Russian would say the price in rubles.

In general, everything is simple. There is a “game currency", and you (like a cracker) do not want to give real money for it. Our goal is to get more memes without clicking the "Purchase Currency" button.

We roughly understood what the application does, let's take a deeper look. What else can we learn?

The mentioned class-dump-z utilitywill show us all the declarations that it can get from the executable file. Download the latest version of the utility (for example, 0.2a), unzip the archive. In the terminal, go to the folder class-dump-z_0.2a/mac_x86/. There is an executable file class-dump-z, install it, for example, by copying to /usr/bin/:

sudo cp class-dump-z /usr/bin/

Go to the folder of the iOS simulator: (instead of 7.0.3 - your version)

cd ~/Library/Application\ Support/iPhone\ Simulator/7.0.3/Applications/

Here are all the applications that you run in the simulator. There may be many of them. How to find Meme Collector?

Option 1. If you just launched Meme Collector, then it lies in the folder with the latest modification date. Just go to it:

cd `ls -tr | tail -1`
What kind of magic is this?
  • The ls command returns the contents of the folder. The -tr flag sorts by time: the newest folder will be the last in the list.
  • This entire list goes to the input of the tail command. She takes a certain amount of data from the end. In this case, exactly one line (flag "-n 1" or just "-1").
  • Next, the cd command goes to this newest folder.

Option 2. Take and find:

find . -name "Meme Collector"

In my case, the folder is called 9A72F266-8851-4A25-84E4-9CF8EFF95CD4- hereinafter we will call it simply the “application folder”. It contains:
  • Meme - the main bundle
  • something else :)

A bundle is a folder (namely a folder, yes, with the extension .app), in which there is one or several executable files plus resources for them (pictures, sounds, digital signature, in general, anything, even other bundles ... read more ). Let's go to the main bundle folder:

cd Meme

There is an executable file, which is called: Meme Collector(without extension). Let's see which frameworks and shared libraries are referenced in it. The standard utility will help us otool:

otool -L "Meme Collector"

And here is what we see:

Meme Collector:
	/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration (compatibility version 1.0.0, current version 615.0.0)
	/System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices (compatibility version 1.0.0, current version 51.0.0)
	/System/Library/Frameworks/Security.framework/Security (compatibility version 1.0.0, current version 1.0.0)
	/System/Library/Frameworks/StoreKit.framework/StoreKit (compatibility version 1.0.0, current version 1.0.0)
	/System/Library/Frameworks/QuartzCore.framework/QuartzCore (compatibility version 1.2.0, current version 1.8.0)
	/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 2903.23.0)
	/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1047.22.0)
	/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics (compatibility version 64.0.0, current version 600.0.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0)
	/usr/lib/libSystem.dylib (compatibility version 1.0.0, current version 111.0.0)

Mm, interestingly, the application uses the Store Kit framework - in- app purchases? Well, let's move on. Run the class-dump-z utility :

class-dump-z "Meme Collector" > ClassDump.txt

And open the resulting file in a standard gui editor:

open ClassDump.txt
Wow! Although not, compared to the example from the original article (Xcode 4, iOS 6 SDK), there were unpleasant moments like XXUnknownSuperclass, but still! We see not only the interface part, but also declarations of private methods, properties, and protocols.

Studying the dump of classes in a serious project is often a tedious task. But it can give an amazing picture of the internal structure of the application!

So, my young ranger! Find me all the singletones in the app.

In signaltones, class method declarations with keywords are often found : manager, shared, store.

If you meet an interesting singleton, learn all its methods.
(Apparently, the "interesting" = "it seems to be relevant to the application logic." - Note lane.. )

Found exactly? Take a closer look at yourself. There are about four of them.

Yes all.
  • AFNetworking

  • MemeManager - an interesting singleton! He contains:
    @property(retain, nonatomic) AFHTTPClient* client;
    @property(readonly, assign, nonatomic) NSMutableArray* memes;
    -(void)getMemeInformation; // кстати, это private-метод

  • MoneyManager is also an interesting singleton:
    @property(readonly, assign, nonatomic) NSNumber* money;
    -(BOOL)saveState; // кстати, это private-метод
    -(void)loadState; // кстати, это private-метод

  • SVProgressHUD

Hackers often do what you just do - look for specific words in a class dump. For example, if they want to find out if the application has logic tied to the jailbreak of the device, then search by the words 'jailbroken', 'security', etc. can give a quick answer.

How to prevent this?

There are two news. I'll start with a good one.

Apple does this for you automatically. When you submit the app to the App Store, they encrypt your binaries using DRM technology called FairPlay . If you dump class-dump-z'om encrypted binary, you get ... gibberish.

The bad news: getting around this protection is pretty easy! The case for 10 minutes (manually), and there is still a means to automate this process. In general, be sure that your application will be decrypted and see the names of all your classes, methods, protocols, etc.

Plist files: vulnerable!

We learned something about the application. Now let's look for everything that is bad. Developers tend to make mistakes. Attackers tend to use these errors for their own purposes.

Mistakes ... Let's start with the most stupid ones! For example, how do you like the idea: use a .plist file to store critical information? Crackers always look at plists: they are easy to view, and their study can provide a key to the internal logic of the application. (Plist = property list, text file with serialized objects).

Let's see what plists we have?
(I remind you that we are still in the bundle folder “Meme”)

ls *.plist

And here are two things:

Info.plist           MoneyDataStore.plist

Let's see the first one - Info.plist:

plutil -p Info.plist


  "DTSDKName" => "iphonesimulator7.0"
  "CFBundleName" => "Meme Collector"
  "CFBundleDevelopmentRegion" => "en"
  "CFBundleVersion" => "1.0"
  "DTPlatformName" => "iphonesimulator"
…и ещё куча всего…

Nothing interesting, some general information. Okay. Well, and the second:

plutil -p MoneyDataStore.plist

And we see:

  "userCurrency" => 108

Joke! This .plist contains a key userCurrencywith the same value that you just saw on the simulator screen. Does this mean that the application stores money in .plist? There is only one way to find out!

open MoneyDataStore.plist

Change the value userCurrency, for example, to 1234. Save and close the .plist file.

Let's go back to the simulator. Let's remove our application from the RAM (as they say, “from multitasking”).
Just in case, an instruction.
The ⇧⌘H key combination in the iOS simulator corresponds to pressing the Home button . Press this combination twice to display the multitasking screen, and swipe the Meme Collector up to nowhere .

It seems that he is not very pleased that he is being brushed aside:
In the future, when I say "restart the application", I will keep in mind this particular operation.

Launch the application again. 1234 virtual tugriks at your disposal!
From a translator: I was waiting for more intrigue. It can't be that easy! At least write your test project.

User settings: unsafe!

Well do you understand? Keeping important information in .plist is not a good idea. Now guess: what are user settings ( NSUserDefaults)? Yeah, plist too! Physically, he is at the address {App Directory}/Library/Preferences/{Bundle Identifier}.plist.

This is exactly the place where developers often mistakenly feel safe. Not only freelancers: large corporations fall into this trap from time to time. Countless applications store important data in NSUserDefaults. Let's see what the Meme Collector has prepared for us here?

From the terminal (we are still in Meme, right?) Open the file:

open ../Library/Preferences/com.selander.Meme-Collector.plist

A simple exercise for you: using the methods mentioned above, modify NSUserDefaultsit to get a bunch of memes from the YU No ... series for free. Even if you already guessed everything, I advise you to do this to consolidate.

But attackers can gain access to plist files even when the iOS device is locked - so where is it safe to store data? One solution is to store the data NSUserDefaultsin encrypted form. In this case (and not only. - Approx. K.O. ), the data read from there must be checked for validity.

Keychain: the best recipes

Another possible solution is to transfer important data from .plists to the iOS Keychain. How to do this is written, for example, here .

The keychain "increases bids" for the hacker. Attackers will not be able to steal anything if the device is locked.

However, you should not rely completely on the Keychain alone! And that's why. The keychain is supported by Apple. (Well, you already understood everything, right?) The information in it is encrypted with a user password, which is usually a simple 4-digit digital code. This means that the brute force attack will take about twenty minutes. Having learned the password, it is easy to dump the entire keychain.

What to do? Some general recommendations:

  • Шифруйте данные! Связка ключей вроде как безопасна, но это приоритетная цель для хакеров, поэтому её ломают в первую очередь. (Про джейлбрейкнутые устройства вообще нечего говорить — для них существуют утилиты, показывающие содержимое Связки ключей.) Усложните жизнь взломщикам хотя бы ненамного: шифруйте данные с помощью CommonCrypto API, который входит в состав стандартного Security Framework (пример).

  • Не прописывайте ключ шифрования в приложении. Длинная строка в секции данных представляет потенциальный интерес для хакера. И вообще: если закрытый ключ прописан в приложении, злоумышленник может выложить его в сеть, скомпрометировав данные всех пользователей приложения! Обязательно генерировать уникальный ключ шифрования на каждом устройстве.

  • Контролируйте код! Конкретно — следите за возможностью хакера использовать ваш код в своих целях. Ваш метод шифрования/дешифрования может быть самым прекрасным решением. Но хакеры возьмут отладчик и применят ваш метод дешифрования к вашим же зашифрованным данным. Вы увидите это во второй части данного туториала (следующий пост).

  • Это точно нужно хранить? Раз злоумышленник может искать, модифицировать и выполнять ваши бинарники — просто спросите себя: эту информацию действительно нужно хранить на девайсе?

Сеть: тестирование на проникновение

Hackers also like to watch how the application interacts with the network. The dumbest way to see if there is any kind of network activity on the device is to look for URLs in the binary.

From the bundle folder (Meme, type in the terminal:

strings "Meme Collector"

Wait so much! The strings command goes through the sections of the binary and displays all data items that look like strings. Filter out the noise:

strings "Meme Collector" | grep http

Well, one line:

It seems that at some point the application turns to the meme generator for this url. As a hacker, you would like to investigate this matter further by examining the network traffic of the application. To do this, we need a network monitor that intercepts all incoming and outgoing requests.

Charles, mentioned at the beginning of the article, is a good option for such a study. Download it if you have not already done so. Install and run.

Check that Charles catches network interaction from the iOS simulator (by launching the "Maps", or in Safari to dial url). You will see how network requests run in Charles. If this does not happen, make sure that the Proxy> Mac OS X Proxy menu is checked.

By the way, Charles perfectly intercepts SSL traffic.
Мы не будем это делать, потому что не увидели HTTPS-урлов на выходе команды strings. Но этот шаг потребуется для других приложений, которые могут использовать HTTPS. В меню Proxy > Proxy Settings… > SSL нужно включить SSL-прокси и добавить домены, по которым требуется перехватывать (и расшифровывать) HTTPS-трафик. Пока вы это не сделаете, SSL будет выглядеть примерно так:

With Charles running, restart the Meme Collector. After starting, you should see three requests to version1.api.memegenerator.netby clicking on the triangle to the left of the url (see below). Three requests will be revealed, differing in GET parameters. For example, the first one has a GET parameter: urlName=Foul-Bachelor-Frog- this can be seen on the Request tab.

Select the Response tab and then below the JSON. The server response, decrypted from JSON, is presented in the form of a beautiful plate:

We see here a lot of lines of the "key-value" type: heading ( displayName), description ( description), URL of the image ( imageUrl) - in general, some information on this type of meme “Four Bachelor Frog ”from the GET parameter.

What happens next? The application does the same thing three times: an HTTP request for the image url, tries to download it from, receives the 301st redirect tocdn.memegenerator.netand shakes from there.

It looks like what we saw in the application, right? Two other pictures this time were less fortunate, they did not wait for a response from the server (Charles reports this on the Overview tab) and therefore did not appear in the application.

And I don’t see pictures being requested at all!
When you restart the images can be taken from the simulator cache, Charles does not know this. Clear the cache and restart the application.

rm -R Library/Caches/

So, with a certain degree of probability, we conclude: the application takes memes from this API and presents them in the form of paid content. But what if you try to change the URL in order to acquire some new content besides these three memes? It looks like there is a check here if the application really receives from the server what the developer expected!

Are you tired of these three memes? Well, let's try whether it is possible to display and “buy” something new, say, “Success Kid”.

Select Charles: Tools> Rewrite from the menu . This function allows you to intercept incoming / outgoing requests and modify them according to the rules that you set. Turn on the Enable Rewrite checkbox . Rules are grouped into “sets”. Under the Sets list, click add a new set of rules. Rename (Name) as desired. We have created a rule set, but it is empty so far. Let's add a rule - in the Rules section there is an Add button , click it.

The Rewrite Rule window opens. Change Type to “Modify Query Param” and fill in two fields:

  • Match> Name:urlName
  • Replace> Value:success-kid

Click OK, OK. Restart the application ... Success! We may purchase content that was previously unavailable.

Interesting: a specific price is indicated for this new meme. Where from? The application had to somehow determine the cost based on the JSON response.

Open the Response tab and look at the JSON that the server returns. What can determine the price value?

Try to find JSON keys that can determine the value of the meme in the application. Maybe it's generatorID, totalVotesScore, instancesCount, templatesCount or ranking. As an exercise for you: find the key that affects the cost of the meme.

To do this, go to Proxy> Breakpoints. Click Enable Breakpoints and click add a new breakpoint. The Edit breakpoint window will appear, enter the following data in it:
  • Protocol: http
  • Host:
  • Response option is enabled

Now restart the application. As soon as we get a response from the server, a breakpoint will work. When this happens, click on the Edit Response tab, select JSON below:

Here you can manually modify the JSON response that will go to the application. Play around with these options and try to determine which keys affect the price displayed in the application. After modifying the JSON response, click Execute to send the response. The application makes three API calls, so you need to click Execute three times.

Found which key affects the price?
That ranking. The more ranking, the lower the price.

Important: act fast! AFNetworkinghas a timeout of 30 seconds. If you intercepted the answer but didn’t manage to make changes, it AFNetworkingwill return a request timeout error and execute the corresponding handler in the code (which in this case does nothing). If you run out of time, restart the application and try again.

What's next?

You discovered hacking abilities and performed the simplest penetration tests using the example of a file system and network interaction of a specific application. You defeated simple plists and you can even modify server responses.

Perhaps this knowledge will increase the security of your iOS application ... a little. In the next part, we will delve much deeper into the bowels of the application, we will change its functionality! In the meantime, you are waiting for me to post the translation (until next Friday), you can try a lot of things on the topic of data storage in the application:

  • Try tools like iExplorer . iExplorer allows you to examine the contents of files that are used by your real applications. See what they store there.

    No jailbreak? Yah?

  • Set up SSL proxies in Charles and test it on real applications. Well, what is sending this application from your device, quietly sitting in the corner with a cute UI? You will probably be surprised. And observing the network connectivity of competing applications can provide an amazing understanding of how they solved network connectivity issues that are similar to yours.

  • Pull up your iOS assembler knowledge (ARM). The author advises this tutorial (in English). The next part of our lesson will be much more eventful! Get ready.

Comments about translation or broken examples can be sent to dev mail .

Also popular now: