Substrate extensions are compiled as a shared object (using the compound extension .cy.so) and are distributed as part of standard Android packages as a native library. (Android native libraries have their own filename restrictions: they must begin with "lib" and end with ".so".)
# ls -l /data/data/com.example.HelloExtension/lib -rwxr-xr-x system system 70949 2012-02-24 18:48 libFancyGreeting.cy.so
Android has a fine-grained permissions model that allows us to verify that Substrate extensions are only registered by packages that the user trusts enough to have the far-reaching power to make arbitrary modifications to other packages or the system itself.
Substrate manages this by registering its own permission, cydia.permission.SUBSTRATE
, which packages must request in their manifest files with the uses-permission
tag.
<permission android:name="cydia.permission.SUBSTRATE" android:label="modify code from other packages" android:protectionLevel="dangerous" android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS" />
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <uses-permission android:name="cydia.permission.SUBSTRATE"/> </manifest>
The configuration of a Substrate extension is embedded into the binary in a manner very similar to that of a Linux kernel module: a .substrate
ELF section is created that contains name=value pairs as null-terminated strings.
Developers set these configuration options in their code using the macro MSConfig
. Care should be taken to only use configuration options that are defined: if unknown ones are detected by the loader at runtime the library will be ignored. It is therefore recommended to use the provided macros.
The MSConfig
macro takes two arguments: the name of a configuration parameter and a string value, both as constant C string values.
Name | Description |
Filter:Executable |
The absolute path to an executable the developer is attempting to hook. This will often be zygote, "/system/bin/app_process". For more information on zygote, see our guide to process loading. |
Filter:Library |
The name (last path component) of a library the developer is attempting to hook. As an example, to hook __android_log, specify "liblog.so". |
MSConfig(MSFilterExecutable, "/system/bin/app_process")
MSConfig(MSFilterLibrary, "liblog.so")
# file libFancyGreeting.cy.so libFancyGreeting.cy.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, not stripped # objdump -s -j .substrate libFancyGreeting.cy.so libFancyGreeting.cy.so: file format elf32-littlearm Contents of section .substrate: 1200 46696c74 65723a45 78656375 7461626c Filter:Executabl 1210 653d2f73 79737465 6d2f6269 6e2f6170 e=/system/bin/ap 1220 705f7072 6f636573 73000000 00000000 p_process.......