This writeup covers the process of creating, disassembling and analyzing a very simple iOS app written in Swift. The main insight for me was an interesting handling of strings in Swift and how they are represented in the disassembly created by Hopper Disassembler. These insights, might be useful in future researches.
- Hopper Disassembler v4
I wanted to create a very simple app with Swift, to analyze the resulting disassembly. Therefore, a Single View App with only one View Controller projects was created with Xcode. I will not go through all of the necessary steps for creating a iOS app here, as it will have no value for the topic. The main functionality of the app was to check if the entered value for the passwordTextField is the same as defined in the variable secretPassword, and accordingly switching the text value of the resultLabel to either „Passed!“ or „You shall not pass!“.
On the following screenshot you can see all necessary information.
We will focus on the following string (?) values:
- „You shall not pass!“
Next a .ipa file was created, then extracted and the binary opened with Hopper.
I expected to discover all of the above mentioned string values to be visible in the Str section of Hopper. Guess what? I was wrong… Take a look at the following extract from the disassembly, here we can only see one of the three strings („You shall not pass!“):
How could that be? And were are the other values hidden? Why is the value „You shall not pass!“ treated different then „Passed!“?
A lot of questions so far… The question we will cover in this post is:
- Were are the other string values, and how can we recover them?
As we know, the value „1234“ must be somewhere around the variable definition of secretPassword, so that is where our search will start.
Right clicking on the variable name in Hopper and selecting References to „aSecretpassword“ at (address) lead to the corresponding structure. Repeating the process with the structure showed the following References:
I selected the first reference, and started reading the assembly code.
The interesting instructions are located at the addresses 0000000100005164 and 0000000100005168:
0000000100005164 movz w10, #0x3231
0000000100005168 movk w10, #0x3433, lsl #16
As we can see the values #0x3231 and #0x3433 are moved into the register w10. The arm processor has a little-endianness, that means the values can be re-arranged and concatenated as 0x31323334. This is the hex representation of the ascii-value „1234“.
Searching for the usage of the movk instruction also reveals the other hidden string „Passed!“.
Again we can re-arrange and concat the values moved to x1 this time as the following 0x50617373656421, which is decoded as ascii-value, the missing string „Passed!“.
When analyzing a iOS app written in Swift (no additional obfuscation applied, blackbox approach), one cannot always easily discover all string values from looking at the Str section in Hopper. Always look for noticeable instruction combinations of movz and movk in interesting methods or after promising variable names.