شعار مشروع fl3xbl0w

نسخ احتياطي لمحتويات وحدة التحكم الخاصة بك - fl3xbl0w

تم الإطلاق في ٢٨ مايو ٢٠٢٢

مشروع هندسة عكسية. بدأ بجهاز المشي Bowflex Treadmill 22 ولكن تم تعميمه لأي جهاز أندرويد يباع من قبل شركة Nautilus Inc. (Nautilus, Bowflex, Schwinn).

بعد التحرر من AppMonitorService (أو بعد تلقي أي تحديث OTA)، أول شيء يجب القيام به هو نسخ كل البيانات الممكنة احتياطيًا.

تأكد من أنك متصل بالفعل بجهاز التحكم:

> adb connect <عنوان IP الجهاز>

نسخ احتياطي لمحتوى /sdcard

قد يحتوي على بعض الملفات الضرورية للعمل بشكل صحيح بعد إعادة ضبط المصنع (خاصة في مجلدات /sdcard/Android و /sdcard/Nautilus). سنقوم بنسخ كل شيء باستخدام:

> adb pull /sdcard/ .

نسخ احتياطي للـ APK

أولاً، احصل على قائمة بجميع الحزم المثبتة على جهاز التحكم (فقط لتكون لديك مرجع):

> adb shell pm list packages -f

سوف تظهر بالتنسيق التالي: package:<موقع APK>=<اسم الحزمة>

سيتعين عليك العثور على التطبيقات التي تريد نسخها احتياطيًا. ليس كل التطبيقات ضرورية، معظمها تطبيقات أندرويد قياسية، لذا سنبحث فقط عن “التطبيقات غير القياسية” باستخدام بعض المرشحات:

> 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، وربما بعض التطبيقات الأخرى في المستقبل. سنرغب في نسخ كل ما نراه في تلك القائمة (معرفات فريدة مخفية، استخدم نتائجك الخاصة):

> 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 كمثال (معرف فريد مخفي)

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

الآن كرر العملية لبقية التطبيقات.

نسخ احتياطي لـ AppData

يبدو أنه قادر على نسخ بعض (لست متأكدًا إذا كان الكل) بيانات التطبيق احتياطيًا.

ضع في اعتبارك أنه ليس كل التطبيقات المثبتة تولد بيانات تطبيق، أو قد لا نملك نحن كمستخدم shell الأذونات لنسخ كل شيء احتياطيًا.

قم بإنشاء نسخة احتياطية كاملة لجميع التطبيقات المثبتة من قبل المستخدم:

> adb backup -f appdata.adb -all -noapk -nosystem

بديلًا، يمكنك الحصول على نفس النتيجة من أمر بديل:

> adb shell 'bu backup -all -noapk -nosystem' > appdata.adb

كلا الأمرين سيطلب “تأكيد على الشاشة” بأنك تريد عمل نسخة احتياطية. انقر على “BACK UP MY DATA”:

شاشة تأكيد النسخ الاحتياطي

إذا كنت ترغب في استخراج المحتويات (على Linux، macOS)، ستحتاج إلى zlib-flate من qpdf وتشغيل:

> dd if=appdata.adb bs=24 skip=1 | zlib-flate -uncompress | tar xf -

هناك بعض البيانات المثيرة للاهتمام لـ com.nautilus.bowflex.usb. هناك معلومات شخصية قابلة للتعريف (PII) بداخلها، لذا تأكد من التحقق جيدًا من الملفات التي تشاركها.

تأتي هذه الطرق للنسخ الاحتياطي والاستخراج من هذا الرابط. لقد اختبرت فقط طرق النسخ الاحتياطي المذكورة هناك، وهي آمنة للتجربة. إذا كنت تلعب بالاستعادة من الرابط، فأنت على مسؤوليتك الخاصة. أخبرنا إذا نجحت!

السكربت

طورت سكربت Python سريع وبسيط لنسخ بعض المحتويات احتياطيًا (لا يتضمن AppData حتى الآن). تم اختباره فقط على macOS مع تثبيت android-platform-tools عبر brew. اقرأ السكربت وتأكد من أنه منطقي بالنسبة لك قبل تشغيله.

import sys
import os
import subprocess
from datetime import datetime

# تحقق مما إذا كان قد تم إعطاء وسيط
if len(sys.argv) != 2:
    print("Usage: python3 dump.py <Console IP Address>")
    sys.exit(1)

ipaddr = sys.argv[1]

# تحقق مما إذا كان adb متاحًا للشل
adb_path = subprocess.check_output(["which", "adb"]).decode("utf-8").strip()
if not os.path.exists(adb_path):
    print("adb not found")
    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("Connecting to {}...".format(ipaddr))
subprocess.call(["adb connect {}".format(ipaddr)], shell=True)

# نسخ محتوى /sdcard احتياطيًا
print("Backing up content of /sdcard...")
subprocess.call(["adb pull /sdcard/ {}".format(dump_folder)], shell=True)

# الحصول على معلومات APK
print("Backing up 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("Found {} 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("Backing up {} 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("Backing up appdata.adb ...")
print('TAP THE "BACK UP MY DATA" BUTTON ON SCREEN NOW !!!')
subprocess.call(
    ["adb backup -f {}/appdata.adb -all -noapk -nosystem".format(dump_folder)],
    shell=True,
)

# قطع الاتصال بـ adb
print("Disconnecting...")
subprocess.check_output(["adb disconnect"], shell=True)
المحتوى مترجم بواسطة gpt-4-1106-preview

©2022-2024 سيباستيان بارينيشيا. جميع الحقوق محفوظة.

مبني بواسطة Astro v4.15.9.