As an exercise I am researching all methods of hiding a secret in an android mobile app binary... Yes I know that with more or less effort they can always be extracted with static analyses, run time introspection or with a MITM attack.

In my research to hide the secret, the best way I found for Android is by using JNI/NDK and until now I was not able to find a way of reverse engineer it.

NOTE: I understand the high level concept of reverse engineer but I don't have any experience of doing it.

My Attempts

$ strings -aw lib/x86/libnative-lib.so | grep -C 1 -irn 'the-secret-api-key-goes-here' -
934-cannot allocate __cxa_eh_globals

So I find the API key in the binary because I know it, but I would like to be able to find it by searching by the variable it is associated with:

$ strings -aw lib/x86/libnative-lib.so | grep -C 1 -irn 'JNI_API_KEY' -


$ strings -aw lib/x86/libnative-lib.so | grep -C 1 -irn 'SECRETS_API_KEY' -

Both doesn't return any result... I tried to use also hexdump and objdump without any success!!!

I tried also radare2 and retdec but my lack of knowledge may have not helped me in finding the API keys to.

As a last attempt I have de-compiled the binary with MobSF and searched the smali code for the JNI_API_KEY, SECRETS_API_KEY and the-secret-api-key-goes-here without any success.

At this point I don't want to resort to Frida or xPosed for a run-time reverse engineer technique or a MITM attack approach...

So for now I just want to know if I can employ other binary or de-compile techniques to find the API key?

NOTE: Looking for open source tools, not commercial ones.

The Code

The code that I have used to hide the API key with JNI and NDK in the Android app is the following...

file: native-lib.cpp

#include <jni.h>
#include <string>
#include "api_key.h"

extern "C" JNIEXPORT jstring JNICALL
        JNIEnv *env,
        jobject /* this */) {

    // To add the API_KEY to the mobile app when is compiled you need to:
    //   * copy `api_key.h.example` to `api_key.h`
    //   * edit the file and replace this text `place-the-api-key-here` with your desired API_KEY
    std::string JNI_API_KEY = SECRETS_API_KEY;

    return env->NewStringUTF(JNI_API_KEY.c_str());

file: api_key.h

#define SECRETS_API_KEY "the-secret-api-key-goes-here"


file: CMakeLists.txt

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# orJNI_API_KEY SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.

        # Sets the library as a shared library.

        # Provides a relative path to your source file(s).

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.

        # Specifies the name of the NDK library that
        # you want CMake to locate.

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.

        # Links the target library to the log library
        # included in the NDK.

1 Answer 1


If the API key is a string then just running strings would reveal it w/o grep as you do in your example. There might be some other strings but longer ones seems to stand out so it should be clearly visible that this is something meaningful. Having that API key I would probably go and use regular disassembler tools to see where and how it is used.

You can't search by variable names as those are not preserved in the binary (.so), with APK it might be a bit different.

  • The problem is to search the .so for meaningful strings... in my case was easy to find because I know the string I want to find... Not aware that the .so binary was not preserving the variable names, good to know ;)
    – Exadra37
    Feb 10, 2019 at 11:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.