Overview
At Cognisys, our days are filled with uncovering the intricacies of various applications, but some projects stand out due to their complexity and the insights they provide. Recently, we tackled an Android React Native application using the Hermes JavaScript engine, which presented unique challenges and learning opportunities.
Today, we will walk through the detailed process of decompiling a React Native application, focusing on using Hermes-dec to handle Hermes bytecode. This guide is aimed at security researchers eager to delve deep into mobile application internals, uncover potential vulnerabilities, and enhance their penetration testing skills.
Understanding React Native and Hermes
React Native is a widely used framework for building mobile applications using JavaScript. To optimise performance, many developers choose Hermes, a JavaScript engine designed to improve startup times and runtime efficiency of React Native apps.
Why do Devs Use Hermes?
Hermes offers several key benefits:
- Improved Startup Time: By precompiling JavaScript to bytecode, Hermes reduces the time for an app to start.
- Reduced Memory Usage: Hermes is optimised to use memory efficiently, which is crucial for mobile devices.
- Smaller App Size: Hermes applications can be smaller, as the engine is designed to be lightweight.
- Better Performance: Hermes enhances the runtime performance of JavaScript code, making applications more responsive.
For more details, check out the official React Native documentation on Hermes.
Step-by-Step Guide to Decompiling an Android React Native Application
Step 1: Extract the APK
Extract the APK: If you don’t already have the APK file, extract it from your device using adb:
1
2
3
$ adb shell pm list packages
$ adb shell pm path com.example.app
$ adb pull /path/to/your.apk
Step 2: Decompile the APK
Decompile the APK: Use APKTool to convert the APK into readable resources and smali code:
1
$ apktool d your.apk -o decompiled_folder
This command generates a decompiled_folder
containing the resources and smali files.
Step 3: Extract the Binary Bundle
Locate the Binary Bundle: Navigate to the assets
directory within the decompiled APK folder. Look for index.android.bundle
. In most cases, you’ll find a JavaScript instead of a bytecode, which is great for testing purposes, but if you find a bytecode ready for the adventure to reverse engineer the binary to get the pseudocode in JavaScript. In this case it was binary as seen below:
Step 4: Detecting Hermes in a React Native Application
To determine if an app uses Hermes, you can perform the following steps:
Inspect the APK Contents: After decompiling the APK with APKTool, navigate to the
assets
directory and look for Hermes-specific files, such asindex.android.hermes
orindex.android.bundle
.File Inspection: Use the
file
command to inspect the JavaScript bundle:
1
2
$ file index.android.bundle
index.android.bundle: Hermes JavaScript bytecode, version 94
If the output indicates Hermes JavaScript bytecode, version 94
, it confirms the use of Hermes.
Why Does the Version Matter?
The version number (e.g., version 94) is crucial because it signifies the specific version of the Hermes engine used to compile the bytecode. Each version of Hermes might have different features, optimisations, or bug fixes. Knowing the version can help in:
- Choosing the Right Tools: Some decompilation tools, like
hermes-dec
by @P1sec, must support specific Hermes versions to decompile the bytecode correctly. This tool might not support older versions, but for example,hbctool
by @bongtrop supports versions 59, 62, 74, and 76. - Understanding Bytecode Changes: Different versions of Hermes can introduce changes in the bytecode format, which can affect how you analyse and interpret the decompiled code.
Step 5: Install Hermes decompile tool
- Decompile Hermes Bytecode: Use
hermes-dec
to convert the Hermes bytecode back to JavaScript. Let’s first set thehermes-dec
1
2
3
$ git clone git@github.com:P1sec/hermes-dec.git
$ cd hermes-dec/
$ python3 setup.py install
Step 6: Try to Disassemble and Decompile the Hermes Binary
- While decompiling React Native applications typically involves extracting and analysing JavaScript code, applications using the Hermes engine require an additional step to handle the Hermes bytecode. Here’s how you can disassemble and decompile the Hermes bytecode using hermes-dec:
1
2
$ python3 hbc_disassembler.py ../index.android.bundle disassemreact
[+] Disassembly output wrote to "disassemreact"
- Lets Decompile and get the pseudocode
1
2
$ hbc_decompiler.py ../index.android.bundle decompiledreact
[+] Decompiled output wrote to "decompiledreact"
For further deobfuscation, use tools like JavaScript Deobfuscator if your JavaScript code is still obfuscated and not easily readable. https://github.com/ben-sb/obfuscator-io-deobfuscator
Conclusion:
Decompiling an Android React Native application using the Hermes engine involves detailed and technically challenging steps. By leveraging tools such as adb
, APKTool
, hermes-dec
, and Deobfuscation tools, security researchers can gain deep insights into the app’s structure and functionality, aiding in vulnerability discovery and security assessments.