DexPatcher: Opravte Android APK pomocou Java

DexPatcher umožňuje vývojárom opravovať súbory APK pomocou jazyka Java. To má niekoľko výhod a používanie DexPatcher je oveľa jednoduchšie ako klasický Smali prístup.

Pravdepodobne ste už videli alebo si nainštalovali upravené aplikácie, či už ide o opravený dialer pre vaše rozlíšenie alebo vlastnú verziu WhatsApp s pridanými funkciami. Ako to však vývojári robia? Veľa času nie je dostupný ani zdrojový kód aplikácií, tak ako to celé funguje? Najprv to uvidíme, potom sa pozrieme na nový nástroj, ktorého cieľom je značne zjednodušiť tento proces, a nakoniec ho porovnáme s populárnym rámcom Xposed, aby sme zistili, ako sa líšia.

Možno ste už počuli o tom, ako sa zvyčajne upravujú súbory APK – vývojári sa k nim pripájajú matrix, začnite vidieť všetko v Smali a získajte schopnosť upravovať veci pomocou sily Zdroj. Stačí zavolať, aby ste ich dostali von, keď to bude hotové, a vtedy sú pripravení zdieľať nablýskané nové súbory APK.

Vážnejšie... Začnime od začiatku. Ak sa nevyznáte v úpravách aplikácií pre Android, možno sa pýtate, čo je to smali. Vývojári zvyčajne používajú programovací jazyk Java na kódovanie aplikácií pre Android. Program (kompilátor) potom „preloží“ tento kód do iného formátu vhodného pre vaše zariadenie, výsledkom čoho sú súbory .dex obsiahnuté v balíku aplikácie (alebo APK).

V tom momente už nemáte prístup k pôvodnému zdrojovému kódu (pokiaľ nie ste vývojár alebo aplikácia nie je open source). Čo však máte, je súbor APK, pretože je to to, čo je nainštalované vo vašom zariadení. Z neho môžete získať súbory dex (zvyčajne class.dex) a potom sa pokúsiť preložiť ho späť do formátu, ktorému rozumiete. Tu nastupuje smali, ako čitateľnejší, no vernejší preklad. Môžete ísť ešte o krok ďalej a preložiť ho späť do Javy, aj keď tento proces nie je dostatočne verný – dostanete pochopiteľný výsledok, ale je pravdepodobné, že ho už nebudete môcť preložiť naopak, pretože sa stratia niektoré detaily pozdĺž cesty. Inými slovami, akékoľvek úpravy, ktoré vykonáte, budú zbytočné, pretože ho nebudete môcť znova premeniť späť na súbor APK, aby ste ho nainštalovali do svojho zariadenia... aspoň nie bez veľkého úsilia.

smali/baksmali je vlastne assembler/dissembler pre formát dex -- to je to, čo to doslova znamená v islandčine. Keď povieme „Smali“, zvyčajne sa odvolávame na formát, ktorému smali rozumie (myslite na to ako na pokyny definovanie každého malého detailu, aj keď to nie je všetko potrebné pre nás ľudí – je preto podrobnejší ako Java). Všimnite si tiež, že vyššie uvedené vysvetlenie je trochu zjednodušené, ale malo by to byť blízka analógia a zároveň byť ľahko pochopiteľné.

Čo by potom vývojár musel urobiť, aby upravil aplikáciu (bez prístupu k zdroju)? Postup je viac-menej nasledovný:

  1. Získajte súbor APK (z webu alebo zo zariadenia).
  2. Použite niečo ako apktool dekompilovať súbor APK na Smali. (apktool využíva smali/baksmali, ale výrazne uľahčuje dekompiláciu a prestavbu súborov APK a stará sa aj o dekódovanie zdrojov, ako sú súbory XML.)
  3. Extrahujte class.dex zo súboru APK a potom použite dex2jar a nakoniec dekompilátor Java na získanie (neúplného, ​​často nefunkčného, ​​ale väčšinou zrozumiteľného) kódu Java. (Je to voliteľné, ale môže byť užitočné, pretože Smali je oveľa ťažšie pochopiteľné.)
  4. Identifikujte, čo zmeniť.
  5. V skutočnosti ho upravte priamou úpravou kódu Smali.
  6. Prípadne napíšte modifikáciu v jazyku Java, skompilujte ju, znova ju dekompilujte do Smali a potom skopírujte výsledný kód Smali.
  7. Keď všetko skončí, použite apktool znova na prebudovanie súboru APK.
  8. Podpíšte súbor APK (na overenie identifikácie autora; všetky balíky musia byť podpísané) a nakoniec ho nainštalujte.

Písanie Smali kódu je dosť ťažké a náchylné na chyby. V Smali je možné vykonať menšie zmeny, no pridávanie nových funkcií s ním je náročnejšie. Okrem toho nebudete mať žiadne chyby v čase kompilácie, takže aj preklepy môžu byť zistené iba za behu. Rozširovanie a zdieľanie záplat Smali môže byť tiež problematické, pretože rozdiely bývajú veľmi špecifické pre konkrétnu verziu APK. Hoci existujú niektoré nástroje na uľahčenie častí procesu vysvetleného vyššie (Štúdio Virtuous Ten príde na myseľ), stále to môže byť únavné.

DexPatcher od XDA Senior Member Lanchon má za cieľ vyriešiť tieto problémy tým, že proces zjednoduší a umožní vývojárom úplne sa vyhnúť riešeniu Smali. Namiesto toho môžu vývojári písať záplaty v samotnej Jave a nechať DexPatcher zvládnuť všetko ostatné.

To má hlavnú výhodu v ľahko čitateľných a spravovateľných záplatových súboroch. Oprava súborov APK je tiež vo všeobecnosti pohodlnejšia. O chvíľu uvidíme úplný príklad, ako používať DexPatcher, ale tu je najprv rýchly prehľad toho, čo ponúka:

  • Open source.
  • Viacplatformový: mal by bežať na systémoch Linux, Mac a Windows.
  • Opravné súbory: vykonané úpravy sú obsiahnuté v opravných súboroch Java, ktoré môžete nezávisle zdieľať.
  • Java: to nie je Smali.

Získate tiež výhodu kontroly chýb počas zostavovania, takže chyby sa objavia na začiatku vývojového cyklu. Kompilovaná Java poskytuje svoju obvyklú kontrolu času kompilácie (s prístupom k pôvodným symbolom APK) a DexPatcher vynucuje kompatibilita zdroja a opravy pri oprave, poskytovanie užitočných informácií a varovanie, keď sa zdá, že niečo robíte legálne, ale rybie.

Okrem toho DexPatcher prichádza so sadou pomocné skripty (dostupné iba v systéme Linux, aj keď môžu byť prenesené aj na iné platformy). Tie sa starajú o nastavenie pracovného priestoru, extrahovanie tried a zdrojov cieľového súboru APK, dekompiláciu tried do jazyka Java (tzv. CFR Java dekompilátor sa používa pre druhý) a nakoniec zostavenie a podpísanie opraveného súboru APK, keď skončíte.

Pozrime sa na príklad (v systéme Linux):

Nainštalujte 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

OTVORENÉ dxp.config vo svojom obľúbenom textovom editore a nezabudnite zmeniť potrebné premenné tak, aby vyhovovali vášmu systému. Stačí zmeniť nasledujúci riadok tak, aby namiesto toho ukazoval na miesto inštalácie vašej súpravy Android SDK:

dxp_android_sdk_dir=(~/android/sdk)

(DexPatcher automaticky vyberie najvyššiu dostupnú verziu platformy. Okrem toho môžete upraviť aj ďalšie možnosti konfigurácie, aby používala vaše vlastné verzie niektorých nástrojov namiesto predvolených nastavení balíka.)

Pre uľahčenie prístupu môžeme pridať výpravca adresár do nášho PATH, alebo dokonca symbolicky prepojiť rôzne dxp-* skripty do umiestnenia, ktoré sa už nachádza vo vašom PATH, ako napr ~/bin:

export PATH=$PWD:$PATH

Upravte aplikáciu

V tomto príklade použijeme jednoduchú a open source aplikáciu. Samozrejme, v tomto konkrétnom prípade by bola možná oprava zdrojového kódu priamo, ale to nie je žiadna sranda!

Vezmeme si aplikáciu „Get ID“ od basil2style, aplikáciu, ktorá vám ukáže niektoré podrobnosti o vašom zariadení. Naším cieľom je upraviť tlačidlo „Kopírovať“ pre „ID zariadenia“ a nechať ho zdieľať toto ID:

  • Najprv si stiahneme súbor APK, ktorý sa chystáme upraviť: Získajte ID.
  • Dekompilujte aplikáciu.
  • Vytvorte podpisový kľúč, ktorý neskôr použijeme na podpísanie súboru APK.

Môžeme to urobiť aj cez shell pomocou pomocných skriptov:

$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 niekoľko rôznych adresárov:

  • dekódovať: zdroje a Smali nájdete tu, ako ich dekódoval apktool.
  • src: Prázdny adresár. Tu umiestnime naše opravné súbory.
  • src-cfr: toto je kde cfr dekompiloval aplikáciu (spolu s chybami). Dobré miesto, kde sa môžete pozrieť, aby ste sa rozhodli, čo zmeniť (možno budete potrebovať aj zdroje a ich ID z vyššie uvedeného dekódovacieho adresára, ale nie pre tento konkrétny príklad).
  • src-cfr-nodecode: rovnaké ako vyššie, ale obsahuje iba prázdne útržky (bez kódu, len kostry). Tieto súbory môžete použiť ako základ pre váš patch, ako o chvíľu uvidíme.

Ako sme už spomenuli, chceme zmeniť tlačidlo „Kopírovať“ ID zariadenia, aby namiesto toho zdieľalo text ID. Ak sa pozrieme po zdrojovom kóde, všimneme si, že tlačidlo Kopírovať ID zariadenia (device_copy) po kliknutí udalosť spracováva anonymná trieda v src-cfr/makeinfo/com/getid/MainActivity.java. Aj keď by sme to mohli upraviť tu, zvyčajne je lepšie nájsť alternatívny spôsob, ako to urobiť, pretože anonymné triedy majú číselné názvy (MainClassName$SomeNumber, napr. Hlavná aktivita 3 doláre), ktoré sa môžu medzi verziami nepredvídateľne meniť.

Namiesto toho zaregistrujeme vlastnú triedu pre udalosť úpravou súboru Hlavná činnosť trieda. Najprv skopírujeme verziu „kostra“. src-cfr-nocode/makeinfo/com/getid/MainActivity.java do src/makeinfo/com/getid/MainActivity.java (zapamätaj si to src je miesto, kde bude žiť náš patch). (Ak chcete, môžete skopírovať verziu s úplným kódom, je to čisto vec vkusu.)

Teraz ho môžeme upraviť nasledovne:

  • Pridajte potrebný import pre anotáciu DexPatcher:
importlanchon.dexpatcher.annotation.*;
  • Pridajte značku na označenie, že triedu upravujeme. Tiež sme nastavili predvolenú akciu pre členov triedy patch na IGNOROVAŤ, čo znamená, že členovia sú tu na to, aby na nich odkazoval náš kód počas kompilácie Java, ale DexPatcher ich bude ignorovať.
@DexEdit(defaultAction=DexAction.IGNORE)

publicclassMainActivity

// The reference to ActionBarActivity will be satisfied by symbols

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

extendsActionBarActivity{

  • Okrem toho pridajte prázdne telá do konštruktora a onCreate metódu, ako aj všetky ostatné metódy, ktoré plánujeme použiť (nezabudnite, že budú ignorované, keď sa naša oprava skutočne použije - iba ich pridávame, aby sme sa na ne mohli v prípade potreby odvolať). Môžete tiež len pridať natívny kľúčové slovo.
  • V tomto bode už môžeme zostaviť opravu, ak ste zvedaví:
    $ dxp-make # Output: `patched.apk`.
    Celkom jednoduché, však? Pokračujme však – stále sme neskončili.
  • Poďme upraviť onCreate teraz sa vydať na vlastnú päsť OnClickListener aby sme mohli zdieľať ID zariadenia namiesto kopírovania 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();}}}
  • Zdá sa, že teraz sme skončili! Celá náplasť by mala vyzerať toto. Teraz môžeme zostaviť opravený súbor APK a nainštalovať ho:
    $ dxp-make$ adb install patched.apk
  • Poďme sa pozrieť na výsledok:

(Vďaka Lanchonovi za pomoc so vzorovým kódom!)

Xposed je nesmierne populárny a má na to dobrý dôvod – výrazne zjednodušuje vytváranie, zdieľanie a inštaláciu modov pre vývojárov aj používateľov. Existuje niekoľko rozdielov medzi DexPatcher a Xposed, ktoré môžu spôsobiť, že niektorí uprednostnia jeden pred druhým:

  1. Xposed robí svoje kúzlo tým, že zachytáva metódy za behu a umožňuje vývojárom urobiť niečo pred, po alebo namiesto akejkoľvek metódy. Na druhej strane DexPatcher upravuje všetko pred spustením a vytvára samostatný upravený súbor APK -- spustenie kódu pred, po alebo namiesto metód je stále možné a v skutočnosti máte niečo navyše slobody.
  2. Vytvorenie samostatného súboru APK znamená, že nezávisí od žiadneho externého rámca. To tiež znamená, že root nie je potrebný na úpravu používateľských aplikácií.
  3. Keďže ste nový súbor APK vytvorili pomocou DexPatcher, bude podpísaný inak. To znamená, že používatelia nemôžu dostávať oficiálne aktualizácie od pôvodného autora a môžu spôsobiť určité problémy s aplikáciami, ako je Google Apps, ak sa skontrolujú podpisy.
  4. Zdrojový kód modulov a záplat DexPatcher možno ľahko distribuovať a upravovať. Majú tiež veľa podobností, ak sa s každým trochu zoznámite.

O DexPatcher sme toho nahovorili dosť. Teraz si na rade, aby si to vyskúšal, tak zamier k Vlákno fóra DexPatcher aby ste mohli ihneď začať!