逆向工程项目。起初是针对Bowflex Treadmill 22,但后来泛化为适用于Nautilus Inc.(Nautilus、Bowflex、Schwinn)销售的任何Android设备。
在从 AppMonitorService
释放(或收到任何 OTA 更新)后,首先要做的是尽可能多地备份数据。
确保您已经连接到控制台:
> adb connect <控制台 IP 地址>
它可能包含一些在出厂重置后机器正常工作所必需的文件(主要在 /sdcard/Android
和 /sdcard/Nautilus
文件夹中)。我们将使用以下命令备份所有内容:
> adb pull /sdcard/ .
首先,获取控制台上安装的所有包的列表(仅供参考):
> adb shell pm list packages -f
它们将以以下格式出现:package:<APK 位置>=<包名>
您将需要找到您想要备份的应用程序。并非所有应用程序都是必需的,大多数是标准的 Android 应用程序,所以我们将只寻找“非标准应用程序”,使用一些过滤器:
> adb shell pm list packages -f | grep -wviE 'com.android|com.google|framework-res|/vendor/overlay'
您将看到来自 com.nautilus
、com.redbend
、com.netflix
、com.amazon
、com.disney
的应用程序记录,也许将来还会有更多。我们将想要备份我们在该列表上看到的所有内容(隐藏的唯一 ID,请使用您自己的结果):
> adb shell pm list packages -f | grep -wviE 'com.android|com.google|framework-res|/vendor/overlay'
package:/data/app/com.nautilus.sbctest-XXXXXXXXXXXXXXXX/base.apk=com.nautilus.sbctest
package:/data/app/com.redbend.client-XXXXXXXXXXXXXXXX/base.apk=com.redbend.client
package:/data/app/com.nautilus.nlssbcsystemsettings-XXXXXXXXXXXXXXXX/base.apk=com.nautilus.nlssbcsystemsettings
package:/system/priv-app/RBDualPartService/RBDualPartService.apk=com.redbend.dualpart.service.app
package:/data/app/com.netflix.mediaclient-XXXXXXXXXXXXXXXX/base.apk=com.netflix.mediaclient
package:/data/app/com.nautilus.nautiluslauncher-XXXXXXXXXXXXXXXX/base.apk=com.nautilus.nautiluslauncher
package:/data/app/com.amazon.avod.thirdpartyclient-XXXXXXXXXXXXXXXX/base.apk=com.amazon.avod.thirdpartyclient
package:/data/app/com.nautilus.sbc_demo_app-XXXXXXXXXXXXXXXX/base.apk=com.nautilus.sbc_demo_app
package:/data/app/com.nautilus.UtilityApp-XXXXXXXXXXXXXXXX/base.apk=com.nautilus.UtilityApp
package:/data/app/com.nautilus.g4assetmanager-XXXXXXXXXXXXXXXX/base.apk=com.nautilus.g4assetmanager
package:/data/app/com.nautilus.platform_hardwaretest-XXXXXXXXXXXXXXXX/base.apk=com.nautilus.platform_hardwaretest
package:/data/app/com.nautilus.webviewer-XXXXXXXXXXXXXXXX/base.apk=com.nautilus.webviewer
package:/data/app/com.nautilus.bowflex.usb-XXXXXXXXXXXXXXXX/base.apk=com.nautilus.bowflex.usb
package:/data/app/com.disney.disneyplus-XXXXXXXXXXXXXXXX/base.apk=com.disney.disneyplus
注意:
com.redbend.dualpart.service.app
来自/system/priv-app/
,这意味着即使在出厂重置后它也会保持安装状态。如果您对逆向工程应用程序感兴趣,我们可以无论如何都备份它。
以 Disney Plus 为例(隐藏的唯一 ID)
package:/data/app/com.disney.disneyplus-XXXXXXXXXXXXXXXX/base.apk=com.disney.disneyplus
根据我提到的格式,那行将是:
包位置:/data/app/com.disney.disneyplus-XXXXXXXXXXXXXXXX/base.apk
包名:com.disney.disneyplus
我们将根据这些信息查找我们拥有的应用程序版本。使用我们刚刚识别的包名运行:
> adb shell dumpsys package com.disney.disneyplus | grep versionName
在我的案例中,我收到:
> adb shell dumpsys package com.disney.disneyplus | grep versionName
versionName=2.4.2-rc2
现在,为 Disney Plus 包创建备份的过程将是:
> adb pull /data/app/com.disney.disneyplus-XXXXXXXXXXXXXXXX/base.apk .
立即完成后,转到您的文件资源管理器并将新备份的 base.apk
文件重命名为 com.disney.disneyplus-2.4.2-rc2.apk
。
我建议的 APK 格式,以该示例为准,是:<包名>-<版本>.apk
现在重复其他应用程序的过程。
它似乎能够备份 一些(我不确定是否全部) 应用程序数据。
请记住,并非所有已安装的应用程序都会生成应用程序数据,或者我们作为 shell
用户可能没有权限备份所有内容。
创建所有用户安装的应用程序的完整备份:
> adb backup -f appdata.adb -all -noapk -nosystem
或者,您可以从另一个命令获得相同的结果:
> adb shell 'bu backup -all -noapk -nosystem' > appdata.adb
两个命令都会请求一个“屏幕确认”,您想要进行备份。点击“备份我的数据”:
如果您想要提取内容(在 Linux、macOS 上),您将需要来自 qpdf 的 zlib-flate
并运行:
> dd if=appdata.adb bs=24 skip=1 | zlib-flate -uncompress | tar xf -
对于 com.nautilus.bowflex.usb
有一些迷人的数据。
里面有个人身份信息(PII),所以确保检查好您分享的文件。
这些备份和提取方法来自这个 Gist。我只测试了那里列出的备份方法,这些方法是安全的。如果您使用 Gist 中的恢复功能,您将自行承担风险。如果它有效,请告诉我们!
我开发了一个快速而简陋的 Python 脚本来备份一些内容(现在还不包括 AppData)。 仅在 macOS 上测试过,通过 brew 安装了 android-platform-tools。 在运行之前阅读脚本并确保它对您有意义。
import sys
import os
import subprocess
from datetime import datetime
# 检查是否给出了参数
if len(sys.argv) != 2:
print("使用方法:python3 dump.py <控制台 IP 地址>")
sys.exit(1)
ipaddr = sys.argv[1]
# 检查 shell 是否可以使用 adb
adb_path = subprocess.check_output(["which", "adb"]).decode("utf-8").strip()
if not os.path.exists(adb_path):
print("未找到 adb")
exit()
# 设置当前日期和时间的备份文件夹
dump_folder = os.path.join(
os.environ["HOME"],
"Desktop",
"nautilus_dump",
"{}".format(datetime.now().strftime("%Y-%m-%d_%H-%M-%S")),
)
if not os.path.exists(dump_folder):
os.makedirs(dump_folder)
# 连接 adb
print("正在连接到 {}...".format(ipaddr))
subprocess.call(["adb connect {}".format(ipaddr)], shell=True)
# 备份 /sdcard 的内容
print("正在备份 /sdcard 的内容...")
subprocess.call(["adb pull /sdcard/ {}".format(dump_folder)], shell=True)
# 获取 APK 信息
print("正在备份 APKs...")
packages = (
subprocess.check_output(["adb shell pm list packages -f"], shell=True)
.decode("utf-8")
.split("\n")
)
# 过滤掉空行
packages = [x for x in packages if x.strip()]
# 过滤掉包含 "com.android", "com.google", "framework-res" 的行
packages = [package for package in packages if package.find("com.android") == -1]
packages = [package for package in packages if package.find("com.google") == -1]
packages = [package for package in packages if package.find("framework-res") == -1]
print("找到 {} 个 APKs".format(len(packages)))
for package in packages:
package_name = package.split("=")
package_name = package_name[len(package_name) - 1].strip()
package_version = (
subprocess.check_output(
["adb shell dumpsys package {} | grep versionName".format(package_name)],
shell=True,
)
.decode("utf-8")
.split("=")[1]
.strip()
)
package_path = package.split(":")[1].split(".apk=")[0].strip()
package_path = "{}.apk".format(package_path)
print("正在备份 {} v{}...".format(package_name, package_version))
subprocess.call(["adb pull {} {}".format(package_path, dump_folder)], shell=True)
os.rename(
os.path.join(dump_folder, os.path.basename(package_path)),
os.path.join(dump_folder, "{}-{}.apk".format(package_name, package_version)),
)
# 备份 appdata
print("正在备份 appdata.adb ...")
print('现在请在屏幕上点击“备份我的数据”按钮!!!')
subprocess.call(
["adb backup -f {}/appdata.adb -all -noapk -nosystem".format(dump_folder)],
shell=True,
)
# 断开 adb 连接
print("正在断开连接...")
subprocess.check_output(["adb disconnect"], shell=True)
©2022-2024 Sebastian Barrenechea. 保留所有权利.
构建于 Astro v4.16.13.