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:
- Decompile APK to Smali Code
- Find the right place to inject the code
- Use safe (or unsafe) local variables to inject
- Recompile the Smali Code to APK
- Generate Signature Key
- 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:
- Use smali code instructions. You can use this link for more details.
- 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. 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.
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
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.
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.
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
Hi. As I understand, you want to log some data in some place. You can use this tool to convert your java code into smali: https://github.com/izgzhen/java2smali or java2smali plugin for intellij (https://plugins.jetbrains.com/plugin/7385-java2smali).
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).