[Android Security] Smali and reverse analysis

copy : https://blog.csdn.net/u012573920/article/details/44034397

1. Introduction to Smali

Smali is Dalvik's register language, and its relationship with Java is simply comprehension to C. If you have enough control over assembly, you can change the direction of the C/C++ code by modifying the assembly code. Of course, those who have learned assembly know that assembly is harder to learn than BrainFuck , let alone decompile and modify.

But Smali is a little different, that is, it is very simple and only has a little syntax. As long as you know java and understand Android related knowledge, you can completely modify the java code in reverse by modifying the Smali code. In some cases you have to do it. Fortunately, Smali is simple.

2.apktool

Having said so much, where did Smali come from? That's right. The Smali code is decompiled from the Android APK, so the Smali file corresponds to the Java file one by one. To get the Smali file, we need to download an auxiliary tool: ApkTool . The command-line tool apktool has many function parameters if used in detail, but here we only need to use the two most basic functions:

One is to decompile decode:

apktool d xxx.apk

Another is to package the build:

apktool b

What should be paid attention to here is the path problem. If apktool is not added to the environment variable, remember to cd to the apktool directory to use it. The other is packaging. If the parameter b is simply used, the requirement is to execute it in the decompiled project directory, and the packaged file will be saved in the dist directory under the project directory.

Here is the decompiled and packaged directory structure of a HelloWorld application:

3.Smali syntax

(1) Data type

 

There are two types of dalvik bytecode, primitive types and reference types. Objects and arrays are reference types, others are primitive types.

The smali data type is represented by a letter. If you are familiar with Java data types, you will find that the letter representing the smali data type is actually the capital of the first letter of the Java basic data type, except for the boolean type, which is capitalized in smail" Z" for boolean type.

V void, can only be used for return value types
WITH boolean
B byte
S short
C char
I int
J long (64 bits)
F float
D double (64 bits)

 Objects are represented in the form of Lpackage/name/ObjectName;. The preceding L indicates that this is an object type, package/name/ is the package where the object is located, ObjectName is the name of the object, and ";" indicates the end of the object name. Equivalent to package.name.ObjectName in java.

For example: Ljava/lang/String; equivalent to java.lang.String

 

array representation

[I——represents an integer one-dimensional array, equivalent to int[] in java. For multidimensional arrays, just add [. [[I is equivalent to int[][], and [[[I is equivalent to int[][][]. Note the maximum of 255 for each dimension.

 Representation of an array of objects

[Ljava/lang/String; represents an array of String objects.

(2) Method

 

The method usually must specify the method type (? the type that contains the method) method name, parameter type, return type, all these information is for the virtual machine to be able to find the correct method and execute it.

Method representation: Lpackage/name/ObjectName;->MethodName(III)Z

In the above example, Lpackage/name/ObjectName; represents the type, and MethodName is the method name. III is the parameter (here 3 integer parameters) and Z is the return type (bool).

The parameters of the method are one after the other, not separated.

A more complex example: method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;

In java: String method(int, int[][], int, String, Object[])

A more comprehensive example:

.class public interface abstract Lcom/kit/network/CachableImage;  
.super Ljava / lang / Object;  
.source "SourceFile"  
  
# virtual methods  
.method public abstract getIsLarge()Z  
.end method  
  
.method public abstract getUrl()Ljava/lang/String;  
.end method  
  
.method public abstract getViewContext()Landroid/content/Context;  
.end method  
  
.method public abstract setBitmap(Landroid/graphics/Bitmap;Z)V  
.end method  
  
.method public abstract setIsLarge(Z)V  
.end method  
  
.method public abstract setUrl(Ljava/lang/String;)V  
.end method  

The restored java code of the above smali code is:

 
//# Note: In the actual code, we must also introduce related packages  
import android.content.Context;  
import android.graphics.Bitmap;  
  
public interface CachableImage {  
  
    public abstract boolean getIsLarge();  
  
    public abstract String getUrl();  
  
    public abstract Context getViewContext();  
  
    public abstract void setBitmap(Bitmap bitmap);  
  
    public abstract void setIsLarge(boolean islarge);  
  
    public abstract void setUrl(String url);  
}  

  

 

 (3) Field

 

Representation: Lpackage/name/ObjectName;->FieldName:Ljava/lang/String; that is, package name, field name and field type. eg:

 
.field private _requestLayout:Z  
  
.field public isLarge:Z  
  
.field public resize:Z  
  
.field public thumbnailSize:I  
  
.field public url:Ljava/lang/String;  

  

The restored java code is:
 
public boolean _requestLayout;  
public boolean isLarge;  
public boolean resize;  
public int thumbnailSize;  
public String url;  

  

Here is still a default HelloWorld application to explain it. Create a new HelloWorld Android project and keep only the onCreate function in MainActivity. code show as below:

package com.fusijie.helloworld;  
  import android.app.Activity;  
  import android.os.Bundle;  
  public class MainActivity extends Activity {  
  @Override  
  protected void onCreate(Bundle savedInstanceState) {  
      super.onCreate (savedInstanceState);  
      setContentView(R.layout.activity_main);  
      }  
  }  

 

The decompiled Smali file is as follows:

 
.class public Lcom/fusijie/helloworld/MainActivity;  
.super Landroid/app/Activity;  
.source "MainActivity.java"  
# direct methods  
.method public constructor ()V  
  .locals 0  
  .prologue  
  .line 14  
  invoke-direct {p0}, Landroid/app/Activity;->()V  
  return-void  
.end method  
# virtual methods  
.method protected onCreate(Landroid/os/Bundle;)V  
  .locals 1  
  .parameter "savedInstanceState"  
  .prologue  
  .line 18  
  invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V  
  .line 19  
  const / high16 v0, 0x7f03  
  invoke-virtual {p0, v0}, Lcom/fusijie/helloworld/MainActivity;->setContentView(I)V  
  .line 20  
  return-void  
.end method  

 

By comparison, it can be clearly seen that the smali code is actually a translation of the java code, but it is not as simple as java looks. smali restores many things that should be complicated to a complex state. Briefly explain this code.

  • The first three lines specify the class name, parent class name, and source file name.
  • The class name starts with "L", I believe that children's shoes who are familiar with Jni are relatively clear.
  • "#" is a comment in smali.
  • ".method" and ".end method" are similar to curly braces in Java and contain the implementation code snippet of the method.
  • The return type is specified after the parentheses of the method, which is also similar to the Jni call.
  • ".locals" specifies the number of registers used by this method. Of course, registers can be reused, starting from "V0".
  • ".prologue" specifies where the code begins.
  • ".line" indicates which line is in the java source code. In fact, it doesn't matter how much this value is, it can be modified arbitrarily, mainly for debugging.
  • "invoke-direct" is a call to the method. You can see that the init method of Android.app.Activity is called here, which is implicitly called in java.
  • "return-void" indicates the return type, which is different from java, even if there is no return value, it needs to be written like this.
  • Next is the onCreate method. ".parameter" indicates the parameter name, but it is generally useless. It should be noted that p0 represents this, p1 starts to represent function parameters, and static functions do not have this, so p0 represents parameters.
  • In the implementation, the method of the parent class is called first, and then setContentView is called. Note that a parameter is given here. Integer parameter, this value is first assigned to register v0, and then passed in by calling. This is used in smali, all values ​​must be transferred through registers. This is very similar to assembly.

Comparing the Java code and Smali code, it can be clearly seen that the original code with only a few lines has been extended to Smali, and the content has been greatly expanded. Smali restores what Java hides while specifying a lot of details explicitly. This is just the most basic onCreate function of HelloWorld. If there is an inner class, it will be displayed in separate files.

In this way, in fact, Smali can only say that it is complicated, not difficult. If you want to fully understand the syntax of smali, here are a few links, which can be considered as a relatively good summary (in fact, I have not seen a systematic summary... If you have good information, please share it in the thread)

Here are 2 tools by the way:

The purpose of Smali is clear from the above example, yes, Smali injection . Now the common uses other than testing, Smali injection is obviously hacking, such as cracking games, replacing game advertisements, and even exploiting loopholes to crack passwords, steal personal data, property and so on. For Smali, Android reverse analysis, Android system security is relatively clear, these things are actually not a problem.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324695913&siteId=291194637