Smali - Decompiling/[Modifying]/Compiling
Tip
AWS Hacking öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking öğrenin ve pratik yapın:HackTricks Training Azure Red Team Expert (AzRTE)
Değerlendirme yolları (ARTA/GRTA/AzRTA) ve Linux Hacking Expert (LHE) için tam HackTricks Training kataloğuna göz atın.
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna, telegram grubuna katılın, X/Twitter üzerinde @hacktricks_live hesabını takip edin veya LinkedIn sayfasını ve YouTube kanalını kontrol edin.
- HackTricks ve HackTricks Cloud github depolarına PR göndererek hacking tricks paylaşın.
Bazen uygulama kodunu, sizin için gizli bilgilere erişmek amacıyla (ör. iyi obfusk edilmiş parolalar veya flags) değiştirmek ilginç olabilir. Bu durumda apk’yı decompile edip kodu değiştirip yeniden derlemek ilginç olur.
Opcodes reference: http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html
Fast Way
Visual Studio Code ve APKLab eklentisini kullanarak, herhangi bir komut çalıştırmadan uygulamayı otomatik olarak decompile edebilir, kodu değiştirebilir, yeniden derleyip, imzalayıp yükleyebilirsiniz.
Another script that facilitates this task a lot is https://github.com/ax/apk.sh
Split APKs / App Bundles
Güncel hedefler genellikle tek bir monolitik APK yerine split APKs (base.apk + split_config.*.apk) şeklinde dağıtılır. Yalnızca base.apk’yi yama yaparsanız, kaynaklar veya native kütüphaneler senkron dışı kalabilir ve kurulum başarısız olabilir.
Quick triage from a device:
adb shell pm path com.example.app
adb pull /data/app/.../base.apk
adb pull /data/app/.../split_config.arm64_v8a.apk
adb pull /data/app/.../split_config.en.apk
Hedef bir split package ise, ya tüm seti yeniden derleyin ya da önce APK’ları birleştiren araçları kullanın. apk.sh burada kullanışlıdır çünkü split APK’ları tek bir patchable APK’ye birleştirip public resource identifiers’ı düzeltebilir.
Frida/Objection-oriented repacking workflows için ayrıca Android Anti-Instrumentation & SSL Pinning Bypass sayfasına bakın.
APK’yi decompile et
APKTool kullanarak smali code and resources’a erişebilirsiniz:
apktool d APP.apk
Eğer apktool herhangi bir hata verirse, installing the latest version yüklemeyi deneyin
Some interesting files you should look are:
- res/values/strings.xml (and all xmls inside res/values/*)
- AndroidManifest.xml
- Any file with extension .sqlite or .db
If apktool has problems decoding the application take a look to https://ibotpeaches.github.io/Apktool/documentation/#framework-files or try using the argument -r (Do not decode resources). Then, if the problem was in a resource and not in the source code, you won’t have the problem (you won’t also decompile the resources).
Smali kodunu değiştirin
Bazı talimatları değiştirebilir, bazı değişkenlerin değerini değiştirebilir veya yeni talimatlar ekleyebilirsiniz. Ben Smali kodunu VS Code ile değiştiriyorum, ardından smalise extension’ı kuruyorsunuz ve editör herhangi bir talimatın yanlış olduğunu söyleyecektir.
Bazı örnekler şu adreste bulunabilir:
Veya check below some Smali changes explained.
APK’ı yeniden derleyin
Kodu değiştirdikten sonra yeniden derleyebilirsiniz kullanarak:
apktool b . #In the folder generated when you decompiled the application
Yeni APK’yı dist klasörünün içinde derleyecek.
Eğer apktool bir hata verirse, deneyin installing the latest version
Yeni APK’yı imzala
Sonra, bir anahtar oluşturmanız gerekiyor (size bir parola ve rastgele doldurabileceğiniz bazı bilgiler sorulacak):
keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias <your-alias>
Son olarak, yeni APK’yı imzala:
jarsigner -keystore key.jks path/to/dist/* <your-alias>
jarsigner hala bazı hızlı testler için çalışır, ancak modern Android derlemeleri için apksigner tercih edilir çünkü daha yeni APK imzalama şemalarını destekler.
Yeni uygulamayı optimize edin
zipalign bir arşiv hizalama aracıdır ve Android uygulama (APK) dosyalarına önemli optimizasyon sağlar. More information here.
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
zipalign -v 4 infile.apk
APK, gömülü native kütüphaneler (lib/*.so) içeriyorsa, Android artık -P 16 kullanmayı önerir; böylece .so dosyaları hem 16 KiB hem de 4 KiB sayfa boyutuna sahip cihazlar için hizalanmış olur:
zipalign -P 16 -f -v 4 infile.apk outfile.apk
Yeni APK’yı İmzala (yine mi?)
Eğer jarsigner yerine apksigner kullanmayı tercih ediyorsanız, zipaling ile yapılan optimizasyonu uyguladıktan sonra apk’yı imzalamalısınız. ANCAK DİKKAT: UYGULAMAYI SADECE BİR KEZ İMZALAMANIZ YETERLİDİR — jarsigner ile (zipalign’dan önce) veya aspsigner ile (zipaling’den sonra).
apksigner sign --ks key.jks ./dist/mycompiled.apk
Daha pratik, modern bir akış şöyledir:
apktool b . -o dist/app-unsigned.apk
zipalign -P 16 -f -v 4 dist/app-unsigned.apk dist/app-aligned.apk
apksigner sign --ks key.jks --out dist/app-signed.apk dist/app-aligned.apk
apksigner verify --verbose --print-certs dist/app-signed.apk
Önemli notlar:
- Eğer bir APK’yi
apksignerile imzaladıktan sonra değiştirirseniz, imza geçersiz hale gelir ve yeniden imzalamanız gerekir. apksigner verify --print-certsyeniden oluşturulmuş APK’nin yüklenebilir olduğunu doğrulamak ve hedefin çalışma zamanında sunacağı sertifikayı incelemek için faydalıdır.
Smali’yi Değiştirme
Aşağıdaki Hello World Java kodu için:
public static void printHelloWorld() {
System.out.println("Hello World")
}
Smali kodu şöyle olur:
.method public static printHelloWorld()V
.registers 2
sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
const-string v1, "Hello World"
invoke-virtual {v0,v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
return-void
.end method
Smali komut seti here.
Hafif Değişiklikler
Bir fonksiyon içindeki bir değişkenin başlangıç değerlerini değiştirin
Bazı değişkenler fonksiyonun başında opcode const kullanılarak tanımlanır, bu değerleri değiştirebilir veya yeni değişkenler tanımlayabilirsiniz:
#Number
const v9, 0xf4240
const/4 v8, 0x1
#Strings
const-string v5, "wins"
Temel İşlemler
#Math
add-int/lit8 v0, v2, 0x1 #v2 + 0x1 and save it in v0
mul-int v0,v2,0x2 #v2*0x2 and save in v0
#Move the value of one object into another
move v1,v2
#Condtions
if-ge #Greater or equals
if-le #Less or equals
if-eq #Equals
#Get/Save attributes of an object
iget v0, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I #Save this.o inside v0
iput v0, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I #Save v0 inside this.o
#goto
:goto_6 #Declare this where you want to start a loop
if-ne v0, v9, :goto_6 #If not equals, go to: :goto_6
goto :goto_6 #Always go to: :goto_6
Daha Büyük Değişiklikler
Smali’nin genellikle yeniden derlemeleri bozan tuzakları
- Mevcut bir metodun gövdesinde yalnızca geçici register’lara ihtiyacınız olduğunda
.locals’u artırmayı tercih edin. Parametre register’ları (p0,p1…) metodun en yüksek register’larına eşlenir, bu yüzden körü körüne.registers’a geçmek sıklıkla argüman düzenini bozar. move-result,move-result-wide, vemove-result-objecteşleşeninvoke-*’ten hemen sonra görünmelidir. Aralarına loglama veya başka herhangi bir opcode eklemek metodu geçersiz kılar.longvedoubledeğerler wide değerlerdir ve bir register çifti tüketir. Bu register’ları daha sonra tekrar kullanırsanız,v10’un aynı zamandav11’i de işgal ettiğini unutmayın.- Eğer çok sayıda register geçirmeniz gerekiyorsa veya çok yüksek numaralı olanları kullanmanız gerekiyorsa,
invoke-virtual/rangegibi/rangevaryantlarını kullanın.
Loglama
#Log win: <number>
iget v5, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I #Get this.o inside v5
invoke-static {v5}, Ljava/lang/String;->valueOf(I)Ljava/lang/String; #Transform number to String
move-result-object v1 #Move to v1
const-string v5, "wins" #Save "win" inside v5
invoke-static {v5, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I #Logging "Wins: <num>"
Recommendations:
- If you are going to use declared variables inside the function (declared v0,v1,v2…) put these lines between the .local
and the declarations of the variables (const v0, 0x1) - If you want to put the logging code in the middle of the code of a function:
- Add 2 to the number of declared variables: Ex: from .locals 10 to .locals 12
- The new variables should be the next numbers of the already declared variables (in this example should be v10 and v11, remember that it starts in v0).
- Change the code of the logging function and use v10 and v11 instead of v5 and v1.
Yaygın anti-tamper kontrollerinin düzeltilmesi
Bir uygulama yeniden paketlendiğinde, bozulabilecek ilk şeylerden biri uygulama içi signature / installer / integrity kontrolü olabilir. JADX’de veya smali ağacında aranacak iyi stringler şunlardır:
GET_SIGNATURESGET_SIGNING_CERTIFICATESapkContentsSignersMessageDigestSHA-256Base64getInstallerPackageNamecom.android.vending
Modern uygulamalar genellikle PackageManager.getPackageInfo(..., GET_SIGNING_CERTIFICATES) çağırır, signer baytlarını MessageDigest ile hash’ler ve sonucu sabit bir değerle karşılaştırır. Pratikte, tüm imza işleme kodunu yeniden yazmaktansa final boolean / branch’i yamamak genellikle daha kolaydır.
Example patterns:
# Force a boolean result to "valid"
const/4 v0, 0x1
# Or invert the branch that sends execution to the tamper handler
if-eqz v0, :tamper_detected # original
if-nez v0, :tamper_detected # patched
Doğrulama kodu gereksiz yere gürültülüyse, tüm rutini değiştirmek yerine hata diyaloğu / finish() / System.exit() / telemetri çağrısından önceki son karşılaştırmayı bulun ve oraya patch uygulayın.
Toast Gösterme
Fonksiyonun başındaki .locals sayısına 3 eklemeyi unutmayın.
Bu kod, bir fonksiyonun ortasına eklenmek üzere hazırlanmıştır (gerekirse değişken sayısını değiştirin). Bu kod this.o değerini alacak, String’e dönüştürecek ve sonra değeriyle bir toast yapacaktır.
const/4 v10, 0x1
const/4 v11, 0x1
const/4 v12, 0x1
iget v10, p0, Lcom/google/ctf/shallweplayagame/GameActivity;->o:I
invoke-static {v10}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;
move-result-object v11
invoke-static {p0, v11, v12}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v12
invoke-virtual {v12}, Landroid/widget/Toast;->show()V
Başlangıçta Yerel Bir Kütüphaneyi Yükleme (System.loadLibrary)
Bazen bir native kütüphaneyi önceden yüklemeniz gerekebilir, böylece diğer JNI kütüphanelerinden önce başlatılır (ör. işlem düzeyinde telemetry/logging’i etkinleştirmek için).
System.loadLibrary() çağrısını bir static initializer içinde veya Application.onCreate()’de erken bir noktaya enjekte edebilirsiniz. Örnek smali, bir static sınıf initializer’ı (
.class public Lcom/example/App;
.super Landroid/app/Application;
.method static constructor <clinit>()V
.registers 1
const-string v0, "sotap" # library name without lib...so prefix
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
return-void
.end method
Alternatif olarak, kütüphanenin mümkün olduğunca erken yüklenmesini sağlamak için aynı iki talimatı Application.onCreate() metodunuzun başına yerleştirin:
.method public onCreate()V
.locals 1
const-string v0, "sotap"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
invoke-super {p0}, Landroid/app/Application;->onCreate()V
return-void
.end method
Notlar:
- Doğru ABI varyantının lib/
/ altında (ör. arm64-v8a/armeabi-v7a) bulunduğundan emin olun; aksi halde UnsatisfiedLinkError oluşabilir. - Çok erken yükleme (class static initializer), native logger’ın sonraki JNI etkinliğini gözlemlemesini garanti eder.
Smali Statik Analiz / Kural-Tabanlı Av
apktool ile decompile ettikten sonra, Smali’yi satır satır taramak için regex kurallarını kullanarak anti-analysis mantığını (root/emulator kontrolleri) ve muhtemel hardcoded secret’leri hızlıca tespit edebilirsiniz. Bu bir hızlı ön eleme tekniğidir: bulunan sonuçları çevresindeki Smali veya yeniden yapılandırılmış Java/Kotlin içinde doğramanız gereken ipuçları olarak ele alın.
Temel fikirler:
- Library filtering: ortak üçüncü taraf namespace’leri altındaki bulguları bastırın veya etiketleyin, böylece uygulamaya ait kod yollarına odaklanırsınız.
- Context hints: şüpheli dizelerin bunları kullanan API’lerin yakınında (aynı method içinde, N satır içinde) görünmesini şart koşun.
- Confidence: bulguları sıralamak ve false positive’leri azaltmak için basit seviyeler (high/medium) kullanın.
Varsayılan olarak bastırılacak örnek kütüphane önekleri:
Landroidx/
Lkotlin/
Lkotlinx/
Lcom/google/
Lcom/squareup/
Lokhttp3/
Lokio/
Lretrofit2/
Örnek tespit kuralları (regex + bağlam heuristikleri):
{
"category": "root_check",
"regex_patterns": [
"(?i)invoke-static .*Runtime;->getRuntime\\(\\).*->exec\\(.*\\"(su|magisk|busybox)\\"",
"(?i)const-string [vp0-9, ]+\\"(/system/xbin/su|/system/bin/su|/sbin/su)\\""
],
"context_hint": "Only report when the same method also calls File;->exists/canExecute or Runtime;->exec."
}
Uygulamada iyi işleyen ek heuristikler:
- Root package/path checks: yakınlarda
PackageManager;->getPackageInfoveyaFile;->existsçağrıları olması gerektiğini kontrol edin; örneğincom.topjohnwu.magiskveya/data/local/tmpgibi dizeler için. - Emulator checks: şüpheli literal dizeleri (ör.
ro.kernel.qemu,generic,goldfish) yakınlardakiBuild.*getter’ları ve string karşılaştırmaları (->equals,->contains,->startsWith) ile eşleştirin. - Hardcoded secrets:
const-stringyalnızca yakınlarda.fieldveyamove-resultidentifier’ıpassword,token,api_keygibi anahtar kelimeleri içeriyorsa işaretleyin.AutofillType,InputType,EditorInfogibi yalnızca UI ile ilgili işaretleri açıkça görmezden gelin.
PulseAPK Core gibi kural tabanlı tarayıcılar bu modeli uygulayarak Smali’de analiz önleyici (anti-analysis) mantığını ve potansiyel sırları hızla ortaya çıkarır.
References
- PulseAPK Core
- PulseAPK Smali Detection Rules
- SoTap: Lightweight in-app JNI (.so) behavior logger – github.com/RezaArbabBot/SoTap
- Android Developers: apksigner and zipalign
- apk.sh: github.com/ax/apk.sh
Tip
AWS Hacking öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking öğrenin ve pratik yapın:HackTricks Training Azure Red Team Expert (AzRTE)
Değerlendirme yolları (ARTA/GRTA/AzRTA) ve Linux Hacking Expert (LHE) için tam HackTricks Training kataloğuna göz atın.
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna, telegram grubuna katılın, X/Twitter üzerinde @hacktricks_live hesabını takip edin veya LinkedIn sayfasını ve YouTube kanalını kontrol edin.
- HackTricks ve HackTricks Cloud github depolarına PR göndererek hacking tricks paylaşın.


