应广大网友的要求,笔者近期对乐安全的软件锁进行了分析,下面简单就一篇博文向大家介绍一下乐安全软件锁的实现原理。测试的乐安全版本为V4.2.4。
先说下结论,如果有兴趣的同学可以继续往下看分析。乐安全在本地进程得到了AMS的Bp,直接调用其getTasks方法,每隔一秒检测一下当前topActivity是否是需要被锁定的,如果是的话,就弹出一个解锁界面盖住本该启动的APP。
下面进行分析
首先要爆料的是,乐安全做的实在是有点不小心,打了些对于破解有用的log出来,降低了破解的难度。比如下面的:
这是在触发软件锁的时候打出的log,给了我们启发,通过反编译APK文件后,我们很快定位到了相关的代码。
while (AppCheck.isRun)
try
{
Thread.sleep(1000L);
List localList1 = AppCheck.a(AppCheck.this).getTasks(1, 0, null);
if (localList1.size() > 0)
{
AppCheck.a(AppCheck.this, ((ActivityManager.RunningTaskInfo)localList1.get(0)).topActivity.getPackageName());
if (!AppCheck.c(AppCheck.this).equals(AppCheck.b(AppCheck.this)))
{
Log.i("AppCheck", "old" + AppCheck.c(AppCheck.this) + "------------new:" + AppCheck.b(AppCheck.this));
String[] arrayOfString3 = new String[3];
arrayOfString3[0] = "runningTask";
arrayOfString3[1] = AppCheck.b(AppCheck.this);
arrayOfString3[2] = AppCheck.c(AppCheck.this);
a(arrayOfString3);
AppCheck.b(AppCheck.this, AppCheck.b(AppCheck.this));
}
}
可以看到,乐安全在这里做了一个循环操作,首先sleep一秒,然后直接调用getTasks()方法得到一个List。我们先看下AppCheck.a(AppCheck.this)返回的是什么。由于jd反编译的不全面,下面要po上一个smali的代码片段。
.method static synthetic a(Lcom/lenovo/safecenter/utils/AppCheck;)Landroid/app/IActivityManager;
.locals 1
.parameter "x0"
.prologue
.line 21
iget-object v0, p0, Lcom/lenovo/safecenter/utils/AppCheck;->a:Landroid/app/IActivityManager;
return-object v0
.end method
这里可以看到a(AppCheck.this)返回的是一个IActivityManager的对象。这里可能大家会有一个疑问,IActivityManager是hide的,为什么可以在这里被调用。@安卓安全小分队的大牛讲师认为乐安全很有可能自己编译了一套framework.jar使得乐安全在编译阶段顺利通过,并且在手机上也能正常运行,关于这一部分的机理,如果大家觉得有必要,我们可以在以后的时间作为一个专题来讲解。
在这里笔者对之前的猜测做下更正,乐安全并不是通过注入方式来调用AMS的一个方法,而是简单的在本地得到了AMS的Bp,也就是这个IActivityManager的对象。下面再po一个smali的代码段来说明这个IActivityManager是如何得到的。
.line 38
invoke-static {}, Landroid/app/ActivityManagerNative;->getDefault()Landroid/app/IActivityManager;
move-result-object v0
iput-object v0, p0, Lcom/lenovo/safecenter/utils/AppCheck;->a:Landroid/app/IActivityManager;
通过直接调用ActivityManagerNative的getDefault静态方法就获得了这个IActivityManager对象,很简单。
好,回到前面的分析阶段。我们已经知道了,乐安全通过调用AMS的getTasks方法得到了tasks的list,到了第一if分支(参考前面贴出的代码)。
首先检查的是新启动的activity是否与前一个activity属于同一包。说白了就是如果用户已经在使用敏感APP了,乐安全就不要再去搞软件锁了,不然用户启动一个activity就有一锁出来不的把人烦死。
但是如果不属于同一个包,就进入了这个分支,先打了个被我们抓住尾巴的log,然后把old的包名和new的报名放进数组交给了a()方法。我们看看a()里都做了什么
private void a(Object[] paramArrayOfObject)
{
if (paramArrayOfObject[0].equals("runningTask"));
for (String str = "com.lenovo.safecenter.activityswitch"; ; str = "com.lenovo.safecenter.activityswitch2")
{
Log.i("AppCheck", paramArrayOfObject[0] + "------------action:" + str + " " + paramArrayOfObject[1] + " " + paramArrayOfObject[2]);
Intent localIntent = new Intent(str);
localIntent.putExtra("newPkg", (String)paramArrayOfObject[1]);
localIntent.putExtra("oldPkg", (String)paramArrayOfObject[2]);
AppCheck.g(AppCheck.this).sendBroadcast(localIntent);
Settings.System.putString(AppCheck.g(AppCheck.this).getContentResolver(), "safe_input_method", "com.android.inputmethod.latin/.LatinIME");
Log.i("AppCheck", paramArrayOfObject[0] + "------------end");
return;
}
}
很简单,把old package和new package用广播给发出去了。我们到接收端看一下如何处理。
乐安全的assets包里有一个LenovoSafeBox429.apk,打开后在里面发现一个MonitorAppService的类,他在onCreate的时候注册了一个BroadcastReceiver,接收名为com.lenovo.safecenter.activityswitch的action如下。
public void onCreate()
{
this.getBroadcast = false;
this.mContext = this;
this.pattern = Pattern.compile("(.*)(\\={1})(.*)(//*)");
this.runtime = Runtime.getRuntime();
this.filter = new IntentFilter();
this.filter.addAction("android.intent.action.SCREEN_OFF");
this.filter.addAction("android.intent.action.SCREEN_ON");
this.filter.addAction("com.lenovo.safecenter.activityswitch");
this.filter.addAction("com.lenovo.safebox.lockscreen");
this.lastPkg = "";
registerReceiver(this.receiver, this.filter);
if (canGetPassword())
{
if (!this.watchAppOpen)
watchAppStart();
if (!this.getBroadcast)
{
this.mTimer = new Timer(true);
restartTimer();
}
}
在receiver的onReceive函数里,这个receiver做了下面的事情。我们捡主要的说
label498: if ((MonitorAppService.this.lastPkg == null) || (MonitorAppService.this.lastPkg.equals("com.lenovo.safebox")) || (MonitorAppService.this.lastPkg.equals(str)) || (!MonitorAppService.this.checkList.contains(str)) || (MonitorAppService.isLocked))
continue;
Intent localIntent = new Intent(MonitorAppService.this.mContext, LockScreenActivity.class);
localIntent.putExtra("pkg", str);
localIntent.addFlags(268435456);
if (MonitorAppService.DEBUG)
Log.i("MonitorAppService", "Lock in Broadcast TopTask :" + str);
MonitorAppService.this.mContext.startActivity(localIntent);
关键的位置就是到一个list里查看当前启动的package是不是我要锁住的,如果是锁住的,那就直接启动一个activity盖在上面,就是我们看到的效果了。
PS:有的网友提到乐安全阻止了程序的正常启动,相关进程不会被启动。但是通过我们的观察,进程是已经被启动了的,如下图。
需要关注的是,AMS首先启动了被锁软件。Start了它的activity以及process(最开始的两条log),然后才会执行我们之前分析的部分,然后LockScreenActivity才被启动。这个时候可以通过ps命令查看当前进程。我们发现了被锁软件:
相关推荐
乐安全3.0专用升级包
乐安全是一款完全免费的手机安全软件,适用于所有安卓手机。 提供集病毒查杀、隐私保护、吸费克星、骚扰拦截等安卓手机必备的安全防护; 更有广告拦截、手机加速、流量监控、私密空间、安全备份、省电优化、手机防盗...
乐安全是一款完全免费的手机安全软件,适用于所有安卓手机。 提供集病毒查杀、隐私保护、吸费克星、骚扰拦截等安卓手机必备的安全防护; 更有广告拦截、手机加速、流量监控、私密空间、安全备份、省电优化、手机防盗...
这份乐安中学初二上期中数学试卷主要涵盖了初中数学的基础知识点,包括了算术平方根、平方根、立方根、实数的比较、代数表达式的运算、因式分解、直角三角形的性质、科学记数法以及解方程等。 1. 算术平方根:题目...
这篇文档是江西省乐安县第一中学2020学年七年级英语上学期第三次月考试题,主要涵盖了听力测试和单项选择两大板块,旨在检测学生对英语基础知识和听力理解能力的掌握程度。 听力测试部分分为三个小节:A) 五个问题...
综合题部分主要考察了地形识别、纬线名称、温度带划分、气候特征分析和降水季节性变化等相关地理知识。 这些题目旨在帮助学生巩固和应用他们所学习的地理知识,提高他们的空间思维能力和环境理解能力。通过解答这些...
【审题训练与分析】 审题是写作的关键步骤,它要求我们深入理解题目或材料的含义,从而确定文章的主题和立意。对于高二学生来说,掌握审题技巧至关重要,因为这直接影响到作文的质量和得分。 练习一的材料中,引用...
为研究其污染现状,于2003-2004年度对乐安河水体、底泥及水生生物的重金属污染进行了调查与分析.结果表明,乐安河水体中的重金属除cu的含量超出地表水环境质量标准Ⅲ类标准外,其它各项监测指标均能达到地表水环境...
江西省乐安一中高二语文 期中考试试卷
2005年10月 ,采集了乐安江及其支流漫滩区表层土中的优势植物——稗草 ,并测定了其中 6种重金属(Cd、Cr、Ni、Cu、Pb、Zn)的含量。流经亚洲最大露天铜矿(德兴铜矿)的乐安江 ,其三条支流由于被德兴铜矿的酸性矿山废水...
乐安实验幼儿园家长委员会工作计划.doc
江西省乐安一中高二语文 期末质量检测试题
【乐安2017年事业编招聘考试真题及答案解析】 这是一份关于乐安2017年事业单位招聘考试的完整真题及答案解析文档。事业单位招聘考试通常涉及多个领域的知识,包括但不限于行政能力测试、专业知识、公共基础知识等。...
江西省乐安一中高二语文 现代文阅读练习试题
江西省乐安一中高二语文 现代诗三首试题
这表明了施工方案的制定是经过全面考虑和专业分析的。 2. **工程概况**:项目包括北区两栋物业用房和南区商业房、大门与超市,总建筑面积约172864m2和2542.29m2,均为二层建筑,结构分别为框架和砖混。施工现场已...
江西省乐安一中高二语文 装在套子里的人试题
乐安2017年事业编招聘考试真题及答案解析版.docx