吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 23359|回复: 83
上一主题 下一主题
收起左侧

[Android 分享] [危险!]支付宝钱包手势密码实战破解(root过的手机可直接绕过手势密码)

  [复制链接]
跳转到指定楼层
楼主
tab00 发表于 2014-10-22 22:28 回帖奖励
随着移动互联网的普及以及手机屏幕越做越大等特点,在移动设备上购物、消费已是人们不可或缺的一个生活习惯了。随着这股浪潮的兴起,安全、便捷的移动支付需求也越来越大。因此,各大互联网公司纷纷推出了其移动支付平台。其中,用的比较多的要数腾讯的微信和阿里的支付宝钱包了。            
      正所谓树大招风,移动支付平台的兴起,也给众多一直徘徊在网络阴暗地带的黑客们又一次重生的机会。因为移动平台刚刚兴起,人们对移动平台的安全认识度还不够。就拿我身边的很多朋友来说,他们一买来手机就开始root,之后卸载预装软件,下载游戏外挂等等。今天,我们就以破解支付宝钱包的手势密码为例,来深入了解下android系统上的一些安全知识,希望能引起人们对移动平台安全的重视。


    在此申明:以下文章涉及的代码与分析内容仅供android系统安全知识的学习和交流使用,任何个人或组织不得使用文中提到的技术和代码做违法犯罪活动,否则由此引发的任何后果与法律责任本人概不负责。

实验环境
小米4TD版
MIUI-JHACNBA13.0(已ROOT)
支付宝钱包8.1.0.043001版

使用工具
APK IDE
Smali.jar
Ddms
SQLite Expert
应用宝
程序分析
准备阶段

安装完支付宝钱包之后,运行软件,我这里选择淘宝帐号登录,界面如图1所示。

登录之后,设置手势密码,如图2所示

完成上述两步之后,退出支付宝进程。用腾讯应用宝定位到支付宝的安装目录\data\data\com.eg.android.AlipayGphone,查看目录结构如图3所示。

实战开始 - 破解手势密码错误次数限制

使用APK IDE对支付宝的安装包进行解包分析。解包完成之后,搜索setgestureErrorNum字样,结果如图5所示

经过大致分析,UserInfoDao.smali文件中的addUserInfo函数比较可疑,截取其中一段设置手势密码错误次数的代码如下:
{v0}, Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;->getGestureErrorNum()Ljava/lang/String;
move-result-object v1  
#调用getGestureErrorNum函数获得未加密的错误次数,并保存到v1寄存器

invoke-virtual {v0}, Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;->getUserId()Ljava/lang/String;
move-result-object v2  
#调用getUserId函数获得user id,并保存到v2寄存器

invoke-static {v2}, Lcom/alipay/mobile/security/gesture/util/GesutreContainUtil;->get8BytesStr(Ljava/lang/String;)Ljava/lang/String;
move-result-object v2  
#获取user id的前8个字节,保存到v2寄存器

invoke-static {v1, v2}, Lcom/alipay/mobile/common/security/Des;->encrypt(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
move-result-object v1  
#以user id的前8字节作为key,调用des加密错误次数字符串,并保存到v1寄存器

invoke-virtual {v0, v1}, Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;->setGestureErrorNum(Ljava/lang/String;)V
#调用setGestureErrorNum函数,将加密的字符串保存[/code]通过对上述代码的分析得知,第一次getGestureErrorNum的调用取出的错误次数应该是未加密的字符串,添加log代码验证,代码如图6所示

保存修改的smali文件,重新编译打包,安装完成之后,输入错误的手势密码,log输出数字依次递增。最后一次输入正确的手势密码,错误次数重新归0。LogCat捕捉到的日志如图7所示。

程序分析到这里,我不禁猜测,在错误次数未加密前,把v1寄存器的值设置为字符串“0”是不是就可以骗过支付宝而可以无限次的输入手势密码了呢?于是乎,我又开始了下面的验证,代码如图8所示。

编译打包,重新安装支付宝,输入错误的手势密码,发现5次错误之后程序还是让我们重新登录。看来我们这里设置错误次数已经晚了,于是乎,继续搜索调用addUserInfo函数来加密gestureErrorNum的地方。其中,AlipayPattern.smali文件的settingGestureError函数引起了我的注意。函数代码如下:
.method public settingGestureError(Lcom/alipay/mobile/framework/app/ui/BaseActivity;Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;I)V
.locals 1
new-instance v0, Ljava/lang/StringBuilder; #初始化StringBuilder实例

invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V

invoke-virtual {v0, p3}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
#p3是一个I类型的整型变量,调用StringBuilder. append赋值

move-result-object v0

invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

move-result-object v0  #调用toString函数转换成字符串类型,赋给v0

invoke-virtual {p2, v0}, Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;->setGestureErrorNum(Ljava/lang/String;)V #调用setGestureErrorNum设置未加密的错误次数字符串

invoke-static {}, Lcom/alipay/mobile/framework/AlipayApplication;->getInstance()Lcom/alipay/mobile/framework/AlipayApplication;

move-result-object v0

invoke-static {v0}, Lcom/alipay/mobile/framework/service/ext/dbhelper/SecurityDbHelper;->getInstance(Landroid/content/Context;)Lcom/alipay/mobile/framework/service/ext/dbhelper/SecurityDbHelper;

move-result-object v0

invoke-virtual {v0, p2}, Lcom/alipay/mobile/framework/service/ext/dbhelper/SecurityDbHelper;->addUserInfo(Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;)Z
#调用SecurityDbHelper.addUserInfo函数加密、更新数据库

return-void
.end method
分析到这里,想必这里才是最原始的设置手势输入错误次数的地方吧,修改p3的值为0,测试代码如图9所示。

继续打包、编译、测试。随意输入错误的手势密码,支付宝始终显示“密码错误,还可以输入5次”字样,如图10。

至此,手势密码中的错误次数限制已经被我们解除了。理论上来说,我们可以使用穷举法来获取支付宝的手势密码。但是,作为一名分分钟几百万上下的大黑阔来说,使用穷举法来获得密码这种方式,显然是在浪费生命和金钱呀。

越战越勇 – 查找关键跳转
只破解手势输入错误次数限制显然是不够的。下面我们以手势密码的存储展开来说起。查看alipayclient.db数据库的userinfo表可知,手势密码的存储字段为gesturePwd,搜索getGesturePwd函数得到如图11的结果。

搜索到的结果比较多,根据前面对手势密码错误次数限制的分析,这里可以排除几个文件,例如UserInfoDao.smali文件,它主要用来保存一些用户态的信息,可暂时跳过。剩下的smali文件,我们一个个分析过来。在这里我想说的一点是,逆向分析确实是很考验一个人耐心和细心的一件事情,一个恍惚就会迷失在浩瀚的汇编代码中,但是等到你找到关键的调用点,分析出核心的算法时,那么心境会豁然开朗,真是有种踏破铁鞋无觅处,得来全不费工夫的感脚。好了,扯远了,下面我们继续。
经过我的仔细分析,e.smali文件最有可能是比较输入密码的地方,双击上面e.smali文件的LINE 47行,跳转到的是a函数。由于函数比较长,只贴关键部分,代码如下:
.method public final a(Ljava/lang/String;)V
.locals 4

invoke-virtual {p1}, Ljava/lang/String;->length()I #取输入字符串的长度

move-result v0  

sget v1, Lcom/alipay/mobile/security/gesture/component/LockView;->MINSELECTED:I

  if-lt v0, v1, :cond_1  #比较字符串长度

:try_start_0
iget-object v0, p0, Lcom/alipay/mobile/security/gesture/component/e;->a:Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo; #获取UserInfo对象

invoke-virtual {v0}, Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;->getGesturePwd()Ljava/lang/String; #调用UserInfo的getGesturePwd函数获得加密过的正确的手势密码

move-result-object v0

invoke-virtual {v0}, Ljava/lang/String;->length()I #取加密过的正确密码的长度

move-result v0

const/16 v1, 0x20

if-le v0, v1, :cond_0 #长度是否小于32

new-instance v0, Ljava/lang/StringBuilder;

invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V #初始化StringBuilder对象

invoke-virtual {v0, p1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
#将输入的明文手势密码赋值给StringBuilder对象
  
move-result-object v0  

iget-object v1, p0, Lcom/alipay/mobile/security/gesture/component/e;->a:Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;

invoke-virtual {v1}, Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;->getUserId()Ljava/lang/String; #调用UserInfo的getUserId函数获取user id
  
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
#将加密好的user id字符串附加到StringBuilder对象上

move-result-object v0

invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

:goto_0
iget-object v1, p0, Lcom/alipay/mobile/security/gesture/component/e;->a:Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;

invoke-virtual {v1}, Lcom/alipay/mobile/framework/service/ext/security/bean/UserInfo;->getGesturePwd()Ljava/lang/String; #调用UserInfo的getGesturePwd函数获得加密过的正确的手势密码
  
move-result-object v1

invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
#比较输入的密码和正确的密码
  
move-result v0

if-eqz v0, :cond_1[/code]很显然,上面这个if-eqz是关键,如果比较函数equals返回false,那么跳转到cond_1标签处。cond_1标签处的主要任务就是取当前输入错误的次数,在这个基础上加上1,然后调用settingGestureError函数重新设置错误次数。如果两个字符串相等,那么调用settingGestureError函数把错误次数重新置为0。
下面为了验证我们的猜测,进行如下两步操作:
1、在a函数中加入类似如图12的打印日志代码,这里未全部截图下来,其他地方留给大家自行添加。

2、在if-eqz v0前patch v0,代码如图13所示。

完成上述两步操作之后,保存修改过的smali文件,编译打包,重新安装支付宝钱包客户端,随意输入手势密码。这里引用大魔术师刘谦的一句话,“接下来就是见证奇迹的时刻”。在我们随意输入密码之后,熟悉的支付宝主界面出现在我们眼前,同时LogCat输出日志如图14所示。

日志的组成大致如下:
第一行:用户输入的,还未加密的手势代码;
第二行:保存在数据库中正确的加密后的手势密码;
第三行:未加密的user id;
第四行:采用des加密后的user id;
第五行:拼接用户输入和加密后的user id;
第六行:采用sha1算法计算出来的加密之后的用户输入的手势密码。
     
通过仔细的分析日志,我们从中可以得出两个结论:
1、真实的手势密码和我们输入的密码是不一样的,但是我们还是进入了支付宝的主界面,证明我们上面第2步中修改的地方非常关键,从而也印证了e.smali文件的a函数确实是比较用户输入和真实密码的关键函数。
2、支付宝是将用户的手势操作转化成对应的数字,然后再做一定的加密处理之后保存到数据库中。比较用户输入的时候,是用相同的加密步骤对用户输入进行加密,再与数据库中保存的密码做比较。数字代码对应如图15所示。

程序分析到这里,我们已经清楚的明白了支付宝手势密码的加密过程和算法,并且通过修改关键跳转的方法,使得我们随意输入手势密码都可以进入支付宝主界面。

        如上所述,通过修改支付宝钱包数据库来达到破解目的的方法是需要在已经root过的手机上才能使用的设想一下这种情况,我的手机已经root,并且手机被盗。那么,除了手机上的艳照有可能泄露之外,小偷还可以通过修改支付宝的手势密码来登录我的支付宝,因此,造成直接的金钱损失也不是没有可能。

所以一般来说,请52的朋友日常使用的手机尽量不要去root,也不要随便去下载来历不明的软件和外挂。有人问到,这只是登陆的密码,那么我还有支付密码呢?答案是这样的:在一般情况下200一下的转款是不会用短信通知,同时也不需要去输入支付密码,所以可以直接分N次转走你支付宝里面的所有钱,这是有案例在先的。

点评

我转五块钱都要支付密码的  发表于 2014-10-22 22:58
转载的请写明出处  发表于 2014-10-22 22:35

免费评分

参与人数 2热心值 +2 收起 理由
xieyuchao + 1 看了之后已经麻利的关闭小额免密码支付
wmc + 1 楼主 好!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
小泡泡_ 发表于 2014-10-22 22:32
好强大,膜拜
推荐
1339008553 发表于 2014-10-23 01:27 来自手机
还有更邪恶的,利用   写个马  上传支付宝的备份,再还原  再破解密码,再呵呵
3#
aitest 发表于 2014-10-22 22:35
前排支持楼主,幸好我不用手势密码的{:1_902:}
4#
羅少 发表于 2014-10-22 22:42
前排占位   广告招租请联系我    顺便卖瓜子~~
5#
w448723928 发表于 2014-10-22 22:48
虽然破解过程看不懂,但让我知道有 这么一回事 存在。
6#
书写寂伤 发表于 2014-10-22 22:53
破个支付密码,然后就可以找小偷专门偷那些奸商,贪官的手机了。。。。哈哈我真是太有才了
7#
似水丶流年 发表于 2014-10-22 23:10
我们不root  捡到的人不可以自己root???  
8#
狼魂 发表于 2014-10-22 23:10
这个世界越来越不安全了
9#
q619619 发表于 2014-10-22 23:14
值得学习·················
10#
[VIP]MG 发表于 2014-10-22 23:24
如果是手机丢了。。root不root都无所谓了。。。人家都懂破解这货 。。root更不是什么难事了哈哈
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-4 02:43

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表