自己动手Bypass Android Exchange

一直以来巨硬提供的Exchange电子邮件系统都是企业级邮件解决方案的首选,它具有NB的安全性,同时也具备很多优秀的功能。

用户在使用Exchange服务时,电子邮件客户端会根据服务器要求的安全等级进行验证客户端系统的安全性设置是否满足服务器的要求,如果满足服务器要求的安全等级则允许进行收发邮件,否则将无法继续与服务器进行通信。

以我所在使用的邮箱为例,在安卓客户端中登录邮箱时,会提示”***.com”服务器要求您允许其远程控制您Android设备的某些安全功能。

在提示信息内我们可以看到服务器具体要求了清除所有数据、设置密码规则、监视屏幕解锁尝试次数、锁定屏幕、设置锁屏密码的有效期、设置存储设备加密、停用相机等要求。

这里面最影响用户使用的是“设置密码规则”这一项,它意味着在使用时必须将设备的锁屏密码设置为4位以上的PIN码或者6位以上的密码。

对于不愿意每次解锁都输密码还没指纹解锁且懒癌晚期的我来说,这是很痛苦的事情。所以,为了解放我的手指,我决定想办法解决掉它。

在了解了这种安全验证的原理之后,我们可以发现:客户端的安全验证完全由客户端软件按照Exchange标准自行验证,而服务器并未验证客户端是否真正满足安全需求。

所以,如果我们想办法让客户端的验证功能废除掉,即可达到绕过的目的。

方法1:通过通用Hook框架Xposed

在许久以前,曾经对小伙伴抱怨过这个坑爹设定,然后他给我指了条明路:使用Xposed插件“ExchangeSecurityBypass”(http://repo.xposed.info/module/org.flacid.exchangebypass)。

Xposed无需过多解释,通过Hook Java API的方法来修改很多东西。然而由于我的手机并没有root,所以就无法使用此种方法了。

方法2:使用沙箱运行时Hook

通过应用沙箱的方法运行邮箱应用,具体可参照平行空间、分身大师、DroidPlugin等的原理。

优点有很多,比如不需要Root权限,如果熟悉了这套Hook方法,那么以后很多应用都可以通过这种方法去动态Hook应用,甚至可以用此方法运用在动态调试上。但同时也有弊端,会增加手机的耗电量。

在以后对这方面接触更多一些以后,我会考虑重新写一篇文章来使用此方法。

方法3:静态修改APK文件

前两种方法都是动态去修改,然而受限于我的环境和能力,并未选择这两种方法,因此,为了实现目标,选择使用静态修改apk文件的方法,去修改smali代码来完成。

那么我们该怎么去修改?

当然我们可以根据标准Exchange协议和设计要求去自己分析调用流程和方法,但是这时候想到前面提及的ExchangeSecurityBypass,他们都已经实现了动态Hook,我们为何不直接学习他的总结成果,将动态的Hook转为静态编码呢?

当然小伙伴想手动分析也可以,这里提醒一句,安卓上大部分电子邮件应用的代码都或多或少“参考”了AOSP中Email应用的代码,所以小伙伴可以直接参照AOSP源码进行学习。

首先我们来看一下ExchangeSecurityBypass都做了什么功能(https://github.com/jcarr/exchangebypass/)。

找到源码,我们定位至关键部分:

Hook了如下:

com.android.email.SecurityPolicy类的isActiveAdmin方法,使其返回值为true;isActive方法,使其返回值为true;getInactiveReasons方法,使其返回值为0。

remoteWipe方法,使其不做任何操作;com.android.emailcommon.provider.Policy类的normalize方法,使其初始调用为updatePolicy方法;

其他修改返回值的方法我们已经比较明白,我们继续跟进初始调用为updatePolicy的方法,看其究竟做了些什么操作。

我们可以看到他对一些成员变量进行了赋值。我们在对应到apk中对应被hook的方法看其逻辑。

了解了该模块所做的工作之后,我们只需将对应的hook方法应用到静态smali代码之中。

首先使用AndroidKiller打开要修改的apk文件。

挨个定位至对应的方法。首先看isActiveAdmin方法。

我们可以看到isActiveAdmin中使用许多方法判断了当前是否为激活的系统管理员,如果当前是已经激活的管理员的话,则返回true,否则返回false,所以我们修改对应v1 = false改为v1 = true即可。

再来看isActive方法

同样,返回值为v2,需要将其改为true,由于v2初始化为false且后续仅有一次赋值为true,因此我们直接将其默认值改为true即可。

同理,我们以此修改getInactiveReasons。

由于这里v7为返回值且当policy != Policy.NO_POLICY时流程较为复杂,我们可以将判断语句直接改为判断policy==policy,这样就可以将返回值直接改为0,代码如下。

同理修改remoteWipe方法,直接return掉即可。

最后,我们来修改com.android.emailcommon.provider.Policy类的normalize方法,使其在执行有效代码前被赋予值。

这里注意区分不同属性的类型,比如mPasswordMode为int类型,而mRequireEncryption的类型为boolean类型,那么对于int类型我们使用iput即可,而boolean我们则应使用iput-boolean。

按照对应的语法和变量名,我们在方法有效代码前添加上对应的赋值语句。这样我们即可成功控制程序代码流。

修改完成后我们来编译试一下。

经过编译、打包、签名之后,adb install安装到手机上。我们可以发现已经成功绕过了他对于Exchange的安全要求。输入账户密码之后,我们就可以正常使用锁屏而无需设置锁屏密码了。

有兴趣的可以实战下,文中的apk文件,链接: http://pan.baidu.com/s/1qXZaZdM 密码: 6udb

本文分享自微信公众号 - FreeBuf(freebuf)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-03-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏编程坑太多

跟我学习springmvc+dubbo-简介(一)

12140
来自专栏java思维导图

mybatis-plus思维导图,让mybatis-plus不再难懂

1 mybatis-plus与mybatis mybatis Mybatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis...

39480
来自专栏Java架构师学习

深度剖析Swagger原理swagger简介

swagger确实是个好东西,可以跟据业务代码自动生成相关的api接口文档,尤其用于restful风格中的项目,开发人员几乎可以不用专门去维护rest api,...

63420
来自专栏JAVA高级架构

Java技术大纲

51630
来自专栏技术博文

Memcached 及 Redis 架构分析和比较

Memcached和Redis作为两种Inmemory的key-value数据库,在设计和思想方面有着很多共通的地方,功能和应用方面在很多场合下(作为分布式缓存...

38030
来自专栏PHP在线

CI一些优秀实践

最近准备接手改进一个别人用Codeigniter写的项目,虽然之前也有用过CI,但是是完全按着自己的意思写的,没按CI的一些套路。用在公众的项目,最好还是按框架...

36950
来自专栏实战docker

Docker下的Kafka学习之三:集群环境下的java开发

在上一章《Docker下的Kafka学习之二:搭建集群环境》中我们学会了搭建kafka集群环境,今天我们来实战集群环境下的用java发送和消费kafka的消息;...

29850
来自专栏walterlv - 吕毅的博客

如何在 MSBuild Target(Exec)中报告编译错误和编译警告

发布于 2018-06-20 05:17 更新于 2018-07...

7320
来自专栏大内老A

《Enterprise Library深入解析与灵活应用》博文系列汇总

Enterprise Library是微软P&P部门开发的众多Open source框架中的一个,最新的版本已经出到了4.1。由于接触Enterprise Li...

19670
来自专栏JAVA烂猪皮

基于ZooKeeper,Spring设计实现的参数系统

基于ZooKeeper服务端、ZooKeeper Java客户端以及Spring框架设计的用于系统内部进行参数维护的系统。

13020

扫码关注云+社区

领取腾讯云代金券