吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 11510|回复: 28
收起左侧

[Android 原创] app隐藏大师绕过密码与多开分析

[复制链接]
L剑仙 发表于 2020-2-21 19:14
本帖最后由 L剑仙 于 2020-2-22 08:46 编辑

准备工作:jadx反编译另存为gradle导入as,打开monitor方便方法回溯,启动frIDA-server以便hook。

菜鸟最近看到一个应用隐藏大师,可以隐藏app和相册图片等,隐身模式是一个绿色的计算器,输入正确的密码后会跳转到隐藏app的页面,感觉很神奇,想分析一下密码认证功能实现的函数和app的创建实现。首先分析跳转界面,输入正确6位密码后可以直接跳转,否则调用计算功能进行计算,看起来就像个真实的计算器,哈哈,猜测有一个跳转函数,当输入数字为6位时,调用认证函数进行认证,然后通过新建activity跳转到主界面。
然后,我tm就走到了岔路,我不断的搜索intent相关,想找到切换activity的地方,找了好几个地方都不对,最终我只能进行方法回溯,寻找关键函数,一步一步追溯源头。
1.追溯密码认证函数
很明显,当text改变时就会进行判断,所以必定有一个对于text监听的afterTextChanged的调用,monitor方法回溯后直接搜索,定位到    com.prism.hider.vault.calculator.Calculator$1.afterTextChanged,查找到源码如下:
[Asm] 纯文本查看 复制代码
public void afterTextChanged(Editable editable) {
    if (Calculator.this.f6590w && editable != null && C3154h.m10228a(editable.length()) && PinCodeCertifier.m10216a((Context) Calculator.this).mo23413a(editable.toString())) {//这一句判断密码是否正确
        Calculator.this.m10160b();//这一句必定实现了跳转界面
    }
    Calculator.this.m10155a(CalculatorState.INPUT);
    Calculator.this.f6588u.mo23401a((CharSequence) editable, (C3137a) Calculator.this);//如果密码错误,实现后面这2句话的计算功能
}
 
 
    public boolean mo23413a(String str) {//这个判断密码,f6652c就是我们设的密码
        return this.f6652c != null && this.f6652c.equals(EncodeUtils.m4661a(str));
    }

这句话就是判断密码调用的地方,如果忘记密码,直接hook这个函数,修改返回值,就可以绕过密码验证了。当然如果有人安装这个app也可以通过hook做坏事,嘿嘿
Calculator.this.f6590w && editable != null// 判断有没有输入
&& C3154h.m10228a(editable.length())//判断输入数字长度
&& PinCodeCertifier.m10216a((Context) Calculator.this).mo23413a(editable.toString())//mo23413a 函数判断密码是否正确
2.追溯界面切换原理

下面定位 m10160b和它的下层函数m10167e ,分析它是如何通过密码实现界面切换的。
[Asm] 纯文本查看 复制代码
com.prism.hider.vault.calculator.Calculator.b()V = m10160b
 
public void m10160b() {
    if (getIntent() == null || getIntent().getExtras() == null || !getIntent().getExtras().getBoolean(f6568a)) {
        m10167e();//跟进去这个函数
        return;
    }
    Log.d(f6570j, getIntent().toString());
    finish();
}
 
private void m10167e() {
    String str = f6570j;
    StringBuilder sb = new StringBuilder();
    sb.append("GlobalVaultListener  :");
    sb.append(GlobalVaultListener.f6648a);
    Log.d(str, sb.toString());
    if (GlobalVaultListener.f6648a != null) {
        GlobalVaultListener.f6648a.mo23188c(this);//mo23188c是一个接口实现,好像跟intent无关
    } else {
        Log.d(f6570j, "GlobalVaultListener Not Found");
    }
    this.f6592y = false;
    finish();//???居然是直接退出当前界面
}

看了这2个函数,我有点慌,怎么会没有intent切换activity呢,那他是怎么实现界面切换的呢,我当时在这卡了半天,没有找到通过intent启动SplashActivity的地方,又去查了activity堆栈,还是没搞明白,难道这个SplashActivity主界面在计算器之前已经启动了,如果判断密码正确,通过finish()退出计算器来到SplashActivity吗,那样的话,hook调mo23413a函数直接返回true是通过finish退出计算器进入SplashActivity了,
带着疑问,我再次方法回溯,果然,在系统函数performCreate里,同时调用了Calculator和SplashActivity的oncreate方法,也就是说,没有输入密码的时候SplashActivity已经启动了,里面的app其实根本就没有加密,密码只是让你绕过了计算器而已。 图片.png
3.追溯app多开原理

后面我又简单跟了一下,它安装app的方法跟一般的双开应用一样,修改了包名,安装的第一个app的界面是Com.prism.gaia.client.stub.GuestActivityStub$Guest0,后面分别是1234等等。创建多开应用,并且用方法回溯追踪,从onclick追溯到com.prism.hider.b.l.a(Landroid/view/View;Lcom/android/launcher3/AppInfo;Lcom/android/launcher3/Launcher;Landroid/content/DialogInterface;)V = m9886a这个关键函数
[Asm] 纯文本查看 复制代码
private void m9886a(View view, AppInfo appInfo, Launcher launcher, DialogInterface dialogInterface) {
    AppInfo appInfo2 = appInfo;
    Launcher launcher2 = launcher;
    Workspace workspace = launcher.getWorkspace();
    int[] iArr = new int[2];
    long[] jArr = {-1};
    Iterator it = workspace.getScreenOrder().iterator();
    while (true) {
        if (!it.hasNext()) {
            break;
        }
        long longValue = ((Long) it.next()).longValue();
        String str = f6338a;
        StringBuilder sb = new StringBuilder();
        sb.append("screenid:");
        sb.append(longValue);
        Log.d(str, sb.toString());
        if (launcher2.getCellLayout((long) -100, longValue).findCellForSpan(iArr, 1, 1)) {
            jArr[0] = longValue;
            break;
        }
    }
    if (jArr[0] < 0) {
        workspace.addExtraEmptyScreen();
        jArr[0] = workspace.commitExtraEmptyScreen();
    }
    long j = (long) -100;
    CellLayout cellLayout = launcher2.getCellLayout(j, jArr[0]);
    String str2 = f6338a;
    StringBuilder sb2 = new StringBuilder();
    sb2.append("targetScreen:");
    sb2.append(jArr[0]);
    sb2.append(" targetx:");
    sb2.append(iArr[0]);
    sb2.append(" targety:");
    sb2.append(iArr[1]);
    Log.d(str2, sb2.toString());
    ShortcutInfo makeShortcut = new PromisedGuestAppInfo(appInfo2).makeShortcut();//这里应该就是通过appInfo2创建新的app与shortcut图标
    View createShortcut = launcher2.createShortcut(cellLayout, makeShortcut);//把创建的shortcut图标放到launcher2,也就是自己的launch里
    launcher.getModelWriter().addOrMoveItemInDatabase(makeShortcut, j, jArr[0], iArr[0], iArr[1]);
    makeShortcut.container = j;
    makeShortcut.cellX = iArr[0];
    makeShortcut.cellY = iArr[1];
    workspace.addInScreen(createShortcut, makeShortcut);
    GuestAppStateExtension.m9874a().mo23238b().mo23268a(appInfo2);
    dialogInterface.dismiss();
    workspace.post(new Runnable(jArr) {
        private final /* synthetic */ long[] f$1;
 
        {
            this.f$1 = r2;
        }
 
        public final void run() {
            Workspace.this.moveToScreen(this.f$1[0]);
        }
    });
}

容易看出new PromisedGuestAppInfo(appInfo2).makeShortcut()这句应用双开前的appinfo创建新的PromisedGuestAppInfo 并创建Shortcut图标,launcher2.createShortcut(cellLayout, makeShortcut)这句把创建的shortcut图标放到launcher2,也就是自己的launch里
这里由于点击了好几个按钮,lamda函数套了几层,贴一下堆栈,以免搞乱了
[Asm] 纯文本查看 复制代码
var sa = Java.use('com.prism.hider.b.l');
// int updateWithOnConflict(String str, ContentValues contentValues, String str2, String[] strArr, int i)
sa.a.overload('android.view.View', 'com.android.launcher3.AppInfo', 'com.android.launcher3.Launcher', 'android.content.DialogInterface').implementation=function(a1,a2,a3,a4)
{   
  console.log("hook e start");

   var threadef = Java.use('java.lang.Thread');
   var threadinstance = threadef.$new();
   var stack = threadinstance.currentThread().getStackTrace();
   function Where(stack){
    for(var i = 0; i < stack.length; ++i){
      console.log(stack[i].toString());
    }
  }
   console.log("Full call stack:" + Where(stack));

  this.a(a1,a2,a3,a4);
}

堆栈调用
[Asm] 纯文本查看 复制代码
com.prism.hider.b.l.a(Native Method)
com.prism.hider.b.l.a(ItemClickHandlerExtensionImpl.java:205)
com.prism.hider.b.l.lambda$1v3PIwaoDBWd6OM-CRLs-RNzmUQ(Unknown Source:0)
com.prism.hider.b.-$$Lambda$l$1v3PIwaoDBWd6OM-CRLs-RNzmUQ.onClick(Unknown Source:10)
com.prism.hider.ui.a.a(AppOperateDialog.java:93)
com.prism.hider.ui.a.lambda$OTuIeTAl3vf4RmjQk_3g0AXegkk(Unknown Source:0)
com.prism.hider.ui.-$$Lambda$a$OTuIeTAl3vf4RmjQk_3g0AXegkk.onClick(Unknown Source:2)
android.view.View.performClick(View.java:6294)
android.view.View$PerformClick.run(View.java:24770)
android.os.Handler.handleCallback(Handler.java:790)
android.os.Handler.dispatchMessage(Handler.java:99)
android.os.Looper.loop(Looper.java:164)
android.app.ActivityThread.main(ActivityThread.java:6494)
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:440)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

我们再看一下PromisedGuestAppInfo的构造函数,很明显就是改了包名和组件名实现多开,就是在之前附加一个gaia_guest_字符串,然后把组件添加进去,结束。
[Asm] 纯文本查看 复制代码
public PromisedGuestAppInfo(AppInfo appInfo) {
    super(appInfo);
    this.packageName = ExtensionPkgUtils.m9976a(appInfo.packageName);// m9976a修改包名和组件名
    this.componentName = new ComponentName(ExtensionPkgUtils.m9976a(this.componentName.getPackageName()), this.componentName.getClassName());
    this.intent = new Intent("android.intent.action.MAIN").addCategory("android.intent.category.LAUNCHER").setComponent(this.componentName).setFlags(270532608);
}
 
private static final String f6410b = "gaia_guest_.";
 
public static String m9976a(String str) {
    StringBuilder sb = new StringBuilder();
    sb.append(f6410b);// f6410b = "gaia_guest_.";
    sb.append(str);
    return sb.toString();
}


总结一下,经过这次逆向,学习了这个软件的思路:
1.app入口同时oncreate 2个activity,计算器或者其他干扰界面放在真正的界面前面,输入密码错误就执行干扰界面app功能,输入密码正确就finish干扰界面,这样真正的界面就显示出来。比如说,这里用计算器做干扰界面,你可以用bmi计算器或者单位换算器做干扰界面,这样认识这个软件的人也判断不出来了哈哈
2.多开软件原理,复制安装原app,然后把包名和组件名都改了,系统就会认为这是2个软件了,然后把图标放到真正界面的launcher,实现隐藏

免费评分

参与人数 3威望 +1 吾爱币 +11 热心值 +3 收起 理由
qtfreet00 + 1 + 9 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
笙若 + 1 + 1 谢谢@Thanks!
28128 + 1 + 1 谢谢@Thanks!

查看全部评分

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

elysiumt 发表于 2020-5-12 10:57
我有个问题,这个隐藏设计的不错,但是在系统的应用列表会体现这个隐藏大师的应用的图标跟名称,在老婆检查手机的时候还是完蛋,问下怎么能给它的安装名称跟那个图标改了,那就完美了
jianqing11 发表于 2020-3-11 02:25

链接: https://pan.baidu.com/s/1kjeJ0Z42tJnRP0QfAJDjeg 提取码: 6dyb
s985967 发表于 2020-2-21 19:20
lijinhu000 发表于 2020-2-21 19:26
求软件名字。
 楼主| L剑仙 发表于 2020-2-21 19:37
叫应用隐藏大师
We. 发表于 2020-2-21 19:41
感谢分享
封神之剑 发表于 2020-2-21 19:42
现在手机都自带隐藏功能
SCKII 发表于 2020-2-21 19:46
这一组组的码和思路确实值得学习
zxpkpk 发表于 2020-2-21 20:06
这和思学习一组组的码路确实值得
故人曲散离别伤 发表于 2020-2-21 20:14
感谢分享
單炅 发表于 2020-2-21 20:15
感谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-24 21:28

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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