本篇文章是Android逆向系列的第五篇,开始介绍学习NDK的开发及JNI接口。本文先介绍使用NDK套件编译出一个基于arm平台的程序,并在手机上测试运行,接着介绍引入JNI,先简单入门熟悉下JNI头文件中的内容,包括定义的一些基本类型和本地接口结构体
本篇文章是Android逆向系列的第五篇,开始介绍学习NDK的开发及JNI接口。本文先介绍使用NDK套件编译出一个基于ARM平台的程序,并在手机上测试运行,接着介绍引入JNI,先简单入门熟悉下JNI头文件中的内容,包括定义的一些基本类型和本地接口结构体。
一、简介
本节介绍使用NDK工具编译一个运行于arm上的可执行程序,上传至手机上并测试运行。
开始之前,首先要了解架构平台,arm架构非常适用于移动平台,所以安卓手机基本上都是arm架构,除此Linux系统上使用的通常是x86_64架构,那么在Linux上编译出的可执行文件就无法直接在手机上运行,这就造就了架构平台的不一样,编译出的可执行程序不能通用。所以需要交叉编译器,用于在本平台上编译出基于其他平台的程序,本节所使用的NDK工具就可以视为一款交叉编译器,在Windows上编译出基于ARM架构的可执行程序。
二、NDK工具安装
1、Android NDK安装
Android NDK(Native Development Kit)原生开发工具,用于编译生成so文件、可执行文件。(适用于ARM架构)
下载地址:https://developer.android.com/ndk/downloads
参考:NDK 使用入门
1)下载解压至C盘
2)配置环境变量
C:\android-ndk-r10e
3)构建build
三、源文件及配置文件
1、编写.c源文件
编写文件anquan.c
,内容如下,测试输出test
#include <stdio.h>
int main (){
printf("test");
printf("\n");
return 0;
}
2、.mk文件简介
.mk
文件是makefile文件,定义了一系列的规则来指定文件那部分需要编译及如何编译。
Android.mk
文件描述要编译某个具体的模块,所需要的一些资源,包括要编译的源码、要链接的库等。
Application.mk
文件用来描述你的应用程序需要哪些模块,以及这些模块所要具有的一些特性。
3、编写Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_MODULE := anquan
LOCAL_SRC_FILES := anquan.c
LOCAL_CFLAGS += -pie -fPIE
LOCAL_LDFLAGS += -pie -fPIE
include $(BUILD_EXECUTABLE)
内容解释:
LOCAL_PATH := $(call my-dir)
:返回Android.mk文件的路径(jni目录路径),my-dir是由编译系统提供的一个宏include $(CLEAR_VARS)
:CLEAR-VARS变量由编译系统提供,定时清理LOCAL开头的文件,但不会清理LOCAL_PATH字段,清理的目的是因为以LOCAL开头的变量是全局的,清理后避免影响。LOCAL_ARM_MODE := arm
:指定编译后的指令集,arm指令集中的每个指令有4个字节LOCAL_MODULE := anquan
:定义的模块文件(编译后的名字)LOCAL_SRC_FILES := anquan.c
:同目录下的源文件LOCAL_CFLAGS += -pie -fPIE
LOCAL_LDFLAGS += -pie -fPIE
:指定源文件基于PIE安全机制来编译include $(BUILD_EXECUTABLE)
:指定编译文件的类型,EXECUTABLE可执行文件,SHARED_LIBRARY共享库文件.so文件
4、编写Application.mk文件
APP_ABI := x86 armeabi-v7a
APP_ABI
:指明编译与调试的CPU架构,v7a是第七代及以上的ARM处理器。
四、ndk编译可执行程序
1、在jni目录下创建上述三个文件
三个文件内容在第三部分中已经描述了,可以回去看看
2、使用ndk工具进行编译
进入到jni目录下,使用命令ndk-build
进行编译
可以在上一级目录下看到三个文件夹,其中编译出的可执行文件位于libs\armeabi-v7a
下
五、在手机上执行文件
1、usb连接调试
插入usb线后,可以通过命令adb devices
进行查看连接的设备
2、将编译后的程序移到手机上
adb push D:\EveryCode\AndroidLearning\libs\armeabi-v7a\anquan /data/local/tmp
3、adb工具进入手机内部
adb shell
su
cd /data/local/tmp
4、执行该文件
chmod 777 anquan
./anquan
六、JNI入门介绍
1、JNI概述
JNI接口是一大堆函数的接口API
在Java和C中起到桥梁的作用
2、JNI作用
通过JNI接口实现Java层与Native层相互调用,在使用Jadx等反编译软件时就只能显示出方法名而无法显示方法体内容,具体的在更底层。
方便Java层调用C++的优秀资源库,也方便交叉开发
七、JNI头文件
1、基本类型的定义
这部分使用typedef关键字定义了jbyte、jchar、jint等一系列变量
2、本地接口结构体的定义
这里给出了一堆调用Java的方法
主要有get、set、call三种,下面简单介绍下
1)Call开头的方法
如下图,简单了解第一行的CallobjectMethod()
方法
jobject:表示返回值
JNIEnv*:参数之一,本地调用的一个接口,提供了大量的JNI接口函数调用。(默认传入)
jobject:参数之一(默认传入)
jmethodID:参数之一,该方法需要一个方法ID,即Java层方法的ID,这里可以通过另一个方法GetMethodid来获取ID值
2)Get开头的方法
GetFieldID方法用于获取FieldID值,返回值为jfieldID
JNIEnv*:默认参数之一
jclass:参数之一,由findclass方法获取
两个const char*:分别是Java层方法名称和函数签名(返回值+参数)
3)Set开头的方法
设置各种字段,返回值为空void
3、Java参数类型与Native参数类型
上面简单介绍了JNI头文件中部分调用Java层的方法,其中的参数大致相同但还是有区别,这里详细解释下:
Java层中的八种基本类型,在JNI中对应的是类型前加上j即可
Java层中的object(类、接口等),在JNI中对应于jobject
Java层中基本数据类型的数组,在JNI中对用jarray类型
可参考下图,基本数据类型对比图
引用数据类型图
- 本文作者: xigua
- 本文来源: 奇安信攻防社区
- 原文链接: https://forum.butian.net/share/683
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!