How I Reverse-Engineered one of the biggest GSM Operator’s application.

This is a story of how I found a critical bug in one of the biggest GSM Operator’s application in our country.

That bug allows me to login to any user account that I want, without a password.

After logging into an account, there was endless possibility what you can do, like forwarding all calls, reading his messages, fetching all invoices etc. So, that was a serious BUG and reported to the company immediately. This blog post will not make any disclosure about the company, about the application itself etc. All variable names and method names in the post were changed.

So, how I found the bug?

The story consists of 4 parts. Let me explain step by step.

After downloading their mobile application to my phone, I started to sniff all traffics of the application.

I used Charles MacBook app to sniff all traffics. All you must do;

Enable SSL sniff option in Charles, note your MacBook local wifi address (alt+wifi icon), set your wifi proxy address as your MacBook local address and set 8080 as port number (port of Charles) in your phone’s wifi configuration.

Alt + wifi icon to get your local address.

Phone WIFI settings to route traffic to Charles.

This is Charles:

Let me clarify some caveats.

You can not sniff SSL (https) traffics unless you trust Charles root certificate on your mobile phone.

Even you trust the root certificate, some applications like Facebook, AppStore etc. use more security protocols like SSL Pinning to block sniffing.

When SSL Pinning in use, the client does not trust your Self-Signed root certificate.

But even SSL Pinning in use, you can bypass it also.

Reference 1, Reference 2.

Lesson 1) So, you must know that, there is no way, NO WAY, no way to block curious eyes. Don’t forget this! Never forget this! Anyone can sniff your all network requests even you use SSL, even you use SSL Pinning! So, do not send critical information as plain texts in your requests!

So, after sniffing all traffics, I have tried to login to my account first and I have analyzed the login network request in Charles.

There was nothing interesting. But after logging in, the app displayed a page with some of the images like rabbit, lion, rose etc.

It was designed for fast login, after you choose an image and want to re-login the app, you just click your security image to login without your password.

The bug was there. When setting security image, I have analyzed the network request, there was only my phone number and image_id and some kinda signature in the POST data. Did you get it? There was neither my password nor a access-token in the POST data!

Lesson 2) Never trust your clients! Never trust your client’s input values on the request! You are in danger if you think “hashing something” is enough to execute requests!

So, I decided to re-simulate the first request in Charles (the request when I set my security picture). (to re-simulate a request in Charles, just right click on it and click “Compose”, after that, you can easily modify everything like post parameters, url etc. and after you can execute it)

Sample composing in Charles:

What I have realized when I play with the request was; Whenever I modify “my phone number” OR “my security image id” OR that “signature“, the server simply did not accept my request. So, that signature must consist of “my phone number” and “my security image id”, the server just compare the real signature and client signature in order to continue.

That signature was looking like that: “0b0e2288fc5e619c5587b914cf4830e34e1976b3”, so it has 40 characters, if you have ever used some hashing algorithms, you would know that MD5 algorithm creates 32 characters output, SHA-1 algorithm creates 40 characters output etc. So, it is likely they have used SHA-1 algorithm to create that signature.

Now, the fun part is here. Let’s decrypt the signed iOS app!

You may heard the jailbroken iOS devices’ capabilities.

The most important part of a jailbroken device for me is the ability to decrypt any app! Normally, you can not decrypt an app which is downloaded from AppStore because Apple signs all applications before distributing them! So, basically, no-one can decrypt an application. But, in jailbreak world, you can bypass Apple’s sign mechanism too!

After you apply jailbreak to your iOS device, activate SSH and connect your phone.

Get the application’s PID number on your iOS device by looking processes;

ps aux | grep /var/containers/Bundle/Application/

After you find the PID number, it’s time to decrypt it. I personally use bfdecrypt to decrypt apps.

bash bfinject -p APPS_PIDNUMBER -l /bfdecrypt-master/bfdecrypt.dylib -L decrypt

After that command, you will see a message in device logs, something like:

[dumpDecrypted] IPAFile: /var/mobile/Containers/Data/Application/E188FD33-F01B-4F5F-A4D5-F415C3E094D3/Documents/decrypted-app.ipa

Go and download the decrypted-app.ipa file to your macbook.

After you download it, change the extension to .zip to unzip it’s contents.

After unzipping, you will see a folder like that:

The folder consists of all images and files app uses, localization files etc. There is also App’s executable file in that folder with the name of: “APPNAME”

After you got the executable APPNAME file. It’s time to dump all headers of it!

I personally use Class-Dump for this.

Open your MacBook terminal and run this command:


After that command, there will be a new folder named OUTPUT_FOLDER_NAME, let’s look it’s content!

Oops, I can see your application’s all header files and I can easily guess what 3rd party SDK’s you are using!

I can also see your all method names, your all variables name too!

After looking all header files, I found the method which creates the SHA-1 signature. It was not so hard to find it because the method name was like “createSHA1SignatureStringForPhoneNumber:andPictureId” !

I have opened the executable file with IDA, to see what that method is doing step by step, (nowadays, I’m using Hopper instead of IDA)

(I have painted important parts with red, sorry, no disclosure!)

So, what is important here, please look number 1 and number 2 parts in red.

In number 1 part , I saw a static string like “35235nnASaf12” and in number 2 part I saw ‘%s%s’ method before returning the signature.

So it means, that method puts 2 string together and creates SHA-1 of them! I got the first string already in number 1 part.

So that method creates SHA-1 like SHA1(“35235nnASaf12+SOME_OTHER_STRING”).

But, how can I see SOME_OTHER_STRING part?

So, at this point, I was very close to understanding how the application creates the signature.

It is time to dive into the method itself! I mean : “createSHA1SignatureStringForPhoneNumber:andPictureId”

I personally use a fantastic tool for that, Cycript

With Cycript, you can inject into processes, you can call any method of the application, you can create Objects which app uses, whatever you want! It’s like the root access for any process and it uses JavaScript syntax!

First, start cycript with the PID number of app.

cycript -p PIDNUMBER

After that, you are like the root of the app!

You can call any method of the app with any parameters you want;

You can read & write all created objects and their values!

Or you can extend (hook) any method of the app with Theos Tweaks!

So what happens now when applying Hooks into functions?

Whenever the app calls this method, my hook will be called BEFORE, as you see in my code, I have logged all parameters the method receives (arg1 and arg2) and after that I have called and returned the main original method (so app can continue to execution)

I saw how they created the SHA-1 signature string, it was something like: “THAT_PART1_STRING(35235nnASaf12) + APPTOKEN + UDID+ MYPHONENUMBER + SECURITY_IMAGE_ID”

Lesson 3) Never do this mistake! If you think creating hash algorithms with some static random strings is enough, you are in a big mistake!

After all this information, I have tested to login my sister’s account with 8 lines of PHP code which generates SHA-1 string for the POST data, I was able to login her account without her password!

Timeline1: Bug was reported to the company immediately via email.

Timeline2 (+1 day): They have returned me and asked a couple of questions about how I could obtain that static string and SHA-1 algorithm etc.

Timeline3 (+1 day) I have summarized them the problem and the bug again.

Timeline4 (+6 days): They have returned me back and confirmed that they have fixed the bug.

Award for bug bounty: Nothing, the CTO’s and the CFO’s of most of the technology companies in Turkey are unqualified and have no vision. I hope one day, Turkey can keep up with the times on this issue. 🙂

Boğaziçi University, addicted to math algorithms, reverse engineering.