WEBVTT

1
00:00:00.600 --> 00:00:06.175
Welcome. This tutorial covers the debugger, emulator, and simulator signals.

2
00:00:06.625 --> 00:00:12.575
Two of them look at attached debuggers, one per platform, and two look at virtual devices.

3
00:00:13.025 --> 00:00:18.100
We will see what each one checks, when it is expected, and how to set the policy.

4
00:00:19.700 --> 00:00:26.450
A debugger lets an attacker pause the app, read and change memory, and step through your security logic.

5
00:00:26.900 --> 00:00:33.325
An emulator gives them a disposable, scriptable device, perfect for fraud farms and bots.

6
00:00:33.775 --> 00:00:37.625
But both are completely normal while you develop your own app.

7
00:00:38.075 --> 00:00:43.425
So the library reports them as context signals, and lets you decide what they mean.

8
00:00:45.033 --> 00:00:53.433
On iOS, the debugger check uses sysctl, the Apple documented way, to read this process's kinfo proc structure.

9
00:00:53.883 --> 00:01:01.133
It then tests the P_TRACED flag. If it is set, a debugger such as LLDB is attached.

10
00:01:01.583 --> 00:01:07.458
Frida and similar tools attach without setting that flag, so this check does not catch them.

11
00:01:07.908 --> 00:01:15.558
It also fires while you debug from Xcode, which is expected, and is why it is marked as a context signal.

12
00:01:17.167 --> 00:01:24.492
On Android the check uses the Debug API: is a debugger connected, and is the app waiting for one.

13
00:01:24.942 --> 00:01:33.067
Either one being true means a Java debug wire protocol debugger, like Android Studio, is attached or awaited.

14
00:01:33.517 --> 00:01:39.667
A native debugger using ptrace, or Frida, does not set it, so those are not caught here.

15
00:01:40.117 --> 00:01:45.767
Same rule as iOS: expected during development, so treat it with context.

16
00:01:47.400 --> 00:01:52.500
The Android emulator check fingerprints the device through its Build properties.

17
00:01:52.950 --> 00:02:01.425
It looks for generic or unknown fingerprints, goldfish, ranchu, or vbox86 hardware, and the Genymotion manufacturer.

18
00:02:01.875 --> 00:02:09.925
It also checks for QEMU device nodes. Requiring one strong indicator avoids false positives on real phones.

19
00:02:10.375 --> 00:02:15.925
Anti-detection emulator builds can spoof the Build fields and delete those nodes.

20
00:02:17.533 --> 00:02:25.308
On iOS the simulator signal is a compile-time fact: the module was built with TARGET_OS_SIMULATOR.

21
00:02:25.758 --> 00:02:31.758
So it cannot be faked at runtime. It is not an adversarial check, it just reports a fact.

22
00:02:32.208 --> 00:02:41.408
On the simulator, the filesystem, URL scheme, symlink, writable, and DYLD checks are skipped, because they would inspect the host Mac.

23
00:02:41.858 --> 00:02:48.708
The hooking library and debugger checks still run. Skipped by design is not the same as incomplete.

24
00:02:50.333 --> 00:02:57.658
By default, every category except emulator makes the status compromised. That includes an attached debugger.

25
00:02:58.108 --> 00:03:04.683
Set treat emulator as compromised to block emulators and simulators, for example in production.

26
00:03:05.133 --> 00:03:09.508
Or pass a policy listing exactly which categories should count.

27
00:03:09.958 --> 00:03:16.908
And during development, ignore the debugger signal so Xcode and Android Studio runs are not blocked.

28
00:03:18.533 --> 00:03:26.908
Here is the real example app on the iOS Simulator. The status is clean, with a single context signal: simulator.

29
00:03:27.358 --> 00:03:35.033
Now we switch on, treat emulator as compromised. The very same signal now turns the status to compromised.

30
00:03:35.483 --> 00:03:43.708
Opening the protected screen shows what a fail-closed app does: access is blocked, and the screen lists the signal that caused it.

31
00:03:44.158 --> 00:03:51.408
Switch the policy off again and the protected content opens, because the device passes the integrity check.

32
00:03:53.933 --> 00:04:02.908
Here are real runs. The iOS Simulator with LLDB attached reports two signals: simulator, and debugger_attached.

33
00:04:03.358 --> 00:04:17.808
Launched from Xcode on a physical iPhone, debugger attached and DYLD insert fire as well, because Xcode injects its view-debugging library. The phone also carries the Frida gadget, which adds hooking libraries.

34
00:04:18.258 --> 00:04:24.858
Launch from the home screen, or untick debug executable in the scheme, to see the production result.

35
00:04:26.467 --> 00:04:37.517
Let us recap. One: debuggers are read through P_TRACED on iOS and the Debug API on Android, and neither catches Frida or a native debugger.

36
00:04:37.967 --> 00:04:43.992
Two: emulator and simulator are context signals, and not compromising by default.

37
00:04:44.442 --> 00:04:51.367
Three: an attached debugger does count by default, and it is expected from Xcode and Android Studio.

38
00:04:51.817 --> 00:04:58.942
Four: you decide the policy, with treat emulator as compromised, compromising categories, or ignore.

39
00:05:00.567 --> 00:05:07.592
Thanks for watching. Policy and status rules are documented in the README, under result semantics.

40
00:05:08.042 --> 00:05:10.992
Next, watch the hooking frameworks video.
