前言
此文章仅适用于兴趣研究,不可作为损坏他人或其他机构等利益之用,本文只是提出一个设想,并不保证具有普适性
开题
对于安全来说,app是毫无安全性可言的。
不管您是用了proGuard来混淆app,还是用了360加固宝,腾讯加固,等加固产品,最终都会被以各种方法破解。
例如使用IDA Pro,来进行dump,很容易就可以进行还原未加固的.dex文件,源代码就会暴露出来
因为app要运行,总会把加固的东西还原进内存,总是会有一些工具可以做到脱壳。
所以与其想办法在前端做加密,不如使用SSL和安全的服务器端
本讲主要介绍如何利用手写xposed模块,hook(钩)出我们想要的密码的盐值
注,此方法对于native method无解
需求
1.需求的出现
我学校有个查成绩的app,抓包发现使用的是RESTful风格的WebService,配合手机端的app
原理是
使用用户名和加密的密码登录,返回一个由时间和用户信息共同决定的token,以后的各种请求都由此token来确定请求者身份,可以很容易把此WebService搬到网页上面来,而不用为了安装一个一年只用2次的app而到处求包
于是决定搞清楚p字段(密码)加密的原理
2.分析p字段
p字段的长相
c98f9b47a56d685001b94a9827feef36
他的特点有:32位,最大字母是f
由此可以初步判断,他可能是使用了较为常见的MD5消息摘要算法进行的加密
利用站长工具MD5在线加密,对‘password’这个密码进行了测试,发现
与上文
c98f9b47a56d685001b94a9827feef36
是不一样的
3.对app进行反编译
由于第2步中的两次测试结果不一致,猜测app内部可能使用了盐(Salt)
盐(Salt),在密码学中,是指在散列之前将散列内容(例如:密码)的任意固定位置插入特定的字符串。这个在散列中加入字符串的方式称为“加盐”。其作用是让加盐后的散列结果和没有加盐的结果不相同,在不同的应用情景中,这个处理可以增加额外的安全性。
为了探寻加盐方式和加密逻辑,要对app进行反编译
这里使用apktool
apktool的下载地址:https://ibotpeaches.github.io/Apktool/
将app的apk安装包和apktool放在同一文件夹下
cd
到该目录 或 按住shift
键在该目录空白处右键,选择在此处打开cmd/powershell窗口
执行如下命令
java -jar .\apktool_【版本号】.jar d .\【apk名字】.apk
发现整个程序的入口被一个桩模块(stub)取代,再看到qihoo
,就知道是用了360加固
这下就很棘手了
4.面临抉择
app被加固,我有两条路可以走
- 给app脱壳
- 想其他办法
我也在网上搜了不少IDA pro的文章,看的也都似懂非懂,于是还是放弃了这个方法
正文
最后决定使用Xposed模块hook相应方法
hook的话我们需要知道md5加密的方法的方法名,但是由于代码是加固了的,我们无从得知
逆向思维
方法无非有这两大类,一种是我们不知道名字的,一种是系统的类的方法,名字肯定是固定的
既然密码有加盐,那么定然会用到+
来做字符串拼接:pass+salt
而字符串拼接会被编译成StringBuilder
的字节码,所以只要hook了StringBuilder
的toString
方法,就会得到pass+salt
的返回值
StringBuilder在现代化的IDE里面已经不被推荐使用了,因为编译器会把+连接的字符串编译成StringBuilder的append方法,为了保持代码的美观和可读性,IDE都会建议使用+号而不是sb
1.Xposed框架安装
xposed分两部分,一个是框架(framework),一个是模块(module)
框架可以直接安装,需要root的手机和兼容的系统
xposed官网下载地址 - XDA论坛
去百度上搜也可以,推荐使用酷安市场下载
详细的框架安装教程这里不提供,网上可以搜到更为详尽的教程
2.进行模块的开发
1)准备Android Studio
2)新建一个项目
不需要添加Activity,建一个空空的项目就好
您可以选择阅读官方开发教程说明:https://github.com/rovo89/XposedBridge/wiki/Development-tutorial
也可以继续看我的表演
3)添加如下依赖
我在这里使用kotlin语言来发开
//主要的依赖
provided 'de.robv.android.xposed:api:82'
//注解,可选
provided 'de.robv.android.xposed:api:82:sources'
4)在清单文件Application里面加入
5)编写一个普通的类
如Main
/**
* Created by harbo on 2018/1/16.
* Email: [email protected]
*/
class Main : IXposedHookLoadPackage {
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
if (lpparam!!.packageName != "【您要处理的app的包名】")
return
XposedHelpers.findAndHookMethod(StringBuilder::class.java,
"toString",
object : XC_MethodHook() {
override fun beforeHookedMethod(param: MethodHookParam?) {
Log.d("xposed抓到了", "before")
}
override fun afterHookedMethod(param: MethodHookParam?) {
Log.d("xposed抓到了", "after")
val result = param!!.resultOrThrowable
Log.d("xposed抓到了", result.toString())
}
})
}
}
6)代码解释
使用
XposedHelpers
类的静态方法
findAndHookMethod
:
此方法有两个重载,一个适用于系统类,一个适用于要hook的app自定义的类。
我们使用3个参数的那个方法:
- 第一个参数:明确hook对象的类
- 第二个参数:要hook的方法名
- 第三个参数:一个hook方法的匿名内部类实例
重写 afterHookedMethod
,将param
的result
打成日志即可
7)新建xposed_init文件
在项目上右键new -> Folder -> Assets Folder
新建文件
xposed_init
,打开它,在里面写上要执行的xposed动作类
cn.tellyouwhat.mhook.Main
即可
8)编译的时候选择不需要activity
9)激活模块,硬重启手机(虚拟机可以软重启)
在xposed installer中,点击模块选项,勾中您开发的模块,然后重启手机,就能启用该模块
打开您要hook的app,输入用户名和密码进行登录
10)在LogCat中查找
就可能会发现加密字符串的盐值
password后面那几个字母就是盐
还可能出现很多情况,比如加密
md5(md5(pass)+salt)
md5(md5(pass+salt))
md5(pass+salt)
等等情况,需要小心调试,慢慢发现
11)验证
此盐值
c98f9b47a56d685001b94a9827feef36
匹配
结束语
本次测试成功,纯属机缘巧合,如没有解决您遇到的问题,还请见谅。本文只是提供一个思路,靠谱的还得是内存DUMP。也奉劝各位app安全的从业人员,把重心转移到传输层面上,app无绝对的安全可言。