ios app security

How to detect that an emulator is being used to run the app?

Attacks on mobile applications (e.g. payment apps) often start with the use of an emulator for the mobile operating system in which the target application will be run and analyzed.

In order for an attacker to e.g. attach a debugger, reverse the code, tamper the app, he usually needs to use an iOS emulator in the first step.

The role of a well-secured application is therefore to prevent it from running in a simulated environment.

So let’s go to the solution. To detect if an application is running on a simulator, you can perform this check in two ways:

  • static analysis using platform ‘targetEnvironment‘ (Swift Evolution SE-0190) condition with explicit argument ‘simulator’
    func performStaticChecks() -> Bool {
        #if targetEnvironment(simulator)
            return true
        #else
            return false
        #endif
    }
  • dynamic analysis using the ProcessInfo object (a set of information about the current process) by evaluating the value of the environment dictionary for the SIMULATOR_DEVICE_NAME key.
    func performDynamicChecks() -> Bool {
        ProcessInfo().environment["SIMULATOR_DEVICE_NAME"] != nil
    }

Let’s talk a bit about the first solution. You could say that dynamic analysis is enough, but what if, for example, you wanted to have different imports on the device and on the simulator. This is not possible with dynamic checking.

There is also a story behind the first solution. In the past, the technique for doing this involved testing for particular combinations of presumed mismatch between architecture and operating system. This was fragile and non-obvious, and required reasoning about complex nested conditions that obscured the user’s purpose.

For example, to detect any simulator, the code looked like this:

#if (arch(i386) || arch(x86_64)) && (os(iOS) || os(watchOS) || os(tvOS))
...
#endif

Luckily since Swift 4.1, we have the improvement mentioned above (targetEnvironment), and now we have only one condition for all types of simulators.

More explanation can be found in the Swift SE-0190 proposal.

Finally, I would like to mention one important thing. You have to remember that there are differences between emulator, virtual machine, and simulator. The emulator “emulates” the entire system (including the processor) in the software. The virtual machine uses a real CPU to perform virtualization. The simulator works more like a “stub” system that mimics rather than emulates (hence the name).

So different checks can fail in certain environments (hackers come up with different ideas, and can create different solutions).

It is therefore also worth adding additional security measures, such as file system, network and hardware availability analysis.

Leave a Reply

Your email address will not be published.