3

Inside the java it is calling a native function from "something.so":

public static native byte[] functionName(int i, byte[] bArr);

This function is supposed to return byte array as you can see. So I tried this:

Interceptor.attach (Module.findExportByName ( "something.so", "functionName"), {
    onEnter: function (args) 
    {
            console.log("entered");
            var ptr_data = env.getClassName(args[1]);
            var length = args[2];
            var data = Memory.readByteArray(ptr_data, length);
            console.log(data);
    }   
    });

But frida is not able to return any result. Not even print "entered". Note you are not able to see the name "functionName" if you open with ida because it was stripped elf (.so)
I have no idea where is this location of "functionName" and I want to find it because it contains a lot of junk codes.

Is there any other way to find it using frida? Please kindly write an example and share with me.

Gin May
  • 43
  • 1
  • 8
  • You post is confusing me. On the one hand you are talking about classes (which usually means "Java classes") - on the other hand you are using code for hooking native (e.g. C/C++ and therefore non-Java) methods. – Robert Oct 22 '19 at 17:35
  • @Robert thanks for addressing the issue. I edited the post, I meant to say in the java class it called the native function functionName – Gin May Oct 23 '19 at 04:53
  • You should give more details - exact class, method and function names, otherwise most likely you will get no answers because it is unclear where the problem is. – Robert Oct 23 '19 at 07:17
  • there's no other clues it's stripped elf, you won't see anything inside using ida – Gin May Oct 23 '19 at 10:22
  • what is "not anything"? Usually you are getting at least the function list, may be no names. Any you are trying to use the exported function, therefore I assume there is a list of exported methods. – Robert Oct 23 '19 at 11:21
  • @Robert it do have a lot of funtion sections but u never know which is the real one. Yup there's exported method but it is outside the range of the visible function. But when you view the export tab u never see the real name.. Here u can have a look to get what I mean https://drive.google.com/open?id=1G_RQHNPqJUdTUDZDMehjcTuICizJJUc5 – Gin May Oct 24 '19 at 19:41
  • also I wanted to ask how do looking at the export table allowed us to find back the function? – Gin May Oct 24 '19 at 21:03

1 Answers1

4

It can be registered natively and it will not be exported which means you will not see it with Module.enumerateExports

This snippet will hook JNI RegisterNatives and will reveal functionName offset which yoy can Intercept via Module.findBaseAddress('something.so').add(offset)

registerNativeMethods can be used against anti reversing technique to the native .so libraries, e.g. hiding the symbols as much as possible, obfuscating the exported symbols and eventually adding some protection over the JNI bridge. Find manually registered (obfuscated) native function address

var RevealNativeMethods = function() {
  var pSize = Process.pointerSize;
  var env = Java.vm.getEnv();
  var RegisterNatives = 215, FindClassIndex = 6; // search "215" @ https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html
  var jclassAddress2NameMap = {};
  function getNativeAddress(idx) {
    return env.handle.readPointer().add(idx * pSize).readPointer();
  }
  // intercepting FindClass to populate Map<address, jclass>
  Interceptor.attach(getNativeAddress(FindClassIndex), {
    onEnter: function(args) {
      jclassAddress2NameMap[args[0]] = args[1].readCString();
    }
  });
  // RegisterNative(jClass*, .., JNINativeMethod *methods[nMethods], uint nMethods) // https://android.googlesource.com/platform/libnativehelper/+/master/include_jni/jni.h#977
  Interceptor.attach(getNativeAddress(RegisterNatives), {
    onEnter: function(args) {
      for (var i = 0, nMethods = parseInt(args[3]); i < nMethods; i++) {
        /*
          https://android.googlesource.com/platform/libnativehelper/+/master/include_jni/jni.h#129
          typedef struct {
             const char* name;
             const char* signature;
             void* fnPtr;
          } JNINativeMethod;
        */
        var structSize = pSize * 3; // = sizeof(JNINativeMethod)
        var methodsPtr = ptr(args[2]);
        var signature = methodsPtr.add(i * structSize + pSize).readPointer();
        var fnPtr = methodsPtr.add(i * structSize + (pSize * 2)).readPointer(); // void* fnPtr
        var jClass = jclassAddress2NameMap[args[0]].split('/');
        console.log('\x1b[3' + '6;01' + 'm', JSON.stringify({
          module: DebugSymbol.fromAddress(fnPtr)['moduleName'], // https://www.frida.re/docs/javascript-api/#debugsymbol
          package: jClass.slice(0, -1).join('.'),
          class: jClass[jClass.length - 1],
          method: methodsPtr.readPointer().readCString(), // char* name
          signature: signature.readCString(), // char* signature TODO Java bytecode signature parser { Z: 'boolean', B: 'byte', C: 'char', S: 'short', I: 'int', J: 'long', F: 'float', D: 'double', L: 'fully-qualified-class;', '[': 'array' } https://github.com/skylot/jadx/blob/master/jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java
          address: fnPtr
        }), '\x1b[39;49;00m');
      }
    }
  });
}

Java.perform(RevealNativeMethods);
whoopdedoo
  • 2,815
  • 23
  • 46