An Introduction to Smali

An Introduction to Smali

Smali is a type of assembly language for the Dalvik virtual machine, which is used by Android devices. It is used to modify and reverse engineer Android apps, and allows developers to make changes to the bytecode of an app.  

One of the main advantages of Smali is that it allows for more fine-grained control over the behavior of an app than Java, as it operates at the bytecode level. This makes it useful for tasks such as hooking into specific methods or modifying the behavior of an app without modifying its Java source code. 

In this blog, we will look at three different test cases which include decompiling the APKs and converting them into Smali code which can be edited, modified and then recompiled back into the APKs. So, let’s get started. 

Pre-requisite 

This blog has some pre-requisite that one should be familiar with basics of java and basic knowledge of android application. If you are not familiar with these, you can first read few blogs to gain some insights.  

Introduction 

smali/baksmali is an assembler/disassembler for the dex format used by dalvik, Android’s Java VM implementation. When we create an android application, the structure of the apk folder looks like below: 

As you can see, one of the files is classes.dex which is basically binary dalvik bytecode that the android platform understands. Suppose if we want to read/modify this binary file, we need to convert this file to a more human readable format. This is when smali comes into play. The classes are then converted into Smali code, which can be edited and modified. The modified code can then be recompiled back into an APK file and installed on an Android device. 

For example, say you have Java code that does something like 

int x = 42; 

Assuming this is the first variable, then the dex code for the method will most likely contain the hexadecimal sequence 

13 00 2A 00

If you run baksmali on it, you’d get a text file containing the line 

const/16 v0, 42 

Which is obviously a lot more readable than the binary code. 

So, let’s start with learning the basics of smali first. Then we will create an android application and modify some variables. After that we will rebuild the mod apk. 

Registers & Locals Directive 

  • In Smali, registers are used to hold any type of value and are always 32 bits. To hold 64-bit values (long/double), two registers are used.  
  • Each method/function has a declaration of the number of registers used in that method/function.  
  • The .registers directive specifies the total number of registers used in the method, while the alternate .locals directive specifies the number of non-parameter registers used in the method. 
  • For example, if there is a non-static method with two arguments, there would be three parameter registers. If the total number of registers used in that method is 5, then the .locals directive will be 2, as 3 are parameter registers (this, arg1, arg2). 

For example, look at the following java code: 

Converting this java code into Smali Bytecode using locals directive: 

Don’t worry if you don’t understand the code, we will be explaining it in a later section. For now, you can find out that the number of locals directive used is 1. So we can conclude that the method addIntger and addInteger2 both have one non-parameter registers. 

Now, Smali Bytecode using registers directive: 

In the above Smali code in which we have used registers directive, you can find out that addInteger method has four registers while the addInteger2 method has three registers.  This is because addInteger method is non-static while the addInteger2 method is static. As in non-static class, we need to create instance of the class first and then using this keyword, we call the method.

So, the total number of registers used in addInteger method is 4, then the .locals directive will be 1, as 3 are parameter registers (this, arg1, arg2). Similarly, the total number of registers used in addInteger2 method is 3, which includes 1 locals directive and 2 parameter registers(arg1, arg2). 

So now we have covered how the variables are defined in smali code. Now let us take a look on Smali Data Types. The below table depicts how data types of Java gets mapped into Smali: 

Data Type Smali Notation 
byte 
short 
int 
long 
float 
double 
boolean 
char 
class or interface Lclassname; 

A HelloWorld Class 

Now we will follow the same tradition to learn smali as any developer do to learn any other language. We will look at a famous HelloWorld Example in Smali. I have also attached the java code for HelloWorld method as it will help in understanding the code better. But during the practical demonstration, we didn’t have access to the java code.  

Java Code: 

Smali Code: 

The above piece of Smali code has a method named “HelloWorld” which takes no arguments and returns void. 

The first line “.method public HelloWorld()V” declares the method “HelloWorld” as public and takes no arguments and returns void. 

The next line “.locals 2” declares that this method uses 2 local variables. Local variables are used to temporarily hold values within a method. 

The next line “.line 6” is used to indicate the source code line number, in this case line 6. 

The next line “sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;” is used to retrieve the value of the “out” field of the “java.lang.System” class, which is an instance of the “java.io/PrintStream” class, and store it in register v0. 

The next line “const-string v1, “Hello World!”” loads the string “Hello World!” into register v1. 

The next line “invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V” invokes the “println” method of the “java.io.PrintStream” class, passing in the value of v1 as the argument. The “println” method writes the passed string to the standard output. 

The next line “.line 7” is used to indicate the source code line number, in this case line 7. 

The last line “return-void” is used to return from the method and indicate that the method returns void. 

Dalvik Opcodes 

You may be wondering from where is sget-object or const-string coming from in the smali. These are basically instructions that are used to manipulate value in the registers. The “sget-object” instruction is used to retrieve the value of a static object field and store it in a register, while the “const-string” instruction is used to load a constant string value into a register. The “s” in “sget” stands for “static”, indicating that the field is a static field. 

Working with Smali requires a good understanding of the Dalvik virtual machine and its instruction set, as well as experience with assembly language programming. 

You can find dalvik-opcodes here that will help you get started with what a specific instruction does. 

Practical Demonstration 

Now we will look at three test cases where we will try to modify the smali code of the application and then repatch the application. So let us get started without any further delay. 

Test Case 1: Modify value of a variable 

In this test case, we will try to modify some variable to gain some confidence that smali is not at all hard to read. For this, we have created an android application named Smali Application 1 which is doing an addition operation on two numbers: 

So, as the application is challenging us to prove it wrong.  

First, we will pull the apk file of the installed Smali Application 1 from the device, decompile it using apktool and then analyze the smali code. 

I have written a small bash script that pulls the base apk file and decompile the application: 

  1. adb pull \  
  1. /data/app/com.app.smali1-c8JScvSVY2hu8a-65GbOIg==/base.apk ./smali1.apk  
  1. apktool d -r -f smali1.apk 

Running the above bash script will create a directory named smali1 of Smali Application 1. First thing first, we will search for MainActivity in this directory as this Activity is usually the entry point for any application. So it is better to start looking into this file first. 

Load the file smali1/smali_classes3/com/app/smali1/MainActivity.smali into any editor of your choice and try to read the smali code. 

You will find a function named addInteger. In that function, there is one local variable used ,I.e v0. From line 18, we can conclude that It takes two arguments of data type Integer and return an integer. The .param p1, and p2 are the parameters that are given input as arguments in the function. And on line 24, it has an opcode add-int that is doing addition of p1 and p2 and storing the result in v0. And finally v0 get returned to the calling function of addInteger. 

Scrolling below to the MainActivity.smali, you will find a method named onCreate which is calling addInteger method and giving arguments of v0 and v1. The value of v0 and v1 are set to 0x14 which is 20 in decimal.  

Now we will modify this variable simply to some another hex value let’s say 0x1f and patch the application and install it in the device. I am using APKlab extension in VSCode to patch and sign the application, but you are free to use whatever way you prefer. 

Now go to the dist folder and install the apk file in the device. 

Test Case 2: Change return value of a function 

In the previous test case, we successfully modified the value of a variable. In this test case, we are going to change the return value of a function. For the demonstration of this test case, we have created another application named Smali Application2.  

It is also performing addition operation on two numbers. Let’s decompile the apk and analyze the smali code to get understanding of the application. The MainActivity.smali has a function named add_nums as shown below 

Since the goal of this test case is to modify the return value of the function add_nums, we will modify the function itself. Instead of addition, we will perform subtraction by adding a new local variable v1 in the function. Thus, the locals directive count will increase to 2. Here is what the modified code will look like: 

Let’s patch the rebuild the application and install it in the device. 

And we have successfully modified this application. You are free to modify other variables as well, like you can try to modify this alert message. 

Test Case 3: Write a new evil function and calling that evil function instead of a legitimate function in smali 

Till now, we have successfully modified the variable, inserted new smali code inside a function. In this test case, we are going to insert an evil function in smali and call that evil function instead of a legitimate function.  For the demonstration of this test case, we have created another application named Smali Application3,   

As you can see, it is just displaying a Hello team… string on the homepage with an alert of “I am saying hello to the team”. 

Let’s analyze the application by decompiling it using apktool. The MainActivity.smali has a method named say_hello as shown below 

And this say_hello method gets called inside onCreate method of MainActivity.smali file. 

First, we will insert a new evil_method inside the MainActivity.smali file and call this evil_method instead of say_hello method. Here is how the evil_method will look like: 

It is simply returning a string of “Cheers Team!!!” . Lets replace the say_hello() method in onCreate method with evil_method and rebuild the application. 

So, we have successfully inserted a method inside the application by modifying the smali code.  

Conclusion 

This is it for this blog and for the next blog, we will see some real scenarios how an attacker can modify the Smali application to gain access to some sensitive data or bypass some checks. 

Subscribe to our Newsletter
Subscription Form
DOWNLOAD THE DATASHEET

Fill in your details and get your copy of the datasheet in few seconds

CTI Report
DOWNLOAD THE EBOOK

Fill in your details and get your copy of the ebook in your inbox

Ebook Download
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download ICS Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Cloud Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download IoT Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Code Review Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Red Team Assessment Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download AI/ML Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download DevSecOps Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Product Security Assessment Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Mobile Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Web App Sample Report

Let’s make cyberspace secure together!

Requirements

Connect Now Form

What our clients are saying!

Trusted by