闲不住a 发表于 2019-9-24 22:26:00

Android逆向之NDK开发

Android NDK,即Android Native Development Kit。
众所周知,Android程序运行在Dalvik虚拟机中,NDK允许用户使用类似C / C++之类的原生代码语言执行部分程序。
NDK包括了:

1. 从C / C++生成原生代码库所需要的工具和build files。

2. 将一致的原生库嵌入可以在Android设备上部署的应用程序包文件(application packages files ,即.apk文件)中。

**那为什么要用到NDK呢?原因如下:**

\1. 代码的保护,由于apk的java层代码很容易被反编译,而C/C++库被反编译的难度较大。

\2. 在NDK中调用第三方C/C++库,因为大部分的开源库都是用C/C++代码编写的。

\3. 便于移植,用C/C++写的库可以方便在其他的嵌入式平台上再次使用。

**本文主要介绍利用Android Studio进行Android NDK开发。**

官方说明:http://tools.android.com/tech-docs/new-build-system/gradle-experimental

笔者用的是Android Studio2.3版本进行开发。
每一个不同版本的 experimental plugin都对应了特定版本的 Gradle 。
此时为**2017年4月11日**,最新对应列表如下:

| Plugin Version | Gradle Version |
| -------------- | -------------- |
| 0.1.0          | 2.5            |
| 0.2.0          | 2.5            |
| 0.3.0-alpha3   | 2.6            |
| 0.4.0          | 2.8            |
| 0.6.0-alpha1   | 2.8            |
| 0.6.0-alpha5   | 2.10         |
| 0.7.0-alpha1   | 2.10         |
| 0.7.0          | 2.10         |
| 0.7.3          | 2.14.1         |

需要修改的文件结构如下:

├── app/

│——├── app.iml

│—— |── **build.gradle**

│——└── src/

├── **build.gradle**

├── gradle/

│——└── wrapper/

│ ——├── gradle-wrapper.jar

│ ——└── **gradle-wrapper.properties**

├── gradle.properties

├── gradlew*

├── gradlew.bat

├── local.properties

├── MyApplication.iml

└── settings.gradle

**./gradle/wrapper/gradle-wrapper.properties**
每一个新的plugin 版本都会支持一个特定版本的Gradle

如:

‘#’Wed Apr 10 15:27:10 PDT 2013

distributionBase=GRADLE_USER_HOME

distributionPath=wrapper/dists

zipStoreBase=GRADLE_USER_HOME

zipStorePath=wrapper/dists

distributionUrl=https://services.gradle.org/distributions/gradle-2.14.1-all.zip

**./build.gradle**

将plugin的路径由”com.android.tools.build:gradle.

“改为”com.android.tools.build:gradle-experimental ”

如:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {

repositories {

jcenter()

}

dependencies {

classpath “com.android.tools.build:gradle-experimental:0.7.3”

```
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}

```

}

allprojects {

repositories {

jcenter()

}

}


**./app/build.gradle**

具体修改如下:

apply plugin: “com.android.model .application”

model {

android {

compileSdkVersion 23

buildToolsVersion “23.0.2”

defaultConfig {

applicationId “com.example.user.myapplication”

minSdkVersion.apiLevel 15

targetSdkVersion.apiLevel 22

versionCode 1

versionName “1.0”

}

buildTypes {

release {

minifyEnabled false

proguardFiles.add(file(“proguard-rules.pro”))

}

}

ndk{

moduleName “mainactivity”

}

dependencies {

compile fileTree(dir: “libs”, include: [“*.jar”])

compile “com.android.support:appcompat-v7:22.2.0”

**//testCompile ‘junit:junit:4.12’**

}

最后在以下目录new一个jni目录文件夹:



再在**./app/build.gradle**添加以下代码:

android {

。。。

**ndk{**

**moduleName “mainactivity”**

**}**

}

声明在jni文件夹中生成mainactivity.c文件。

然后sync now!得到c文件:



**接下来我们就可以编写Native原生程序了。**

先在MainActivity.java中添加方法:

```java
public static native String Hello1(); //静态无参native函数
public native String Hello1(int i);//非静态有参native函数
```

利用Android Studio自带的功能自动在**mainactivity.c**中创建对应的C函数并修改得:

```c
#include <jni.h>

JNIEXPORT jstring JNICALL
Java_com_example_alen_hellonative_MainActivity_Hello1(JNIEnv *env, jclass type) {

    // TODO
    return (*env)->NewStringUTF(env,"Hello Hello1");

}

JNIEXPORT jstring JNICALL
Java_com_example_alen_hellonative_MainActivity_Hello2(JNIEnv *env, jobject instance, jint a) {

    // TODO

    return (*env)->NewStringUTF(env, "Hello Hello2");
}
```

而c函数受Java方法的影响:

\1. Java方法的类型,如返回值,静态或非静态,将影响c函数的形参;

\2. c函数的函数名对应Java方法的路径;

\3. Java方法的形参将影响对应c函数的形参;

然后利用Button控件分别调用Hello1()与Hello2()。

**activity_main.xml**

```
<Button
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:id="@+id/Button1"
      android:text="Hello1"/>
    <Button
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:id="@+id/Button2"
      android:text="Hello2"/>
```

MainActivity.java

```java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button hello1;
    private Button hello2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      hello1 = (Button)findViewById(R.id.Button1);
      hello2 = (Button)findViewById(R.id.Button2);
      hello1.setOnClickListener(this);
      hello2.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
      switch (v.getId()){
            case R.id.Button1:
                Log.d("jk7aLen", Hello1());
                break;
            case R.id.Button2:
                Log.d("jk7aLen",Hello2(2));
                break;
            default:
                break;
      }
    }
    public static native String Hello1();
    public native String Hello2(int a);
}
```

运行后发现下面错误

com.DefiantDev.SkiSafari:bdservice_v1 E/socket: Native library not found! Please copy libbdpush_V2_2.so into your project!

解决:在MainActivity.java添加相应的Library即可:

```
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    static {
      System.loadLibrary("mainactivity");
    }
    ...
    ...
}
```

其中**“mainactivity”**对应

**ndk{**

**moduleName “mainactivity”**

**}**

运行后在Logcat中显示得:



即调用成功

页: [1]
查看完整版本: Android逆向之NDK开发