I'm trying to load a external library for certain app when it be launched (on Platform Android 12).
And the external library will hook some function in it initialize function and then can help me get app's info.
The point is ,i can't load my library correctly.
I know Android 8+ dont allow load system lib by app,and dlopen will do return address check as blow
__attribute__((__weak__))
void* dlopen(const char* filename, int flag) {
const void* caller_addr = __builtin_return_address(0);
return __loader_dlopen(filename, flag, caller_addr);
}
You should make the caller_addr be a system lib address(or some like this?).
So,I used PLT hook tools to hook __loader_dlopen() in libdl.so,and do external load for target app like this to pass validation.
void* my_fake__loader_dlopen(const char* filename,int flag,void* caller_addr)
{
if(in_target_app)
{
void* res = __loader_dlopen(target_so_path,flag,caller_addr)//res always return NULL
}
return __loader_dlopen(filename,flag,caller_addr);
}
But res always return NULL,i cant load my lib correctly.
which of the above steps went wrong ? or is there another way to achieve my goal?
PS:
I can make sure:
put my lib in /system/lib64/
hook function correctly
Related
I have a method inside the cpp shared library which uses system() call to execute an android command.
I have a cpp executable as well which uses this shared library and calls that particular method. When the executable calls the method inside shared library, the method successfully calls system() and I can see the android command ran successfully.
Now, I have a xamarin app which also loads the same shared cpp library and calls the same method from the shared library. However, this time, the system() call fails and it can't execute the Android command. The Android command is to open browser
Why is it not working when called from Xamarin app? Do I need to provide any specific permissions to the app. I know that the app has permissions to access storage and internet.
std::string getName()
{
std::streambuf* cout_sbuf = std::cout.rdbuf(); // save original
std::ofstream fout("/sdcard/cout.txt");
std::cout.rdbuf(fout.rdbuf()); // redirect 'cout' to a 'fout'
std::string httpUrl = "https://www.google.com";
std::string cmd = "/system/bin/am start -a
android.intent.action.VIEW -d \"" + httpUrl + "\"";
std::cout<<"cmd passing to system(): "<< cmd <<std::endl;
if(system(cmd.c_str())==0)
{
std::cout<<"system() returned successful. Return value: " <<
system(cmd.c_str()) <<std::endl;
}
else
{
std::cout<<"system() returned failure. Return value: " <<
system(cmd.c_str()) <<std::endl;
}
std::cout.rdbuf(cout_sbuf); // restore the original stream buffer
return "return from getName()";
}
The above code works fine when we run a cpp exe from the command line. However, it won't work when the xamarin app calls this method. The return code of system() is 65280
Is there any way to use jniRegisterNativeMethods to map JNI functions in a NDK app? i.e. use a method_table to map native (C/C++) functions via the JNI instead of using ridiculously long JNI method names?
For example, in one exercise I saw, there was a C file added onto the platform it self,
#include "core_jni_helpers.h"
#include "jni.h"
static jlong init_native(JNIEnv *env, jobject clazz)
{
return 0;
}
// ...
static JNINativeMethod method_table[] = {
{ "init_native", "()J", (void*)init_native },
{ "finalize_native", "(J)V", (void*)finalize_native },
// ...
};
int register_android_server_ExampleService(JNIEnv *env)
{
return jniRegisterNativeMethods(env, "com/android/server/OpersysService",
method_table, NELEM(method_table));
};
But then the register_android_server_ExampleService was was manually invoked in services/core/jni/onload.cpp (on the platform)
Is there any way to do this or something similar with the NDK though?
My guess is no, as JNIHelp.h and core_jni_helpers.h aren't available in the NDK, and the Kotlin tools in Android Studio likely wouldn't be able to run a function in order to perform the auto complete. However I thought it was worth asking in the small case I could somehow avoid naming functions like Java_vendor_<name>_<name>_<name>_test_MainActivity_stringFromJNI
I have spent a ridiculous amount of time trying to figure this out and I am at an absolute loss.
I am working with the JUCE library and have modified one of their sample projects. My goal is to have a very simple Android app that is written in C++ and then ported to Android. I need a function in C++ that I can call that will then call a function on the Android side that will return my heap size and other characteristics to my C++ code so that I can manage memory there.
If anyone has a simple solution that would be amazing. Right now my current snag is this:
char const buf[] = "From JNI";
jstring jstr = env->NewStringUTF(buf);
jclass clazz = env->FindClass("android/os/Debug");
But I keep getting an error saying that 'NewStringUTF' is not a _JNIEnv member... but if I right click on the method and jump to the definition, I see it in my jni.h file... any suggestions? I'm working in Xcode by the way...
Is it plain C, not C++? Perhaps your file has a .c extension.
If it's plain C it should be
JNIEnv* env;
JNI_CreateJavaVM(&jvm, (void **)&env, &args);
(*env)->NewStringUTF(env, buf);
I have integrated two native libraries (.so ) in my application. The libraries compile fine and I can load them in my application too. The first time I invoke a native method of a library it works fine, but if I call the same method again in the Activity the application shuts down.
The problem I am facing is exactly the same as mentioned in here :
http://grokbase.com/t/gg/android-ndk/1226m68ydm/app-exit-on-second-native-call
The solution that works is to invoke the native method in another Activity and shut it down forcefully via System.exit(0). Following the article I tried setting the pointers to NULL of the called method after a successful operation, but this too didn't help me. Also its not possible to unload a library once its loaded by System.loadLibrary().
I want to call the native methods more than once without creating a new Activity. Any ideas how to solve this issue ?
(I FINALLY FOUND A SOLUTION ... HERE IT IS)
Okay, I have finally found a way to resolve this issue. The solution is actually pretty simple. Build another independent native library (utility library) to load and unload the other libraries. What we need to do is use dlopen() and dlclose() in the native method of the utility. We can load the utility library like before via System.loadLibrary().
So in the native method of the utility library what we need to do is:
Use#include <dlfcn.h> // this is required to call dlopen() and dlclose() functions.
Provide handler and function prototype:
void *handle;
typedef int (*func)(int); // define function prototype
func myFunctionName; // some name for the function
Open the library via dlopen() :
handle = dlopen("/data/data/my.package.com/lib/somelibrary.so", RTLD_LAZY);
Get and Call the function of the library:
myFunctionName = (func)dlsym(handle, "actualFunctionNameInLibrary");
myFunctionName(1); // passing parameters if needed in the call
Now that the call is done. Close it via dlclose():
dlclose(handle);
Hope this will help others facing the same issue.
So ... my solution was starting a service that runs the shared library code, this service has a different process name ( you can set it in the Android Manifest ), as it is a different process you can kill it ( Using Process.killProcess(Process.myPid()) when it finishes running, without affecting your application in any way.
Worked very well for me, hope it helps someone else.
As this is the top hit for this issue and as the issue itself still exists, it seems that the approach that ZakiMak shared with us is still the most popular solution.
For others who may want to implement it and would like a little more detail for the latest Android releases, here are some notes I made as I stumbled through this:
Firstly, there is a solution which implements this approach on GitHub now. I have not tried it personally, but I have used it as a reference. It is very useful to see how the Android.mk file is structured and how the library is opened and methods called. Link is here: https://github.com/jhotovy/android-ffmpeg
The path to the native library folder changes over Android releases and it also appears to change every time you run the app (although this may be just in debug mode). Either way, it is best to pass the path in from the calling Java method if possible. For example:
In the Java wrapping class:
import android.content.Context;
import android.util.Log;
public class FfmpegJNIWrapper {
//This class provides a Java wrapper around the exposed JNI ffmpeg functions.
static {
//Load the 'first' or 'outer' JNI library so this activity can use it
System.loadLibrary("ffmpeg_wraper_multi_invoke_jni");
}
public static int call_ffmpegWrapper(Context appContext, String[] ffmpegArgs) {
//Get the native libary path
String nativeLibPath = appContext.getApplicationInfo().nativeLibraryDir;
//Call the method in the first or 'outer' library, passing it the
//native library past as well as the original args
return ffmpegWrapper(nativeLibPath, ffmpegArgs);
}
// Native methods for ffmpeg functions
public static native int ffmpegWrapper(String nativeLibPath, String[] argv);
}
In the 'first' or 'outer' native library:
JNIEXPORT jint JNICALL Java_com_yourpackage_androidffmpegwrapper_FfmpegJNIWrapper_ffmpegWrapper(JNIEnv *pEnv, jobject pObj, jstring nativeLibPath, jobjectArray javaArgv) {
//Get the second or 'inner' native library path
char* nativePathPassedIn = (char *)(*pEnv)->GetStringUTFChars(pEnv, nativeLibPath, NULL);
char ourNativeLibraryPath[256];
snprintf(ourNativeLibraryPath, sizeof (ourNativeLibraryPath), "%s%s", nativePathPassedIn, "/libffmpeg_wraper_jni.so"); //the name of your ffmpeg library
//Open the so library
void *handle;
typedef int (*func)(JNIEnv*, jobject, jobjectArray);
handle = dlopen(ourNativeLibraryPath, RTLD_LAZY);
if (handle == NULL) {
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "could not open library: %s", dlerror());
printf("Could not dlopen(\"libbar.so\"): %s\n", dlerror());
return(-1);
}
//Call the ffmpeg wrapper functon in the second or 'inner' library
func reenterable_ffmpegWrapperFunction;
reenterable_ffmpegWrapperFunction = (func)dlsym(handle, "Java_com_yourpackage_androidffmpegwrapper_FfmpegJNIWrapper_ffmpegWrapper");
reenterable_ffmpegWrapperFunction(pEnv, pObj, javaArgv); //the original arguments
//Close the library
dlclose(handle);
// return
return(1);
}
The Android.mk file is a little 'flaky' to put it politely. Because you are building two separate libraries in one Android.mk file, this may be a little more complex that other NDK make files so if you get some strange errors do some searching before you start taking your project apart. For example: https://stackoverflow.com/a/6243727/334402
I want to incorporate small, lean and mean C-based parser into my Android project. I've done JNI programming in the past but not any type of native (C) development on Android. My plan is to compile C lib into SO and create JNI wrapper around it which I'm going to use in my app. Is this how it can/should be done? Second and most important question - how can I include .so into my APK? Where would it go?
Depending on how much data you pass and how often I seriously doubt a Java/JNI/C would perform faster than a native java implementation.
Passing anything other than a "Java Int" to a "C long" invokes the JNI data conversion routines which are anything but lean and mean.
So unless your JNI routine fits the pattern:
Pass small amount of data.
Do lots and lots of work in C.
Pass small result set back.
You will be considerably slower than a native java implementation. If you stick with the basic "C" like java operations (+,-,*,==,>) using the "native" data types (int, char, String) and avoid the fancy libraries Java will perform nearly as fast as C.
The remaining bug-bear of java performance is the time taken to fire up the JVM and get everything going, but as you are starting off from a Java program this is a non issue.
The other reason for "slow" java performance is people insist on unnecessary factories, containers, xml beans etc. etc. where plain, simple methods would do the job better.
Create a JNI folder in your Android root Application folder(where there is src, res) .Place the code (1) there name it as someshared-lib.c.
(1)
Java_YourPackageName_YourClassNameWhereYoudeclareYourNativeFunction_NativeFuntionName(JNIEnv* env,jobject thiz)
{
//your c code , the JNI will act as a wrapper for it
return (*env)->NewStringUTF(env, "<string to pass or you can mention jchar * type string >");
}
(2)IN java file
package YourPackageName;
public class YourClassNameWhereYoudeclareYourNativeFunction extends Activity
{
public native String NativeFuntionName();
String returnValue = NativeFuntionName();
}
(3)IN Android.mk do this :
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := someshared-lib //note the libname same as c file name
LOCAL_SRC_FILES := someshared-lib.c //this is the file where you placed the code (1)
include $(BUILD_SHARED_LIBRARY)
export your ndk-build
(do export PATH=:$PATH
go to the JNI folder as created above :
execute ndk-build command
you will get a library formed someshared-lib in the lib folder formed in the Application root folder.While building and running the application this will get bundled up with the apk and will get installed in the device.To verify this you can go to the
/data/data/your_package_name/lib folder.
The app searched this lib in the /data/data/your_package_name/lib ( also /system/lib as well ) folder and use it for the dynamic calls(JNI) being made from the Android application.
Now if you want to return anything other than string you have to change the above method declration in c file as below :
Java_YourPackageName_YourClassNameWhereYoudeclareYourNativeFunction_NativeFuntionName(JNIEnv* env,jclass obj,jobject thiz)
{
jfieldID fid;
jboolean enable_flag;
//Pass the class object having all the variable from the android app to the JNI in the jclass obj and access its members using the field ID and using Get and Set firld ID.
clazz = (*env)->GetObjectClass(env, info);
fid = (*env)->GetFieldID(env,clazz,"some_variable","X"); //"X" - type of variable for boolean it //is Z , for INtezer it is I, for double it is D,
refer this document for detailed explaination
//for getting teh value fomr the JNI
enable_flag = (*env)->GetBooleanField(env, **thiz**, fid);
//for setting the value
fid = (*env)->GetFieldID(env,clazz,"other_float_variable","D");
(*env)->SetDoubleField(env,**thiz**,fid,other_float_variable);
}
Also in the Android Application you have to pass the Class object of the structure.
e.g
(2) will become now :
package YourPackageName;
public class YourClassNameWhereYoudeclareYourNativeFunction extends Activity
{
public native String NativeFuntionName();
String returnValue = NativeFuntionName( exampleStruct exst);
where exampleStruct :
public class exampleStruct {
protected boolean some_variable = 0;//no log saving by default
protected float other_float_variable = 0;
}
}
Hope this helps.
use Android NDK
Download n docs Android NDK 1.6
This will save you from writing JNI layer for lib and also will install the app in the lib folder of your app data folder.
Someone said that JNI in android sucks : http://www.koushikdutta.com/2009/01/jni-in-android-and-foreword-of-why-jni.html