Android NDK编译

Android NDK 编译

写在前面的絮叨

万分的尴尬,今天测试一个Android 系统Binder driver UAF问题的时候,需要编译C语言编写的PoC,在考虑到手机肯定是ARM架构以后,果断在电脑上安装了”全套”的ARM交叉编译环境。经过编译、上传、运行果然不出所料,不是找不到文件,就是SegmentFault。

自己鼓捣了半天,最后灵机一动想到Android里面的C语言貌似是要用NDK直接编译的,于是。。。果然就能用了,不过使用NDK编译也有一点小坑,在此记录一下。

环境配置

首先需要将NDK添加到系统环境变量中,具体的就是编辑器打开~/.bashrc,然后加入下面这个:

1
2
export NDK_HOME=/home/skywang/workspace/ndk/r7b/android-ndk-r7b
export PATH=$PATH:$NDK_HOME

根据自己的NDK路径去配置,保证在bash中输入ndk-build命令能够正常运行.

完成之后建立一个文件夹(以helloworld为例),并在该目录下再建立一个jni文件夹,最后再jni文件夹下创建*.c、Android.mk、Application.mk三个文件。

C文件

在这些文件中,编写功能需要的C语言代码,如编写一个hello.c

1
2
3
4
5
#include <stdio.h>
int main(void){
printf("Hello World!\n");
return 0;
}

Android.mk 文件

这个文件类似于Makefile,定义C语言文件的编译方式,举个例子:

1
2
3
4
5
6
7
8
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := hello
LOCAL_SRC_FILES := hello.c

include $(BUILD_EXECUTABLE)

这是编译可执行文件的例子,当然大部分使用NDK做开发的时候,都是需要编译成为库文件的,于是:

编译为静态链接库:

1
2
3
4
5
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := hello
LOCAL_SRC_FILES := hello.c
include $(BUILD_STATIC_LIBRARY)

编译为动态链接库:

1
2
3
4
5
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := hello
LOCAL_SRC_FILES := hello.c
include $(BUILD_SHARED_LIBRARY)

编译为动态库+静态库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := mylib_static
LOCAL_SRC_FILES := src.c
include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := mylib_shared
LOCAL_SRC_FILES := src2.c

LOCAL_STATIC_LIBRARIES := mylib_static

include $(BUILD_SHARED_LIBRARY)

更多详细信息,请移步android.mk编写指南:

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

Application.mk 文件

该文件控制编译出来支持的指令集架构,最方便的就是写个ALL:

1
APP_ABI := all

编译与运行

跑到我们创建好的文件下,运行ndk-build,然后就会报错。。。

Google了一下,发现需要完善下命令,如下:

1
ndk-build NDK_PROJECT_PATH=. NDK_APPLICATION_MK=./jni/Application.mk