Smali: Assembler for Android’s VM
Assembly language for the dex format, used by Android’s Dalvik virtual machine.
When testing Android mobile apps, quite often you can find yourself in a situation where you face a security mechanism that you wish to bypass, either because the app won’t run (e.g root detection) or there is something else you want to investigate more (e.g SSL pinning).
Usually a tester has 2 options to bypass these mechanisms:
- Bypassing these checks at runtime when executing the app using tools such as Frida; attach the tool to the app process to inject code to manipulate the behaviour.
Although fast and usually easier: you need to attach to the app process every time you run the app.
- Otherwise, another more powerful approach while at the same time slightly more complex, consists in modifying the app binary for the specific checks we wish to bypass. In the Android security community this process is referred to as smali code patching.
By patching the underlying binary code, we can bypass app protections and manipulate its behaviour.
From the official git¹, “smali/baksmali is an assembler/disassembler for the dex format used by dalvik, Android’s Java VM implementation”.
The smali code, which is what we wish to modify, can be thought of as an equivalent of assembly code of a C program.
Having said this, in order to fully understand what smali code is and how it works, it is worth taking a look at the compilation process of an Android app written in Java and where dalvik and dex fit into this.
Android apps are usually written in Java and compiled to Dalvik bytecode. Dalvik bytecode is created by first compiling the Java code to .class files, then converting the JVM bytecode to the Dalvik .dex format with the
Extracted from the OWAP Mobile Security Testing Guide²
In this comparison, it can be observed that in Android systems we have an extra compilation step rather than the usual Java program. The Java bytecode is compiled into Dalvik bytecode which is then executed by the Android environment; which in modern devices is Android RunTime (ART). ART is the modern day replacement for the Dalvik VM however still runs the .dex file format.
With this in mind, what smali/backsmali tools do is to reverse the compilation of this bytecode in this .dex format. This is exactly what tools such as apktool³ do; it uses smali/backsmali internally when decompiling an APK file.
There are still challenges that remain despite smali being a hybrid language; using opcodes as well as semi-readable code.
Despite all this, smali patching presents a couple of challenges:
- Although smali code does not look exactly like assembly (in terms of syntax), at the same time it does not look like readable code. It is a hybrid mix of the two which the tester must understand.
- Considering the complexity and how low level smali code is, quite often it is easy to modify something that breaks the logic of the app, making the app unusable or unstable.
Having introduced and explained the basics of what smali code is, and the reason for modifying it, we’ll begin to talk over some of its structure and syntax, however we will not discuss all opcodes⁴
Before we start exploring the syntax and patching we first need to decompile the target apk. This can be done using apktool to reverse the application, the code and resources; the smali code files can then be found in myAppDirSrc\smali.
java -jar apktool.jar d MyAppName.apk -o myAppDirSrc
Once we’ve done the smali patches, we need to recompile our code to build it from .dex files back into an .apk.
java -jar apktool.jar b myAppDirSrc -o MyNewAppName.apk
However to ensure the modified app installs on a device, it also needs to be signed with a developer signature.
keytool -genkey -v -keystore myKey.jks -keyalg RSA -keysize 2048 -validity 10000 -alias myAliaszipalign -v -p 4 MyNewAppName.apk MyNewAppNameAligned.apkapksigner sign — ks myKey.jks — out MyNewAppNameSigned.apk MyNewAppNameAligned.apk
We will look at some examples of Java and the associated smali code to identify where the similarities lie between the two. It is important to be aware of the syntax when working on smali patches in order understand the workflow of the application.
Registers and opcodes
.locals x #local variables
.field public a:Ljava/lang/String; # instance fields
.method public constructor <init>(Ljava/lang/String;)V #methodsv0 #local variable 0
v1 #local variable 1
...p0 #parameter 0 (Java 'this' context)
p1 #parameter 1
...const/4 v0, 0x1 #constant value, putting decimal 1 into v0
if-eqz v0 #if v0 is equal to zero
if-nez v0 #if v0 is not equal to zeromove-result v1 #store previous result into v1
return v1 #return value of v1 back to calling method
return void #return a void value back to calling methodinvoke-direct #invokes non static method, e.g private/constructor
invoke-static #invoke a static method
invoke-virtual #invoke non private/static/final, e.g native libs
Single characters are used to define various Java types when used in method calls and return values.
V - void
Z - Boolean
B - byte
S - short
C - char
F - float
I - int
J - long
D - double
[ - array
L - class definition
- method declaration of myMethod with a void return type
private static void myMethod()smali
.method private static myMethod()V
- method declaration of myArgMethod with a Boolean return type and a Float argument
private Boolean myArgMethod(float floatnum)smali
.method private myArgMethod(F)Z –
- method declaration of myStrMethod with a Boolean return type and a Byte and String argument
public Boolean myStrMethod(byte mybyte, String str)smali
.method public myStrMethod(B; Ljava/lang/String)Z –
We covered a brief intro into some of the vast subject that denotes the smali language; however with only understanding the basics we can start to pull apart the app structure, understand input parameters and return types, and try to modify certain behaviours to manipulate the underlying logic.
¹ smali — https://github.com/JesusFreke/smali/wiki
² OWASP MSTG — https://owasp.org/www-project-mobile-security-testing-guide/
³ Apktool — https://github.com/iBotPeaches/Apktool
⁴ Dalvik opcodes — 1. http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html