Smali - Decompiling/[Modifying]/Compiling
Tip
AWS Hacking सीखें & अभ्यास करें:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking सीखें & अभ्यास करें:HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking सीखें & अभ्यास करें:HackTricks Training Azure Red Team Expert (AzRTE)
assessment tracks (ARTA/GRTA/AzRTA) और Linux Hacking Expert (LHE) के लिए full HackTricks Training catalog ब्राउज़ करें।
HackTricks का समर्थन करें
- subscription plans देखें!
- जुड़ें 💬 Discord group, telegram group, follow करें @hacktricks_live X/Twitter पर, या LinkedIn page और YouTube channel देखें।
- HackTricks](https://github.com/carlospolop/hacktricks) और HackTricks Cloud github repos में PRs सबमिट करके hacking tricks साझा करें।
कभी-कभी यह उपयोगी होता है कि application code को modify करके आपके लिए hidden information तक पहुँच बनाई जाए (शायद अच्छी तरह से obfuscated passwords या flags)। तब, यह रोचक हो सकता है कि आप apk को decompile करें, code को modify करें और उसे recompile करें।
Opcodes संदर्भ: http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html
तेज़ तरीका
Visual Studio Code और APKLab extension का उपयोग करके, आप स्वचालित रूप से decompile, modify, recompile, sign & install कर सकते हैं application को बिना किसी कमांड को execute किए।
Another script जो इस कार्य को काफी आसान बनाता है वह है https://github.com/ax/apk.sh
Split APKs / App Bundles
आधुनिक targets आमतौर पर एक single monolithic APK के बजाय split APKs (base.apk + split_config.*.apk) के रूप में वितरित किए जाते हैं। अगर आप केवल base.apk को patch करते हैं, तो resources या native libraries sync से बाहर हो सकते हैं और installation fail हो सकती है।
डिवाइस से त्वरित triage:
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
यदि लक्ष्य एक split package है, तो या तो पूरे सेट को फिर से बनाएं या ऐसे टूलिंग का उपयोग करें जो पहले APKs को जोड़ता है। apk.sh यहाँ उपयोगी है क्योंकि यह split APKs को एक single patchable APK में combine कर सकता है और public resource identifiers को fix कर सकता है।
Frida/Objection-उन्मुख repacking workflows के लिए, यह भी देखें Android Anti-Instrumentation & SSL Pinning Bypass.
APK को Decompile करें
APKTool का उपयोग करके आप smali code और resources तक पहुँच सकते हैं:
apktool d APP.apk
यदि apktool आपको कोई त्रुटि देता है, तो installing the latest version आज़माएँ
कुछ दिलचस्प फ़ाइलें जिन्हें आपको देखना चाहिए:
- res/values/strings.xml (और res/values/* के अंदर की सभी xmls)
- AndroidManifest.xml
- किसी भी फ़ाइल जिसकी एक्सटेंशन .sqlite या .db हो
यदि apktool को application को decode करने में समस्या हो तो https://ibotpeaches.github.io/Apktool/documentation/#framework-files देखें या argument -r का उपयोग करें (संसाधनों को decode मत करें)। तब, यदि समस्या resource में थी और source code में नहीं, तो आपको यह समस्या नहीं आएगी (आप resources को भी decompile नहीं करेंगे)।
smali कोड बदलें
आप निर्देशों को बदल सकते हैं, कुछ variables का मान बदल सकते हैं या नए निर्देश जोड़ सकते हैं। मैं Smali कोड को VS Code का उपयोग करके बदलता/बदलती हूँ; फिर smalise extension इंस्टॉल करें और editor आपको बताएगा अगर कोई instruction गलत है.
कुछ उदाहरण यहाँ मिल सकते हैं:
या आप check below some Smali changes explained देख सकते हैं।
APK को पुनः कंपाइल करें
कोड में बदलाव करने के बाद आप निम्न का उपयोग करके कोड को पुनः कंपाइल कर सकते हैं:
apktool b . #In the folder generated when you decompiled the application
यह नया APK dist फ़ोल्डर के अंदर compile करेगा।
यदि apktool कोई त्रुटि फेंकता है, तो installing the latest version आज़माएँ
नए APK को साइन करें
फिर, आपको generate a key करना होगा (आपसे पासवर्ड और कुछ जानकारी पूछी जाएगी जिसे आप यादृच्छिक रूप से भर सकते हैं):
keytool -genkey -v -keystore key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias <your-alias>
अंत में, नए APK को sign करें:
jarsigner -keystore key.jks path/to/dist/* <your-alias>
jarsigner अभी भी कुछ त्वरित परीक्षणों के लिए काम करता है, लेकिन आधुनिक Android बिल्ड्स के लिए apksigner को प्राथमिकता दी जाती है क्योंकि यह नए APK सिग्नेचर स्कीमों को संभालता है।
नए एप्लिकेशन का अनुकूलन
zipalign एक आर्काइव अलाइनमेंट टूल है जो Android application (APK) फाइलों के लिए महत्वपूर्ण अनुकूलन प्रदान करता है। More information here.
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
zipalign -v 4 infile.apk
यदि APK में बंडल किए गए native libraries (lib/*.so) शामिल हैं, तो Android अब -P 16 का उपयोग करने की सिफारिश करता है ताकि .so फाइलें 16 KiB और 4 KiB पेज-आकार वाले दोनों डिवाइसों के लिए संरेखित हों:
zipalign -P 16 -f -v 4 infile.apk outfile.apk
नई APK पर साइन करें (फिर से?)
यदि आप apksigner का उपयोग jarsigner के बजाय करना पसंद करते हैं, तो zipaling के साथ optimization लागू करने के बाद आपको apk को साइन करना चाहिए। लेकिन ध्यान दें कि आपको केवल एप्लिकेशन पर एक बार साइन करना होता है jarsigner के साथ (before zipalign) या aspsigner के साथ (after zipaling).
apksigner sign --ks key.jks ./dist/mycompiled.apk
एक अधिक व्यावहारिक आधुनिक प्रवाह है:
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
Important notes:
- यदि आप किसी APK को
apksignerसे साइन करने के बाद परिवर्तित करते हैं, तो signature अमान्य हो जाएगा और आपको इसे फिर से साइन करना होगा। apksigner verify --print-certsपुनर्निर्मित APK के इंस्टॉल योग्य होने की पुष्टि करने और उस certificate का निरीक्षण करने के लिए उपयोगी है जिसे target runtime पर expose करेगा।
Smali में संशोधन
निम्नलिखित Hello World Java code के लिए:
public static void printHelloWorld() {
System.out.println("Hello World")
}
Smali कोड होगा:
.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
The Smali instruction set उपलब्ध है here.
हल्के बदलाव
किसी फ़ंक्शन के अंदर किसी वेरिएबल के प्रारम्भिक मान बदलें
कुछ वेरिएबल फ़ंक्शन की शुरुआत में opcode const का उपयोग करके परिभाषित किए जाते हैं, आप उनके मान बदल सकते हैं, या आप नए वेरिएबल परिभाषित कर सकते हैं:
#Number
const v9, 0xf4240
const/4 v8, 0x1
#Strings
const-string v5, "wins"
बुनियादी संचालन
#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
बड़े बदलाव
Smali में ऐसी जटिलताएँ जो आमतौर पर पुनर्निर्माण को तोड़ देती हैं
- Prefer increasing
.localswhen you only need temporary registers in the body of an existing method. Parameter registers (p0,p1…) are mapped to the highest registers of the method, so switching blindly to.registersoften breaks argument layout. move-result,move-result-wide, andmove-result-objectmust appear immediately after the matchinginvoke-*. Inserting logging or any other opcode between them makes the method invalid.longanddoublevalues are wide values and consume a register pair. If you reuse those registers later, remember thatv10also occupiesv11.- If you need to pass many registers, or very high-numbered ones, use the
/rangevariants such asinvoke-virtual/range.
लॉगिंग
#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:
- यदि आप फ़ंक्शन के अंदर declared variables का उपयोग करने जा रहे हैं (declared v0,v1,v2…) तो ये लाइनें .local
और variables की declarations (const v0, 0x1) के बीच रखें। - यदि आप लॉगिंग कोड को फ़ंक्शन के कोड के बीच में डालना चाहते हैं:
- 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.
सामान्य anti-tamper चेक्स का पैच करना
जब कोई app repack किया जाता है, तो पहली चीज़ों में से एक जो टूट सकती है वह है इन-ऐप signature / installer / integrity check. JADX या smali tree में खोजने के लिए अच्छे strings हैं:
GET_SIGNATURESGET_SIGNING_CERTIFICATESapkContentsSignersMessageDigestSHA-256Base64getInstallerPackageNamecom.android.vending
आधुनिक apps अक्सर PackageManager.getPackageInfo(…, GET_SIGNING_CERTIFICATES) को कॉल करते हैं, signer bytes को MessageDigest से hash करते हैं, और परिणाम की तुलना एक हार्डकोडेड कॉन्स्टेंट से करते हैं। व्यवहार में, पूरे signature-handling code को फिर से लिखने से बेहतर होता है कि आम तौर पर final boolean / branch को पैच किया जाए।
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
यदि सत्यापन कोड noisy है, तो पूरे रूटीन को छेड़ने की बजाय त्रुटि संवाद / finish() / System.exit() / telemetry कॉल से पहले की आखिरी तुलना ढूंढें और वहीं पैच करें।
Toasting
याद रखें कि फ़ंक्शन की शुरुआत में .locals की संख्या में 3 जोड़ें।
यह कोड फ़ंक्शन के बीच में डालने के लिए तैयार है (बदलें आवश्यकता के अनुसार वेरिएबल्स की संख्या)। यह this.o के मान को लेगा, इसे String में परिवर्तित करेगा और फिर उसके मान का एक toast बनाएगा।
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
स्टार्टअप पर Native Library लोड करना (System.loadLibrary)
कभी-कभी आपको एक Native library को preload करना पड़ता है ताकि यह अन्य JNI लाइब्रेरीज़ से पहले initialize हो जाए (उदाहरण के लिए process-local telemetry/logging सक्षम करने के लिए)। आप एक static initializer में या Application.onCreate() के शुरुआती हिस्से में System.loadLibrary() कॉल inject कर सकते हैं। static class 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
वैकल्पिक रूप से, लाइब्रेरी जितनी जल्दी संभव हो लोड होने को सुनिश्चित करने के लिए वही दो निर्देश अपनी Application.onCreate() की शुरुआत में रखें:
.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
नोट:
- सुनिश्चित करें कि लाइब्रेरी का सही ABI वेरिएंट lib/
/ के अंतर्गत मौजूद हो (उदा., arm64-v8a/armeabi-v7a) ताकि UnsatisfiedLinkError से बचा जा सके। - बहुत जल्दी लोड करने से (class static initializer) यह सुनिश्चित होता है कि native logger बाद की JNI activity को देख सके।
Smali Static Analysis / Rule-Based Hunting
apktool से decompiling करने के बाद, आप regex नियमों के साथ Smali को लाइन-दर-लाइन scan Smali line-by-line करके जल्दी से anti-analysis logic (root/emulator checks) और संभावित hardcoded secrets का पता लगा सकते हैं। यह एक fast triage technique है: मिलने वाली hits को ऐसे leads मानें जिन्हें आप आसपास के Smali या reconstruct किए गए Java/Kotlin में verify करें।
Key ideas:
- Library filtering: सामान्य third-party namespaces के अंतर्गत आने वाले findings को suppress या tag करें ताकि आप app-owned code paths पर ध्यान केंद्रित कर सकें।
- Context hints: संदिग्ध strings को उन APIs के पास दिखना आवश्यक करें जो उन्हें consume करती हैं (एक ही method के भीतर, N lines के भीतर)।
- Confidence: सरल स्तरों (high/medium) का उपयोग करके leads को rank करें और false positives घटाएँ।
Example library prefixes to suppress by default:
Landroidx/
Lkotlin/
Lkotlinx/
Lcom/google/
Lcom/squareup/
Lokhttp3/
Lokio/
Lretrofit2/
उदाहरण पहचान नियम (regex + context heuristics):
{
"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."
}
ऐसी अतिरिक्त हीयुरिस्टिक्स जो व्यवहार में अच्छी तरह काम करती हैं:
- Root package/path checks: निकटवर्ती
PackageManager;->getPackageInfoयाFile;->existsकॉल्स की आवश्यकता रखें जब स्ट्रिंग्स जैसेcom.topjohnwu.magiskया/data/local/tmpमौजूद हों। - Emulator checks: संदिग्ध literals (जैसे
ro.kernel.qemu,generic,goldfish) को निकटवर्तीBuild.*getters और string comparisons (->equals,->contains,->startsWith) के साथ जोड़ें। - Hardcoded secrets: केवल तभी
const-stringको flag करें जब निकटवर्ती.fieldयाmove-resultidentifier मेंpassword,token,api_keyजैसे keywords शामिल हों। UI-only markers जैसेAutofillType,InputType,EditorInfoको स्पष्ट रूप से नज़रअंदाज़ करें।
PulseAPK Core जैसे rule-driven scanners इस मॉडल को लागू करते हैं ताकि Smali में anti-analysis logic और संभावित secrets को जल्दी से surface किया जा सके।
संदर्भ
- 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 सीखें & अभ्यास करें:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking सीखें & अभ्यास करें:HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking सीखें & अभ्यास करें:HackTricks Training Azure Red Team Expert (AzRTE)
assessment tracks (ARTA/GRTA/AzRTA) और Linux Hacking Expert (LHE) के लिए full HackTricks Training catalog ब्राउज़ करें।
HackTricks का समर्थन करें
- subscription plans देखें!
- जुड़ें 💬 Discord group, telegram group, follow करें @hacktricks_live X/Twitter पर, या LinkedIn page और YouTube channel देखें।
- HackTricks](https://github.com/carlospolop/hacktricks) और HackTricks Cloud github repos में PRs सबमिट करके hacking tricks साझा करें।


