Android native string deobfuscation
Background
Android native string deobfuscation
Background
With the continuous escalation of security countermeasures, it is common to encounter encrypted strings in target .so files during native reverse engineering. Since strings are crucial for locating key code, decrypting and restoring these encrypted strings becomes essential. This article introduces several common methods for cracking string encryption and explains them with practical examples.
Tracing All Returned Strings
Concept:
Some string obfuscation schemes decrypt strings at runtime and return the decrypted strings as C pointers to the caller. However, locating these decryption functions can be challenging. Using Frida, we can hook all functions in the module and attempt to output results with readCString() when the functions return.
Advantages:
- If lucky, sensitive key strings can be directly observed, allowing quick identification of critical functions.
Disadvantages:
- May cause the app to crash, making the tracing process unstable.
- Produces a large amount of output data, making it difficult to filter useful information.
Steps:
- Run the script
toolchain_collect_ret_insn.py.
- Select “Yes” to generate a hook script for all return instructions in the IDB directory.
- Select “No” to generate a hook script only for exported functions’ return instructions.


- Make minor adjustments to the generated script and use it.
Example Output:

Identifying Frequently Called Functions
Concept:
Some string obfuscation schemes frequently call fixed string decryption functions at runtime. Since a single .so file typically contains hundreds or thousands of strings, these decryption functions are often called far more frequently than regular functions. By analyzing the cross-references of all functions and sorting them in descending order, these string decryption functions can be quickly identified. This method can also be used to locate string constructors, serving as key points for deobfuscation.
Advantages:
- High stability, requiring hooks for only a few functions.
- Minimal interference data.
- Suitable for both heap-based and stack-based string encryption schemes.
Disadvantages:
- Requires manual inspection to locate string decryption functions.
Steps:
- Run the script
top_xrefs.pyand input the number of functions (N) with the highest reference counts to view.

- Example Results:
xxard:

String decryption implementation:

xxsec:

xxny:

Tracing JNI String-Related Functions
Concept:
When strings are passed between Java and native layers as parameters or return values, JNI functions such as NewString, NewStringUTF, and GetStringUTFChars are typically called. By hooking these interfaces, we can trace the strings.
Advantages:
- Produces minimal irrelevant data.
Disadvantages:
- Limited output data, making it difficult to locate key functions.
Implementation:
- Use the open-source project FridaContainer by deathmemory for JNI tracing:
FCAnd.jni.hookJNI(‘NewString’, {
onEnter: function (args) {
try {
var str = args[1].readCString();
console.log(‘NewString ‘ + ‘ str: ‘ + str);
} catch (error) {}
}
});
FCAnd.jni.hookJNI(‘NewStringUTF’, {
onEnter: function (args) {
try {
var str = args[1].readCString();
console.log(‘NewStringUTF ‘ + ‘ str: ‘ + str);
} catch (error) {}
}
});
FCAnd.jni.hookJNI(‘GetStringUTFChars’, {
onLeave: function (retval) {
try {
var str = retval.readCString();
console.log(‘GetStringUTFChars ‘ + ‘ str: ‘ + str);
} catch (error) {}
}
});
- Alternatively, use the open-source project JnitraceForCpp by zhenxi.
Memory Dump
Concept:
Some .so files use open-source OLLVM for string encryption, where strings are decrypted back into the .data section during the init function. Using Frida dump tools, decrypted strings can be directly extracted from memory.
Advantages:
- Highly effective for encryption schemes that refill decrypted strings into the
.datasection.
Disadvantages:
- Ineffective for heap- or stack-based string encryption.
Steps:
-
Launch the app and trigger critical logic to ensure the target module is loaded into memory.
-
Use Frida dump tools to extract the decrypted
.sofile from memory. -
Copy the script
fix_convey_str_list.pyto the IDA plugin directory and restart IDA to activate it. -
Load the dumped
.sofile in IDA and use the plugin to export the parsed string list.

- Re-import the exported string list into the original (non-dumped)
.sofile for analysis.

Memory Scanning
Concept:
For heap-based string encryption schemes, decrypted strings are dynamically allocated in memory, and their pointers are stored in global variables. By writing IDA scripts to scan the .data and .bss sections, string pointers can be identified, and decrypted strings can be output.
Advantages:
- Highly effective for dynamically allocated memory-based string encryption schemes.
Disadvantages:
- Ineffective for stack-based string encryption.
Steps:
-
Use the script
toolchain_trace_dyn_dec_str.pyto generate a Frida JavaScript script and modify the module name inModule.findBaseAddress. -
Launch the app, trigger critical logic, and wait for string decryption to complete before dumping.

- Save the dumped string information to a file and use the IDA script
toolchain_trace_dyn_dec_str.pyto supplement the information back into the IDB file.

- For
.bsssection addresses without allocated space in the file, set breakpoints at the corresponding addresses and add comments. This allows easy string lookup through the breakpoint window (Ctrl+ALT+B).

- View string annotations in the assembly window:

Conclusion
This article focuses on reverse engineering techniques for cracking native-layer string encryption. It provides detailed explanations of various strategies, including tracing returned strings, identifying frequently called functions, JNI string tracing, memory dumps, and memory scanning. These methods effectively address different types of string encryption schemes, offering strong support for reverse analysis. It is hoped that this article will inspire and assist readers in their practical work.
Code repository: https://github.com/imb4dm4n/Deadly-3000

메타데이터
- post_id
- 3d21c5a9df5d
- slug
- android-native-string-deobfuscation-3d21c5a9df5d
- url
- https://medium.com/@jackSparr0w/android-native-string-deobfuscation-3d21c5a9df5d
- canonical_url
- https://medium.com/@jackSparr0w/android-native-string-deobfuscation-3d21c5a9df5d
- author_url
- https://medium.com/@jackSparr0w
- status
- ok
- fetched_at
- 2026-07-19 03:40:01