DexPatcher: zakrpite Android APK-ove pomoću Jave

DexPatcher omogućuje programerima da krpaju APK-ove pomoću Jave. Ovo ima nekoliko prednosti, a korištenje DexPatchera puno je lakše od klasičnog Smali pristupa.

Vjerojatno ste vidjeli ili instalirali modificirane aplikacije, bilo da se radi o zakrpanom biraču za vašu rezoluciju ili prilagođenoj verziji WhatsAppa s dodanim značajkama. Međutim, kako programeri to rade? Puno vremena izvorni kod aplikacije nije čak ni dostupan, pa kako to sve funkcionira? Prvo ćemo vidjeti to, a zatim pogledati novi alat koji ima za cilj učiniti proces mnogo lakšim i na kraju ga usporediti s popularnim okvirom Xposed da vidimo u čemu se razlikuju.

Možda ste čuli o tome kako se APK-ovi obično modificiraju -- programeri se uključe u matricu, počnite vidjeti sve u Smaliju i steknite sposobnost mijenjanja stvari koristeći moć Izvor. Dovoljan je telefonski poziv da ih izvuče nakon što to bude gotovo, a tada su spremni podijeliti sjajne nove APK-ove.

Još ozbiljnije... Krenimo od početka. Ako niste upoznati s modificiranjem Android aplikacija, možda se pitate što je smali. Programeri obično koriste programski jezik Java za kodiranje Android aplikacija. Program (prevoditelj) zatim "prevodi" taj kod u drugi format prikladan za vaš uređaj, što rezultira .dex datotekama koje se nalaze unutar paketa aplikacije (ili APK-a).

U tom trenutku više ne možete pristupiti izvornom izvornom kodu (osim ako niste programer ili je aplikacija otvorenog koda). Međutim, ono što imate je APK, jer je to ono što je instalirano na vašem uređaju. Iz njega možete dobiti dex datoteke (obično classes.dex) i zatim ih pokušati prevesti natrag u format koji možete razumjeti. Tu dolazi smali, kao čitljiviji, ali vjerniji prijevod. Možete otići korak dalje i prevesti ga natrag u Javu, iako taj proces nije dovoljno vjeran -- dobit ćete razumljiv rezultat, ali vjerojatno ga više nećete moći prevesti obrnuto jer će se neki detalji izgubiti Putem. Drugim riječima, sve izmjene koje napravite bit će uzaludne jer ga nećete moći ponovno pretvoriti u APK da biste ga instalirali na svoj uređaj... barem ne bez puno truda.

smali/baksmali je zapravo asembler/dissembler za dex format -- to doslovno znači na islandskom. Međutim, obično se pozivamo na format koji smali razumije kada kažemo 'Smali' (zamislite to kao upute definiranje svakog sitnog detalja, čak i ako nije sve potrebno nama ljudima -- stoga je opširnije od Java). Također imajte na umu da je gornje objašnjenje malo pojednostavljeno, ali bi trebalo biti bliska analogija, a opet lako razumljivo.

Što bi onda razvojni programer trebao učiniti da izmijeni aplikaciju (bez pristupa izvoru)? Proces je više-manje sljedeći:

  1. Preuzmite APK (s weba ili s uređaja).
  2. Koristite nešto poput apktool za dekompiliranje APK-a u Smali. (apktool koristi smali/baksmali, ali čini puno lakšim dekompilaciju i ponovnu izgradnju APK-ova, a također se brine za dekodiranje resursa poput XML datoteka.)
  3. Izdvojite classes.dex iz APK-a, a zatim upotrijebite dex2jar i konačno Java decompiler za dobivanje (nepotpunog, često pokvarenog, ali uglavnom razumljivog) Java koda. (Ovo nije obavezno, ali može biti od pomoći jer je Smali mnogo teže razumjeti.)
  4. Odredite što modificirati.
  5. Zapravo ga izmijenite izravnim uređivanjem Smali koda.
  6. Alternativno, napišite modifikaciju u Javi, kompajlirajte je, ponovno dekompilirajte u Smali, zatim kopirajte rezultirajući Smali kod.
  7. Kada je sve gotovo, koristite apktool ponovo za obnovu APK-a.
  8. Potpišite APK (kako biste potvrdili identitet autora; svi paketi moraju biti potpisani) i na kraju ga instalirati.

Pisanje Smali koda prilično je teško i podložno pogreškama. Manje promjene mogu se napraviti u Smaliju, ali dodavanje novih značajki s njim je izazovnije. Osim toga, nećete imati nikakvih pogrešaka u vrijeme kompajliranja, tako da se čak i pogreške pri upisu mogu otkriti samo tijekom izvođenja. Proširenje i dijeljenje Smali zakrpa također može biti problematično jer su razlike obično vrlo specifične za određenu verziju APK-a. Iako postoje neki alati koji olakšavaju dijelove gore objašnjenog procesa (Studio Virtuous Ten pada na pamet), još uvijek može postati zamorno.

DexPatcher od starijeg člana XDA Lanchon ima za cilj riješiti ove probleme, čineći proces jednostavnijim i dopuštajući programerima da potpuno izbjegnu suočavanje sa Smalijem. Umjesto toga, razvojni programeri mogu pisati zakrpe samo u Javi i dati DexPatcheru da upravlja svim ostalim.

To ima glavnu prednost jer ima lako čitljive i upravljive datoteke zakrpa. Krpanje APK-ova općenito postaje praktičnije. Uskoro ćemo vidjeti potpuni primjer kako koristiti DexPatcher, ali evo prvo kratkog pregleda onoga što nudi:

  • Otvoreni izvor.
  • Više platforma: trebao bi raditi na Linuxu, Macu i Windowsu.
  • Datoteke zakrpe: izmjene koje napravite sadržane su u datotekama zakrpe Java koje možete neovisno dijeliti.
  • Java: nije Smali.

Također dobivate prednost provjere pogrešaka tijekom izrade, tako da se greške pojavljuju rano u razvojnom ciklusu. Prevedena Java pruža uobičajenu provjeru vremena kompajliranja (s pristupom izvornim APK simbolima), a DexPatcher provodi kompatibilnost izvora i zakrpe prilikom krpanja, pružanje korisnih informacija i davanje upozorenja kada se čini da nešto radite legalno, ali sumnjivo.

Uz to, DexPatcher dolazi sa setom pomoćne skripte (dostupno samo na Linuxu, iako se mogu prenijeti i na druge platforme). Oni se brinu o postavljanju radnog prostora, izdvajanju klasa i resursa ciljnog APK-a, dekompiliranju klasa u Javu ( CFR Java dekompiler koristi se za potonje), i konačno izgradnja i potpisivanje zakrpanog APK-a kada završite.

Pogledajmo primjer (na Linuxu):

Instalirajte DexPatcher skripte

$# 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.

Konfigurirajte DexPatcher skripte

Otvoren dxp.config u svom omiljenom uređivaču teksta i pobrinite se da promijenite potrebne varijable kako bi odgovarale vašem sustavu. Trebate samo promijeniti sljedeći redak da umjesto toga pokazuje na instalacijsku lokaciju vašeg Android SDK-a:

dxp_android_sdk_dir=(~/android/sdk)

(DexPatcher će automatski odabrati najvišu dostupnu verziju platforme. Osim toga, također možete izmijeniti druge opcije konfiguracije kako bi koristile vaše vlastite verzije nekih alata umjesto zadanih postavki u paketu.)

Za lakši pristup možemo dodati otpremnik imenik našem STAZA, ili čak simboličku vezu na različito dxp-* skripte na mjesto koje je već u vašem STAZA, kao što je ~/bin:

export PATH=$PWD:$PATH

Izmijenite aplikaciju

Za ovaj primjer upotrijebit ćemo jednostavnu aplikaciju otvorenog koda. Naravno, izravno krpanje izvornog koda bilo bi moguće u ovom konkretnom slučaju, ali to uopće nije zabavno!

Uzet ćemo aplikaciju "Get ID" tvrtke basil2style, aplikaciju koja vam prikazuje neke detalje o vašem uređaju. Naš cilj je izmijeniti gumb "Kopiraj" za "ID uređaja" i omogućiti mu da umjesto toga dijeli ovaj ID:

  • Prvo preuzmimo APK koji ćemo modificirati: Dobiti ID.
  • Dekompilirajte aplikaciju.
  • Izradite ključ za potpisivanje koji ćemo kasnije koristiti za potpisivanje APK-a.

Sve to možemo učiniti i putem ljuske, koristeći pomoćne skripte:

$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".

Tamo ćete primijetiti nekoliko različitih direktorija:

  • dekodirati: ovdje ćete pronaći resurse i Smali, kako ih je dekodirao apktool.
  • src: Prazan direktorij. Ovo je mjesto gdje ćemo smjestiti naše datoteke zakrpa.
  • src-cfr: ovo je gdje usp dekompilirao aplikaciju (zajedno s pogreškama). Dobro mjesto za pogledati kako biste odlučili što promijeniti (možda će vam također trebati resursi i njihovi ID-ovi iz gornjeg direktorija za dekodiranje, ali ne za ovaj konkretan primjer).
  • src-cfr-kod čvora: isto kao gore, ali sadrži samo prazne nedovršetke (bez koda, samo kosture). Ove datoteke možete koristiti kao osnovu za svoju zakrpu kao što ćemo vidjeti malo kasnije.

Kao što smo već spomenuli, želimo promijeniti gumb "Kopiraj" ID-a uređaja kako bismo umjesto toga dijelili ID tekst. Ako pogledamo izvorni kod, primijetit ćemo da gumb Kopiraj ID uređaja (uređaj_kopija) na klik događajem upravlja anonimna klasa in src-cfr/makeinfo/com/getid/MainActivity.java. Iako bismo to mogli modificirati ovdje, obično je bolje pronaći alternativni način da to učinite jer anonimne klase imaju numerička imena (Glavno ImeKlase$NekiBroj, npr. Glavna aktivnost $3) koji se mogu nepredvidivo mijenjati između verzija.

Umjesto toga, registrirat ćemo vlastitu klasu za događaj izmjenom Glavna aktivnost razreda. Prvo, kopirajmo "kostur" verziju iz src-cfr-nocode/makeinfo/com/getid/MainActivity.java do src/makeinfo/com/getid/MainActivity.java (Zapamti to src gdje će naša zakrpa živjeti). (Možete također kopirati verziju s punim kodom ako želite, to je čisto stvar ukusa.)

Sada ga možemo urediti na sljedeći način:

  • Dodajte potreban uvoz za napomenu DexPatcher:
importlanchon.dexpatcher.annotation.*;
  • Dodajte oznaku da naznačite da uređujemo razred. Također smo postavili zadanu radnju za članove klase patch na ZANEMARITI, što znači da su članovi tu kako bi ih naš kod referencirao tijekom Java kompilacije, ali će ih DexPatcher ignorirati.
@DexEdit(defaultAction=DexAction.IGNORE)

publicclassMainActivity

// The reference to ActionBarActivity will be satisfied by symbols

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

extendsActionBarActivity{

  • Dodatno dodajte prazna tijela u konstruktor i onCreate metoda, kao i sve druge metode koje planiramo koristiti (zapamtite da će biti zanemarene kada se naša zakrpa stvarno primijeni -- samo ih dodajemo kako bismo ih ovdje mogli pozvati ako zatrebamo). Također možete samo dodati domaći umjesto toga ključna riječ.
  • U ovom trenutku već možemo napraviti zakrpu, ako ste znatiželjni:
    $ dxp-make # Output: `patched.apk`.
    Prilično jednostavno, zar ne? Ipak, nastavimo - još nismo gotovi.
  • Uredimo onCreate sada da iznesem svoje OnClickListener tako da možemo podijeliti ID uređaja umjesto da ga kopiramo u međuspremnik:
    // 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();}}}
  • Čini se da smo sada gotovi! Cijela zakrpa trebala bi izgledati ovako ovaj. Sada možemo izgraditi zakrpani APK i instalirati ga:
    $ dxp-make$ adb install patched.apk
  • Pogledajmo rezultat:

(Hvala Lanchonu na pomoći s uzorkom koda!)

Xposed je iznimno popularan, i to s dobrim razlogom -- čini izgradnju, dijeljenje i instaliranje modova mnogo jednostavnijim za programere i korisnike. Postoji nekoliko razlika između DexPatchera i Xposeda zbog kojih bi neki mogli više voljeti jedan od drugoga:

  1. Xposed čini svoju magiju povezujući metode tijekom izvođenja i dopuštajući programerima da učine nešto prije, poslije ili umjesto bilo koje metode. DexPatcher, s druge strane, mijenja sve prije vremena izvođenja i proizvodi samostalni, modificirani APK -- izvođenje koda prije, poslije ili umjesto metoda i dalje je moguće, a zapravo imate nešto više sloboda.
  2. Izrada samostalnog APK-a znači da ne ovisi ni o kakvom vanjskom okviru. To također znači da root nije potreban za izmjenu korisničkih aplikacija.
  3. Budući da ste izradili novi APK s DexPatcherom, on će biti drugačije potpisan. To znači da korisnici ne mogu primati službena ažuriranja od izvornog autora i može uzrokovati probleme s aplikacijama kao što je Google Apps ako se potpisi provjeravaju.
  4. Izvorni kod modula i DexPatcher zakrpa može se jednostavno distribuirati i mijenjati. Također dijele mnoge sličnosti ako se malo upoznate sa svakim.

Dosta smo pričali o DexPatcheru. Sada je vaš red da pokušate, pa prijeđite na Tema foruma DexPatcher da počnete odmah!