• Android逆向笔记之AndroidStudio生成so并调用native方法


    AndroidStudio版本: 4.0.1


    使用AndroidStudio进行ndk开发很简单,我们的目标是生成一个so文件,里面有一个getSign方法,在Java层调用so文件中的getSign方法获取。

    先创建一个NDK项目,创建的时候拉到最下面选择Native C++,然后Next:

    1

    然后输入项目的名字:

    1

    这一步保持默认即可(反正我也不懂C++...):

    1

    创建完项目之后糟糕红色叹号了,有这么个提示:

    1

    这是因为创建的项目没有配置NDK,NDK需要单独下载,可以去这个页面选择自己平台对应的NDK下载:

    https://developer.android.com/ndk/downloads?hl=zh-cn

    下载完解压到本地即可,注意解压后的路径名中尽量不要包含中文以免无谓踩坑。

    然后回到AndroidStudio,为项目设置上刚刚下载的这个NDK,菜单选择File-->Project Structure:

    1

    切换到SDK Location,然后在Android NDK Location那一项选择刚刚下载的NDK解压到的目录,OK之后项目就会自动开始sync。

    1

    sync完之后就不会报错了,还显示了个小对号:

    1

    切换到Project视图看下生成的项目结构:

    1

    先看MainActivity自动生成的内容:

    package cc11001100.android.ndk_study_003;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity {
    
        // Used to load the 'native-lib' library on application startup.
        static {
            System.loadLibrary("native-lib");
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // Example of a call to a native method
            TextView tv = findViewById(R.id.sample_text);
            tv.setText(stringFromJNI());
        }
    
        /**
         * A native method that is implemented by the 'native-lib' native library,
         * which is packaged with this application.
         */
        public native String stringFromJNI();
    }
    

    自动加载了一个native-lab的so文件,然后还自动声明了一个stringFromJNI的native方法,然后再来看cpp下自动生成的这个native-lib.cpp文件:

    #include <jni.h>
    #include <string>
    
    extern "C" JNIEXPORT jstring JNICALL
    Java_cc11001100_android_ndk_1study_1003_MainActivity_stringFromJNI(
            JNIEnv* env,
            jobject /* this */) {
        std::string hello = "Hello from C++";
        return env->NewStringUTF(hello.c_str());
    }
    

    看起来跟我们想要的结果已经差不多了,不行,名字不一样,接下来就是修改名字为getSign,先改Java层的MainActivity,注意修改的时候使用重构重命名,Shift+6,改完之后:

    package cc11001100.android.ndk_study_003;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity {
    
        // Used to load the 'native-lib' library on application startup.
        static {
            System.loadLibrary("native-lib");
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // Example of a call to a native method
            TextView tv = findViewById(R.id.sample_text);
            tv.setText(getSign());
        }
    
        /**
         * A native method that is implemented by the 'native-lib' native library,
         * which is packaged with this application.
         */
        public native String getSign();
    }
    

    会发现native-lib.cpp的名字也自动修改了,都不用我们手动干预,很方便:

    #include <jni.h>
    #include <string>
    
    extern "C" JNIEXPORT jstring JNICALL
    Java_cc11001100_android_ndk_1study_1003_MainActivity_getSign(
            JNIEnv* env,
            jobject /* this */) {
        std::string hello = "Hello from C++";
        return env->NewStringUTF(hello.c_str());
    }
    

    然后Run一下看看安装效果:

    1

    OK,接下来打包成apk,然后反编译观察一下这种方式打包的效果是怎样的:

    1

    选择打包成apk:

    1

    key可以创建一个新的也可以用老的:

    1

    构建release包,签名版本为V2,然后“Finish”等一段时间:

    1

    如果打包成功的话,在app下会多出一个release文件夹,下面有个app-release.apk文件,这就是本次打包成功的apk文件:

    1

    然后启动jeb,把打包好的apk文件拖到jeb中看下,项目结构是这样的:

    1

    反编译MainActivity看下:

    1

    然后到lib下,把so文件拿出来:

    1

    然后拖到IDA64中,在Function name窗口中输入Java搜索我们的JNI方法,因为我们是静态注册的,所以这里是能搜到的,然后双击搜索到的函数名,查看其汇编代码:

    1

    然后分析这段汇编的代码就能还原原本逻辑了,其实arm汇编我也没整太明白,就赶紧结束以免露馅,本篇文章到此为止吧。

  • 相关阅读:
    Cookie和Session的区别
    get和post的区别
    TCP和UDP的区别
    TCP三次握手过程
    docker 安装prometheus
    大数据集群环境搭建之一 hadoop-ha高可用安装
    大数据集群环境 zookeeper集群环境安装
    Centos 脚本中几个特殊符号的作用笔记
    VMware 设置虚拟机Centos 上网的两种方式
    大数据集群环境搭建之一 Centos基本环境准备
  • 原文地址:https://www.cnblogs.com/cc11001100/p/13974841.html
Copyright © 2020-2023  润新知