Introduction
Long back I had written about how we can reverse engineer an Android App and learn its code here. But for the longest time, I wanted to try and re-assemble the reverse-engineered APK (obviously for education purposes!) but I never tried or understood it. Finally, one night I sat with a stomach ache trying to reassemble a reverse-engineered APK of a dummy app I wrote, and TLDR; I vomited right after I was able to run the modified APK! :p
To understand if the disassembled app worked with the modified code, I wrote a simple application where a SharedPreference value was responsible for a toast message –
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val setValue = false
val sharedPreferences: SharedPreferences = applicationContext.getSharedPreferences(
"SharedPref", MODE_PRIVATE)
sharedPreferences.edit().putBoolean("hello", setValue).apply()
if (sharedPreferences.getBoolean("hello", false)) {
Toast.makeText(this, "Toast for hello", Toast.LENGTH_LONG).show()
}
}
}
Now that we’ve set this up and generated the APK, our de-assembling process beings.
Disassembling an APK
Disassembling is easier than you thought (if you’ve come here after reading my reverse engineering article, you would already be aware of it).
We’ll use an open-source tool apktool
.
To begin with, we just need to get the latest Jar file from the News
section on the page and download it.
Next, copy the Jar to a directory where you have the APK file and run the below command –java -jar apktool.jar d -r basicapp.apk
This will give us a directory with a lot of things in it but for now, we have to look at the smali_classes
directories.
Smali Files – Smali Files are basically assembly language code which the Android Dalvik Virtual Machine understands and are the executables file for them. The Java/Kotlin code is converted into .DEX file and when we decompile the .DEX file, we get the Smali Files.
There is where our decompiled code is. Now, we just have to search for the package across these directories and see where our activity/fragment/viewmodel or whichever file we are searching for is.
varun:~ varun$ cd Desktop/
varun:Desktop varun$ cd basicapp
varun:basicapp varun$ cd smali_classes3/
varun:smali_classes3 varun$ cd com/example/demoapp/
varun:demoapp varun$ ls
BuildConfig.smali
FirstFragment$$ExternalSyntheticLambda0.smali
FirstFragment.smali
MainActivity.smali
SecondFragment$$ExternalSyntheticLambda0.smali
SecondFragment.smali
varun:demoapp varun$ vim MainActivity.smali
You can open the file in any notepad editor and the above code will look something like this –
invoke-virtual {v0}, Lcom/example/demoapp/databinding/ActivityMainBinding;->getRoot()Landroidx/coordinatorlayout/widget/CoordinatorLayout;
move-result-object v0
check-cast v0, Landroid/view/View;
invoke-virtual {p0, v0}, Lcom/example/demoapp/MainActivity;->setContentView(Landroid/view/View;)V
.line 20
const/4 v0, 0x1
.line 22
.local v0, "setValue":Z
invoke-virtual {p0}, Lcom/example/demoapp/MainActivity;->getApplicationContext()Landroid/content/Context;
move-result-object v1
.line 23
nop
.line 22
const-string v2, "SharedPref"
const/4 v3, 0x1
invoke-virtual {v1, v2, v3}, Landroid/content/Context;->getSharedPreferences(Ljava/lang/String;I)Landroid/content/SharedPreferences;
move-result-object v1
const-string v2, "applicationContext.getSh\u2026haredPref\", MODE_PRIVATE)"
invoke-static {v1, v2}, Lkotlin/jvm/internal/Intrinsics;->checkNotNullExpressionValue(Ljava/lang/Object;Ljava/lang/String;)V
.line 24
.local v1, "sharedPreferences":Landroid/content/SharedPreferences;
invoke-interface {v1}, Landroid/content/SharedPreferences;->edit()Landroid/content/SharedPreferences$Editor;
move-result-object v2
const-string v4, "hello"
invoke-interface {v2, v4, v0}, Landroid/content/SharedPreferences$Editor;->putBoolean(Ljava/lang/String;Z)Landroid/content/SharedPreferences$Editor;
move-result-object v2
invoke-interface {v2}, Landroid/content/SharedPreferences$Editor;->apply()V
.line 25
invoke-interface {v1, v4, v3}, Landroid/content/SharedPreferences;->getBoolean(Ljava/lang/String;Z)Z
move-result v2
if-eqz v2, :cond_1
.line 26
move-object v2, p0
check-cast v2, Landroid/content/Context;
const-string v3, "Toast for hello"
check-cast v3, Ljava/lang/CharSequence;
const/4 v4, 0x1
invoke-static {v2, v3, v4}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v2
invoke-virtual {v2}, Landroid/widget/Toast;->show()V
.line 28
:cond_1
return-void
.end method
Here, we have to look at –
const/4 v3, 0x0
This is basically our ‘val setValue = false
‘
In smali code, false is 0x0, and true is 0x1.
As you would’ve guessed, we have to change this line from 0x0 to 0x1. Which will eventually make setValue true.
After doing that, save the file. That’s it, we’ve modified the code. Now we have to re-assemble the APK.
Reassembling an APK
Now to re-assemble the APK, we will use the same apktool
.
Running the following command gives us an APK –
java -jar apktool.jar b basicapp
We’ll have to sign the APK to install it on our device. To do that, run the following commands –
keytool -genkey -v -keystore my-keystore.keystore -alias name_alias -keyalg RSA -validity 10000
jarsigner -verbose -keystore varun.keystore basicappmodified.apk varun
If you run into the following error –
Failure [-124: Failed parse during installPackageLI: Targeting R+ (version 30 and above) requires the resources.arsc of installed APKs to be stored uncompressed and aligned on a 4-byte boundary]
You’ll have to follow some extra steps and the Convert APK GitHub repository here has a very quick way to fix it. Run their script on your signed APK and it fixes the above warning for you.
Install the APK and see the toast showing up!
References
- https://proandroiddev.com/how-i-hacked-an-android-app-for-a-premium-feature-d9ca74e797ad
- https://www.syssec-project.eu/m/page-media/158/syssec-summer-school-Android-Code-Injection.pdf
The End
And that’s how we can disassemble, read through the code, modify it, and reassemble it! This is just for educational purposes and I am sure none of you would want to use this for any piracy or any such thing.
My next article would be a detailed explanation on different type of security measures we can adopt (and how it can be wore down by a third person).
If you like the article, might as well give it a like below? 😀