(A)AssetHook is an LD_PRELOAD-based hooking library that allows for replacing
APK asset files dynamically without modifying an APK. It's also written in rust.
It redirects asset file loads to a filepath on an Android device under
/data/local/tmp/assethook/com.pkg.name. Needless to say, due to this
(really SEAndroid's ridiculous DRM scheme that now blocks app access to
/data/local/tmp), AssetHook currently requires that the SELinux mode be set
to permissive. If the raw asset path (typically assets/path/to/file.name)
exists under the respective package's AssetHook path, the replacement will
be loaded instead. AssetHook consists of two separate LD_PRELOAD hook
implementations, one for the "public" C API, and one for the internal C++ API.
In general, use the C++ hook, but if it breaks on a new version of Android,
try the C one (just note the limitations of it described below).
Because things like React Native use the native asset manager API, which can't be hooked via things like Xposed.
A "relatively stable" LD_PRELOAD-based hook that hooks the underlying C++ asset
implementation called by the public C API and the Java APIs among other things.
As this lower level API is occasionally used by other internal Android code to
load/check other static resources from APKs, it can also be used to replace
those files (if read via this API) by placing replacements under non-assets/
APK paths.
Note: While files such as res/layout/activity_main.xml are at least
opened via this API, they are not read with it and cannot be replaced at
runtime with AssetHook.
(Note the two 'a's in "aasset")
A "conservative" LD_PRELOAD-based hook that won't hook the Java-level
android.content.res.AssetManager. As the C API it hooks (AAsset*) is public, this is
a stable hook to be used if new changes in the internal C++ implementation
break the C++ API hook. Using this hook, only files under
/data/local/tmp/assethook/com.example.name/assets/ can be hooked.
-
Install AAssetHook and enable it for a particular app package
-
Push (as
shellto make sure the file is world-readable) replacement files:adb push index.android.bundle.mod /data/local/tmp/assethook/com.pkg.name/assets/index.android.bundle
-
Restart the hooked app
Note: Shared objects for 32-bit and 64-bit arm are embedded in the repository.
Note: The C API hooking AAssetHook uses some rust syntax extensions to cut down on a tremendous amount of
boilerplate, and therefore needs to be compile using rust nightly. It is known
to build using rust at commit daf8c1dfc from 2016-12-05 (in case internal
changes in the rust compiler break the build).
-
Install the Android NDK
-
Install rust via rustup (https://github.com/rust-lang-nursery/rustup.rs)
-
Run the following commands:
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`
-
Add the following to
~/.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" -
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
Note: The build.sh script in the cppapi directory performs the last three commands.
Note: If falling back to the capi implementation, swap all instances of
cppapi for capi.
First install SELinuxModeChanger from F-Droid or MrBIMC/SELinuxModeChanger, and set it to permissive mode.
Note: You can also just run /system/bin/setenforce 0 after each boot.
cd cppapi
./install.shNote: If falling back to the capi implementation, swap all instances of
cppapi for capi.
cd cppapi
./hook.sh <pkg.name> <32|64|unhook>- Migrate hook file storage to an application's local file directory to bypass the need for SEAndroid disabling
- Resource hooking