安卓逆向的核心流程

一、背景

  安卓逆向的东西比较多,刚接触容易不知道怎么入手。如果知道安卓逆向的核心流程有哪些,对安卓逆向有一个整体的认知,就能比较清晰地知道自己缺什么和学什么。这篇文章梳理一下安卓逆向的要点,方便学习安卓逆向的小伙伴参考对照。

二、设备

  一开始先准备好手机和电脑这些硬件设备。安卓系统是从linux系统过来的,进程之间互相隔离,想突破隔离就需要有root权限。手机root目前有三种方案:Magisk、KernelSU和APatch。

  1、Magisk:上手比较简单,只需要修改启动文件boot.img,插件也比较多。
  2、KernelSU:修改内核,相对Magisk更加稳定,但门槛高,插件比较少。
  3、APatch:结合上面两个的优势,只需要修改boot.img+支持加载内核模块。

  安卓系统或linux系统分为用户层和内核层,APK只能运行在用户层。如果有内核插件的能力,就可以从更底层进行拦截修改。就逆向分析来说,比较推荐的是APatch:既能够使用上层的安卓插件AndroidPatch Modules(APM),也能够用底层的内核插件KernelPatch Modules(KPM)

三、工具

  拿到一个APK,先看看这个APK有没有加壳。加壳的原理是把原本的代码资源进行加密保护,等到运行的时候再解密释放出来。而脱壳就是把解密释放的代码资源拷贝出来。查壳可以用ApkCheckPack,脱壳可以用frida_dump

  得到没有保护壳的APK之后,就可以进行静态分析,先看看整个APK都有哪些文件资源。APK本身也分为两层:Java层和Native层(C/C++层),对应两种工具:
  1、Java层的静态分析工具:jadx
  2、Native层的静态分析工具:IDA Pro

  静态分析一开始只是看个大概,之后还得进行动态调试,才能知道APK运行的细节。动态调试对应的工具有两种:
  1、单步调试:lldb,适合下断点之后跟踪数据和逻辑
  2、拦截打印:frida,适合拦截看参数和整体调用

  如果一用工具进行分析,就提示环境异常或者直接闪退,那就意味着工具被检测到了。
  检测要么基于原理,比如lldb正在进行动态调试,status会有TracerPid的信息,APK只要检查TracerPid字段,就能知道是不是被动态调试。而反检测就是根据原理,检查的时候修改返回正常的值,比如抹掉TracerPid字段。
  要么是基于特征进行检测,比如frida的默认端口是27042,APK只要检查端口27042是不是存在,就能知道是不是被frida工具入侵了。而反检测就是修改特征值,比如修改frida的端口号;或者直接换魔改版的工具Florida

四、分析

  有了工具,接下来就是进行具体的功能分析,这个时候需要具备两种能力:
  1、正向开发的能力:比如点一个按钮,弹一个提示框。起码要知道正向开发的时候,代码正常是怎么写的,这样逆向分析的时候才能找到切入点。
  2、代码反编译的能力:正向开发是清晰明了的源代码,编译之后看到的是汇编。java编译成smail,Native(C/C++)编译成ARM汇编。而逆向分析就得从底层的这些汇编看出原本代码的逻辑。

  在进行分析代码的时候,也会遇到很多保护手段,给逆向分析带来更多的麻烦:
  1、代码混淆:Java或者Navite(JNI)清晰的名字被替换成abc这些代替符号。这种只能根据代码的逻辑去猜测。
  2、字符串加密:静态分析看到的是混乱的密文,运行的时候才解密成明文。要么运行的时候把明文拷贝出来,要么根据解密算法用脚本去还原。
  3、控制流扁平化:原本结构清晰的ifelse,被打乱成一个状态机不断跳转。现在比较多的是OLLVM的扁平化、对应的可以写脚本去还原原本的结构。
  4、代码变异:原本的代码变异成相同语义的多条代码,一眼看上去不那么直观易懂。这种得走代码优化,或者脚本识别之后的还原。
  5、代码虚拟化:原本的一句代码,变成了一套虚拟代码和虚拟机器,虽然运行的结果一样,但分析难度特别高。这种就得跟踪代码的执行过程,然后根据虚拟机的原理去还原。

五、框架

  分析之后,除非纯协议不依赖客户端,不然就得对客户端的功能进行调用和拦截。如果自用而且功能少,直接按原理写代码也可以。但大多时候功能多,设备复杂,用现成的框架写业务代码更舒服,不用去管底层细节。

  因为APK分成java层和native层,对应的框架也有多种。单纯java层可以用Xposed或者LSPosed;单纯native层可以用Dobby或者Frida Gum;如果java和native都想要,可以用Frida提供的gadget

六、落地

  框架选完,就是落地应用起来。这个时候就得决定最终要运行在什么样的设备环境里。设备环境按root权限可以先分成两种:有root权限和没root权限。

  有root权限具体又分为:真机root和云手机root。
  1、真机root:直接真实的手机进行root,优势是真实机器不用担心设备参数;缺点是支持root的机型有限,目前就pixel和一加手机支持直接root,而且号多会有IP集中的问题。
  2、云手机root:网络云端虚拟出来的手机,优势是可以集中管理,IP分散;缺点是设备参数可能不全或不真实。

  没root权限具体又分为:重打包和虚拟沙箱。
  1、重打包:把APK解开,加入逆向的东西、然后重新签名打包,优势是直接在正常手机上安装运行;缺点是需要过改包的检测。
  2、虚拟沙箱:虚拟APK提供一个虚拟环境,然后加载目标APK,虚拟环境自由注入东西到目标APK里面;好处是不用修改APK,也不需要特殊硬件环境;缺点就是虚拟环境的工作量很大,要做很多接口代理。

  如果只是几个号自己玩,用真实手机root就可以了。如果账号很多需要群控,可以考虑云手机。如果是要在正常手机上运行,因为没有root权限,就得重打包和虚拟沙箱。

七、风控

  不管选择什么样的落地应用方案,多多少少都会和原生APK+真实手机有差异。风控就是开发APK的人不想被逆向破解,在APK里面收集一些关键,看有没有差异。而逆向分析就需要知道风控收集了哪些数据,然后进行隐藏或者修改,尽量模仿:原生APK+真实手机。

  APK收集信息也分为两层:Java层和Native层。这里按读取APK签名信息做例子:
  Java层收集信息:1、直接调用android提供的api:getPackageInfo;2、通过底层的IPC:api最终是通过IPC和系统服务进程通讯拿到数据,应用进程 → Binder IPC → system_server → 返回数据。
  Native层收集信息:1、直接使用syscall:open,read去解析读取;2、比如syscall更底层,直接用汇编指令SVC:mov x8, #56,svc #0。

  想要修改或者隐藏信息,也就得对应拦截:api、IPC、syscall和SVC。前三个都可以在用户层进行拦截,但最后的SVC再下去就是内核。如果是静态的SVC汇编代码,因为地址固定还可以hook;如果是动态生成的,就得在用户层外面拦截了,上内核模块或者定制ROM。此外,linux内核提供了安全模块:seccomp,可以在用户层和内核层之间进行拦截。关键是seccomp的接口暴露给用户层,不用修改内核。

八、结尾

  以上,就是安卓逆向的核心流程。里面的关键点说得很简略,展开说会有很多内容。就像一棵树,先理清主干,之后再开枝散叶。(一堆坑,后续填)


转自:https://bbs.kanxue.com/thread-288487.htm

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2015-2026 Kaisar
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信