目的
能快速,簡(jiǎn)單(主要是指脫離AndroidStudio)的把c/c++ 源碼進(jìn)行交叉編譯成Android上的動(dòng)態(tài)庫(kù),靜態(tài)庫(kù),或者可執(zhí)行文件。從而為逆向分析構(gòu)建demo節(jié)省時(shí)間。
編譯環(huán)境配置
電腦:Mac OS 10.13.4
NDK:官網(wǎng)下載,目前最新的好像android-ndk-r17 我用的是 android-ndk-r14b,ndk不需要安裝官網(wǎng)下載后解壓就行。
測(cè)試機(jī): 華為EVA-AL00 Android7.0
配置環(huán)境變量
為了方便使用ndk的命令行工具,我們配置環(huán)境變量
在 ~/.bash_profile 文件中添加如下配置
export ANDROID_NDK_HOME=/Users/user01/Development/android-ndk-r14b
export PATH=${PATH}:${ANDROID_NDK_HOME}:${ANDROID_NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin
然后命令行運(yùn)行如下命令:
$ source ~/.bash_profile
然后命令行運(yùn)行:
$ ndk-build -h
如果能打印出 ndk-build 這個(gè)工具的幫助文檔說(shuō)明環(huán)境變量配置成功
測(cè)試簡(jiǎn)單的例子
創(chuàng)建如下目錄結(jié)構(gòu)(注意jni這層目錄很重要,名字不要隨便取):
~/Desktop/test/
└── jni/
├── Android.mk
├── Application.mk
└── test.c
主要有三個(gè)文件,其中Android.mk和Application.mk 是輔助ndk-build進(jìn)行編譯的,test.c是我們的c測(cè)試用例
- Application.mk
主要指定生成哪些cpu架構(gòu)的動(dòng)態(tài)庫(kù),這里只生成armeabi 和armeabi-v7a架構(gòu)的庫(kù)
APP_ABI := armeabi armeabi-v7a
APP_PLATFORM := android-14
- Android.mk
具體Android.mk的更詳細(xì)的配置自行Google
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 生成的so庫(kù)的名字為libdemo.so
LOCAL_MODULE := demo
# 用于編譯的c文件
LOCAL_SRC_FILES := test.c
# 生成庫(kù)的類(lèi)型,是動(dòng)態(tài)庫(kù),靜態(tài)庫(kù)還是可執(zhí)行文件,這里先來(lái)生成一個(gè)動(dòng)態(tài)庫(kù)
include $(BUILD_SHARED_LIBRARY)
# 下面這么寫(xiě)是生成可執(zhí)行文件
#include $(BUILD_EXECUTABLE)
- test.c
很簡(jiǎn)單就是打印一句 hello world!
#include <stdio.h>
int main(const int argc,const char* args[]){
const char* str = "hello world!";
printf("%s\n",str);
return 0;
}
然后命令行進(jìn)入到test目錄下面:
$ cd ~/Desktop/test
$ ndk-build -C ./jni
然后會(huì)生成如下目錄結(jié)構(gòu),obj目錄下是生成動(dòng)態(tài)庫(kù)的中間文件,libs里面是最終生成的不同CPU架構(gòu)的動(dòng)態(tài)庫(kù):
test
├── jni
│ ├── Android.mk
│ ├── Application.mk
│ └── test.c
├── libs
│ ├── armeabi
│ │ └── libdemo.so
│ └── armeabi-v7a
│ └── libdemo.so
└── obj
└── local
├── armeabi
│ ├── libdemo.so
│ └── objs
│ └── demo
│ ├── test.o
│ └── test.o.d
└── armeabi-v7a
├── libdemo.so
└── objs
└── demo
├── test.o
└── test.o.d
為什么非要有jni那一層目錄
約定優(yōu)于配置,沒(méi)有不行嗎?行,但是要改點(diǎn)東西。去掉jni那層目錄再編譯一次,當(dāng)前目錄結(jié)構(gòu)如下:
test/
├── Android.mk
├── Application.mk
└── test.c
命令行執(zhí)行
$ cd ~/Desktop/test$ ndk-build
結(jié)果報(bào)錯(cuò)如下:
Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
錯(cuò)誤日志上說(shuō)什么路徑找不到錯(cuò)誤,需要定義一個(gè)xx變量,我們只需要把編譯命令改成如下就可以了:
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk NDK_APPLICATION_MK=./Application.mk
編譯一個(gè)可以運(yùn)行的文件
修改Android.mk 文件如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := demo
LOCAL_SRC_FILES := test.c
#include $(BUILD_SHARED_LIBRARY)
# Android4.4 以后 調(diào)用的可執(zhí)行文件不是基于PIE方式編譯的,則無(wú)法運(yùn)行
LOCAL_CFLAGS += -pie -fPIE
LOCAL_LDFLAGS += -pie -fPIE
# 編譯一個(gè)可執(zhí)行文件
include $(BUILD_EXECUTABLE)
這個(gè)可執(zhí)行文件在電腦上是沒(méi)法執(zhí)行的,只能放到手機(jī)里面執(zhí)行,執(zhí)行如下命令,我們把剛生成的文件放到手機(jī)上:
- push 文件到手機(jī)
$ adb push libs/armeabi-v7a/demo /data/local/tmp - 為手機(jī)中的demo文件添加可執(zhí)行權(quán)限(為了方便直接給予所有權(quán)限了)
$ adb shell 'chmod 777 /data/local/tmp/demo' - 用手機(jī)環(huán)境運(yùn)行demo這個(gè)文件
$ adb shell '/data/local/tmp/demo'
運(yùn)行結(jié)果會(huì)打印一行
hello world!