这篇文章上次修改于 572 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
无聊水
前言
在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
没有评论