有时候,我们反编译apk得到一个so库,如果直接使用这个so库的话,必须使用原来so库同样的package名字,才能用。
很明显,这个so库是libNativeExampleActivity.so, 库里面有两个native函数addFunction和getString。
虽然知道了这两个native函数,但是我们还不能直接使用,因为这两个native函数在so库里面的真实函数名不是addFunction和getString,
它在native函数名之前还有包名,所以必须使用nm命令,查看so库里面的函数名。
显示so库函数的命令:
nm -A libNativeExampleActivity.so
或者
nm -D libNativeExampleActivity.so
这样我们看到so库里的主要信息:
Java_org_natives_example_NativeExampleActivity_addFunction
Java_org_natives_example_NativeExampleActivity_getString
看到没有,在addFunction函数前面还有包名,这就是为什么直接使用人家的so库的时候,一定要使用原来的package名字!
好了,现在是怎么调用这两个函数了,4个步骤完成。
1.用Eclipse创建一个项目
2.在终端进入到项目的路径soHello/bin/classes,执行命令:
guo@guo-desktop:~/workspace/soHello/bin/classes$ javah -jni so.hello.SoHelloActivity
在soHello/bin/classes目录下会生成一个文件so_hello_SoHelloActivity.h
3.写一个so_hello_SoHelloActivity.cpp文件
4.编写Android.mk
然后这个so库就可以用啦!
综述:
这里主要使用了dlopen、dlsym、dlclose三个函数来加载so库:
这样人家反编译你的apk,就知道你侵犯了人家的版权。为了达到混淆的目的,我们可以再写一个so库调用人家的so库,即把人家的so库放到root的某个路径下,用c/c++语言调用这个so库。比如说,我得到一个APK,反编译这个APK看到下面的代码:
static {
try {
System.loadLibrary("NativeExampleActivity");
} catch (Throwable t) {
}
}
public native int addFunction(int a, int b);
public native String getString(String name);
很明显,这个so库是libNativeExampleActivity.so, 库里面有两个native函数addFunction和getString。
虽然知道了这两个native函数,但是我们还不能直接使用,因为这两个native函数在so库里面的真实函数名不是addFunction和getString,
它在native函数名之前还有包名,所以必须使用nm命令,查看so库里面的函数名。
显示so库函数的命令:
nm -A libNativeExampleActivity.so
或者
nm -D libNativeExampleActivity.so
这样我们看到so库里的主要信息:
Java_org_natives_example_NativeExampleActivity_addFunction
Java_org_natives_example_NativeExampleActivity_getString
看到没有,在addFunction函数前面还有包名,这就是为什么直接使用人家的so库的时候,一定要使用原来的package名字!
好了,现在是怎么调用这两个函数了,4个步骤完成。
1.用Eclipse创建一个项目
package so.hello;
import android.app.Activity;
import android.os.Bundle;
public class SoHelloActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
static {
try {
System.loadLibrary("soHello");
} catch (Throwable t) {
}
}
public native int addFunction1(int a, int b);
public native String getString1(String name);
}
2.在终端进入到项目的路径soHello/bin/classes,执行命令:
guo@guo-desktop:~/workspace/soHello/bin/classes$ javah -jni so.hello.SoHelloActivity
在soHello/bin/classes目录下会生成一个文件so_hello_SoHelloActivity.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class so_hello_SoHelloActivity */
#ifndef _Included_so_hello_SoHelloActivity
#define _Included_so_hello_SoHelloActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: so_hello_SoHelloActivity
* Method: addFunction1
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_so_hello_SoHelloActivity_addFunction1
(JNIEnv *, jobject, jint, jint);
/*
* Class: so_hello_SoHelloActivity
* Method: getString1
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_so_hello_SoHelloActivity_getString1
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
3.写一个so_hello_SoHelloActivity.cpp文件
#include "so_hello_SoHelloActivity.h"
#include <stdlib.h>
#include <fcntl.h>
#include <android/log.h>
#include <stdio.h>
#include <stdarg.h>
#include <dlfcn.h>
void *filehandle = NULL;
jint (*addFunc)(JNIEnv *,jobject,jint,jint) = NULL;
jstring (*getStringFunc)(JNIEnv *, jobject, jstring) = NULL;
JNIEXPORT jint JNICALL Java_so_hello_SoHelloActivity_addFunction1
(JNIEnv *env, jobject obj, jint a, jint b);
{
jint mun = 0;
//事先把libNativeExampleActivity放到root/system/lib/目录下
filehandle = dlopen("/system/lib/libNativeExampleActivity.so", RTLD_LAZY);
if(filehandle)
{
addFunc = (jint (*)(JNIEnv *,jobject,jint,jint))dlsym(filehandle, "Java_org_natives_example_NativeExampleActivity_addFunction");
if(addFunc)
mun = addFunc(env, obj, a, b);
dlclose(filehandle);
filehandle = NULL;
}
return mun
}
/*
* Class: so_hello_SoHelloActivity
* Method: getString1
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_so_hello_SoHelloActivity_getString1
(JNIEnv *, jobject, jstring name)
{
jstring mun = 0;
//事先把libNativeExampleActivity放到root/system/lib/目录下
filehandle = dlopen("/system/lib/libNativeExampleActivity.so", RTLD_LAZY);
if(filehandle)
{
getStringFunc = (jstring (*)(JNIEnv *,jobject,jstring))dlsym(filehandle, "Java_org_natives_example_NativeExampleActivity_getString");
if(getStringFunc)
{
mun = getStringFunc(env, obj, name);
}
dlclose(filehandle);
filehandle = NULL;
}
return mun
}
4.编写Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_C_INCLUDES += system/core/include/cutils
LOCAL_SHARED_LIBRARIES := \
libdl \
libcutils
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libsoHello
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := so_hello_SoHelloActivity.cpp
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
include $(BUILD_SHARED_LIBRARY)
使用mm命令编译so_hello_SoHelloActivity.cpp,便可以生成libsoHello.so库。
然后这个so库就可以用啦!
综述:
这里主要使用了dlopen、dlsym、dlclose三个函数来加载so库:
void *filehandle = NULL;
jint (*addFunc)(JNIEnv *,jobject,jint,jint) = NULL;
jint mun = 0
//事先把libNativeExampleActivity放到root/system/lib/目录下
filehandle = dlopen("/system/lib/libNativeExampleActivity.so", RTLD_LAZY);
if(filehandle)
{
addFunc = (jint (*)(JNIEnv *,jobject,jint,jint))dlsym(filehandle, "Java_org_natives_example_NativeExampleActivity_addFunction");
if(addFunc)
mun = addFunc(env, obj, a, b);
dlclose(filehandle);
filehandle = NULL;
}