Skip to content

Port MASTG-TEST-0049: Testing Emulator Detection (android)#3607

Open
jacobocasado wants to merge 14 commits intoOWASP:masterfrom
jacobocasado:port-MASTG-TEST-0049
Open

Port MASTG-TEST-0049: Testing Emulator Detection (android)#3607
jacobocasado wants to merge 14 commits intoOWASP:masterfrom
jacobocasado:port-MASTG-TEST-0049

Conversation

@jacobocasado
Copy link
Collaborator

This PR closes #3016

Description

Summary

  • Ported emulator detection test to MASTG v2 (MASTG-TEST-0x49) with static + dynamic steps and Play Integrity references.
  • Updated emulator detection knowledge (MASTG-KNOW-0031) to reflect current indicators and add notes on bypassing/hooking.
  • Added Android demo (MASTG-DEMO-0086) with Frida tracing and reproducible output.

Testing

  • Built and ran the demo in MASTestApp-Android on Android 16 emulator.
  • Captured Frida runtime traces in output.txt to generate proper evidences.

### Notes

  • Play Integrity checks are documented but not implemented in the demo (requires Play Console + server verification).

[x] I have read the contributing guidelines.

@cpholguera cpholguera changed the title Porting MASTG-0049 to v2 Port MASTG-TEST-0049: Testing Emulator Detection (android) Jan 2, 2026
@cpholguera cpholguera requested a review from Copilot January 25, 2026 19:59
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

This test verifies that the app runs emulator detection checks on Android and modifies its behavior when it detects an emulated device. It focuses on code and runtime checks that look for emulator indicators and how the app reacts to such indicators.
It does not attempt to bypass these checks; it only verifies that the application executes them.

Common checks use [`android.os.Build`](https://developer.android.com/reference/android/os/Build) fields, [`TelephonyManager`](https://developer.android.com/reference/android/telephony/TelephonyManager) identifiers, package visibility via [`PackageManager`](https://developer.android.com/reference/android/content/pm/PackageManager), or OpenGL renderer values from [`GLES20.glGetString`](https://developer.android.com/reference/android/opengl/GLES20#glGetString(int)). If the app uses Play Integrity for emulator detection, it should evaluate `deviceRecognitionVerdict` values such as `MEETS_VIRTUAL_INTEGRITY`. See @MASTG-KNOW-0031, @MASTG-KNOW-0035, and [Emulation-based Dynamic Analysis](../../../Document/0x04c-Tampering-and-Reverse-Engineering.md#emulation-based-dynamic-analysis) for more detail on common emulation indicators.
Copy link

Copilot AI Jan 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reference link uses relative path "../../../Document/0x04c-Tampering-and-Reverse-Engineering.md" which may be fragile. Consider using a proper @MASTG-* reference identifier instead if such a reference exists for this content.

Suggested change
Common checks use [`android.os.Build`](https://developer.android.com/reference/android/os/Build) fields, [`TelephonyManager`](https://developer.android.com/reference/android/telephony/TelephonyManager) identifiers, package visibility via [`PackageManager`](https://developer.android.com/reference/android/content/pm/PackageManager), or OpenGL renderer values from [`GLES20.glGetString`](https://developer.android.com/reference/android/opengl/GLES20#glGetString(int)). If the app uses Play Integrity for emulator detection, it should evaluate `deviceRecognitionVerdict` values such as `MEETS_VIRTUAL_INTEGRITY`. See @MASTG-KNOW-0031, @MASTG-KNOW-0035, and [Emulation-based Dynamic Analysis](../../../Document/0x04c-Tampering-and-Reverse-Engineering.md#emulation-based-dynamic-analysis) for more detail on common emulation indicators.
Common checks use [`android.os.Build`](https://developer.android.com/reference/android/os/Build) fields, [`TelephonyManager`](https://developer.android.com/reference/android/telephony/TelephonyManager) identifiers, package visibility via [`PackageManager`](https://developer.android.com/reference/android/content/pm/PackageManager), or OpenGL renderer values from [`GLES20.glGetString`](https://developer.android.com/reference/android/opengl/GLES20#glGetString(int)). If the app uses Play Integrity for emulator detection, it should evaluate `deviceRecognitionVerdict` values such as `MEETS_VIRTUAL_INTEGRITY`. See @MASTG-KNOW-0031, @MASTG-KNOW-0035, and the "Emulation-based Dynamic Analysis" section of the Tampering and Reverse Engineering chapter for more detail on common emulation indicators.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jacobocasado
Copy link
Collaborator Author

I will use MASTG-DEMO-0x86 instead of 0086; I will do this for each created file in the future to avoid conflicts. The copilot messages are marked as solves, i guess I ignore them? @cpholguera, thanks for the attention


Threat model: an attacker runs the app on an emulator and can instrument or hook the process.

## Steps
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm adding this comment here since it's relevant but it addresses other files in this PRs. Let's try to keep things simple and reduce the overall size of the PR.

Try to keep the steps as short as possible and aligned with other recent tests.

Anything that's about specific APIs should be addressed in the Overview. At the same time, the Overview must be in balance with the MASTG-KNOW page.

For example:

  • the MASTG-KNOW address Emulator Detection as a whole and specifies all different techniques/methods and APIs that exist. It serves as a general overview about how developers may be doing this.
  • the MASTG-TEST links to that MASTG-KNOW and addresses specific areas of it (without having to specify all APIs methods all over again. Just indicate whatever the test addresses and how it is approached from the testing side in contrast to the developer side.
  • The demo gets even more specific and target one specific method/s from those addressed on the test. Here also avoid being overly verbose and avoiding describing all possible APIs and values again. Prefer to link to the tests and/or the knowledge.

If anything is unclear please let me know anytime. Thanks!

@cpholguera
Copy link
Collaborator

I will use MASTG-DEMO-0x86 instead of 0086; I will do this for each created file in the future to avoid conflicts. The copilot messages are marked as solves, i guess I ignore them? @cpholguera, thanks for the attention

Yes, I resolved them because they weren't useful. I'm afraid that the PR is so big that Copilot cannot handle it properly. See my other comment and let's see if we can make it more manageable. Better for copilot and especially for human reviewers 😁

@jacobocasado
Copy link
Collaborator Author

@cpholguera Sure, what you say it's clear and makes sense. I will refactor the code according to these guidelines and have these things into account for the future PRs. As I said previously, thank you for your time and sorry for the inconvenients :)

val missingPermissions = ensureTelephonyPermissions()
val buildQueries = queryBuildProperties()
val telephonyQueries = queryTelephonyProperties()
val packageQueries = queryPackageChecks()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need to QUERY_ALL_PACKAGES to the AndroidManifest.xml for this API to work?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is something I missed, thank you @serek8 for pointing it out!

The getInstalledPackages function call won't work, but the afterwards list used queryLauncherPackages (which only retrieves the apps that have a launcher) will work, covering a subset of the applications of the system.

Thanks for the detail! According to @cpholguera I will reduce the demo checks to only hardware and build properties (only one as an example). However I might include this detail in the knowledge section so that the developer has that little detail into account when implementing these checks.

Copy link
Collaborator

@cpholguera cpholguera Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant, you can keep checks in the code of the demo. But not list everything in the markdown file. As long as the checks are legitimate you can keep them in the code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cpholguera Ok! Understood. Thanks!

Copy link
Collaborator Author

@jacobocasado jacobocasado Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm performing the related changes and by reading the official Google Play notes about the usage of this permission I will remove the usage of this API call in the demo application as it requires a very sensitive permission; instead, the demo will contain the query of the installed packages that have a launcher (which does not need this permission). In the demo notes I will comment that this option (list ALL the installed apps) and can be also used, but doing so requires this permission and will point to the Google Play documentation for more information on the topic. I think this is a good approach, what do you say? @serek8 @cpholguera

@jacobocasado
Copy link
Collaborator Author

Refactored demo file (MASTG-DEMO-0x86) with @cpholguera indications about reducing the information in the demo file and making a direct reference to MASTG-KNOW. I have a question: When deciding to use between @MASTG-TOOL-0001 (Frida for Android) and @MASTG-TOOL-0031 (Generic Frida), which one should I choose? The test would be more portable to iOS if using the generic one, so that was my criteria for choosing the generic Frida one (I also think it's more maintainable)

@jacobocasado
Copy link
Collaborator Author

Refactored TEST file (MASTG-TEST-0x49) to point MASTG-KNOW, where the emulator indicators are described. A few notes and questions:

  1. For the steps of the tests, is it preferrable to use techniques instead of direct tools? For example, the @MASTG-TECH-0043 technique is Method Hooking; we could directly use the Frida tool in this test, but pointing to a technique seems more maintainable in the future (e.g, the tool gets out of state of the art); modifying the technique allows all the tests that point to that technique to be "updated" fast.
  2. I reduced the scope from static analysis to dynamic analysis; at the end, the device must perform emulator checks and runtime; seeing them in the code does not give additional information for the evaluation verdict.

…acy; update output.txt for emulator detection consistency
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MASTG v1->v2 MASTG-TEST-0049: Testing Emulator Detection (android)

3 participants