android使用C/C++調用SO庫


有時候,我們反編譯apk得到一個so庫,如果直接使用這個so庫的話,必須使用原來so庫同樣的package名字,才能用。
這樣人家反編譯你的apk,就知道你侵犯了人家的版權。為了達到混淆的目的,我們可以再寫一個so庫調用人家的so庫,即把人家的so庫放到root的某個路徑下,用c/c++語言調用這個so庫。比如說,我得到一個APK,反編譯這個APK看到下面的代碼:

 

[html]  view plain copy
 
 
  1. static {  
  2.     try {  
  3.         System.loadLibrary("NativeExampleActivity");  
  4.     } catch (Throwable t) {  
  5.     }  
  6. }  
  7. public native int addFunction(int a, int b);  
  8. 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創建一個項目

[html]  view plain copy
 
 
  1. package so.hello;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5.   
  6. public class SoHelloActivity extends Activity {  
  7.     /** Called when the activity is first created. */  
  8.     @Override  
  9.     public void onCreate(Bundle savedInstanceState) {  
  10.         super.onCreate(savedInstanceState);  
  11.         setContentView(R.layout.main);  
  12.     }  
  13.     static {  
  14.         try {  
  15.             System.loadLibrary("soHello");  
  16.         } catch (Throwable t) {  
  17.         }  
  18.     }  
  19.     public native int addFunction1(int a, int b);  
  20.     public native String getString1(String name);  
  21. }  

2.在終端進入到項目的路徑soHello/bin/classes,執行命令:
guo@guo-desktop:~/workspace/soHello/bin/classes$ javah -jni so.hello.SoHelloActivity
在soHello/bin/classes目錄下會生成一個文件so_hello_SoHelloActivity.h

 

 

[html]  view plain copy
 
 
  1. /* DO NOT EDIT THIS FILE - it is machine generated */  
  2. #include <jni.h>  
  3. /* Header for class so_hello_SoHelloActivity */  
  4.   
  5. #ifndef _Included_so_hello_SoHelloActivity  
  6. #define _Included_so_hello_SoHelloActivity  
  7. #ifdef __cplusplus  
  8. extern "C" {  
  9. #endif  
  10. /*  
  11.  * Class:     so_hello_SoHelloActivity  
  12.  * Method:    addFunction1  
  13.  * Signature: (II)I  
  14.  */  
  15. JNIEXPORT jint JNICALL Java_so_hello_SoHelloActivity_addFunction1  
  16.   (JNIEnv *, jobject, jint, jint);  
  17.   
  18. /*  
  19.  * Class:     so_hello_SoHelloActivity  
  20.  * Method:    getString1  
  21.  * Signature: (Ljava/lang/String;)Ljava/lang/String;  
  22.  */  
  23. JNIEXPORT jstring JNICALL Java_so_hello_SoHelloActivity_getString1  
  24.   (JNIEnv *, jobject, jstring);  
  25.   
  26. #ifdef __cplusplus  
  27. }  
  28. #endif  
  29. #endif  


3.寫一個so_hello_SoHelloActivity.cpp文件

 

 

[html]  view plain copy
 
 
  1. #include "so_hello_SoHelloActivity.h"   
  2. #include <stdlib.h>  
  3. #include <fcntl.h>  
  4. #include <android/log.h>  
  5. #include <stdio.h>    
  6. #include <stdarg.h>    
  7. #include <dlfcn.h>   
  8.   
  9. void *filehandle = NULL;  
  10. jint (*addFunc)(JNIEnv *,jobject,jint,jint) = NULL;  
  11. jstring (*getStringFunc)(JNIEnv *, jobject, jstring) = NULL;  
  12.   
  13. JNIEXPORT jint JNICALL Java_so_hello_SoHelloActivity_addFunction1  
  14.   (JNIEnv *env, jobject obj, jint a, jint b);  
  15. {  
  16.     jint mun = 0;  
  17.     //事先把libNativeExampleActivity放到root/system/lib/目錄下  
  18.     filehandle = dlopen("/system/lib/libNativeExampleActivity.so", RTLD_LAZY);  
  19.     if(filehandle)  
  20.     {  
  21.         addFunc = (jint (*)(JNIEnv *,jobject,jint,jint))dlsym(filehandle, "Java_org_natives_example_NativeExampleActivity_addFunction");  
  22.         if(addFunc)  
  23.             mun = addFunc(env, obj, a, b);  
  24.         dlclose(filehandle);   
  25.         filehandle = NULL;  
  26.     }  
  27.     return mun;
  28. }  
  29.   
  30. /*  
  31.  * Class:     so_hello_SoHelloActivity  
  32.  * Method:    getString1  
  33.  * Signature: (Ljava/lang/String;)Ljava/lang/String;  
  34.  */  
  35. JNIEXPORT jstring JNICALL Java_so_hello_SoHelloActivity_getString1  
  36.   (JNIEnv *, jobject, jstring name)  
  37. {  
  38.     jstring mun = 0;  
  39.     //事先把libNativeExampleActivity放到root/system/lib/目錄下  
  40.     filehandle = dlopen("/system/lib/libNativeExampleActivity.so", RTLD_LAZY);  
  41.     if(filehandle)  
  42.     {  
  43.         getStringFunc = (jstring (*)(JNIEnv *,jobject,jstring))dlsym(filehandle, "Java_org_natives_example_NativeExampleActivity_getString");  
  44.         if(getStringFunc)  
  45.         {  
  46.             mun = getStringFunc(env, obj, name);  
  47.         }  
  48.         dlclose(filehandle);   
  49.         filehandle = NULL;  
  50.     }  
  51.     return env->NewStringUTF(mun);
  52. }  


4.編寫Android.mk

 

 

[html]  view plain copy
 
 
  1. LOCAL_PATH := $(call my-dir)  
  2.   
  3. include $(CLEAR_VARS)  
  4.   
  5. LOCAL_LDLIBS := -llog  
  6. LOCAL_C_INCLUDES += system/core/include/cutils  
  7. LOCAL_SHARED_LIBRARIES := \  
  8.     libdl \  
  9.     libcutils  
  10.   
  11. LOCAL_PRELINK_MODULE := false  
  12. LOCAL_MODULE      := libsoHello  
  13. LOCAL_MODULE_TAGS := optional  
  14. LOCAL_SRC_FILES   := so_hello_SoHelloActivity.cpp  
  15. LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog  
  16.   
  17. 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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM