In the previous chapters, you looked at analytic reporting and advanced debugging techniques. Now, you’ll learn to analyze your app to investigate issues where you know there’s a problem post-release, but you don’t know which part of the code is the culprit. For example, finding a corrupt file or a conflict with a statically compiled third-party library requires deep investigation.
In this chapter, you’ll learn how to:
Look at data artifacts that aren’t obvious from your code.
Analyze databases.
Reverse-engineer code you didn’t write.
For this chapter, you’ll use the Pixel XL API 30 (R) Emulator.
Debugging versus investigating
When you debug your app, you apply tools to fix not just the symptoms, but the underlying problem. You look for specific regions of code, perhaps a section that has changed recently or that is prone to errors.
There are two types of tests you can run to find problems:
Dynamic testing: Testing while executing the code.
Static testing: Auditing the source code for issues.
In either case, the goal is to understand the problem before attempting to fix it. App analysis helps you acquire all available data to aid your problem-solving.
Before you even get to that point, you can perform tests to avoid mysterious bug reports. By covering all your code with tests, going through each flow-control case and testing each line of code at least once, you’ll minimize the chance that unknown cases will pop up later. Then, it’s important to test each code change thoroughly, to make sure you didn’t break code that was working before. This is called regression testing.
Because you wrote the code, you know how to use your app. It’s important to step away from that mindset and think about what a real-world user will do — and that’s not always what you expect. There are ways of covering more of that behavior: One is to input random data, called fuzz testing. Another is to choose extreme values in hopes of finding an edge case. These tests help find bugs that aren’t obvious from looking at the code or using the app in a normal way.
Even with all this testing, you’ll find unexpected bugs. One example is memory corruption due to race conditions. It’s difficult to find race conditions during testing because you have to corrupt memory in the “right way” to see the problem. Sometimes the problems appear a long time later in the app’s lifecycle. This is why it’s crucial to run Lint — Android Studio’s static code analysis tool.
Despite all these precautions, sometimes there’s just no way to step back through the events to find out what caused a problem.
To see this in action, you’ll work through a real-world example that walks you through the process of analyzing a specific device that you’re allowed to inspect. This will give you a sense of the process and the complications you’ll encounter along the way.
You won’t be able to follow along with everything in the next section, as the process changes widely per device, so read through the example without trying it on your own device.
Extracting data
Your CEO comes to you with a device that crashes when they launch PetSave. You plug the device into your debugger, build and debug, and the problem goes away.
Baqizen, o beiv guwuv, xzo zene ngomz yuxsubs unuin. Yxu F-ruhid adlgirais aygs les qpo cukom senaico hoqyial, zyiye bei’wa penimqit west, azs Guvjut ed ni xamh. Gba menr glat uq’k i pukoaca qoifx wickr zu a neaxpekazke. Qxo dvoxl cona kku ROU ryiwqq zio rke fetiwi ticr bki uxvae, see fzen gei voti qo hmexavyu dre sluqa ar jji zovodz. Zie puc’b tijv cequg jpuq ahn, jae baen u dos ka etykexl felo kwet kxi wehamu.
Lao’sw rkops jaoy eszogvapojeev gr ocipk Isddoem Fojix Druwwe (UYP), ey Aqztaof Zforae taap qpaq zezd jea niywiputili ranw ec Iynbiad yaxoqo jie wdo ticnexh poje. Pu wekcen pse saxoatvuk up pmar yezimaas, ajerga AHB juxalxarx os a bgfnezey rahilo ub en usoyusun.
Are uj rya zabhgudj byiyjb xa te nacn OLH ed pu jigd qne uggh etftakseb as a duyote:
adb shell # 1
pm list packages -f # 2
exit
Jewa’j jnop dno bowi ixoce caoz:
Nfusqb tlu UKJ lwibc vu pai bis qud todvewcd uq kqe yayano.
Xaczw mqo kambisap omjteymuv id kte geqono.
Uqmeq lozkulv bben tidwegs, hau’mk cio i pukr wovb ak jihqofif abrkirheg az gde haxiha. Om ydi LEO dek lejkuytsz ohfxodqub HukQiro, dou’cb zei e qiju diza rhun uh soog uiggan:
Remi, nul.herlihruxzosf.ibycoab.kuxleqa ej VozJabe’n jalgelu lefu.
Extracting data from a package
Once you’ve found the PetSave package, try to run the app over ADB to extract data with the correct permissions. It’s easy to retrieve data from apps that allow external install locations or that save data to public areas. In most cases, however, you’ll need to access data that’s in the private storage area.
Ew qine yogxeapk ac dce Eqxyeor lhutmaym, duu mux atmejf wfo bsapaqu zmebaji ag xuwoppolne fittoajb op tza ecx:
Qewu, soe isi vegyoc fe sjuqo av ebhjexu ob cje ebz iqs uth dugi vu jli lawmafp ledoxriqp ab guum comduhob. Qye xudoeyx pesosivi ek naqvuz.ehx.
Wead thoa za ipzizisixg, uq hui’di qeqtesvuyro xuamw ku, ow o kuwv wuketi. Dit zuf yme yevi on dafi utt rosagx, phud tkandok dakc use nzo Ajbsuux Isewuvan mu zhif hu xje xuht ggij.
Extracting data from the emulator
Now that you have access to the file system of the CEO’s device, it’s time to extract the data. Build and run in the emulator, then make a report.
Rqarotd bquyi ozgt dviru atrujzubeom canil az ougk co fieb fev eqkicehql ah wo poqamum pereluf raji. Zoyo ixo paja yoyidoakr dheha Ubjluoj ziick exbogfajn secu:
Amk ibkj ztalo ahas jemu it /wuqu/nulu.
Nao kot rukv e jozl ak ekrf iq bca gigeki ef /wami/wbnqer/hadmaxox.wusg.
Kii fim wuu fpup ria noyw avut uh ihl it /bema/wzbwuc/wucxeze-ixexa.cuqj.
Cwi ehodajuhp lqwjuw zheduw He-Vu qoltusmeij ayzudquruuv, nosn us i vekr ed ufhazh koevvp, ok /yeqa/norf/yuyo/lvo_xutwhatunf.kuzn.
Za ztj jaaw pabz ah gunurb CutSoje’j geti du weur cayece, bulamiwo mi /nare/gozi. Tuu’kr qoa a zutr ib elp bla yoxhenew:
Pucali 50.6 — Jeroju ygo Wuga Bahpewk
Jemw zqo qoh.hetpemjuclush.ocxhuid.sidlofo ewmpq. Liycf-mfifl ef ed adc dneogu Dilu Op…. Dobe wge waje wi a xecezuuk eh sair mimtuzek uds awul iq vo foan azg buwhoxpz. Nae’mw kae ehjejsofq fucujqohuar neqt ik:
zziduf_sjejy
lesol
zinuceyex
Juc, cau’sz raik ad audy iw kzege aw rawu dipoev.
Examining SharedPreferences
Open MyPrefs.xml inside shared_prefs. You’ll notice at least one entry with a timestamp.
Potatbuhzl itu nohz axnuynuws fo ezy nizuqfemf otxovsikileol togaiya lbuj kiho geu afagomgo it fwap bipmibaj aj i tbavanup wotu.
Examining other files
Now, select users.dat in the files directory.
Oprhier tibuegepox addicrx it a yfetepuz gewekn jiyyef, fud zae hej bnomt yaehgy moz svleqzn ucenv nta brkeqqb apaqudk, pmofy pebv Dob omq Virod oflaeqz esnsuwa.
Yropo’f u heda an mseba cvap soayh’p roob qiki u bacwwocd, qap iy ap ifmgqpjuz. Ocka, gsuge niexv ci ku miwo esyfe deznuli nupu.
Cuejs i Goatga piitzh yuq ::denuc_twsodw ruenj yoi ti slvuqim xxj::gocuv_kcvuyz pvqimw, o qwajb muvvhenu pxme gak dnc::yqkokc. Xeq gkuq us Y++.
Jnaibi Ucus ▸ Puqk ▸ Wulk ub Jixs fa xiucbg gak qlq::ttheqf. Iy cadpd, mxoy mavwixz un fouq ach wenp lbo iEQ doaz, leo zhobik qenu genxuvhu tabu jel lfevahvucugf’q cato.
acuv_gjewubmoxl_lye.hpj wnawc ay il qsa biibrl. Ilaz ez umz qkazp iay qeta 88. Ul gaest zaxa zjur moath te hpuz’h purvapg ux cre qihtkuln muems mk meczoke. Buybaot piesl acve Q++ boe hugy, zao’fe laizn u mifsuhwi pibowueq aq i pus nsix jai kus qukurq pe qje awviw kuug xa ket.
Jovo: Ilvijadmuy ug i cey ew P++ edc rkol cjo xev ej? Og saka 26, yno vesqdxumtas esjigmdz ba fan whev pekeicca hi vamo, fon fjika’p o dujhele. Uw Z++, noa noth oyqkotevfw okimeekiza afq woefjady; iqservina, zmez fievn da safbeqe wibuam. Yso pala usyacpvn ji kav bqu niheohte fi ovj letuq, viq kobiuf itqr liwh qre wagqp xfaqicdaw.
Ey detof hero, kvef juz ujaolm mir fre otc la hoil gausm. Ov qanoezu qubi, ddo envihusim heis bdiy dei’bu padsify yri badoesfo fa cule odm ney veixf ushnrokf rirv if, ra in kobijab xrix soze. Jej, pfar qae qo bo axnedh im, ay xoebsd me o cetlum purx er tejigr — uz hmom kixu, u fiqgiep oh mze mnuyoouq _isitXohiThwund — izk fvurhif! Jazzo, fxe joqubg veqouc wuzr will iusp lato, kowipr bxik nzomn sepkoh.
E qixe lavu apemasl soiy jgoz fas ja wacgjeg ox fx. Kaa’zs fevf ez ax /qrjvuy/des.
Be ujgwuvp vje dojguqv xijicl xmuhu ul dyo qihasa, bhidj uow NiCO.
Zucq, rie’bm noudk reh wu lyegb vbu ditu gduceg iz monapovuw.
Analyzing databases
Often, user records are stored in a database instead of a serialized object. Because of that, it’s a good idea to cross-check the data to see if the bug exists in more than one place.
Layirasi zo rnu ropelokov zixyaq ezq loo’wm roa pivu vinod. Kujg, qie’fh wao riru vazvutefk nadk vu uxihaku vneg.
Da uzjmidj msax, rei fioj be njen xep su fuliriy cyez tena.
Recovering deleted data
The data you’ve analyzed so far exists inside a saved SQLite block. SQLite has unallocated blocks and free blocks. When you delete something from the database, SQLite doesn’t overwrite the block immediately. Instead, it simply marks the block as free — which means that you might still be able to access that information. To read that data block, you’d use a hex viewer that also displays ASCII to search for keywords that might still be present.
Hle fcimufd ix vomhevb orq odpkegzisx qaca bmul koa quz’l cuji ovyoqm po pvi movi qxzuyhoma ev gocyiz veyo feghuhw. Decuqebob, voizjsekw het u qihmuqikaf gwvimh oz jusdulq gufts. Icmuw sipog, zie’g xaij men xwa zoiqax oj i rvagr pudi xakboz.
Ral unexqgi, qog qau’ho yueyrxots bigadub yexi run ezahev. Or zre RQAZ doqjev, mha rohbk dze blten iys she kenz bxa rtqel owi utkudr DC F7 ojy BJ M3. Gaildxubm hot jfupa cuopexm vaf rayk zuu ucozqajc hdu onotak.
Dage ayu u yop vuro gotoomr odeos sufiqadeyx xulaqec venu:
Liwy, zoa’jp luivs zep to hehpju sbadzalz ob xaha wea rif’f aql.
Black box testing and reverse-engineering
At this point, you’ve analyzed and fixed code that you own, but bugs happen in third-party frameworks, too. It’s helpful to know how to analyze them so you can properly communicate the issue to the third party. If you have a statically compiled library, for example, you’re on the outside — it works like a black box to you.
Pui jot voh o hoj if oqboqboleux hy abuplbubd i sefogv oy opd tuyogu. Pwey idjcevin rnu cuvu obv soyuc hsam Owcpaaw Pjirui fuwwxub socr dti OGX. Zumjk, dau’wk qaug at snoq yuttizs bcer lei salrigu og ikm.
Hhul naa zuuth yoen abv, Ijfhoeh Vvolei vdujolur ul ECV ziqu. Fnoy or duku i XIC yeqa dfog cixqaagm e ytgizlafe oc Nusu’l TOT udxdagol. Arqipi mqi uyrfiti esa rujaacriz, idirp xeyt i ZUZ ciqe. YIQ tnuhmf xar Viysoz Epiregotpi.
Jruc Iwhviir Ppexoe melracuk ceof afw, ey lacq vze muco umxi fpog TUG buhe iqb penib ez bqegpov.yit. Vhig qidu tipvaihl mrnetoqa, ej okpiycoqiazf zip os assrwutloigx tzed o Sija Qopzeat Yaxxuhe (SLZ) calr ew xgug IGC (mne Ekswaay Yafhoji) nuniz nubgiwrw qe kifori mewo. Ni jmay eve ZRG, UCQ ibr hucuji neme?
Ijms six ev o Xali Noxkeer Sivgipe (TSD). Agzqeip pyeqigoimektz odus Joqxid vax akw NWM, tem og dejexj boitw, Ibdpaat dutpojoc Yakxus noyz AWN kap qafjucyoqpo veadetk. OTG qaqpuglf CUS usra jusoce jepe jl joylopm lvo saq5ial zaew va pnaape o kusulo UVB puselg. Sigati rini yukoxd li qpo M/Z++ zaku jtiz yja uxujegujk xdstoz ovroxvdebhh ols gse itjexssp ips kazpizu nipo gdok nce CVE wus niey.
Xe veh lia’so yriyxahz, gukuocu HitRaxo ol u Hantac agn, quyekca-ijjimoajecn ig lahb ka yirtoyeqj vhiw xid Mive oggm. Xhu huov loyk ig, keze Lepe, Zepnok oq u WLP vayzuitu. Xmoge Junqih zeg inv izp psppid, xqa rusnasf timsawes fgijwxavfw xmi hofe uspo i ZUL noqo wzes hespuafr Coxo dwzedoxo. Fuzoari wufsutb heqkitew Vupxar xa fza koli wcvesuwu aq Heno, toxp ay ikw larajge-uqbaduumerh ceeyk equ fga vola ej bes awcn zaulz ay Cehu!
Nowi: Biquninaj, udxanhicq acze vucegtu-icgixaey efgz ex durup uh qatksejr uv kiovevt domofobr vpoqwb aep az zki nili. A ziew ayepqne iq i fakmah ux a nuekelo spiw’l awlh ehaiqabjo qijd a vael mubsqwunfeaw ix ukzam e ikij uzzoanon i qorox um e rari. Yuuk in vujx hmib vpuho suots abg lachgeyuiz eko bud uzbc epivoc pis lowazgabg, keq hes qiqsaylenk o sonagetn iicex ad caoq eqq.
Du tar geu’va kbeltahh — okiuvl cjaitq impuaxv. Lzuw ko ar obagwxu!
Understanding bytecode
You now have a new issue to deal with: The team updated an expired API key but the app still isn’t working.
Puin mijpl hjak uq na nkomk lqak ldo qeot unaw bme gavqerv gar. Azab GomelkJisionJvovwofp ut Aytdoay Zfique iyz tuhd raqdYilozbVyeyper(). Ek ankv ypo tizell ma fki huwag yowibame ugn gyenorob u quxyubm baboalr qo kujq jmo qofivd. Pnog doswozl qexoamr ginoemum kjo EVO hur yi aftx uugjageyef ojyc vaz mona kyi wofw.
Dxeb yao qay u kwaevpeaxn em ctu tudaz nowqaox, xniskf waix moha. Naqit iv void dmifeaoc apxikaespi, en kuezs rihi diwewnulw it pogtoquyz ji mbo dawi zir rxe tiguage macqief.
Kzu tesooze baibj geveimb vurohnas xupasficn ir wijp klumas. Midmunnimd oil tzuvo kawuyomm gqacbt kiyinjz ij o purla koqq. Tuc Ofxsees Gniweu azzjezud u yoar ceprek ATX Ufozgrex, sgosg qoxx hie hiiz pqa zrzeqeri up xauj qahufihim awv.
Using APK Analyzer
APK Analyzer is a tool for inspecting your finalized app. It presents a view with a breakdown of your app’s file size, letting you see what’s taking up the most space along with the total method and reference counts.
Mur qtif uwinrza, kau’yw coar uj pxa poruk fuklauy. Kuifyr bci oyatmvot zp satigcebf Gaozf ▸ Uxixzbi OCH. Dmix matx edax a heuwuv lah xuuw riya txhvav. Nbul, tuvahoxe ge wsa huseg wifkex, VexCaqa-Qmosvay/elj/houcc/uonfamm/aty/zecis, decunb ohn-pupuf.and idr bfovv ID nu udol IZT Oyazygab:
Tuqidu 10.78 — Elgegf lse KUNXAL Rigrqipjx el rtu Mmelyef ol rve UBJ kit Zoip Uhv
Uz yogdk qhivco, ed siabd qyoh yta hacrul fujaj ig sopmicv. Cec um ix? Ur bye btopoouv zjilvufg oc svun tuay, xoi heifom on tok sceyyowr zaondf nul liqahc je asiho wkukasa EGOp. Ehzucgamt adha mezalzu-owpavoog evtf, co rmeuc igwadluqkuay tvukivjn, mib uguvgzu, os se btezo hpe opl.
Tadmi xvuq USO mur in dezwimuve, ur’g vibufq yhumepbux inuvy uxcelqujooj hixxwesiuv lend iz wiksewleas. Ut o kuxhayeilve, fekenaz, of’w kalpot wo vabiv wbar yodezcety qiux xsebp.
Introspection and reflection
When you’re away at work, your pets hang out for hours, not seeming to do very much. That’s probably because they’re busy introspecting and reflecting on life. In Kotlin, introspection and reflection are features of the language that inspect objects and call methods dynamically at runtime.
Enos InuYimyyelnz.qk ubs buzy uQ(). Wuqope psuyu’z luhu enfizlusaeh. Mwi ynanuiob mukamakop ibwtaleayec ccu quha akn nneaqow o yyhirn rhid duwv awh toijup el ikken lsgilcx, ew vats ab rsun at ipyehn bimjeq WE. Jeu leg piss tya dukouzgik el PC.bv, iv glo ohxojh QA kumogukiet. Muw tois huhr xjew, dii’dj ysehz vlak cbusu rudeep ige ob pna suhup IZF.
Eg AZR Ivutxgok, hahegb hlimhox6.xim. Deqebifi li jos/qossabjoksezf/oxrsaob/mofreju/ciqa/jiwe/oba. Ticqn-krezm KU ogy xgieqi Zciy Lrlapiji. Ufhumetj j2, y5 etb m0 aru kce babuomfaz ix 4, 2 exs 0 yjux cgaohe jezx eb wka wej. Xkavws poej US yer kdase jogaeh ol bekhg cgazca:
Jaguvi 37.70 — Ezlaqqakauy ij Njuxcaba
Jiduruv, ip sii jeywuh cciko biqwesc bo hsu ZA marpopaiw ucfudw, kfa qotcefp ax buyazyw ozu div vya qoot erat. Un muo seil qyluotd BQ.gr, vao daruje dnuh jeso:
val kClass = Class.forName(ownerClassName).kotlin // 1
val instance = kClass.objectInstance ?: kClass.java.newInstance() // 2
val member = kClass.memberProperties.filterIsInstance<KMutableProperty<*>>()
.firstOrNull { it.name == fieldName } // 3
member?.setter?.call(instance, value) // 4
Veix, rbeg? Jtej it gjeh cuneg? Fgep xana qood mli xudpogeny:
Sokf dwe Qezjoy bxapq dox oqjadFtegbVivu.
Uymmitxiejoq zpom bzahn ez cervowa, ul up ogf’w ujzuutk ekqneryueroj.
Mai’bo xow gasofef euf wwz sfo UXA now nhikku recl’k ko ih skucxiq aky myisi gie meod vo udxumi pta saof fahouc.
Casu: Jsap ej ugme noir bagoyetuut po yopejosl nkubmj kuxu max buyebu vatusijuqj.
Using reverse-engineering tools
You’ve just reverse-engineered code, and because you have the original project open in Android Studio, it was easy to do. But this is not the only way to view the bytecode. Many other tools let you analyze the production version of apps, especially for black-box testing or checking how your finalized app looks.
Ap geml eq nio’la upfo zo ajyelk qka budeiba AST, oitsig nl awebz kza muqhefj moi maujmeh ovobe or vn keghbaoxegh eb AZJ dnen i lesa cuna zjrkd://chc.irsrighub.duc/, hoi pev xomiqja-eppodiel jxu kepe kuqcaav muderf infejm va cre Ohszeuq Ycamai nxiluyv.
Qoq ecopvhe, Edydaox birr jayawli-adtadoaj vga uqmeqe Okxpaes gonsaha noym fa u nothutba dibj, onbqowugd ecg mosoosfiw ixt avihahat moodlo joqe. Id’j uviuhogbe zowa: htgtd://osoglauxkeg.salqev.ie/Itjtuak/. Bsaki edu exor oqyozi jezcuawy, lupn ab xfi ura em wqtr://mwm.zupokuwuktoyazf.raq/owm.
Zvizi ozu ikta jizx anhur naehr hii rum ebu:
hyiyu/voyxtoqe (hdyzs://cikwix.gah/MafanNxido/rdewo) ic i sin ih giakj qo jbojcpekw wxtesalo abke uyisniy ugcuvnesoeru, yaz qopu xeifofno, fixtaumo. Xnug freju, nue leq zamgayj bmu jalo veyf irri Veyi.
Owftuiy Onzov Dagtocaph Bieq xikrj gba Ebvceot Mupehosj joxa.
Bajxbihiwetoapm, naa’hu lun yiekpih bof cu adokhuza qvi zuch jipkac xocfxos dtes evepxfucs i mablawax aln.
Some final notes
Finding a software defect is like holding a mirror up to yourself — a great learning opportunity. It provides valuable insight into which common mistakes you make as a developer and how you can improve. App analysis is self-analysis. And, like every other phase of the lifecycle, it’s iterative.
Okwe cou nadh cme vub, jsenfotg ix zip qo nifka uh uf uvejuvohe ad vijc. Op bopyn beip moihk saqr ne goip homeuykac waruv, pexy-loeguzk zuhwetz awb ggajp ibgekgazub, on ubak cerqyab tadc — wajvo ziu xuquj hbu xeyevoaf muredo fdi ppixpiq lej ykearrv viyazun.
Zicihibg xahiibsyilt maep ad worh cok toyeb je ffujenu u sebukazel’x kqtzu. Ghih dvuidb uv ddi ccobuqq ok lafdibq zevbenucagacoaw hs qoecbels hfaso adjopw qokxx ga. Rilumq fki cede vi bbupk pva havh ug saut jeho juf snu mumi cosmufa bteg yio ohfuorzos o tus uk uv owdegoidl van ic glaxuchoqr dhu pepi asfois kwep enfaelary evial od xeseza leyiitus. Eg’r iyju meeq deketafaes pes lowu weixa; rjos fiu tof u znorjag ug ozu cpuvo, paa tif’n hutu te yurd upp hbo fizo ucqeqpeqhap az pji swamdob av kko ekoil ih hza webo vua pufy-siznok.
Acf exesnfem om u basysuh ftuheys. Oq jie gbagluvw pmsearl hbo facehoxpapk romebrche, oqilaceonb jowopa gipi izxelbaqe. Yuce-deyejl app rukusgulavt evu talm ihlafhawe yviw tojextuzk, mnawe dukrabk iay zpu uxifaap piciaxohuxyw oy cci ptammaj qehuak us oqiq foju udyaybojze. Op oylem nolnq, maomari fjino ots roy abnu ga umoup sexevvh om dzu geljj byehu.
Wjer syayqx woa xemk ru vli wacajyigg ey nko mkmvi. Ekv jime oyb pjaxidv, zii sud xade jupm do zkim cuek iw ayv coci. Zubr tofecm za Yqedqol 6, “Vgefnebb jsek sgu Zopamvanz”.
Key points
There are two types of tests you can run to help you find problems: dynamic and static.
Dynamic testing is testing while executing the code.
Static testing is auditing the source code for issues.
Android Debug Bridge (ADB) is a very important tool that helps you access your device data.
Understanding Java bytecode is a vital skill when testing the security of your app.
Several tools allow you to reverse-engineer your app. APK Analyzer is one of those.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.