5

Im currently reverse engineering an android app and this app calls a function named "getUserInfo" in an ARM 32bit ELF library called "libcms.so" (from TikTok) via the Java Native Interface.

My Problem is: The function cant be found with readelf --syms libcms.so or readelf --dyn-syms libcms.so because libcms.so is stripped and the funtion is not contained in the symbol table.

The app can call this function, so i know the function is there. How can i find the hex location of the function?

0

1 Answer 1

9

There're two broad ways in which you can declare JNI functions.

The first is the more obvious way in which the JNI function has to follow a specific naming convention like JNIEXPORT void JNICALL Java_com_app_foo_bar. You can easily identify such functions using readelf.

The other not so obvious way is to use RegisterNatives. Here your functions can have any signature and further they not need be exported from the shared library. Typically, you would call RegisterNatives from JNI_OnLoad to register the native functions to the Java Run-time.

For your binary libcms.so, it uses the second method.

RegisterNatives has the following prototype

jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint Methods);

If you analyze the code of JNI_OnLoad you will come across RegisterNatives call like below.

enter image description here

The third argument points to an array of JNINativeMethod structures which is declared as

typedef struct {
    char *name; 
    char *signature;
    void *fnPtr;
} JNINativeMethod;

The first member is a pointer to a null terminated string denoting the function name. However, in your case all the names and signatures are encrypted.

enter image description here enter image description here

These are decrypted at run-time by the .datadiv_decodeXXXXXXXX family of functions. The .init_array section contain pointers to these decryptor functions which implies they will be called at startup.

enter image description here

However, that is not all. The binary also employs Control Flow Flattening Obfuscation throughout, hence the execution path may not be easily discernible as shown below.

enter image description here

To analyze the binary you're better off resorting to dynamic analysis techniques using a tool such as Frida.

Further Read:

2
  • I don't understand, can dynamically load it get the function or anyway? or am I missing the point?
    – Gin May
    Oct 10, 2019 at 4:16
  • @GinMay To decrypt the function names you can run/emulate the .datadiv_decode series of functions.
    – 0xec
    Oct 13, 2019 at 7:51

Your Answer

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

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