移动端安全的东西很多,花样也很多,不论是从硬件架构,操作系统,还是其他安全角度来讲,每接触一项新事物,都有可能需要学习一整个生态内的安全知识。
最近开学杂事逐渐增多。。。就把我自己关于android的一些学习笔记和内容整理了下发出来,以铺大饼的形式尽量囊括在入门Android安全所学习过的一些知识点,希望对大家有所帮助。
ps:以下内容没有具体例子的分析,原因是其中的大部分知识点,我都是从其他师傅们的文章和代码一路学习过来的。文章也整理了以下放有我自己学习下来感觉收获较大的资源链接。
总结下来,对于一个平台的逆向工程技术需要掌握的技能大致如下:
本文大致分为以下几个模块:
其实总的来说就是--->逆向工程 orz
apktool:可以将apk文件反编译生成smali格式的反汇编代码,也可将apktool重新编译生成apk文件。这里提醒一点就是具体厂商apktool使用会涉及到具体的资源包。
学习途径:官方文档
adb:android sdk自带的命令行工具,用于与设备通信,便于执行各种设备操作
学习途径:官方文档配上awesome系列基本上就够用了
官方文档
awesome-adb
放几条常用指令:
通过此指令可以获取所有包名
启动app
列出所有正在执行app的activity
停止应用程序
signapk,keytool和jarsigner: 用于给apk签名的工具(在这踩过坑,建议搞清楚),这里放一条我常用的解决办法,两条命令,前者是生成自己的密钥,后者是签名,具体选项代表自查
jd-gui和dex2jar: 反编译工具,通常用于阅读反编译生成的java代码
当然这些都是些传统的工具,推荐在熟悉这些工具的具体运作方式之后再选择高效的集成工具,比如说jadx,jeb等。
apk的打包流程:
APK的文件结构:
整体流程如下:
app的安装途径:系统程序安装,android市场安装,adb工具安装,sd卡安装
app安装过程可以追踪分析android系统程序PackageInstaller中PackageInstallerActivity来去理解,具体内容这里不再展开。
Dalvik虚拟机:其设计的初衷也许是是提高运行效率并规避与oracle的版权纠纷
其特点有:
Dalivik文件结构与java文件结构不同,Dalvik虚拟机通过dx工具对java类文件中常量池进行分解,消除冗余信息后在组合成新常量池
又由于Dalvik虚拟机是基于寄存器架构的,相比于基于栈架构的java虚拟机,数据访问会快很多,同时Dalvik的指令即更加精简,程序的执行速度会快些。
android系统架构图:
可见Dalvik属于Android运行时环境,和核心库共同承担Android应用程序的运行工作
这里有一点需要注意就是以消息通信的角度来看又可以分成另一个架构图,其中我们常关注的是native层和java层
初次之外还有art,jvm,可以看这篇博客
Android系统和程序的启动过程:
Android系统启动加载内核后----> 执行init进程 ----> 启动Zygote进程 ----> 初始化Dalvik虚拟机 ---> 启动system_server进入Zygote模式,用socket等待命令 ---> Zygote收到命令后fork一个Dalvik虚拟机实例来执行程序入口函数
流程大致如下图:
其中Zygote有三种创建进程的方法:
fork后 ---> 虚拟机通过loadClassFromDex完成装载(用gDvm.loadedClass全局哈希表存储查询类) ---> dvmVerifyCodeFlow对代码检验 ---> FindClass查找装载main方法类 ---> dvmInterpret初始化解释器并执行字节码流
以上就是Dalvik在程序执行时的要点,还有其涉及到的JIT技术和Dalvik的汇编代码内容繁杂,建议直接阅读官方文档或者相应书籍
其中dex文件主流反汇编工具有BakSmali与Dedexer,详细的dex文件格式内容也建议直接阅读相关资料或源码,这里就出DexFile的数据结构。
结构图
关于模拟器体系结构的梳理
这个链接放在这里的原因是作者自己曾经根深蒂固地把arm和android两个概念紧紧的结合在一起了,忽略了android studio创建的模拟器是Intel x86架构的,导致踩过坑。
这里说是调试而不说逆向的原因是因为逆向的内容实在是太多了,入门可以参考《android软件安全与逆向分析》,《android攻防权威指南》以及《漏洞战争》中的部分内容来学习,这里选择调试中重要的内容来介绍。姑且就分为以下两者吧
在 smali 语法中,使用的都是寄存器,但是其在解释执行的时候,很多都会映射到栈中。通常每个smali会对应一个类。
编译 - smali2dex
给定一个 smali 文件,我们可以使用如下方式将 smali 文件编译为 dex 文件。
运行 smali
在将 smali 文件编译成 dex 文件后,我们可以进一步执行
首先,使用 adb 将 dex 文件 push 到手机上
其次使用如下命令执行
AS + smalidea
smali的修改
之前尝试用apk改之理,但是由于版本太老了有较多不方便,所以弃坑,现在我通常是apktool反编译后修改,然后再编译并使用自签名,这样也可以达到修改安装使用的效果
基本原生程序
如elf文件就可以
so 原生程序的调试
其加载方式有system.load和system.loadlibrary两种,前者加载绝对路径,后者加载libs下的so文件,两者都会在内部调用doload函数,其流程大致如下
doload -> nativeload -> 对应到Dalvik_java_lang_Runtime_nativeLoad-> dvmLoadNativeCode加载相应的native code -> findSharedLibEntry(判断是否已经加载了这个库以及是否是对应的class loader) --如没有加载--> dlopen打开 --> si->CallConstructors()初始化 --> 创建表且用dlsym获取对应so文件中 JNI_OnLoad 函数
静态分析 java 层: 没什么好说的,理解程序逻辑去做就好了
静态分析原生层程序基本的过程如下
在android studio 3.12后已经将ddms移除了,所以官方的建议是
当我们不能使用ddms时意味着我们使用jdb进行转发时无法确定具体的port,有一种方法是加载程序运行时需要的so文件,然后在一些关键函数比如jniString()函数下断,运行apk后,然后attach其进程即可。
当然有时候会需要在jni_load下断,而so文件又被处理或者干脆jni_load被加密了,这时需要pull出来libdvm so文件,参考我们加载方式的流程,直接查找dvmLoadNativeCode,函数中调用dlopen加载so,返回时so已经加载且已经初始化完成,调试下就能找到。
hook
hook的方法很多,但原理就是这么几种,同时又有对Dalvik,ART,inline,GOT等对象hook,这个有太多大佬写过各种类型的hook了,hook的框架也有许多,展开分析内容太多了,就不再累述了,这里就推荐下以frida入门。
Frida hook分为注入进程,直接在源码中修改,以及动态链接三种方式
frida的交互实现大致可以这么理解:默认监听27042端口,对目标进程gadget在启动时进行阻塞,直到实现attach进程或者在使用spawn()后再resume恢复进程,当然这些状态都可以通过配置修改,也可以提前设置好过滤器将特定脚本加载到特定应用中。
由于frida是个轻量级的hook框架,所以还是比较容易添加自己想要的功能,具体请看官网的frida架构图。
frida有一个功能可以为我们生成一个进程而不是将它注入到运行中的进程中,它注入到Zygote中,生成我们的进程并且等待输入。即spawn是注入zygote而attach是注入当前进程。
这里有遇到过的一些小坑,分别是设备检测问题和windows端的编码问题:
https://github.com/frida/frida/issues/1111
https://github.com/rkern/line_profiler/issues/37
一直想挖android上的漏洞,但真正上手的时候发现自己缺乏很多真实场景的经验和思路,毕竟漏洞挖掘和ctf题差距还是不一般的大(汗),于是就整理了下android上常见的问题,尽可能的去整理些思路出来。
ps:这里有一个点没有涉及,就是关于android端会涉及到较多的抓包分析工作,但无奈我是个二进制菜鸡,就不班门弄斧的推荐了。
我们都知道android四大组件,所以这里的大部分内容来自对瘦蛟舞大佬多年前文章的阅读笔记(汗,果然小白只能玩大佬玩剩下的)
常见的关注点
关键方法
activity分为四种,在考虑安全时分别从创建activity和使用activity时考虑
广播接收器既可以在manifest文件中声明,也可以在代码中进行动态的创建,并以调用Context.registerReceiver()的方式注册至系统。
注意关注类型 protectionlevel 权限
广播需要注意广播的对象范围以及持久性带来的影响
关键方法
ContentProvider用来存放和获取数据并使这些数据可以被所有的应用程序访问。它们是应用程序之间共享数据的唯一方法;不包括所有Android软件包都能访问的公共储存区域。
关键方法
startService与bindService两者的区别就是使Service的周期改变.由startService启动的Service必须要有stopService来结束Service,不调用stopService则会造成Activity结束了而Service还运行着.bindService启动的Service可以由unbindService来结束,也可以在Activity结束之后(onDestroy)自动结束.
关键方法
android端的一些常见漏洞
1、组件公开安全漏洞
2、Content Provider文件目录遍历漏洞
3、AndroidManifest.xml中AllowBackup安全检测
4、Intent劫持风险安全检测
5、数据存储安全检测
6、拒绝服务攻击安全检测
7、随机数生成函数使用错误
8、中间人攻击漏洞
9、从sdcard加载dex漏洞
10、Activity被劫持风险
11、WebView高危接口安全检测
12、WebView明文存储密码漏洞
13、Android HTTPS中间人劫持漏洞
14、Webview file跨域访问
有bug就要有patch,所以不可避免的会涉及到热修复。
同时,加壳和混淆是为了保护产权。
因为暂时没接触到太多样例,这里也就不班门弄斧了。
热修复可以理解为紧急补丁但无需重新发布版本的意思,主要分为代码修复,资源修复,so库修复,框架有
热修复具体内容可以从这看
其余的一些好资源推荐:
hook以及frida:
漏洞挖掘
练习题
综合
这篇纯粹是水文,断断续续地记录下来的,本来是打算放自己博客的,但后来一想放下自己的学习笔记或许对和我一样的小白们在道路上会有所帮助,就放个帖子。下次尽可能放些漏洞挖掘,fuzz以及有意思的mobile题:)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-2-23 23:49
被Dawuge编辑
,原因: