MASTG-TECH-0066: Static Analysis on iOS
The preferred method for statically analyzing iOS apps is to use the original Xcode project files. Ideally, you can compile and debug the app to quickly identify potential issues in the source code.
Black box analysis of iOS apps without access to the original source code requires reverse engineering. For example, no decompilers are available for iOS apps (although most commercial and open-source disassemblers can provide a pseudo-source code view of the binary), so a deep inspection requires you to read assembly code.
Using radare2 (iOS)¶
Radare2 (r2) is a powerful reverse engineering framework that provides a wide range of tools for analyzing binaries. This section explains how to use r2 effectively for static analysis, focusing on identifying and analyzing relevant functions in iOS applications.
For interactive analysis, you can also use radare2's visual mode by pressing V after opening a binary, which provides a more graphical interface for navigation and analysis.
Identifying Relevant Functions¶
Listing Functions:
Use the afl command to list all functions in the binary and combine the ~ operator to filter functions by name. For example, if you're interested in cryptographic functions, you can search using a filter like afl~SecKey to find all functions related to SecKey. If you already know the function name, you can use afl~<function_name> to directly filter for that specific function.
afl~SecKeyCreateRandomKey
You can also use the afl, command to output all function information in CSV format, which allows for custom views, filtering, and sorting of function details in a table. This is useful for more advanced analysis or when working with large binaries.
afl,
addr size name noret nbbs nins refs xref axref calls cc file
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
0x100007894 12 sym.imp.SecKeyCopyExternalRepresentation 0 1 3 2 2 2 0 1
0x1000078a0 12 sym.imp.SecKeyCopyPublicKey 0 1 3 2 1 1 0 1
0x1000078ac 12 sym.imp.SecKeyCreateRandomKey 0 1 3 2 1 1 0 1
0x1000078b8 12 sym.imp.SecKeyCreateSignature 0 1 3 2 1 1 0 1
0x1000078c4 12 sym.imp.SecKeyVerifySignature 0 1 3 2 1 1 0 1
0x1000078d0 12 sym.imp.__stack_chk_fail 1 1 3 2 2 2 0 1
...
Additionally, the aflc command shows the total count of functions identified in the binary:
aflc
175
Example: In Uses of Insufficient Key Size in SecKeyCreateRandomKey with r2, SecKeyCreateRandomKey is identified as a function of interest.
When Not to Use afl:
In some cases, functions may not appear in the list generated by afl. For example, canEvaluatePolicy is a dynamically resolved function and may not be listed.
afl~canEvaluatePolicy
< no results >
Instead, use flags (f), string searches with /, /z, iz~ and then use cross-references (axt) to locate its usage in the binary. This approach ensures that dynamically resolved or obfuscated functions are not overlooked.
In visual mode you can use
V_which is the visual hud that interactively filters all the flags, classes, methods, comments, symbols, strings in a single view. So you can simply typeV_, press enter, and then typecanEvaluatePolicyto find the references to the string.
f~canEvaluatePolicy
0x100008360 24 str.canEvaluatePolicy:error:
In the output, you can see a flag str.canEvaluatePolicy:error: representing the string canEvaluatePolicy:error: which is located at 0x100008360. You can then use the axt command to find cross-references to this string using its address:
axt @ 0x100008360
(nofunc) 0x100000350 [UNKNOWN] invalid
sym.func.100004ea8 0x100004f10 [STRING] ldr x1, [x8, 0xa0]
The output shows the cross-references to the given address, indicating where the function is used in the binary in two different locations:
0x100000350: This indicates an invalid reference, possibly due to dynamic resolution.sym.func.100004ea8: This indicates a valid reference to a function located at0x100004ea8, which can be further analyzed. The reference to the string will be at0x100004f10.
Identifying Strings¶
Listing Strings:
Use the iz command to list all strings in the binary. Combine it with ~ filtering to filter for specific strings. For example, to search for a string containing somestring:
iz~+somestring
Alternatively, you can use izz
Searching for Specific Strings:
Use the / command to search for a string directly in the binary:
/ somestring
Use advanced search options with /.
Analyzing Cross-References¶
Finding Cross-References:
Use the ax, command to display a table of all cross-references in the binary, which is especially useful for getting an overview or exporting data. You can filter this table by address using the ~ operator. For example, to show all cross-references to 0x1000078ac, run:
ax,~78ac
0x1000049a0 0x1000078ac 0 CALL --x sym.func.1000046f8 + 680 sym.imp.SecKeyCreateRandomKey
0x1000078ac 0x10000c000 4 ICOD --x sym.imp.SecKeyCreateRandomKey section.16.__DATA_CONST.__got
This will output only the rows related to the address 0x1000078ac, making it easier to focus on relevant references. The table includes columns such as source address, destination address, type, permissions, and symbolic names, helping you quickly identify where and how a function like SecKeyCreateRandomKey is used.
You can also open the entire cross-reference table with ax, and manually search or filter as needed.
ax,
from to size type perm fromname toname
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
0x100000040 0x100000000 0 NULL r-- segment.__TEXT + 64 segment.__TEXT
0x100000080 0x100000000 0 NULL r-- segment.__TEXT + 128 segment.__TEXT
0x1000000d0 0x100004000 0 NULL r-- segment.__TEXT + 208 section.0.__TEXT.__text
...
0x1000049a0 0x1000078ac 0 CALL --x sym.func.1000046f8 + 680 sym.imp.SecKeyCreateRandomKey
0x1000078ac 0x10000c000 4 ICOD --x sym.imp.SecKeyCreateRandomKey section.16.__DATA_CONST.__got
Use the axt command to find cross-references to a specific function or address. This helps you understand how and where the function is invoked.
axt @ 0x1000078ac
sym.func.1000046f8 0x1000049a0 [CALL:--x] bl sym.imp.SecKeyCreateRandomKey
The @ symbol is used for temporal seeking to a specific address for the duration of the command.
You can also pass the address directly to axt without using @:
axt 0x1000078ac
sym.func.1000046f8 0x1000049a0 [CALL:--x] bl sym.imp.SecKeyCreateRandomKey
Alternatively, you can use the s (seek) command to move to an address before running axt, which is useful if you plan to run multiple commands at that location:
s 0x1000078ac
axt
sym.func.1000046f8 0x1000049a0 [CALL:--x] bl sym.imp.SecKeyCreateRandomKey
Both @ and s accept partial addresses, so you don't need to type the full hexadecimal value. For example, [email protected] is sufficient if the address is unique.
There's also axg which finds the path between a function and its cross-references, showing the call graph in reverse of how functions are related. This is particularly useful for understanding the flow of execution in the binary.
The axg command output starts from the target function or address you gave it and works backward, showing which functions lead to it. So even though the output is printed top to bottom, it represents a path from the callee up to its callers.
axg ..78ac
- 0x1000078ac fcn 0x1000078ac sym.imp.SecKeyCreateRandomKey
- 0x1000049a0 fcn 0x1000046f8 sym.func.1000046f8
- 0x1000046f8 fcn 0x1000046f8 sym.func.1000046f8
- 0x1000063d8 fcn 0x1000063a0 sym.func.1000063a0
- 0x1000063a0 fcn 0x1000063a0 sym.func.1000063a0
- 0x100006fc4 fcn 0x100006fbc sym.func.100006fbc
- 0x100006fbc fcn 0x100006fbc sym.func.100006fbc
- 0x100006040 fcn 0x100005c8c sym.func.100005c8c
- 0x100005c8c fcn 0x100005c8c sym.func.100005c8c
- 0x100005944 fcn 0x1000056b8 sym.func.1000056b8
- 0x1000056b8 fcn 0x1000056b8 sym.func.1000056b8
- 0x100006de8 fcn 0x100006d60 sym.func.100006d60
In the above example, the call graph shows how SecKeyCreateRandomKey is invoked by sym.func.1000046f8, which in turn is called by sym.func.1000063a0, and so on, tracing back through the function calls. Reading it becomes easier after you've analyzed the functions and renamed them according to their purpose.
Example: In Uses of Insufficient Key Size in SecKeyCreateRandomKey with r2, cross-references to SecKeyCreateRandomKey are analyzed to ensure secure key sizes.
Inspecting Function Calls:
Use the pdf command to decompile a function and inspect its implementation. This provides insights into how the function operates.
pdf @ <function_address>
The @ symbol seeks to the specified address before executing the command.
Inspecting Specific Instructions:
Use the pd-- command to disassemble a specific number of instructions before and after a given address, providing context around that point in the code:
pd-- 5 @ 0x1000048c4
If you want to disassemble instructions starting from a specific address, use pd <number_of_instructions> instead:
pd 5 @ 0x1000048c4
This is particularly useful for examining the immediate context of a function call or instruction.
Tests¶
MASTG-TEST-0210: Broken Symmetric Encryption Algorithms MASTG-TEST-0317: Broken Symmetric Encryption Modes MASTG-TEST-0311: Insecure Random API Usage MASTG-TEST-0209: Insufficient Key Sizes MASTG-TEST-0213: Use of Hardcoded Cryptographic Keys in Code MASTG-TEST-0211: Broken Hashing Algorithms MASTG-TEST-0214: Hardcoded Cryptographic Keys in Files MASTG-TEST-0345: Embedded or Third-party TLS Stack Configuration MASTG-TEST-0343: URLSession TLS Protocol Configuration MASTG-TEST-0344: Network.framework TLS Protocol Configuration MASTG-TEST-0323: Uses of Low-Level Networking APIs for Cleartext Traffic MASTG-TEST-0333: Overly Broad File Read Access in WebViews MASTG-TEST-0335: WebView File Origin Access Relaxed by Configuration MASTG-TEST-0278: Pasteboard Contents Not Cleared After Use MASTG-TEST-0279: Pasteboard Contents Not Expiring MASTG-TEST-0280: Pasteboard Contents Not Restricted to Local Device MASTG-TEST-0331: Use of Deprecated WebView APIs MASTG-TEST-0332: Attacker-Controlled URI in WebViews MASTG-TEST-0346: References to APIs Hiding Sensitive Data in Text Input Fields MASTG-TEST-0276: Use of the iOS General Pasteboard MASTG-TEST-0266: References to APIs for Event-Bound Biometric Authentication MASTG-TEST-0268: References to APIs Allowing Fallback to Non-Biometric Authentication MASTG-TEST-0270: References to APIs Detecting Biometric Enrollment Changes MASTG-TEST-0303: References to APIs for Storing Unencrypted Data in Shared Storage MASTG-TEST-0313: References to APIs for Preventing Keyboard Caching of Text Fields MASTG-TEST-0297: Insertion of Sensitive Data into Logs MASTG-TEST-0300: References to APIs for Storing Unencrypted Data in Private Storage MASTG-TEST-0215: Sensitive Data Not Marked For Backup Exclusion MASTG-TEST-0281: Undeclared Known Tracking Domains MASTG-TEST-0240: Jailbreak Detection in Code MASTG-TEST-0248: References to APIs for Detecting Secure Screen Lock