这篇文章上次修改于 933 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
无聊水
前言
在MIUI系统设置中,我们可以对第三方APP进行备份和还原,并且在新一点的系统中,备份的是完整数据,而不仅仅是应用
于是就想,是否有可能向备份压缩包添加文件,并且进行还原,以此实现向APP私有目录下添加文件
更进一步可以修改一些动态库或者配置,以此实现代码植入以及hook
结论在前:完全没有校验,除了apk本体,其他随便改了还原
不对,有一个恢复数据账号验证的设置,开启了会有账号验证,不过还是不影响修改数据
记录
先确定下备份功能在那个APP里面,虽然前面提到备份是在系统设置操作,但是有的时候设置里面也会通过调用其他APP,内嵌界面
所以需要确定具体代码在哪个APP里面,首先查找立即备份四个字

使用MT管理器提取设置,即com.android.settings,使用MT管理器查看提取出的APK,点击resources.arsc并使用Arsc++编辑器打开

搜索字符串立即备份


点击name=后面的部分,点击跳转,选择type-info


复制记录下id=后面的内容,这里是0x7f12040a
然后打开全部dex,去搜索这个id,有的时候使用name=后面的内容查找不一定找得到,可能会被一些优化手段去除
优先建议使用id查找,然后发现名字都是同一个,那么现在查找名字
发现是com.android.settings.MiuiMasterClear,到这里也可以确定了,是在系统设置里面做的
现在把apk拿出来,用JEB分析
这里有一个遍历显示私有目录下文件情况的APP

然后停止APP,备份这个软件

备份文件夹下面有一个descript.xml,内容如下,看得出来没有什么签名信息在里面
{
"jsonMsg":"",
"bakVersion":"2",
"brState":"3",
"autoBackup":"false",
"device":"xaga",
"miuiVersion":"V14.0.3.0.TLOCNXM",
"date":"1682838265747",
"size":"12956734",
"storageLeft":"77613150208",
"supportReconnect":"true",
"autoRetransferCnt":"0",
"transRealCompletedSize":"0",
"packages":{
"package":{
"packageName":"com.test.fgum",
"feature":"102",
"bakFile":"FGum(com.test.fgum).bak",
"bakType":"2",
"pkgSize":"14047744",
"sdSize":"0",
"state":"1",
"completedSize":"12956734",
"error":"0",
"progType":"0",
"bakFileSize":"12956734",
"transingCompletedSize":"0",
"transingTotalSize":"12955648",
"transingSdCompletedSize":"0",
"sectionSize":"0",
"sendingIndex":"0"
}
},
"filesModifyTime":""
}另外就是FGum(com.test.fgum).bak文件,这个文件使用7z可以正常打开,但是我们查看文件头,发现并不是标准的压缩包
有一个_manifest文件,里面有很长一串内容,看起来这个很关键

直接修改了bak文件中的js文件内容,文件大小没有改变,然后替换回去,尝试进行还原

然后测试下,确实改变了,但是没有什么错误提示,也就是可以直接改文件,至于_manifest那个是啥,没有影响

不过还是想看看,结果发现设置里面并没有_manifest这个字符串的踪迹,是的备份实际上是另一个APP,即com.miui.backup
原来是就是tar打包?

很快就能定位到_manifest的代码了,如下,可以看到很长那一串是被备份APP的签名信息
所以完全没有什么校验嘛,只要不改APP其他的都可以动
private void writeAppManifest(PackageInfo pkg, File manifestFile) throws IOException {
StringBuilder builder = new StringBuilder(0x1000);
StringBuilderPrinter printer = new StringBuilderPrinter(builder);
printer.println(Integer.toString(1));
printer.println(pkg.packageName);
printer.println(Integer.toString(pkg.versionCode));
printer.println(Integer.toString(Build.VERSION.SDK_INT));
String s = this.mContext.getPackageManager().getInstallerPackageName(pkg.packageName);
printer.println((s == null ? "" : s));
printer.println("0");
if(pkg.signatures == null) {
printer.println("0");
}
else {
printer.println(Integer.toString(pkg.signatures.length));
Signature[] arr_signature = pkg.signatures;
for(int v = 0; v < arr_signature.length; ++v) {
printer.println(arr_signature[v].toCharsString());
}
}
FileOutputStream outstream = null;
try {
outstream = new FileOutputStream(manifestFile);
outstream.write(builder.toString().getBytes());
}
catch(Throwable throwable0) {
if(outstream != null) {
outstream.close();
}
throw throwable0;
}
outstream.close();
}实际的压缩打包代码,也就是把文件头去掉,后面就是正常的tar文件了:
private void buildFormattedFileSysApp(String pkg, int feature, File baseDir, File dst, File manifest, File store, BackupMeta meta) throws IOException, InterruptedException {
ParcelFileDescriptor[] arr_parcelFileDescriptor1;
DeflaterOutputStream deflaterOutputStream0;
FileOutputStream out = null;
ParcelFileDescriptor[] pipes = null;
AtomicBoolean latch = new AtomicBoolean(false);
try {
out = new FileOutputStream(dst);
out.write(("MIUI BACKUP\n2\n" + (pkg + "\n") + (feature + "\n") + "null\n" + "ANDROID BACKUP\n" + 2 + "\n1\n" + "none\n").getBytes("UTF-8"));
deflaterOutputStream0 = new DeflaterOutputStream(out, new Deflater(9), true);
}
catch(Throwable throwable0) {
goto label_44;
}如果文件头不去掉,将文件名后缀改为.tar,那么使用7z打开会出现错误提示:

还有一个问题是,这些文件夹之间的关系是什么,之间看可以指定a里面是apk本身,r里面是APP私有目录下的文件

备份了下QQ,发现更多,sp基本上是shared_prefs的东西,db则是数据库文件

不过这个也很好定位:
com.miui.backup.restore.FullBackup
部分关系如下:
| TOKEN | 备份命名文件夹 | 原始文件夹 |
|---|---|---|
| CACHE_TREE_TOKEN | c | cache |
| DATABASE_TREE_TOKEN | db | databases |
| DEVICE_CACHE_TREE_TOKEN | d_c | user_de/cache |
| DEVICE_DATABASE_TREE_TOKEN | d_db | user_de/databases |
| DEVICE_FILES_TREE_TOKEN | d_f | user_de/files |
| DEVICE_NO_BACKUP_TREE_TOKEN | d_nb | user_de/no_backup |
| DEVICE_ROOT_TREE_TOKEN | d_r | user_de |
| DEVICE_SHAREDPREFS_TREE_TOKEN | d_sp | user_de/shared_prefs |
| FILES_TREE_TOKEN | f | files |
| NO_BACKUP_TREE_TOKEN | nb | no_backup |
| ROOT_TREE_TOKEN | r | ./ |
| SHAREDPREFS_TREE_TOKEN | sp | shared_prefs |
所以我们通常只管向r这个文件夹修改替换文件就好了
总结
MIUI的备份文件没有做校验,完全可以修改或添加内容后还原
这样可以用来修改一些APP的东西,或者配置,以及修改so/jar等,最终实现hook
只有一条评论 (QwQ)
有支持加密功能的。话说有没有相关工具方便改备份内容的?