查看原文
其他

【Android改机系列】全息备份原理剖析

seandong 看雪学院 2019-09-17

上一篇帖子:【Android改机系列】一键新机原理剖析 主要分析的是一键新机功能,一键新机主要用于批量(恶意)注册、拉新之用。今天来介绍全息备份原理及应用。


原版下载地址:https://www.lanzous.com/i5489ri

密码:Dalvik


原版是跑不起来的!跑不起来的!跑不起来的!只供技术分析之用。



全息备份简介


什么是全息备份


一款App运行之后会在应用沙盒目录data/data/xxx或者/sdcard或者/Android/甚至Settings.Global/Secure/System(理论上是没有权限)中生成该App在运行时候产生的文件,例如登录状态,App的设置,聊天文件,游戏存档等等。


全息备份就是备份该App在运行时候已经产生的所有文件,然后在一款新机器中再还原这些文件。


这个时候在新机器中运行该App,你在之前手机中的所有登录状态,App的设置,聊天文件,游戏存档都会出现在这台手机中,所以就不用担心你在该App中的聊天记录或者设置信息丢失。


全息备份能做什么


普通应用场景


举个最简单的例子:你用一台用了五年的Android手机,手机上安装了高德地图、微信、抖音、旅行青蛙等App,现在你手机机已经卡的不行了打算换一台手机,但是又不想之前高德地图的离线地图和微信中的聊天记录和闯关游戏记录丢失。


你想在新手机中也拥有之前的离线地图和微信中的聊天记录和闯关记录,这个时候就需要全息备份,把之前旧手机中所有的数据都搬运到新手机中。


实际上miui和emui等国产第三方定制系统都具有一键换机功能(好像只能在同品牌手机中换)。


改机应用场景


之前我们说过,一键新机可以用来批量注册账号和拉新,但是有时候批量注册的账号权限比较低或者拉新的时候App厂商会看留存率给cp结算,这个时候对应的策略就是养号和做用户留存(次日留存,七日留存,半月留存,月留存)。

例如:一台手机可能一天中批量注册很多微信或陌陌账号,这个时候第二天就需要把之前一天的所注册的账号进行养号(发动态加人之类)操作。

所以需要还原之前注册时候的一键新机的设备信息和注册时候app产生的文件信息,欺骗app服务端该账号一直是在同一台手机中操作,这样就可以慢慢提高账号权限。

再例如:app拉新过程中可能会产生很多新设备,在做留存的时候就需要在之前一键新机的设备环境中和app服务器进行交互(所谓的用户行为)。

所以也需要还原之前拉新时候的一键新机的设备信息和app产生的文件信息,欺骗app服务端该新用户一直是在同一台手机中操作,并且有留存。通过这种操作爆破app厂商的风控。



全息备份的实现


传统实现方案


传统的实现方案是在root的情况下,通过遍历app产生的所有文件并且进行提取,然后在root的手机中进行还原。

这里提到了root,为什么要root呢?因为应用沙盒目录data/data/xxx在非root情况下普通应用是没有读取权限的。

喜欢玩机的朋友应该知道鼎鼎大名的"钛备份",钛备份就是基于root下的全息备份神器。当年Android手机卡成ppt的年代就是靠钛备份活命的。 怀念我的戴妃神机。


免root实现方案


app必须有FLAG_ALLOW_BACKUP属性才能进行全息备份,也就是androidMannifest.xml文件中android:allowBackup属性设置为ture


第一步


直接通过AIDL获取com.android.server.backup.BackupManagerService服务,然后调用BackupManagerServicefullBackup函数进行对某个或某些app进行全息备份。

@param file 备份文件名
@param arrayList 需要备份的包名列表
private static void fullBackup(File file, ArrayList<String> arrayList, boolean z) {
int i = 0;
IBackupManager asInterface = Stub.asInterface(ServiceManager.getService("backup"));
if (asInterface == null) {
Log.e("ContentValues", "Can't obtain Backup Manager binder");
return;
}
ParcelFileDescriptor parcelFileDescriptor = null;
try {
parcelFileDescriptor = openParcelFile(file);
String[] strArr = new String[arrayList.size()];
if (VERSION.SDK_INT <= 19) {
Method[] methods = IBackupManager.class.getMethods();
int length = methods.length;
while (true) {
if (i >= length) {
break;
}
Method method = methods[i];
if ("fullBackup".equals(method.getName())) {
method.setAccessible(true);
method.invoke(asInterface, new Object[]{parcelFileDescriptor, Boolean.valueOf(z), Boolean.valueOf(false), Boolean.valueOf(false), Boolean.valueOf(false), Boolean.valueOf(false), arrayList.toArray(strArr)});
break;
}
i++;
}
} else {
asInterface.fullBackup(parcelFileDescriptor, z, false, false, false, false, false, true, (String[]) arrayList.toArray(strArr));
}
if (parcelFileDescriptor != null) {
try {
parcelFileDescriptor.close();
} catch (IOException e) {
}
}
} catch (Exception e2) {
Log.e("ContentValues", "Unable to invoke backup manager for backup", e2);
if (parcelFileDescriptor != null) {
try {
parcelFileDescriptor.close();
} catch (IOException e3) {
}
}
} finally {
if (parcelFileDescriptor != null) {
try {
parcelFileDescriptor.close();
} catch (IOException e4) {
}
}
}
}

第二步


Hook android.content.pm.PackageParser.parseBaseApplication函数赋予该app FLAG_ALLOW_BACKUP属性。

if ("parseBaseApplication".equals(name) )
{
Package packageR = (Package) methodHookParam.args[0];
ApplicationInfo applicationInfo = packageR.applicationInfo;
String str2 = packageR.applicationInfo.packageName;
applicationInfo.flags |= 32768;
applicationInfo.flags |= 131072;
}

第三步


Hook BackupManagerService.startConfirmationUi(int token, String action) 跳过用户确认弹窗调用,然后再获取BackupManagerService服务,调用acknowledgeFullBackupOrRestore函数完成全息备份。

public void acknowledgeFB(int i) {
try {
Stub.asInterface(ServiceManager.getService("backup")).acknowledgeFullBackupOrRestore(i, true, "", "", new FullObserver());
} catch (RemoteException e) {
e.printStackTrace();
}
}

第四步


还原备份,这个流程和上面三步类似,就不过多赘述了。

结束语


1. 是不是有点懵?去看反编译原版改机对照我的分析和Android源码就明白了。

源码位置:

frameworks/base/services/backup/java/com/android/server/backup/BackupManagerService.java 
frameworks/base/core/java/android/content/pm/PackageParser.java

2. 原版改机的全息备份是有点问题的,不能完整运行。不知道作者故意写错还是不小心写错的,总之我破解修改后的代码是能完美运行的。




- End -




看雪ID:seandong  

https://bbs.pediy.com/user-766159.htm  



本文由看雪论坛 seandong  原创

转载请注明来自看雪社区





往期热门回顾

1、编写Windows Kernel Shellcode

2、【Android改机系列】一键新机原理剖析

3、Windows Kernel Exploit 内核漏洞学习(3)-任意内存覆盖漏洞

4、2019 SDC 圆桌会谈回顾 | 5G时代车联网安全的未来与展望







公众号ID:ikanxue

官方微博:看雪安全

商务合作:wsc@kanxue.com




      ↙点击下方“阅读原文”,查看更多干货

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存