zoukankan      html  css  js  c++  java
  • android使用C/C++调用SO库

    有时候,我们反编译apk得到一个so库,如果直接使用这个so库的话,必须使用原来so库同样的package名字,才能用。
    这样人家反编译你的apk,就知道你侵犯了人家的版权。为了达到混淆的目的,我们可以再写一个so库调用人家的so库,即把人家的so库放到root的某个路径下,用c/c++语言调用这个so库。比如说,我得到一个APK,反编译这个APK看到下面的代码:

    [html] view plaincopy
     
     
    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 plaincopy
     
     
    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 plaincopy
     
     
    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 plaincopy
     
     
    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 plaincopy
     
     
    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;
    }

  • 相关阅读:
    Session 0 隔离
    在DIV容器中使用浮动元素
    Linq学习总结(5)——标准查询运算符
    Linq学习总结(3)——yield
    消息拦截的简单实现
    网站内容可访问性——关于背景与前景颜色的对比标准
    CSS优先级
    Linq学习总结(4)——Lambda表达式
    element ui表格的校验和自定义校验规则
    vue 递归组件的两种方法
  • 原文地址:https://www.cnblogs.com/fnlingnzb-learner/p/7236169.html
Copyright © 2011-2022 走看看