DexPatcher: Opravte Android APK pomocí Javy

DexPatcher umožňuje vývojářům opravovat soubory APK pomocí Javy. To má několik výhod a použití DexPatcher je mnohem jednodušší než klasický přístup Smali.

Pravděpodobně jste viděli nebo nainstalovali upravené aplikace, ať už jde o opravený dialer pro vaše rozlišení nebo vlastní verzi WhatsApp s přidanými funkcemi. Jak to ale vývojáři dělají? Mnohdy není k dispozici ani zdrojový kód aplikací, tak jak to celé funguje? Nejprve to uvidíme, pak se podíváme na nový nástroj, který má tento proces výrazně usnadnit, a nakonec jej porovnáme s populárním rámcem Xposed, abychom viděli, jak se liší.

Možná jste slyšeli o tom, jak se obvykle upravují soubory APK – vývojáři se do nich zapojují matrix, začněte vidět vše ve Smali a získejte schopnost upravovat věci pomocí síly Zdroj. Po dokončení stačí telefonát, aby je dostali ven, a v tu chvíli jsou připraveni sdílet zbrusu nové soubory APK.

Vážněji... Začněme od začátku. Pokud se nevyznáte v úpravách aplikací pro Android, možná vás zajímá, co je to smali. Vývojáři obvykle používají programovací jazyk Java pro kódování aplikací pro Android. Program (kompilátor) pak „přeloží“ tento kód do jiného formátu vhodného pro vaše zařízení, výsledkem čehož jsou soubory .dex obsažené v balíčku aplikace (nebo APK).

V tomto okamžiku již nemáte přístup k původnímu zdrojovému kódu (pokud nejste vývojář nebo aplikace není open source). Co však máte, je soubor APK, protože je to to, co je nainstalováno ve vašem zařízení. Z něj můžete získat soubory dex (obvykle class.dex) a pokusit se je přeložit zpět do formátu, kterému rozumíte. Tam přichází na řadu smali, jako čtivější, ale věrnější překlad. Můžete jít ještě o krok dále a přeložit jej zpět do Javy, i když tento proces není dostatečně věrný – dostanete pochopitelný výsledek, ale je pravděpodobné, že jej nebudete moci přeložit opačně, protože se ztratí některé detaily při cestě. Jinými slovy, jakékoli úpravy, které provedete, budou k ničemu, protože jej nebudete moci znovu proměnit zpět na soubor APK a nainstalovat jej do svého zařízení… alespoň ne bez velkého úsilí.

smali/baksmali je ve skutečnosti assembler/dissembler pro formát dex -- to je to, co doslova znamená v islandštině. Obvykle však odkazujeme na formát, kterému smali rozumí, když říkáme „Smali“ (považujte to za pokyny definování každého malého detailu, i když to všechno nepotřebujeme my lidé – je tedy podrobnější než Jáva). Všimněte si také, že výše uvedené vysvětlení je trochu zjednodušené, ale mělo by být blízkou analogií a přitom být snadno pochopitelné.

Co by tedy vývojář musel udělat, aby upravil aplikaci (bez přístupu ke zdroji)? Postup je víceméně následující:

  1. Získejte soubor APK (z webu nebo ze zařízení).
  2. Použijte něco jako apktool dekompilovat soubor APK na Smali. (apktool využívá smali/baksmali, ale usnadňuje dekompilaci a přestavbu souborů APK a také se stará o dekódování zdrojů, jako jsou soubory XML.)
  3. Extrahujte class.dex z APK a poté použijte dex2jar a nakonec dekompilátor Java pro získání (neúplného, ​​často nefunkčního, ale většinou srozumitelného) kódu Java. (Toto je volitelné, ale může být užitečné, protože Smali je mnohem obtížnější porozumět.)
  4. Určete, co upravit.
  5. Ve skutečnosti jej upravte přímou úpravou kódu Smali.
  6. Případně zapište modifikaci v Javě, zkompilujte ji, znovu dekompilujte do Smali a poté zkopírujte výsledný kód Smali.
  7. Jakmile je vše u konce, použijte apktool znovu a znovu sestavit soubor APK.
  8. Podepište APK (pro ověření identifikace autora; všechny balíčky musí být podepsány) a nakonec jej nainstalujte.

Psaní kódu Smali je poměrně obtížné a náchylné k chybám. Menší změny lze provést ve Smali, ale přidávání nových funkcí s ním je náročnější. Navíc nebudete mít žádné chyby při kompilaci, takže i překlepy mohou být detekovány pouze za běhu. Rozšiřování a sdílení záplat Smali může být také problematické, protože rozdíly bývají velmi specifické pro konkrétní verzi APK. Ačkoli existují některé nástroje, které usnadňují části procesu popsaného výše (Studio Virtuous Ten přijde na mysl), může to být stále únavné.

DexPatcher od XDA Senior Member Lanchon si klade za cíl tyto problémy vyřešit tím, že celý proces zjednoduší a umožní vývojářům zcela se vyhnout jednání se Smali. Místo toho mohou vývojáři psát záplaty pouze v Javě a nechat DexPatcher zvládnout vše ostatní.

To má hlavní výhodu v tom, že má snadno čitelné a spravovatelné záplatové soubory. Záplatování souborů APK je také obecně pohodlnější. Úplný příklad, jak používat DexPatcher, uvidíme za chvíli, ale zde je nejprve rychlý přehled toho, co nabízí:

  • Open source.
  • Multiplatformní: měl by běžet na Linuxu, Macu a Windows.
  • Opravné soubory: provedené úpravy jsou obsaženy v souborech oprav Java, které můžete nezávisle sdílet.
  • Java: to není Smali.

Získáte také výhodu kontroly chyb při sestavení, takže chyby se objeví na začátku vývojového cyklu. Kompilovaná Java poskytuje svou obvyklou kontrolu času kompilace (s přístupem k původním symbolům APK) a DexPatcher vynucuje kompatibilita zdroje a opravy při záplatování, poskytování užitečných informací a varování, když se zdá, že něco děláte legální, ale rybí.

Kromě toho DexPatcher přichází se sadou pomocné skripty (k dispozici pouze na Linuxu, i když mohou být přeneseny i na jiné platformy). Ty se starají o nastavení pracovního prostoru, extrahování tříd a prostředků cílového APK, dekompilaci tříd do Javy (tzv. CFR Java dekompilátor se používá pro druhé) a nakonec sestavení a podepsání opraveného souboru APK, jakmile budete hotovi.

Podívejme se na příklad (na Linuxu):

Nainstalujte skripty DexPatcher

$# Make a directory where we can test stuff out and enter it. 

$ mkdir xda-test

$cd xda-test

$ git clone https://github.com/Lanchon/DexPatcher-scripts.git dexpatcher # Clone the DexPatcher helper scripts repo.

$cd dexpatcher

$ chmod +x dxp-* # Not necessary, but for clarity: we need to make sure the files we'll call later are executable.

Nakonfigurujte skripty DexPatcher

OTEVŘENO dxp.config ve svém oblíbeném textovém editoru a nezapomeňte změnit potřebné proměnné tak, aby vyhovovaly vašemu systému. Stačí změnit následující řádek tak, aby místo toho ukazoval na umístění instalace sady Android SDK:

dxp_android_sdk_dir=(~/android/sdk)

(DexPatcher automaticky vybere nejvyšší dostupnou verzi platformy. Kromě toho můžete také upravit další možnosti konfigurace tak, aby používala vaše vlastní verze některých nástrojů namísto výchozích nastavení v balíčku.)

Pro snadný přístup můžeme přidat výpravčí adresář do našeho CESTA, nebo dokonce symbolicky propojit různé dxp-* skripty do umístění, které je již ve vašem CESTA, jako ~/bin:

export PATH=$PWD:$PATH

Upravte aplikaci

Pro tento příklad použijeme jednoduchou a open source aplikaci. Samozřejmě, že v tomto konkrétním případě by bylo možné opravit zdrojový kód přímo, ale to není vůbec žádná legrace!

Vezmeme si aplikaci „Get ID“ od basil2style, aplikaci, která vám ukáže některé podrobnosti o vašem zařízení. Naším cílem je upravit tlačítko „Kopírovat“ pro „ID zařízení“ a nechat je sdílet toto ID:

  • Nejprve si stáhněte soubor APK, který se chystáme upravit: Získejte ID.
  • Dekompilujte aplikaci.
  • Vytvořte podpisový klíč, který později použijeme k podepsání souboru APK.

Můžeme to také udělat přes shell pomocí pomocných skriptů:

$cd dexpatcher # Go to our working directory. 

$ curl -O https://f-droid.org/repo/makeinfo.com.getid_1.apk # Download the APK.

$ dxp-setup-for-apk makeinfo.com.getid_1.apk # Unpack and decompile the APK.

$cd makeinfo.com.getid_1 # Go to the newly created directory where everything is unpacked/decompiled to.

$ dxp-create-keystore # Create the APK signing key. Press 6 times (or fill out the info), then "yes".

Všimnete si tam několika různých adresářů:

  • dekódovat: zde najdete zdroje a Smali, jak je dekóduje apktool.
  • src: Prázdný adresář. Zde umístíme naše záplatové soubory.
  • src-cfr: to je kde srov dekompiloval aplikaci (spolu s chybami). Dobré místo, kam se můžete podívat, abyste se rozhodli, co změnit (můžete také potřebovat zdroje a jejich ID z výše uvedeného dekódovacího adresáře, ale ne pro tento konkrétní příklad).
  • src-cfr-nodecode: stejné jako výše, ale obsahuje pouze prázdné útržky (žádný kód, jen kostry). Tyto soubory můžete použít jako základ pro váš patch, jak uvidíme za chvíli.

Jak jsme již zmínili, chceme změnit tlačítko Device ID "Kopírovat", aby místo toho sdílelo text ID. Pokud se podíváme po zdrojovém kódu, všimneme si, že tlačítko Kopírovat ID zařízení (kopie_zařízení) při kliknutí událost zpracovává anonymní třída src-cfr/makeinfo/com/getid/MainActivity.java. I když bychom to mohli upravit zde, je obvykle lepší najít alternativní způsob, jak to udělat, protože anonymní třídy mají číselná jména (MainClassName$SomeNumber, např. Hlavní aktivita 3 $), které se mohou mezi verzemi nepředvídatelně měnit.

Místo toho zaregistrujeme vlastní třídu pro událost úpravou Hlavní aktivita třída. Nejprve zkopírujeme verzi „kostra“. src-cfr-nocode/makeinfo/com/getid/MainActivity.java na src/makeinfo/com/getid/MainActivity.java (Pamatuj si to src je místo, kde bude žít náš patch). (Můžete také zkopírovat verzi s úplným kódem, pokud chcete, je to čistě věc vkusu.)

Nyní jej můžeme upravit následovně:

  • Přidejte potřebný import pro anotaci DexPatcher:
importlanchon.dexpatcher.annotation.*;
  • Přidejte značku označující, že třídu upravujeme. Také jsme nastavili výchozí akci pro členy třídy záplat na IGNOROVAT, což znamená, že členové jsou tam, aby na ně odkazoval náš kód během kompilace Java, ale DexPatcher je bude ignorovat.
@DexEdit(defaultAction=DexAction.IGNORE)

publicclassMainActivity

// The reference to ActionBarActivity will be satisfied by symbols

// extracted from the app when we build the patch.

extendsActionBarActivity{

  • Navíc přidejte prázdná těla do konstruktoru a onCreate metodu, stejně jako všechny ostatní metody, které plánujeme použít (nezapomeňte, že budou ignorovány, až bude náš patch skutečně aplikován - pouze je přidáváme, abychom je zde mohli v případě potřeby odkázat). Můžete také jen přidat rodák místo toho klíčové slovo.
  • V tuto chvíli již můžeme vytvořit opravu, pokud jste zvědaví:
    $ dxp-make # Output: `patched.apk`.
    Docela jednoduché, že? Pokračujme, ale stále ještě nekončíme.
  • Pojďme upravit onCreate nyní se vydat vlastní OnClickListener abychom mohli sdílet ID zařízení namísto kopírování do schránky:
    // Rename the target method so that we can still call it (the original)// if needed.@DexEdit(target="onCreate")protectedvoidsource_onCreate(Bundlevar1){}// Add our new custom method.@Override@DexAddprotectedvoidonCreate(Bundlevar1){// Call the original method:source_onCreate(var1);// Replace the text and handler:device_copy.setText("Share");device_copy.setOnClickListener(newDeviceCopyOnClick());}// Note that we don't use an anonymous class to avoid nameclashing with// MainActivity$1, which already exists.// We also could've defined a nested MainActivity.Patch class and used// an anonymous class in MainActivity.Patch.onCreate(), and then called// MainActivity.Patch.onCreate() from MainActivity.onCreate().@DexAddclassDeviceCopyOnClickimplementsView.OnClickListener{@OverridepublicvoidonClick(Viewobject){if(MainActivity.this.val){Intentintent=newIntent(Intent.ACTION_SEND);intent.setType("text/plain");intent.putExtra(Intent.EXTRA_SUBJECT,"Device ID");intent.putExtra(Intent.EXTRA_TEXT,device.getText().toString());startActivity(Intent.createChooser(intent,"Share Device ID"));}else{Toast.makeText(MainActivity.this.getApplicationContext(),"Nothing to Share",0).show();}}}
  • Vypadá to, že jsme teď hotovi! Úplný patch by měl vypadat tento. Nyní můžeme sestavit opravený APK a nainstalovat jej:
    $ dxp-make$ adb install patched.apk
  • Pojďme se podívat na výsledek:

(Děkujeme Lanchonovi za pomoc s ukázkovým kódem!)

Xposed je nesmírně populární a má to dobrý důvod – vývojářům i uživatelům výrazně zjednodušuje vytváření, sdílení a instalaci modů. Mezi DexPatcher a Xposed existuje několik rozdílů, kvůli kterým mohou někteří preferovat jeden před druhým:

  1. Xposed dělá svá kouzla tím, že připojí metody za běhu a umožní vývojářům udělat něco před, po nebo místo jakékoli metody. Na druhou stranu DexPatcher upravuje vše před runtime a vytváří samostatný upravený APK -- spouštění kódu před, po nebo místo metod je stále možné a ve skutečnosti máte něco navíc svoboda.
  2. Vytvoření samostatného souboru APK znamená, že nezávisí na žádném externím rámci. To také znamená, že pro úpravy uživatelských aplikací není vyžadován root.
  3. Protože jste vytvořili nový soubor APK pomocí DexPatcher, bude podepsán jinak. To znamená, že uživatelé nemohou přijímat oficiální aktualizace od původního autora a mohou způsobit problémy s aplikacemi, jako je Google Apps, pokud jsou podpisy kontrolovány.
  4. Zdrojový kód modulů i oprav DexPatcher lze snadno distribuovat a upravovat. Mají také mnoho podobností, pokud se s každým trochu seznámíte.

O DexPatcher jsme toho mluvili dost. Teď je řada na vás, abyste to zkusili, takže zamiřte do Téma fóra DexPatcher abyste mohli začít hned!