Spoofing Android device model via Smali patching
I recently came up against an Android application which gates certain functionality behind detecting a ‘compatible’ Android device – which mine was not. My usual approach, on a rooted device, would be to use XPrivacyLua to spoof the device information returned to the application, but this particular application also disables itself if a rooted device is detected, so this is not trivial. A suitable approach in this case is to modify the application itself and patch out the relevant code.
Firstly, we obtain the APK file of the application:
$ adb shell pm path com.example.app
package:/path/to/base.apk
$ adb pull /path/to/base.apk
/path/to/base.apk: 1 file pulled, 0 skipped. xxx MB/s (xxx bytes in xxxs)
We can then use apktool to extract the APK file and disassemble the code:
$ apktool decode --no-res --output /path/to/disassembly base.apk
I: Using Apktool 2.7.0 on base.apk
I: Copying raw resources...
I: Baksmaling classes.dex...
I: Baksmaling classes2.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...
I: Copying META-INF/services directory
Details of the device are exposed in the android.os.Build class, or, in the Java internal field descriptors syntax, Landroid/os/Build;
. We can simply then grep for references to this class to identify the code responsible for reading the device information:
$ grep -R 'Landroid/os/Build;' /path/to/disassembly
/path/to/disassembly/smali/a/b.smali: sget-object v0, Landroid/os/Build;->MODEL:Ljava/lang/String;
We can then manually edit this file and patch out the sget-object instruction to instead load our desired device information, for example, by replacing the line with:
const-string v0, "Pixel 8"
We could even apply this everywhere automatically, for example:
$ find /path/to/disassembly -name '*.smali' -print0 | xargs -0 sed 's#sget-object \([pv][0-9]\+\), Landroid/os/Build;->MODEL:Ljava/lang/String;#const-string \1, "Pixel 8"#g'
We can repeat this as required for other fields of android.os.Build such as MANUFACTURER and DEVICE.
With the required changes made, we can then rebuild the APK file with apktool:
$ apktool build --output patched.apk /path/to/disassembly
I: Using Apktool 2.7.0
I: Checking whether sources has changed...
I: Smaling smali folder into classes.dex...
I: Checking whether sources has changed...
I: Smaling smali_classes2 folder into classes2.dex...
I: Checking whether resources has changed...
I: Copying raw resources...
I: Copying libs... (/kotlin)
I: Copying libs... (/META-INF/services)
I: Building apk file...
I: Copying unknown files/dir...
I: Built apk into: patched.apk
We can then sign the APK file (for example, with uber-apk-signer) and install it to the target device.