Smali Code Injection

Smali Code Injection

In this post I wanted to demonstrate a simple code injection example in Android. As indicated in previous  posts about reversing java, the method of code execution is same in Android. Whereas Java, the BYTE CODE are SMALI codes here and the executor is Dalvik (recently ART) in Android (not JVM). Here in this post, I will describe shortly how to reverse and inject code in SMALI.

The main steps for code injection are:

  1. Decompile APK to Smali Code
  2. Find the right place to inject the code
  3. Use safe (or unsafe) local variables to inject
  4. Recompile the Smali Code to APK
  5. Generate Signature Key
  6. Sign the Recompiled APK

Decompile APK to Smali Code

Using the tool named APK Tool you can easily decompile APK to its elements. Actually APK is a ZIP compressed file. Which contains Manifest (permissions, activities, services, etc.), all source codes compiled inside DEX (classes.dex), resources (all images, xml elements of UI, sounds, etc.), Libraries (generally native ones), META-INF (public key of the signature).

You can download apk tool from this link. Using the following command you can get the APK decompiled.

java -jar apktool.jar d YOUR_APK.apk

Find right place to inject the code

After successful decompilation, a folder will be generated beside the APK. There is a folder named smali there which contains all the classes inside the main DEX file. All of the classes are in Smali format over there. You can use each of them for injecting the code. Smali is the code like here:

In the above example, I put a simple Toast message after the setContentView() method of an Activity.

For making the smali code you can use two methods:

  1. Use smali code instructions. You can use this link for more details.
  2. TRICK: Write your code in a separate Android project and make its APK. The use apktool for finding out the smali code of your {injection} code!

 Use safe (or unsafe) local variables to inject

As you see in the above example, I have used v1,v2,v3, … for smali code injection. v_i \;\;\;\;\; i \in {1,2, ... , 16} are the local variables. Android has 16 registers for this purpose which contains the inside the class variables (v) and the parameters (p) of the method we are injecting inside. for example onCreate has two parameters (p0 for this, p1 for Bundle) and some variables (vs). You should use vs for your purpose while do not compromise other vs. If you can add extra locals to your file, then you can use safe variables, if not you should use the defined local variables without compromise other variables.

Recompile the Smali Code to APK

If the injection is correct, you can use the following command to recompile the injected code.

java -jar apktool.jar b THE_DECOMPILED_FOLDER

This will generate an APK inside THE_DECOMPILED_FOLDER/dist folder.

Generate Signature Key

Sign the Recompiled APK

10 Comments

  1. Alexandre Teyar

    Hello Mir Saman,

    I am the origin author of SCI (smali code injector) I can see that your whole post is based on my work. I do not mind and in opposite encourage such initiatives but you could have gave me credits at least.

    Kind regards,
    Alexandre Teyar

    • Dear Alexandre,
      I did not know your project and it is a good one. But I did not copied or rebuild your project. I just simply described the process of smali code injection. It is not a tool (as yours are) it is a training post. I’ve only used the content from slides of http://www.syssec-project.eu

      You may post this comment because of the main photo of the post. Actually I just searched for smali code injection in Google Images and chose the image which is the image of your project.

      However, I suggest to all the readers of this post to check your project at the following link:
      https://github.com/AresS31/SCI

  2. lilly

    I lost my laptop and i only have apk of my application on the phone and i need to ad add admob ads so i can monetize it
    is it possible to add it to the decompiled apk ?

    • As I realized from your question, you want to inject ad codes to your APKs and monetize. Correct? For the part of injecting, it is possible. But I cannot assure that the ad can give you the money. Maybe the ad has its own API key or Authentication mechanism that it is needed more than injecting. But generally, YES. You can add advertisement codes to yous APKs.

  3. Vincent

    Hi, I’m looking for an expert to help me with reverse engineering apk. Please contact me if you are able to help me out in a small project

    Thanks

    • I will go to publish a video but do not know when! If you have any question, feel free to ask here.

  4. Alis

    Hello i want to change the request in a delivery apk. I wanna write give me the first request. What is the smali code of this command

  5. ali

    Hi boy
    How can I change this code to ignore my level and receive offer without level
    line 1
    const-string v0, “incomingOffer”

    .line 3
    invoke-static {p1, v0}, Lkotlin/jvm/internal/u;->k(Ljava/lang/Object;Ljava/lang/String;)V

    .line 6
    instance-of v0, p1, Lyj/d;

    .line 8
    const/4 v1, 0x1

    .line 9
    if-nez v0, :cond_b

    .line 11
    return v1

    .line 12
    :cond_b
    iget-object v0, p0, Lcom/snappbox/offering/common/domain/usecase/f;->a:Lxj/c;

    .line 14
    invoke-interface {v0}, Lxj/b;->j()Lkotlinx/coroutines/flow/StateFlow;

    .line 17
    move-result-object v0

    .line 18
    invoke-interface {v0}, Lkotlinx/coroutines/flow/StateFlow;->getValue()Ljava/lang/Object;

    .line 21
    move-result-object v0

    .line 22
    check-cast v0, Ljava/lang/Iterable;

    .line 24
    new-instance v2, Ljava/util/ArrayList;

    .line 26
    invoke-direct {v2}, Ljava/util/ArrayList;->()V

    .line 29
    invoke-interface {v0}, Ljava/lang/Iterable;->iterator()Ljava/util/Iterator;

    .line 32
    move-result-object v0

    .line 33
    :cond_20
    :goto_20
    invoke-interface {v0}, Ljava/util/Iterator;->hasNext()Z

    .line 36
    move-result v3

    .line 37
    if-eqz v3, :cond_32

    .line 39
    invoke-interface {v0}, Ljava/util/Iterator;->next()Ljava/lang/Object;

    .line 42
    move-result-object v3

    .line 43
    instance-of v4, v3, Lyj/d;

    .line 45
    if-eqz v4, :cond_20

    .line 47
    invoke-interface {v2, v3}, Ljava/util/Collection;->add(Ljava/lang/Object;)Z

    .line 50
    goto :goto_20

    .line 51
    :cond_32
    invoke-interface {v2}, Ljava/lang/Iterable;->iterator()Ljava/util/Iterator;

    .line 54
    move-result-object v0

    .line 55
    invoke-interface {v0}, Ljava/util/Iterator;->hasNext()Z

    .line 58
    move-result v2

    .line 59
    if-nez v2, :cond_3e

    .line 61
    const/4 v0, 0x0

    .line 62
    goto :goto_6f

    .line 63
    :cond_3e
    invoke-interface {v0}, Ljava/util/Iterator;->next()Ljava/lang/Object;

    .line 66
    move-result-object v2

    .line 67
    invoke-interface {v0}, Ljava/util/Iterator;->hasNext()Z

    .line 70
    move-result v3

    .line 71
    if-nez v3, :cond_4a

    .line 73
    :goto_48
    move-object v0, v2

    .line 74
    goto :goto_6f

    .line 75
    :cond_4a
    move-object v3, v2

    .line 76
    check-cast v3, Lyj/d;

    .line 78
    invoke-virtual {v3}, Lyj/d;->h()Lcom/snappbox/offering/common/domain/model/OfferPriority;

    .line 81
    move-result-object v3

    .line 82
    invoke-virtual {v3}, Lcom/snappbox/offering/common/domain/model/OfferPriority;->getLevel()I

    .line 85
    move-result v3

    .line 86
    :cond_55
    invoke-interface {v0}, Ljava/util/Iterator;->next()Ljava/lang/Object;

    .line 89
    move-result-object v4

    .line 90
    move-object v5, v4

    .line 91
    check-cast v5, Lyj/d;

    .line 93
    invoke-virtual {v5}, Lyj/d;->h()Lcom/snappbox/offering/common/domain/model/OfferPriority;

    .line 96
    move-result-object v5

    .line 97
    invoke-virtual {v5}, Lcom/snappbox/offering/common/domain/model/OfferPriority;->getLevel()I

    .line 100
    move-result v5

    .line 101
    if-ge v3, v5, :cond_68

    .line 103
    move-object v2, v4

    .line 104
    move v3, v5

    .line 105
    :cond_68
    invoke-interface {v0}, Ljava/util/Iterator;->hasNext()Z

    .line 108
    move-result v4

    .line 109
    if-nez v4, :cond_55

    .line 111
    goto :goto_48

    .line 112
    :goto_6f
    check-cast v0, Lyj/d;

    .line 114
    if-eqz v0, :cond_ad

    .line 116
    invoke-virtual {v0}, Lyj/d;->h()Lcom/snappbox/offering/common/domain/model/OfferPriority;

    .line 119
    move-result-object v2

    .line 120
    invoke-virtual {v2}, Lcom/snappbox/offering/common/domain/model/OfferPriority;->getLevel()I

    .line 123
    move-result v2

    .line 124
    move-object v3, p1

    .line 125
    check-cast v3, Lyj/d;

    .line 127
    invoke-virtual {v3}, Lyj/d;->h()Lcom/snappbox/offering/common/domain/model/OfferPriority;

    .line 130
    move-result-object v4

    .line 131
    invoke-virtual {v4}, Lcom/snappbox/offering/common/domain/model/OfferPriority;->getLevel()I

    .line 134
    move-result v4

    .line 135
    if-ne v2, v4, :cond_94

    .line 137
    invoke-static {p1}, Lyj/c;->d(Lyj/b;)Z

    .line 140
    move-result p1

    .line 141
    if-eqz p1, :cond_ad

    .line 143
    iget-object p1, p0, Lcom/snappbox/offering/common/domain/usecase/f;->b:Lcom/snappbox/offering/common/domain/usecase/g;

    .line 145
    invoke-virtual {p1}, Lcom/snappbox/offering/common/domain/usecase/g;->a()V

    .line 148
    goto :goto_ad

    .line 149
    :cond_94
    invoke-virtual {v0}, Lyj/d;->h()Lcom/snappbox/offering/common/domain/model/OfferPriority;

    .line 152
    move-result-object p1

    .line 153
    invoke-virtual {p1}, Lcom/snappbox/offering/common/domain/model/OfferPriority;->getLevel()I

    .line 156
    move-result p1

    .line 157
    invoke-virtual {v3}, Lyj/d;->h()Lcom/snappbox/offering/common/domain/model/OfferPriority;

    .line 160
    move-result-object v0

    .line 161
    invoke-virtual {v0}, Lcom/snappbox/offering/common/domain/model/OfferPriority;->getLevel()I

    .line 164
    move-result v0

    .line 165
    if-ge p1, v0, :cond_ac

    .line 167
    iget-object p1, p0, Lcom/snappbox/offering/common/domain/usecase/f;->b:Lcom/snappbox/offering/common/domain/usecase/g;

    .line 169
    invoke-virtual {p1}, Lcom/snappbox/offering/common/domain/usecase/g;->a()V

    .line 172
    goto :goto_ad

    .line 173
    :cond_ac
    const/4 v1, 0x0

    .line 174
    :cond_ad
    :goto_ad
    return v1
    .end method

    • Hi. I couldn’t fully understand what you want to do. But as a I can understand, in line 97 there is a getlevel() function, which the result is in v5. You can alter v5 or you can alter the if after it (in line 101).

Leave a Reply

Your email address will not be published. Required fields are marked *