《ANDROID 逆向专题》在android中运行 elf程序

我们已经知道,android的底层是linux。本质上,其实android就是一个经过特殊裁剪处理的linux系统,裁剪是为了让我们有限的移动端硬件能够更好地运行这个linux。

相对linux,很多人更加熟悉window。这里我们来做个对比。

                          windows              linux

可执行文件         exe                      elf

静态链接库         .lib                       .a

动态链接库          .dll                     .so

这里说的不太准确,比如windows 下可执行程序不仅仅只有.exe,还有.com、.sys等(这里重点不是这个,杠精请忽略)。虽说在linux中,不像windows那样通过文件后缀来判断文件名,但是依旧是可以使用文件后缀的,而且使用后缀也能帮助我们快速分辨文件类型。

这里我们注意到,在apk中,经常会出现有so文件,它之所以会执行,也就是因为linux的内核中,so是作为动态链接库或者可执行程序的。也就是说,so还是elf 可执行文件,但是这种情况下,so的后缀一般是不显示的。

这里我们脑洞打开

android 的原生开发,我的理解本质上就是在android 中跑 C/C++ 代码。

因为android 是linux 系统。所以我想的是,换句话说,就是在linux 下跑C/C++ 代码。

如此,我们是否可以把一个linux文件放到我们的android 系统上去运行呢??

瞎搞开始了,我打开我的ubuntu,然后用gedit写了一个hello world

《ANDROID 逆向专题》在android中运行 elf程序

然后,找到压箱底很久的 《C程序设计》,终于按照上面的方法编译得到了可执行文件。而且成功用运行了。

《ANDROID 逆向专题》在android中运行 elf程序

对,就是成功打印出来了 "hello world"

我们使用hex 文件查看器来看看我们生成的hello 文件。可以清楚发现,文件头是有.ELF标记的,也就是hello 确实就是linux下的可执行文件

《ANDROID 逆向专题》在android中运行 elf程序

验证我们想法的时候到了,我们将这个hello 文件上传到android 手机上,让android 来运行它。

《ANDROID 逆向专题》在android中运行 elf程序

然后好像运行不来额,报了一个错误说这个是64-bit 的ELF文件。

其实这里就很接近真相了,我们的elf 是二进制文件直接用来运行的。但是与运行直接相关的是cpu处理器。处理器架构的不同,对应的执行程序肯定是不通用的。

目前市面上的CPU分类主要有两大阵营。

1、intel、AMD为首的复杂指令集CPU。架构是X86

2、IBM、ARM为首的精简指令集CPU。IBM公司的CPU是PowerPC架构,ARM公司是ARM架构。

这里我的pc 是x86架构,android 手机是arm,所以肯定是不能运行的。

那么有没方法可以跨平台编译?

肯定是有的,在windows 下进行android开发不就是这么回事么?

我们知道,android开发需要下载两个组件。一个叫sdk,一个叫ndk。其中ndk就是做native 层开发的,现在就派上用场了。

我们接下来就是要用ndk来编译我们的hello.c 代码,然后来生成适用于android 的可执行程序elf文件。

1、先创建一个叫jni 的文件夹(名称一定是jni 不能改),然后将我们的.c 文件放进去,同时创建Android.mk、Application.mk。如下所示:

《ANDROID 逆向专题》在android中运行 elf程序

2、在Application.mk 中输入如下:

《ANDROID 逆向专题》在android中运行 elf程序

这里也就是说编译生成所有平台的可执行文件,当然也可以不生成所有的平台。

比如你这样:

APP_ABI:= x86 armeabi-v7a

那最后就只生成 x86  和 armeabi-v7a 下 使用的文件

3、在Android.mk 输入如下:

《ANDROID 逆向专题》在android中运行 elf程序

这里设置的是编译 hello.c 这个文件 并最后输出 libhello-jni 文件

这里输出的是可执行程序 BUILD_EXECUTABLE ,所以最终我们生成的elf 是不带so后缀的,可以直接运行

但是在一般的android开发中,我们生成的elf文件一般是带so后缀的,是用来给java 层调用的,这时候 对应值应该是

include $(BUILD_SHARED_LIBRARY)

这个要区别开。

LOCAL_CFLAGS += -pie -fPIE

LOCAL_LDFLAGS += -pie -fPIE

是因为,在Android 4.4之后添加了新的保护机制,可执行文件必须是采用PIE编译的。

《ANDROID 逆向专题》在android中运行 elf程序

这三个文件准备好之后,我们就可以开始编译了。使用ndk-build。这里我将ndk 加到了环境变量中,所以可以直接调用,不然需要进到ndk目录下找到ndk-build.cmd 所在的目录下。

《ANDROID 逆向专题》在android中运行 elf程序

命令执行之后,会看到生成了两个目录 obj 和 libs

《ANDROID 逆向专题》在android中运行 elf程序

我们打开libs ,已经得到了各个平台的编译结果。这些平台就是由Application.mk 配置的

《ANDROID 逆向专题》在android中运行 elf程序

这里面的 libhello-jni 就是我们的生成可执行的elf 文件。是没有so后缀的额。

我们找到自己android设备支持的cpu架构,从里面找到对应的 libhello-jni ,最后将这个 elf 放到 android 中去执行,如下:

《ANDROID 逆向专题》在android中运行 elf程序

顺利执行,打印出 hello world。

上面手动让android运行了elf程序,其实在apk中,调用so原理上也是差不多的。