安卓那档事03
校验
是开发者在数据传送时采用的一种校正数据的一种方式
常见的校验有:签名校验(最常见)、dexcrc校验、apk完整性校验、路径文件校验等
APK签名
通过对 Apk 进行签名,开发者可以证明对 Apk 的所有权和控制权,可用于安装和更新其应用。而在 Android 设备上的安装 Apk ,如果是一个没有被签名的 Apk,则会被拒绝安装。在安装 Apk 的时候,软件包管理器也会验证 Apk 是否已经被正确签名,并且通过签名证书和数据摘要验证是否合法没有被篡改。只有确认安全无篡改的情况下,才允许安装在设备上。
简单来说,APK 的签名主要作用有两个:
- 证明 APK 的所有者。
- 允许 Android 市场和设备校验 APK 的正确性。
Android 目前支持以下四种应用签名方案:
- v1 方案:基于 JAR 签名。
- v2 方案:APK 签名方案 v2(在 Android 7.0 中引入)
- v3 方案:APK 签名方案 v3(在 Android 9 中引入)
- v4 方案:APK 签名方案 v4(在 Android 11 中引入)
V1 签名的机制
主要就在 META-INF 目录下的三个文件,MANIFEST.MF,ANDROID.SF,ANDROID.RSA,他们都是 V1 签名的产物。
- MANIFEST.MF:这是摘要文件。程序遍历Apk包中的所有文件(entry),对非文件夹非签名文件的文件,逐个用SHA1(安全哈希算法)生成摘要信息,再用Base64进行编码。如果你改变了apk包中的文件,那么在apk安装校验时,改变后的文件摘要信息与MANIFEST.MF的检验信息不同,于是程序就不能成功安装。
ANDROID.SF:这是对摘要的签名文件。对前一步生成的MANIFEST.MF,使用SHA1-RSA算法,用开发者的私钥进行签名。在安装时只能使用公钥才能解密它。解密之后,将它与未加密的摘要信息(即,MANIFEST.MF文件)进行对比,如果相符,则表明内容没有被异常修改。
ANDROID.RSA文件中保存了公钥、所采用的加密算法等信息。
在某些情况下,直接对apk进行v1签名可以绕过apk的签名校验
v2方案会将 APK 文件视为 blob,并对整个文件进行签名检查。对 APK 进行的任何修改(包括对 ZIP 元数据进行的修改)都会使 APK 签名作废。这种形式的 APK 验证不仅速度要快得多,而且能够发现更多种未经授权的修改。
V2
v2方案会将 APK 文件视为 blob,并对整个文件进行签名检查。对 APK 进行的任何修改(包括对 ZIP 元数据进行的修改)都会使 APK 签名作废。这种形式的 APK 验证不仅速度要快得多,而且能够发现更多种未经授权的修改。
签名校验
一般来说,普通的签名校验会导致软件的闪退,黑屏,卡启动页等 当然,以上都算是比较好的,有一些比较狠的作者,则会直接rm -rf /,把基带都格掉的一键变砖。
1 |
|
正己说遇到最恶心的校验:三角校验,就是so检测dex,动态加载的dex(在软件运行时会解压释放一段dex文件,检测完后就删除)检测so,dex检测动态加载的dex。
课程作业
这次课程中第一个校验是普通获取签名校验。
正己老师给了普通获取签名校验代码:
1 |
|
在jadx中反编译得到:
简单的分析可以知道这个是最后进行比较,我们可以通过frida hook使得这个函数直接返回true。
常见的签名校验对抗
方法一:核心破解插件,不签名安装应用
方法二:一键过签名工具,例如MT、NP、ARMPro、CNFIX、Modex的去除签名校验功能
方法三:具体分析签名校验逻辑(手撕签名校验)
方法四:io重定向--VA&SVC:ptrace+seccomp
方法五:去作者家严刑拷打拿到.jks文件和密码
手动实现PM代理
什么是PMS
PackageManagerService(简称PMS),是Android系统核心服务之一,处理包管理相关的工作,常见的比如安装、卸载应用等。
示例
1 |
|
感觉和frida差不多,但是不如firda
IO重定向
什么是IO重定向?
例:在读A文件的时候指向B文件
平头哥的核心代码 Virtual Engine for Android(Support 12.0 in business version)
IO重定向可以干嘛?
1,可以让文件只读,不可写
2,禁止访问文件
3,路径替换
具体用处:
过签名检测(使得目标包的签名校验读取的是另一个包[原来的没修改过的包])
风控对抗(例:一个文件记录App启动的次数干扰)
过Root检测,Xposed检测(文件不可读取)
原理(?)
我大概知道的是:就是hook安卓底层的IO读取流,然后最后实现让程序读取自己指定的部分
MT管理器作者做的利用重定向对抗签名校验的开源连接:新版MT去签及对抗
其他的一些校验
root
例子:
1 |
|
代码解析:
定义了一个 isDeviceRooted()
函数,该函数调用了三个检测 root 的方法:checkRootMethod1()
、checkRootMethod2()
和 checkRootMethod3()
。
checkRootMethod1()
方法检查设备的 build tags
是否包含 test-keys
。这通常是用于测试的设备,因此如果检测到这个标记,则可以认为设备已被 root。
checkRootMethod2()
方法检查设备是否存在一些特定的文件,这些文件通常被用于执行 root 操作。如果检测到这些文件,则可以认为设备已被 root。
checkRootMethod3()
方法使用 Runtime.exec()
方法来执行 which su
命令,然后检查命令的输出是否不为空。如果输出不为空,则可以认为设备已被 root。
一些反制手段:
反制手段
- hook
- 分析具体的检测代码
- 利用IO重定向使文件不可读
- 修改Andoird源码,去除常见指纹
模拟器检测
1 |
|
代码解析:
通过检测系统的 Build
对象来判断当前设备是否为模拟器。具体方法是检测 Build.FINGERPRINT
属性是否包含字符串 "generic"
。
下面是一篇正己的模拟器检测对抗
反调试
安卓自带的
1 |
|
和win端的isDebuggerPresent()
一样
debuggable属性
1 |
|
和win端的PEB
中的NtGlobalFlag
相类似(?)
ptrace检测
1 |
|
win端也可以搞这个
调试进程名检测
1 |
|
更完善的安卓反调试文章
看雪的,回头整理一下
frida
有空看看
一些smali
1 Int型赋值
const/4 最大只允许存放4个二进制位(4bit),
const/16 最大值允许存放16个二进制位(16bit), 第一位(即最高位)默认为符号位。单位换算 1byte=8bit
举例说明下寄存器的取值范围: # 以下数据定义高位默认为符号位
const/4 v0,0x2 # 最大只允许存放半字节数据 取值范围为 -8 and 7
const/16 v0 , 0xABCD # 定义一个寄存器变量,最大只允许存放16位数据 比如short类型数据 取值范围为-32768~32767
const v0 , 0xA# 定义一个寄存器, 最大只允许存放32位数据,比如int类型数据 将数字10赋值给v0 取值范围-2147483647~2147483647
const/high16 #定义一个寄存器, 最大只允许存放高16位数值 比如0xFFFF0000末四位补0 存入高四位0XFFFF
2 Long型赋值
const-wide vx, lit32 表示将一个 32 位的常量存储到 vx 与 vx+1 两个寄存器中 —— 即一个 long 类型的数据
PE.
1 |
|
小插曲CRC校验
对于安卓的crc校验,有着一个官方函数:java.util.zip.ZipEntry.getCrc()
该方法会返回未压缩条目数据的CRC-32校验和,如果未知,则为-1
对于安卓自动生成的一个类:Android.R
是不在这个函数的校验范围内的,我们可以用这个保存整个包体的CRC校验结果,从而实现防止篡改包体(虽然找到这个检测干掉也是防不住,防君子不防小人了)
那该如何添加对应的crc值到Android.R
里边?
可以在你的应用中创建一个 res/values/strings.xml
文件,然后在这里定义你自己的字符串资源。例如:
1 |
|
然后,你可以在代码中使用这个字符串资源:
1 |
|
今日的frida
之前还在想,我要是用log插桩或者作者本来有写log的,怎么得到这个log内容,这下在github上找到了个,现在是我的辣()
1 |
|
感谢老哥,看起来还有其他不错的,这里把连接贴上
https://github.com/physics-sec/frida-scripts/tree/master
2023年12月2日21:39:01更新:
靠!原来adb自带日志捕获功能
1 |
|
在adb shell中用这条命令,就能得到日志
这里.[tag]
前面的D
就是表示读取debug类型的日志,就是Log.d()的东西
IO重定向的代码例子
因为有点长,所以放在最后了
1 |
|
学习链接
https://www.52pojie.cn/thread-1731181-1-1.html