
سحر LD_PRELOAD لـ AssetManager في أندرويد
(A)AssetHook هي مكتبة ربط (hooking) مبنية على LD_PRELOAD تسمح باستبدال
ملفات أصول APK ديناميكيًا دون تعديل ملف APK. كما أنها مكتوبة بلغة rust.
تعيد توجيه تحميلات ملفات الأصول إلى مسار ملف على جهاز Android تحت
/data/local/tmp/assethook/com.pkg.name. وغني عن القول، بسبب هذا
(وخاصة مخطط DRM السخيف في SEAndroid الذي يمنع الآن وصول التطبيقات إلى
/data/local/tmp)، يتطلب AssetHook حاليًا ضبط وضع SELinux على permissive.
إذا كان مسار الأصل الخام (عادةً assets/path/to/file.name)
موجودًا تحت مسار AssetHook الخاص بالحزمة المعنية، فسيتم تحميل البديل
بدلاً منه. يتكون AssetHook من تنفيذين منفصلين لخطاف LD_PRELOAD
أحدهما لـ C API "العامة"، والآخر لـ C++ API الداخلية.
بشكل عام، استخدم خطاف C++، ولكن إذا تعطل على إصدار جديد من Android،
جرّب خطاف C (فقط لاحظ القيود الموضحة أدناه).
لأن أشياء مثل React Native تستخدم API مدير الأصول الأصلية، والتي لا يمكن ربطها عبر أشياء مثل Xposed.
cppapi_assethook)خطاف قائم على LD_PRELOAD و"مستقر نسبيًا" يربط تنفيذ الأصول C++ الأساسي
الذي تستدعيه C API العامة وJava APIs من بين أشياء أخرى.
نظرًا لأن هذه الواجهة منخفضة المستوى تُستخدم أحيانًا بواسطة كود Android داخلي آخر
لتحميل/التحقق من موارد ثابتة أخرى من ملفات APK، فيمكن استخدامها أيضًا لاستبدال
تلك الملفات (إذا تمت قراءتها عبر هذه الواجهة) بوضع بدائل تحت مسارات APK غير assets/.
ملاحظة: على الرغم من أن ملفات مثل res/layout/activity_main.xml تُفتح على الأقل
عبر هذه الواجهة، إلا أنها لا تُقرأ بها ولا يمكن استبدالها في
وقت التشغيل باستخدام AssetHook.
capi_aassethook)(لاحظ الحرفين 'a' في "aasset")
خطاف قائم على LD_PRELOAD و"محافظ" لن يربط على مستوى Java
android.content.res.AssetManager. نظرًا لأن C API التي يربطها (AAsset*) عامة، فهذا
خطاف مستقر يمكن استخدامه إذا كانت التغييرات الجديدة في تنفيذ C++ الداخلي
تعطل خطاف C++ API. باستخدام هذا الخطاف، يمكن ربط الملفات الموجودة فقط تحت
/data/local/tmp/assethook/com.example.name/assets/.
قم بتثبيت AAssetHook وتفعيله لحزمة تطبيق معينة
ادفع (بصفتك shell للتأكد من أن الملف قابل للقراءة عالميًا) ملفات الاستبدال:
adb push index.android.bundle.mod /data/local/tmp/assethook/com.pkg.name/assets/index.android.bundle
أعد تشغيل التطبيق المرتبط
ملاحظة: الكائنات المشتركة لمعمارية arm 32 بت و64 بت مضمّنة في المستودع.
ملاحظة: يستخدم خطاف C API AAssetHook بعض امتدادات صيغة rust لتقليل قدر هائل من
الكود المتكرر (boilerplate)، وبالتالي يحتاج إلى الترجمة باستخدام rust الليلية (nightly). ومن المعروف
أنه يُبنى باستخدام rust عند الالتزام daf8c1dfc من 2016-12-05 (في حال كانت
التغييرات الداخلية في مترجم rust تكسر البناء).
قم بتثبيت Android NDK
قم بتثبيت rust عبر rustup (https://github.com/rust-lang-nursery/rustup.rs)
قم بتشغيل الأوامر التالية:
rustup install nightly # C API hook only
rustup default nightly # C API hook only
rustup target add aarch64-linux-android
rustup target add arm-linux-androideabi
rustup target add i686-linux-android # AVD/HAXM
mkdir ~/.cargo/toolchains
cd ~/.cargo/toolchains
/path/to/ndk/build/tools/make-standalone-toolchain.sh \
--platform=android-22 --toolchain=arm-linux-android-4.9 \
--install-dir=android-22-arm-toolchain`
/path/to/ndk/build/tools/make-standalone-toolchain.sh \
--platform=android-22 --toolchain=aarch64-linux-android-4.9 \
--install-dir=android-22-aarch64-toolchain`
/path/to/ndk/build/tools/make-standalone-toolchain.sh \
--platform=android-22 --toolchain=x86-linux-android-4.9 \
--install-dir=android-22-x86-toolchain`
أضف ما يلي إلى ~/.cargo/config
[target.arm-linux-androideabi]
linker = "/path/to/home/.cargo/toolchains/android-22-arm-toolchain/bin/clang"
[target.aarch64-linux-android]
linker = "/path/to/home/.cargo/toolchains/android-22-aarch64-toolchain/bin/clang"
[target.i686-linux-android]
linker = "/path/to/home/.cargo/toolchains/android-22-x86-toolchain/bin/clang"
ملاحظة: السكربت build.sh في دليل cppapi ينفذ الأوامر الثلاثة الأخيرة.
ملاحظة: إذا كنت تعتمد على تنفيذ capi، فاستبدل جميع حالات
cppapi بـ capi.
أولاً، قم بتثبيت SELinuxModeChanger من F-Droid أو MrBIMC/SELinuxModeChanger، واضبطه على وضع permissive.
ملاحظة: يمكنك أيضًا فقط تشغيل /system/bin/setenforce 0 بعد كل إقلاع.
cd cppapi
./install.sh
ملاحظة: إذا كنت تعتمد على تنفيذ capi، فاستبدل جميع حالات
cppapi بـ capi.
cd cppapi
./hook.sh <pkg.name> <32|64|unhook>
cd /path/to/aassethook/cppapi
cargo build --target=arm-linux-androideabi --release
cargo build --target=aarch64-linux-android --release
cargo build --target=i686-linux-android --release