
LD_PRELOAD magic per l'AssetManager di Android
(A)AssetHook è una libreria di hooking basata su LD_PRELOAD che consente di sostituire
dinamicamente i file asset APK senza modificare un APK. È anche scritto in rust.
Reindirizza il caricamento dei file asset a un percorso file su un dispositivo Android in
/data/local/tmp/assethook/com.pkg.name. Inutile dirlo, a causa di questo
(in realtà il ridicolo schema DRM di SEAndroid che ora blocca l'accesso delle app a
/data/local/tmp), AssetHook attualmente richiede che la modalità SELinux sia impostata
su permissive. Se il percorso asset grezzo (tipicamente assets/path/to/file.name)
esiste nel percorso AssetHook del rispettivo pacchetto, la sostituzione verrà
caricata al suo posto. AssetHook consiste in due implementazioni di hook LD_PRELOAD
separate, una per l'API C "pubblica" e una per l'API C++ interna.
In generale, usa l'hook C++, ma se si rompe su una nuova versione di Android,
prova quello C (nota solo i limiti descritti di seguito).
Perché cose come React Native usano l'API nativa del gestore degli asset, che non può essere agganciata con strumenti come Xposed.
cppapi_assethook)Un hook basato su LD_PRELOAD "relativamente stabile" che aggancia l'implementazione C++ sottostante degli asset
chiamata dall'API C pubblica e dalle API Java, tra le altre cose.
Poiché questa API di basso livello è occasionalmente usata da altro codice Android interno per
caricare/verificare altre risorse statiche dagli APK, può anche essere usata per sostituire
quei file (se letti tramite questa API) inserendo le sostituzioni in percorsi non-assets/
degli APK.
Nota: Sebbene file come res/layout/activity_main.xml vengano almeno
aperti tramite questa API, non vengono letti con essa e non possono essere sostituiti a
runtime con AssetHook.
capi_aassethook)(Nota le due 'a' in "aasset")
Un hook basato su LD_PRELOAD "conservativo" che non aggancia il livello Java
android.content.res.AssetManager. Poiché l'API C che aggancia (AAsset*) è pubblica, questo è
un hook stabile da usare se nuove modifiche nell'implementazione C++ interna
rompono l'hook dell'API C++. Usando questo hook, solo i file in
/data/local/tmp/assethook/com.example.name/assets/ possono essere agganciati.
Installa AAssetHook e abilitalo per un particolare pacchetto app
Esegui il push (come shell per assicurarsi che il file sia leggibile da tutti) dei file di sostituzione:
adb push index.android.bundle.mod /data/local/tmp/assethook/com.pkg.name/assets/index.android.bundle
Riavvia l'app agganciata
Nota: Gli shared object per arm a 32 e 64 bit sono inclusi nel repository.
Nota: L'hook dell'API C AAssetHook usa alcune estensioni sintattiche di rust per ridurre un'enorme quantità di
codice boilerplate, e quindi deve essere compilato usando rust nightly. È noto
che la build funziona con rust al commit daf8c1dfc del 2016-12-05 (nel caso in cui
modifiche interne al compilatore rust rompano la build).
Installa l'Android NDK
Installa rust tramite rustup (https://github.com/rust-lang-nursery/rustup.rs)
Esegui i seguenti comandi:
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`
Aggiungi quanto segue a ~/.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"
Nota: Lo script build.sh nella directory cppapi esegue gli ultimi tre comandi.
Nota: Se si ripiega sull'implementazione capi, sostituisci tutte le occorrenze di
cppapi con capi.
Prima installa SELinuxModeChanger da F-Droid o MrBIMC/SELinuxModeChanger, e impostalo in modalità permissiva.
Nota: Puoi anche semplicemente eseguire /system/bin/setenforce 0 dopo ogni avvio.
cd cppapi
./install.sh
Nota: Se si ripiega sull'implementazione capi, sostituisci tutte le occorrenze di
cppapi con 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