Code obfuscation

How iOS obfuscation enhances app security

Mobile apps for both Android and iOS are a constant target for hacking and reverse engineering. But still, many think that apps for iOS do not face the same risks as Android apps and, therefore, do not need the same level of protection.

When creating apps for iOS, many developers will focus on the app’s UX and UI before rushing to get it published to the App Store – potentially overlooking one key factor: security.

This article will give an overview of why iOS apps need code obfuscation, the advantages of using obfuscation methods, and other measures you can take to enhance the security of your iOS apps.

Why iOS apps need obfuscation

Mobile app-based cybercrime is ever-evolving, and hackers always find new and better methods to reverse engineer apps to identify weaknesses and secrets and get a hold of sensitive information.

Objective-C and Swift are the most common programming languages for iOS apps. Both are compiled into machine code, which makes it more difficult to translate the code back to the original source code. This has created a misconception that iOS apps are hard to reverse engineer.

However, the interest in analyzing and understanding machine code is nothing new, and there is a mature technology in place for reverse engineering machine code based on years of research and expertise in the field. In addition, when Objective-C and Swift are compiled to machine code, there is a lot of metadata in the binary that is required for these languages – which makes it much easier to understand the code than if you would, for example, use C code.

In other words, iOS apps are not difficult to reverse engineer and analyze, and it is important that you are aware of the threats and take the necessary steps to prevent them.

Apple encrypts the code of the applications submitted to the App Store and restricts access to the machine code of the apps after download to prevent easy static analysis of the application. A common misconception is that Apple’s own code encryption will be enough to prevent reverse engineering. With different tools for jailbroken devices, decrypted instructions can be dumped from memory, as the device will decrypt the encrypted static binary to execute the app, load it in memory, and reconvert it into the original unencrypted application. This means that if an app can be installed on a jailbroken device, Apple’s app encryption will not be enough to prevent reverse engineering or app analysis by a potential malicious actor. 

Code obfuscation has become standard for app developers to prevent hackers from easily decompiling and reverse engineering app code. The method scrambles the app’s code to make it hard to read and interpret. Concealing the logic and purpose of the code makes it significantly more difficult for an attacker to perform reverse engineering, analyze the code, and retrieve sensitive information.

Advantages of obfuscating your iOS apps

Using obfuscation methods for your iOS apps will make the application hard to reverse engineer, thus ensuring that your product’s intellectual property is protected against security threats, the discovery of application vulnerabilities, and unauthorized access.

When your IOS app’s code is obfuscated, the threshold for an attacker to carry out a reverse engineering attack is significantly heightened, as it will often be too time-consuming and costly to succeed.

With obfuscation, you can:

  • Better protect against intellectual property theft and unauthorized access.
  • Make your app’s functional logic on the client side and algorithms less exposed
  • Make it harder for attackers to find vulnerabilities in your code
  • Provide data and app security and integrity, particularly for those industries dealing with personal data

Obfuscation methods and techniques for iOS

There are various ways to obfuscate code, each with its own advantages and disadvantages. For example, a standard compiler like Clang has three main parts: a frontend that processes the source code, an intermediate level for initial compiling, and a backend that finalizes the code into a runnable binary format. As such, there are three approaches to code obfuscation:

  1. Source level: Alter the source code before the front end compiles it.
  2. Intermediate level: Manipulate the intermediate code before the backend turns it into binary.
  3. Binary level: Change the binary code right after compilation, before distribution.

Intermediate-level obfuscation and its demise

Low-Level Virtual Machine (LLVM) is an example of this intermediate approach. For app developers, LLVM bitcode has been a staple of Apple’s toolchain and the Android Native Development Kit for the past seven years. It’s a toolkit for building compilers that can work with any programming language and target any machine architecture. Compilers like Clang or Rustc use it to support various systems, from Linux on X86_64 to iOS. Obfuscation at this level is easier to manage since it’s not tied to a specific language or architecture.

One catch: this method often depends on the toolchain. For example, iOS and macOS apps that use intermediate-level obfuscation can be affected by updates to Apple’s development software, like the new Xcode 15 version, which has effectively deprecated the ability to build bitcode apps.

Does iOS 17 leave your app exposed?

Are you unsure if Apple’s recent deprecation of the LLVM bitcode in Xcode leaves your app exposed?

Get a consultation with one of our iOS experts

Binary-level obfuscation to the rescue

Binary code obfuscators work on the app code after it’s compiled. It disassembles, changes, and then combines the binary file or library. This way, you don’t have to worry about integrating it into your existing toolchain, and it’s not tied to LLVM bitcode like many other obfuscators. So, it’s not impacted by Apple’s recent changes to Xcode’s bitcode support. Plus, since it’s not tied to any specific toolchain, you can use it to secure different kinds of binaries, from Swift and C/C++ to Rust, Golang, Dart, and Unity. This means you can pick your favorite development tools without sacrificing security. Binary-level obfuscators offer some tremendous benefits:

  • They are not tied to the toolchain, and so, in theory, they can protect binaries from any compiler, e.g., Swift, C/C++, Rust, Golang, Dart, Xamarin, Unity, etc.
  • They are also not dependent on any development tools, and therefore, protection can be run entirely independently of the development process, e.g., by an IT Security function rather than developers.
  • Because they are dealing with actual machine code instructions, they can achieve finer-grained obfuscation than is possible at the intermediate level and certainly way beyond what is possible at the source level

An excellent example of such a next-generation approach is the Promon Jigsaw engine, the first cross-platform, post-compile, native obfuscation technology. Jigsaw is toolchain agnostic, which allows developers to freely choose the tools they prefer without compromising security.

Examples of code obfuscation techniques

You can use different techniques to obfuscate the code of your iOS app, such as control flow obfuscation and string obfuscation.

control-flow-obfuscation
By complicating the control flow, it takes a lot longer to understand where the code is going or why it takes a certain direction.

Control flow obfuscation

When determining the intent of an application, it is important to understand its control flow. Control flow obfuscation is to alter the “logical execution flow” of the application by controlling the flow of the application dynamic in a different and controlled manner. Obfuscating the control flow is a good way to obfuscate app logic and confuse hackers. By complicating the control flow by, for example, control flow flattening (shown in the graphic above), it takes a lot longer to understand where the code is going or why it takes a certain direction. Additional control flow obfuscation can be implemented by using arbitrary and unexpected statements and inserting dead code that would never be executed to hide the true control flow.

String obfuscation

String obfuscation hides strings by scrambling them in various ways. It hides and replaces strings with a (for the human eye) innocuous or non-sensical representation of the string. The CPU can de-scramble the string dynamically during execution, while an attacker would make little meaning out of the string from static analysis.

Is obfuscation alone enough?

While obfuscation is an important security measure that will help protect apps against reverse engineering and intellectual property theft, this security measure alone is not enough to fully protect your apps from malware and real-world attack scenarios.

Therefore, complete code protection combined with comprehensive runtime protection is essential to protect your iOS apps fully. Choose a security product that applies advanced and strong obfuscation techniques to your apps and other protection mechanisms. 

In addition to applying strong obfuscation techniques to your iOS apps, our app shielding solution will also monitor your app’s runtime behavior and detect if your app is executing in an insecure environment. Promon SHIELD™ also detects the presence of code hooks, blocks the injection of malicious code into the app, and enables your app to modify its behavior in real time to interrupt potential malware attacks.

Utilizing code obfuscation in combination with a multi-layered In-App Protection solution will make your apps less prone to reverse engineering and intellectual property theft.