freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

程序分析基础知识
2020-11-12 10:15:25

Android逆向分析基础

Android逆向技术也是安全圈常见的话题,网络上也有很多资料。本节主要介绍一下关于逆向分析apk的时候需要做些什么。在逆向之前必须有好工具,其实还需要掌握逆向的基本知识:smali语法和arm指令,能够大致读懂程序。

1.1逆向工具

这里介绍几个工具,这些工具在我们做逆向的时候都会用到。

1.反编译利器apktool

apktool使用java语言编写的,也是开源的,同时它是逆向的金钥匙,所以非常重要。现在很多apk为了防止被这个工具反编译,就针对这个工具的漏洞做了一层防护策略,如果要成功反编译各个apk的话,那么就必须看懂它的源码,然后针对具体反编译异常具体分析,修复异常即可。

2.反编译姐妹花dex2jar+jd-gui

这两个其实是辅助使用的,一般是直接解压apk得到classes.dex文件,使用dex2jar转化成jar文件,使用jd-gui来直接查看java源码。

3.反编译友好工具JEB和Jadx

这两个工具其实是整合了上面两个工具的功能,让反编译实现了可视化操作,而且高效快捷,适合在快速分析apk内部消息的场景,也是不可或缺的工具。

4.Hook神奇Xposed框架

这个工具主要编写游戏外挂,获取应用关键数据。该工具叶酸上是神奇,有了它,逆向APP就是手到擒来的事儿,它可以把每个APP的关键逻辑分析的非常清楚。

5.Native Hook神奇Cydia Substrate

这个工具跟Xposed框架很相似,除了可以Hook Java层功能,还可以方便地Hook Native层功能。对于一些游戏和应用有so文件,可以利用这个框架进行hook so中的制定函数功能呢。

6.脱壳神器ZjDroid工具

现在很多APP应用为了安全性,做了加固策略,那么在逆向中有一个技术是脱壳就是针对加固策略的。所谓脱壳就是要把原本加固的应用进行解密,那么ZjDroid工具就是一款脱壳神奇。这个工具其实是基于Xposed框架编写的。

7.神器的工具IDA

有了这个逆向工具,才算是进入逆向的大门,可惜她是收费的。这个工具最厉害的地方就是它能够分析so文件,同时可以动态调试so,还可以打开apk文件,dex文件也可以打开。

1.2逆向基本知识

要学习逆向,除了有利的工具,还需要了解一些基本知识,比如smali语法、arm指令、Android中的NDK开发等,因为这些都是在逆向过程中经常会用到的知识。

smali语法是逆向的基础核心知识,有的人觉得这个可能会成为一门新的语言。其实不然,它的语法非常简单,熟悉起来非常方便。有时候我们会利用smali语法手动插入代码,而不是需要手动编写smali代码,可以先用java编写好功能,再反编译成smali代码,再手动插入即可。但是简单的smali语法还是需要看懂,比如赋值、方法调用等操作。

arm指令就不多说了,很多大学都开设了这门学科,不过很多人可能在项目开发中并没有用到,但是arm指令知识对于逆向来说也是至关重要的,也是最复杂的。现在很多应用为了更加安全就把代码都放到so文件中,这样在逆向so文件的时候就必须要了解arm指令,才能大致看懂逻辑代码,才能继续后面的工作。

1.3打开系统调试总开关

这节主要介绍怎么在不需要反编译的情况下添加android:debuggleable属性,就可以进行调试。现在已经有很多工具可以做这件事儿了,我们先来说说具体的实现原理。其实Android中有一些常用的配置信息都是存放在文件夹中,如下图所示,比如设备的系统、版本号、CPU型号等信息,这个文件就位置在:/system/build.prop。

查看该文件的内容,可以看到很多设备的信息,而且以ro开头的文件表示这些属性值是只读的,不能进行修改。Android中提供了两个命令来操作这些信息:getprop和setprop命令,查看系统的sdk版本号如下所示:

设置系统的sdk版本号为22,如下所示:

可是这里并没有设置成功,是因为ro开头的属性是不允许后期修改的。如果修改,需要重新编译系统镜像文件boot.img。

既然Android中的一些系统属性值存放在一个文件中,而且这些值是只读的,近可以通过getprop命令读取,有一个API也是可以直接读取的,就是:

System.getProperty("ro.build.version.sdk");

其实这个方法是native层实现的,具体就不再赘述。那么这个文件是存储这些属性值的,是怎么解析加载到内存汇总,能够给每个APP都能访问到呢?

这个工作就是init.rc进程操作的,系统启动时第一步就是解析init.rc文件,这个文件是在系统的根目录下,这里会做很多初始化操作,同时会做属性文件的解析工作,所以Android属性系统通过系统服务提供系统配置和状态的管理。为了让运行中的所有进程共享系统运行时所需要的各种设置值,系统会开辟一个属性存储区域,并提供访问该内存区域的API。所有进程都可以访问属性值,但是只有init进程可以修改属性值,其他进程所想修改属性值,需要向init进程发出请求,最终由init进程负责修改属性值。

上面说到的是system/build.prop文件。里面主要是系统的配置信息,其实还有一个重要文件在根目录下面:default.prop,如下图所示:

这里有一个重要属性ro.debuggable,它是系统中每个应用是否能够被调试的关键。在Android系统中一个应用能否被调试是这么判断的:当Dalvik虚拟机从Android应用框架中启动时,系统属性ro.debuggable为1,如果该值被置1,系统中所有的程序都是可以调试的。如果系统中的ro.debuggable为0,则会判断程序的AndroidManifast.xml中application标签中的android:debuggable元素是否为true,如果未true则开启调试支持。

这相当于Android系统中的一个开关,即根据目录中default.prop文件中的ro.debuggable属性值,可用于调试所有设备中的应用。如果这个属性值设置为1,设备中所有的应用都可以被调试,即使在AndroidManifest.xml中没有android:debuggable=true,还是可以调试的。而这些系统属性的文件system/build.prop和default.prop,都是init进程来进行解析的,系统启动的时候就会去解析init.rc文件,这个文件中有配置光宇系统属性的解析工作信息。然后会把这些系统属性信息解析到内存中,提供给所有APP进行访问,这块信息也是内存共享的,但是这些ro开头的属性信息只能init进程进行修改。下面我们就分析一下修改这个属性值的三种方式。

第一种方式:直接修改default.prop文件中的值,然后重启社保。那么现在如果按照上面的目的:就是不需要反编译apk,添加android:debuggable属性的话,直接修改default.prop文件,把ro.debuggable属性改成1即可。但是通过分析发现,修改完成后肯定需要重启设备的,因为需要让init进程重新解析属性文件,把属性信息加载内存中方可起作用的。但在实际的操作过程中,修改了这个属性,结果会发现设备死机的情况。如果属性能够通过这些文件来修改的话,那就感觉系统会出现各种问题了,系统是不会允许修改这些文件的。

第二种方式:改写系统文件,重新编译系统镜像文件,然后刷入到设备中

前面已经提到过,这些属性文件是在系统镜像文件boot.img系统启动的时候,释放到具体目录中的,也就是说如果能够直接修改boot.img中的这个属性即可,那么操作是可以进行的。这种方式一旦成功操作,这个设备就是永远可以进行各种应用的调试了。

第三种方式:注入init进程,修改内存中的属性值

上面分析了,init进程会解析这个属性文件,然后把这些属性信息解析到内存中,给所有APP进行访问使用,所以在init进程的内存块中是存在这些属性值的。那么这时候就好办了,有一个技术可以做到,就是进程注入技术。可以使用ptrace注入到init进程,然后修改内存中的这些属性值,只要init进程不重启的话,那么这些属性值就会起效。但是这个方法有个弊端,就是如果init进程挂了重启之后,这个设置就失效了,必须重新操作。但是一般情况下只要保证设备不重启的话,init进程就会一直存在的。而且如果发生了init进程挂掉的情况,那么设备肯定会重启的,到时候再重新操作一下即可。

上面的三种方式设置系统中的调试属性总开关,最后一种方式是最靠谱的。而且思路简单,但是不用重新去写这个代码逻辑的,因为网上已经有mprop这个工具了,是一个执行文件。用法很简单,首先把可执行文件mprop拷贝到设备中的目录下

然后执行命令,如下图所示:

这个工具可以修改内存中所有的属性值,包括机型信息。修改完成之后,使用getprop命令再查看该值,发现已经做了修改。需要注意的是,修改的是内存的值,而不是文件中的值。所以default.prop文件中的内容是没有发生变化。这个时候,可以使用Eclipse的DDMS来查看可以调试的应用列表,也可以用adb jdwp命令来查看可以调试的进程id.通过这种方式,我们发现还是没有展示设备中所有的应用个,其实这里有一个细节问题,虽然已经修改了内存值,但是有一个进程需要重启一下,哪个进程呢?就是adbd这个进程,这个进程是adb的守护进程,就是设备连接信息传输后台进程,所以想看到可以调试的进程信息,那么需要重启这个进程,这样连接信息才会更新。重启这个进程很简单,直接使用命令即可,如下所示:stop;start其实这两个命令,用分号隔开,首先是干掉进程,然后重启。运行完命令之后,再去看DDMS窗口信息。这时候所有的应用进程都是可以调试的,在使用dumpsys package命令查看一个应用包信息。flags标志中并没有debuggable属性值,但是这个应用是可以调试的。

1.4小结

该节主要简单介绍了在做逆向工作之前,要先准备一些基础知识,主要从三个方面介绍了基本知识点:首先是逆向工具,包括apktool、Jadx、Xposed、DjDroid等相关信息,其次是逆向的基本语法知识,主要包括smali和arm语法,最后是逆向的辅助功能,通过修改系统调试开关,方便后续逆向应用。


# Android
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者