For example, in android Java code, it calls a native method:
private native final String native_getParameters();
Where/how should I grep where is the C++ method defined native_getParameters();?
Thank you.
The C++ method will also contain your namespace (e.g. com.domain.your) and classname (e.g. YourActivity), it will look something like
JNIEXPORT jstring JNICALL Java_com_domain_your_YourActivity_native_1getParameters(JNIEnv * env, jclass clazz)
Note the C++ _1 equates to the _ in your Java method
Related
We can write methods to get the key as below both Method 1 and Method 2 for the Android app
Are both Methods have the same security strength? or is there any security weakness in one of the below Methods while decompile/reverse engineering or other app cracking procedures?
Method 1
declare/assign key inside the method in the lib.cpp file
lib.cpp file
extern "C"
JNIEXPORT jstring JNICALL
Java_com_app_keytest_KeyHelper_getKey(JNIEnv *env, jobject) {
std::string API_KEY = "YOUR_API_KEY";
return env->NewStringUTF(API_KEY.c_str());
}
Method 2
declare/assign keys in separate keys.h file in the same directory with lib.cpp and import to lib.cpp file
keys.h file
std::string API_KEY = "YOUR_API_KEY";
lib.cpp file
#include "keys.h"
extern "C"
JNIEXPORT jstring JNICALL
Java_com_app_keytest_KeyHelper_getKey(JNIEnv *env, jobject) {
return env->NewStringUTF(API_KEY.c_str());
}
Your two snippets compile to nearly the exact same code. In both cases the API key is present in plain text in the compiled library. Even if you took pains to obfuscate the native code, an attacker can just attach a debugger and catch the return value of getKey.
You need to rethink your approach and decide if it is actually worth the effort on your part.
You can achieve a good result in another way:
you have to obfuscate JNI function name because "getKey()" is too much self-explained and easy to understand during reverse engineering
add unused parameters to "getKey()" to make it more complex when scrolling while viewing reversed code
getKey() haven't to return the Key but have to call a Java method or set a specific Java variable
About #3: I'm using a dedicated Thread on JNI to receive a "command" and a "callback" for its results:
Java calls JNI's "getKey(fakeArg1, fakeArg2, fn_callback, fakeArg3)"
getKey() sends a request to JNI dedicated Thread and pass even "fn_callback" as part of that request
the dedicated Thread process the request and then call Java Callback
In this way event during normal debugging it's very difficult to follow the Flow because debugging won't go inside dedicated Thread automatically using StepInto/Over key/button.
Update: callback is the first approach but create a link between caller and the result. To avoid this you could call a completly separated Java method from JNI to pass the variable to.
I have native method like this.
public native int NativeMethod(Object object);
JNIEXPORT jint JNICALL NativeMethod(
JNIEnv *,
jobject,
jobject object) {
printf("%d", (int)object);
}
I call the method two times with different Java objects.
In Java I output their hashCode() and toString() info and they have different values.
But in native C, they have same output value.
It is just observed on Android 5.x devices and working well on devices below 5.0.
Also it works first time(different value in C) and doesn't work after that(some operations, not specific).
Really I don't how to fix it.
Anyone can help? Please.
I could call a very simple JNI method below from Java on Android somehow. However I have no idea what should I do next.
JNIEXPORT jstring JNICALL Java_com_test_ndktest_MyActivity_HelloJNI
(JNIEnv *env, jobject obj)
{
(*env)->NewStringUTF(env, "Hello from JNI");
}
What I want to do are two things...
What is compatible Java's substring method.
String str1 = new String("Hello World!");
String new_str1 = str1.substring(2, 5);
System.out.println(new_str1); // llo
I want to have a limitation to call
I may be able to get caller's package name. I want to avoid calling by unexpecting callers.
I am very grateful if you can share any hints or advices.
Thanks
Why don't you do that in Java? As for me the better way is to do this things in java. Sorry if i din't understand something.
As you know you can use C/C++. Did you see this:
Elegant way to copy substring from char* to std::string or http://www.cplusplus.com/reference/string/string/string/?
I read that JNI functions (the native C part) is very complex and must contain the java package name.
However, when reading Android webkit source. For example the nativeMoveGeneration functions in WebView.java
private native int nativeMoveGeneration();
It calls the JNI functions in WebView.cpp
static int nativeMoveGeneration(JNIEnv *env, jobject obj)
{
WebView* view = GET_NATIVE_VIEW(env, obj);
if (!view)
return 0;
return view->moveGeneration();
}
Ihis JNI function does not follow naming rule. Why is it?
P/S: The function above is just for demonstration. I'm reading Android 4.0.3 source, so it may be different from the github source above
UPDATE
Thanks to #Alex Cohn and this JNI Tips, I know that we can use JNI_Onload or use complex name. But where should we put JNI_Onload ?
JNI defines special function, JNI_OnLoad. It is called before any JNI method is called, and it can populate the table of native methods using pointers to any C functions. See the official document
I have the following JNI wrapper C++ code:
#include "map_container.h"
extern "C" {
JNIEXPORT void JNICALL Java_com_map_Map_openMapNative(JNIEnv* env, jobject thiz, jstring path);
};
static map_container* map = NULL;
void Java_com_map_Map_openMapNative(JNIEnv* env, jobject thiz, jstring path)
{
const char* filename_utf8 = env->GetStringUTFChars(path, false);
if ( mapview )
{
delete mapview;
mapview = NULL;
}
mapview = new map_container((char*)filename_utf8);
if (filename_utf8)
{
env->ReleaseStringUTFChars(path, filename_utf8);
}
}
and have com.map.Map.openMapNative declared as static which means that I can operate one map at a time. How do I modify this C++ code so that map_container* map becomes not static and belongs to the exact instance of com.map.Map class? map_container is totally C++ class and has no reflection in Java.
I'm using SWIG to generate all the necessary wrapper code. You simply define the classes and functions you want to wrap in an interface definition file, and let SWIG create all the required C++ and Java code for you. Highly recommended! Writing JNI code by hand is just way too boring and error-prone IMHO. See the SWIG docs for Java, it's very easy to use.
If you have declared Map.openMapNative as "static native" in the Java source, then the current declaration is misleading, because the second argument is actually a reference to the Map class (should be "jclass clazz" rather than "jobject thiz"). Doesn't really matter, since you're not using "thiz", and every jclass is a jobject.
The way you make this non-static is to remove the "static" from the declaration on the Java side, and start using "thiz" to access members of the instance.
It might be a little late, but this cookbook here is invaluable!
http://thebreakfastpost.com/2012/01/23/wrapping-a-c-library-with-jni-part-1/
At first glance, and depending that you need, SWIG might be meta-overkill!