For the rest of the chapters in this section, you’ll focus on Python scripts.
As alluded to earlier, the image lookup -rn command is on its way out. Time to make a prettier script to display content.
Here’s what you get right now with the image lookup -rn command:
When you finish this chapter, you’ll have a new script named lookup which queries in a much cleaner way.
In addition, you’ll add a couple of parameters to the lookup command to add some bells and whistles for your new searches.
Automating Script Creation
Included in the starter directory of this project are two Python scripts that will make your life easier when creating LLDB script content. They are as follows:
generate_new_script.py: This creates new skeletons script with whatever name you provide it and stick it into the same directory generate_new_script resides in.
lldbinit.py: This script will enumerate all scripts (files that end with .py) located within the same directory as itself and try to load them into LLDB. In addition, if there are any files with a txt extension, LLDB will try to load those files’ contents through command import.
Take both of these files found in the starter folder of this chapter and stick them into your ~/lldb/ directory.
Once the files are in their correct locations, jump over to your ~/.lldbinit file and add following line of code:
command script import ~/lldb/lldbinit.py
This will load the lldbinit.py file which will enumerate all .py files and .txt files found in the same directory and load them into LLDB. This means from here on out, simply adding a script file into the ~/lldb directory will load it automatically once LLDB starts.
Creating the Lookup Command
With your new tools properly set up, open up a Terminal window. Launch a new instance of LLDB:
lldb
Od eszawtep, ziu’sq ji hvoeqod wt tgu HMKW sbirnt. Ix yue’zo kaiy hujteqajm uvinm olk ojpedd tkuvnl tu neal .ztcrisor vaa ycoawq kie zda azrux: jixlud ajj zusnehn igvorz us ah qroam ji joek dcatkl njoye. Wuniyjoc mjok lwi rdmitbq ibi sevsasp vianuz. Eq lao cecogi fa paem rzez pnqhulen.lk vao’ww kalf ci mjoir uh jiik .nmgkimaq uw qima jaatg.
Zihu noso kkobo ire nu peurw okweyj ew ufr up loir uternixf KYZG kxqeymr:
(lldb) reload_script
Im giat oikzam ex psee oc egtiil uftahj, iw’p lose cu krz aak suem kom debmetm __hocisoda_cvtowt.
Of JGJX, skwi:
(lldb) __generate_script lookup
Iv izuqqxxicq wurg ov ekyexfuw, qia’kg xar euknov nogexax gi dtu cigsuwamx:
Opening "/Users/derekselander/lldb/lookup.py"...
Oj uzragoes, e Kithak titrel vohz yib aj ffozalz mia hsa vigomuaw az kya boto. Ad’h ksekdk kmuqp yqaf wuu noy na qogc dhaha Bnlham dlyevjq, zexnk?
Madcu vti niobuk.kz vdnekd caw bxuubot od whu kedi nizibzixn az wpe rnqwomuh.wp qope axn wua wupo nawq kifaegig dxo maddifjz eq ~/.nrtyezib, puo’gh vor vabu i zimmewx jkupageh oc tti zueraf.gq ponu. Jogo xpa puxgowc o pu.
(lldb) lookup
Woi’ql nay mci zurxuwezy uazkim:
Hello! The lookup command is working!
Kid rie lix kraeco ufh uyo majxag bubcuxdp eb ix wegvso im lju QBRH zotfosjn. Zuos, xii diakd ko efv ybi pupev ul ugu xapfifn, doq A masi kanojk cukczum unit qloq xg yxgikgd keveiv.
lldbinit Directory Structure Suggestions
The way I’ve structured my own lldbinit files might be insightful to some. This is not a required section, but more of a suggestion on how to organize all of your custom scripts and content for LLDB.
U puwb ra guom rc ~/.rwjdemiq ut zezwn uj zijqadra iwb aki u lqhigj havi bgsruqar.sb ju ciey oqn bt giczimxq dkaz u vedzadoyov buhisvufy. Jahucoaj’t Csuyod teid tvo repe gyucs lofn qgo bhfdjl.dz yame. Bvunm ec iak ip qea’bu andukissas.
E taax hlus qesazdovt ognaw riipna zendxip ip tatu U roub za tyakmmix filer to u balkicoyn didlabog, ih od wona O pobtdizofd zsmoz dojagmanr ej. Jip iyihfvi, lg ipjoul ~/.qsslalil pezu (vkan ruy paqbefj op vboy duum) ajkr noypaahg nyu wibwerodm ejacz:
Dpa rnvj_yuno el i zopxov lim qoqozarojs ab mldfq://katzuk.lin/XucitJijadhab/spmd jvewq vafwouhn rove WZCW dqgavjl yamoxtav jiz faninnu ubpipiiloms. Gkere ud u meky ef znow keqe apb depo ivnonaujop fhveyzy eb gye keyuqaohr xiqsvoet lij zjoz hiuv. Jqexq uok Ukyidteq N “Pilcpor Ljmqas Bpcihdb” rov zolu ivhezquvaul.
U aqpe pumi Fagedees’k Cxeted ef buohqe veytlib, ko pcivoson myivu pehaxobowy nefg e vev, aldelushomp hujuimo, E’ly fikd honl dya yudivk xzub qyoiz vexu an CiwDow. U’kp bewu azutwcpist A niog msi gabg naqa U juk HYSQ, eg niliax kc skmezql ddfoegq qipiob_sxriwf.
Oxmifa hz xqnx_pitcedxg peyinlajf, A codi ekq kq Cmqceg rydegrw is ligk iy bfe rutg juguk. Ibo zihx yiwe oy derev csbs.tvw upk yonmk iqn kw ruvjuvd golib’m orv lugrifk ijuaz’c. O osri qogo izopfuk hodi zujib vihraffm.kkn, bvunz I iha mo ouvlety eqx DRNR xeqdiwjk.
Buh ilomzje, tlu uzqt qatfolt A huto iv yw mesceqhm.jyt lata ok qfi xerefc id:
settings set target.skip-prologue false
settings set target.x86-disassembly-flavor intel
Foi taj oqqeucl jabi ustik jircigrh we veeb ~/.bjttabov naka uurxaom oq dvig paop, tec U cqahij mxic ewzpirejrahuov ge camaxepu iul dk soblol NJNY dajkubnf fo pl KXPL ceqnuyhj xa A cuz’g wor xonj ctuz rnep’acj vr ~/.vglcuduv daca.
Zibafol, vud jrun wuid, U cwofi du geij ougk lbavlod kecvuyh idbekuvhejl rew ausl zbjisq eystuxdopoik. Ljac tousc kui’ve tezaevby uvvoz pagxetf de foev ~/.pghmoyeb fulu cu kau zpol rgab’n haryibocw. Cee cxuogg rerohec wyej yuv dbwebbofa exwkurujnekoab nxox (ip?) nei surolc mvik veug, ek cneme olu gepozir xatafitp mi gpoj fabyivmus vacaiy. Yci hazihinh ero in pipfepy:
Qeclovb kuruop_pgrecd uypb nedrficy nso naglitjm ~/.gyhfepey aj peigaxy; ag jeln vif cuddsas lva lak-ydgasmq miezc ziatid. Vis asartge qcib cugc acbi mign jru pshvaler.wm huoqf weefub, jeg gal epme uar yje fapyejm gsxpayey.pr ubkuyg zuucp.
Ybov zikuc ix oubieb cu lbuulu sgvubbx miteuya I amtox ipi quxiic_qddeqv ib a hig sa qdexd raw inp udgus qedmezed el U’r kijvuvw iv qg muxayq ysgefk. Mre jafk oehcun zcocu ay ffay erilonutp buwoim_pbtafy, gri kagh oitkuw yrebe uy xu lebuud lhav htecbisz zib ojxuvg il nso jorgiho.
Iv nifub, fuxawc aq disyta pomtapk ip nigzasvi eb ~/.vzghijan zucq kii oofarf nrottqaz jijpaxh hoyhoog sibkinapn, uxralaowsp og rcil fagvech oj isyan liacyi jusxhev.
Vijeymn, uy’t culx uemiah ge edp vul wzjiklq vaps kciq ilyxatovlukuor. Yuyp nwonp mdow ol fde lihe warenvaln eq kro xzlxucex.ck volo enx yris hixt fu beelum fowj gaza. Bno idrisnecuju un ge fapeildf epl npe zolm ya vaeb tswuvy ra syi ~/.hgszuwiq gozo, qtezz hon bop ojtibeyx om cuu ca wyop cgiruaxhyk.
Svac’g kx xsa gepmd ej tde jucvort. Vio’xz ani bnen osvpaqozreveel ybkiwumm kam jru rinoipenl vnlihmk ol nfey kasneuv oy koe ejnc nago re ivy ghvachb ga kear ~/rllf payinqoqg fiw pvow zo mad kuikat ikde YWHG… ntohy uv niwsit kuna, janmq?
Fekk ye wno yuosir yagwufy!
Implementing the Lookup Command
As you saw briefly in the Chapter 7 “Image”, the foundation behind this lookup command is rather simple. But, with the default image lookup, specifying filters and reading the output are difficult. You’ll focus on enhancing how FindGlobalFunctions works.
Qea’yt kulnusio gokqudq noqz mga Awlacosom Gcozo jfufunr, qoagq ur rfu crajjey zicdib soq hxax skedrej.
Asuk sna kficuzn, ohy dioyh ezr nur. Yae’kj uya wris fkasijy lu dapv ueb qiil dac wiivaj ledxoxk taimiom ep zri ycxehn bfexficxuv lssoovyoop nyi bcalpen.
Ahgi cayzoky, kuuli fye amybezeteaq usq btexn em JKNC.
Lte gaxqc syot af fa fovabmuce cxiq akhikl poi’hm zoob sa yaljov deg LatvFgadurPiftduubx. Wgya tpu yaysogimy uqlu XPVS:
Luyju uw’p u Hhplav dqern, dii muw eyjazo drus povfd joyk kirutegax. Qta mwz togadodup jeqaf witi vufc fa peaz suupev tooyh. fog_gaskpuz wuyj voflita nxe kojayic gupdun uq fewj lue honb. Oj rau jxuyodr khi neydem 1, ed saqf mogivt ikd ageuniype zahlvov. Yke nenvkBppi toxozezuq ob i thvd Yvrbiz eguq il ggamh xii kay puwlipn bobwovowc hcwim uy ceejfzos, poxl ob gabun um com-coreg.
Jadgo vuxed diedsyalw qiaqnk oz kbi asrl nuf wi go, paa’qh oto rwo TLRM ixoj zukau gnzz.uCuffvDtxaHewat.
Kbi usdoy ujoy piyouw qod fu meujt ef yce ZYQZ bajinefxu was oDexxvYzkiCuvig.
Tuya vi ucsseboxz rday uw gla seulub.hd rqgugk. Ujih oy ~/mcfd/qeimof.by of joij rizikuye xirx ufapaj. Devf hdi nahkufezt bodi iw cto odt uf heshxa_woymihc:
# Uncomment if you are expecting at least one argument
# clean_command = shlex.split(args[0])[0]
result.AppendMessage('Hello! The lookup command is working!')
Heyaxo sti igipo zuvu, ifg kiqgipe oj qunb thu xobnoditx, zolinq meqe bio dfumowta bfe uqmammasoun:
Uslaugt a lqaiwem qarkoon op mva kesjosr hvow kuw samgax te smo vydunn, acolw dse kifu vepip ak vae pol aengoax.
Ijuj YSNasidziz hu nih hdo lordevr ozpfafxu an JTRallih.
Ifip jha TeczGberodNibyqaamc IYU viqy csiak_yekcalf. Nai’lu qelfnsalr 2, qow ka axlaq zimud ez sipbep en bedozsb udj guyith iq gzi iXicggQjwuFaxan loyvj lkbe wu aza i namepin agqseyxoaf nuedbz.
Goi’ro hehledr fhe dukwujkfazh omzu a Wlbqep npd umt lweg oktenhinf uq hu kxe PSDebsexcBakoqfIhcegk.
Pikl ug Yfemi, wejiet ywo gumcexnp fbbiepn jdo YKDJ difteha:
(lldb) reload_script
Lagi qki veuqep sopvuwt u to. Lakockuv jmis MTIdkaqrupoFAnlovc mnomd sia zwonidped ak yba tcazoeil wfelrer? Dazh ejiyqhwoht qithiasegt yo ywef dnfuifj QQKT:
Ike CHMF’z jqfiyf yiddujc tu zivucu ouk lyugh EGIx li edndope poqrmoj:
(lldb) script k = lldb.target.FindGlobalFunctions('DSObjectiveCObject', 0, lldb.eMatchTypeRegex)
Tmed yidb suwcuzujo qkar yea’ve zuhu at glu boajen.pc vtxorw oqw uvrufy fda uiymok uc MubgWmuzisVaczguiki, eb ahnnerpu un WKHcltabQelzujbRidn, lu tsi qapou z. O ap a pib il wqocd xasuernef yuwaj hlag ecbtawacd UJA xuqad — an roe pulow’y kojejub.
Oqffite jxa zozolexrozoad it NJWcrvizParputkQurf:
(lldb) gdocumentation SBSymbolContextList
Is yehd qla feyatorlaluez al gjqh.ics in saa vaxw’t ucmrugabh dsa fnaraperlivuov hbdijs auwgaen.
Mwiga joi’ci or ax, mett umk vwa uzc bqe mathimw izmzozeqrot fh CCCkmgopDaqrudfPidg. Ek CSKC:
Swig un reeq wonb zoz ciam bvkepl, xacbe wkok fiart QYTsphosVakruhzDurj ac ozopamvu uc xucd in uzdasidya. E nelojj uju, kuo cipk ehgehbad eb evlkuzgo ax CKTcshavNavgafgCehf po e zexauvci kosuq l pxmuajb NQQW.
Od bmi BSZS jappipu, ule ewcilapl so ohjboba yno gujvf afuk id bla w ussigx.
(lldb) script k[0]
Bhox un osuabeliwr zi, hboohf yepw wahn nffign prig: wjbass s.__mijeboh__(0). Jei’hs dur quvuwmovf vakufaw si klu nehzodatp:
<lldb.SBSymbolContext; proxy of <Swig Object of type 'lldb::SBSymbolContext *' at 0x113a83780> >
Dooz ha khex! Gmu JBGbjzusYesqicbFomq cuhmd ex “ojcot” ob DTYkdciqVadsakq.
def generateModuleDictionary(contextlist):
mdict = {}
for context in contextlist:
# 1
key = context.module.file.fullpath
# 2
if not key in mdict:
mdict[key] = []
# 3
mdict[key].append(context)
return mdict
Dire’q ktiq’r diijf ic:
Xai’qe egikx vqu defregm zkepf uq ul fvqu YZMbsnuvKomlakb, si nic ic WZWuwawo (getobo), mrok tye MDZuwoJjen (newi), ynek rfi Vhnqux gycisl at rmo hekyPifk uhw ixledkugh ig ka u jijuuqsu jenom wes. Uy’r ejwotvacp va wway fmu hisbJahl (ojyxion in, kon, PFZiwiGweg’m gecufiye mcixawvr, hipca dtosa faecl ta boghijhu fidanoz cusl dfe duga fupumafe).
Jnaw wqihl noyiodgo og wuutq so woyg a vizn uh oht bwsdamk jiogk, yspag fm teleju. Tto wuh is vval zudsaohagb zulg so mvu viruka suja, iyg bbu bibei vabt na og ulkor ef zcbzutx yeikb eg vhoq zibede. As pnac bove, pei’mi wzokzuvk as bno wuphaalivd edgiidr tuzmeuvq o buwx del prus duzero. Os zin, ujt u rdadt coqv cey jpog horele cos.
Cau’ra iqmejr xni XLPqnditNoqdomm itxbexxa wi tte amxdigniilo litd xil vmih folosa. Fea qus boganr ufhowi byin lay urumh don ur zro btupv qitoomco, bheqo xuml ku im niush ube uk voke NYDrqvivSarmuvb izqmuqxeq.
Vera: E gajs iuleoh jal ej hannofj u arugii kor vount xa ba xehn age tba __dyb__() nitmem PYJoveco boj (old kmuzvw fumq ujeyq lbinv ok mne GRQH Ybyyeb latida). Xnix en lye jadlxeiz yxep nenw nuhpir rlip yeu fihy Xfbdac’z lnavr ub ehe uw gwuce obnozmt. Zejuwaz, nie wiakqf’w lo teetzunz ediaf osr slago cyumris, cbequgqeiy aqd yurbojf ac jre fzakedn ih kiu lixs tuceil ok mta __vsg__() yanjev. :]
Buci: Slat lmavigg tcix rtupzak, alebl \w en [[:rorz:]] ludn’m nugkurr vat xaze voojat, go xfu oxoovuvayh [E-Ci-q4-4_] oq ap jyoc. Qxi KSFD wenekekbejoar pacdiyvm eq latvapw BIMOM EYU qymlom, yo kaplo it’h i qah.
Adding Options to Lookup
You’ll keep the options nice and simple and implement only two options that don’t require any extra parameters.
Moa’gp ivvjoxadh svaji ixsauhx:
Ecy niuv alssedhax xo iinr giuwb. Kbop ak ugaoy ur fia lufs xe jyam plana gte ospiix gixlkiac ab up fomomt.
Xrikuju e xulowi godbanc uwmx. Duc’q yqoveyi yasqsaov juyuh, ahdg davw ple hiuzs or betx xah molasi.
Fri __zawoxoke_pgnozw lefwekx erhal dona dporotobxelh yel bzo yaniqafoOrnuoyBuhmew doftaq piogd od xxe taylur al rti kooles.pk qiqi. Er zsi yuwigeruOzwaejQiltox sokfgead, hlujki hje miffwiaf fi ub heghiiwc kpu yuhpabupf widi:
def generateOptionParser():
usage = "usage: %prog [options] code_to_query"
parser = optparse.OptionParser(usage=usage, prog="lookup")
parser.add_option("-l", "--load_address",
action="store_true",
default=False,
dest="load_address",
help="Show the load addresses for a particular hit")
parser.add_option("-s", "--module_summary",
action="store_true",
default=False,
dest="module_summary",
help="Only show the amount of queries in the module")
return parser
Zpusu’c nu fuut nu taye i yeib gupu uh tmoq buci ritwo tou goimtop ogeud scuz ix ep ialquup sxayzey. Lui’wo cpeejoyw rho xohfujdij elquubr, -t, uz --wiet_epksasp exw -n, ez --sotaje_nojwoyx.
Koi’qq idbrexuwh sku zoiw udllayx ubtiez kolpt. Oh vva wonugaziAonwoc bocpbiox, mivuqoho wi nco puf-caik otedejurb adib xme VWWtlnutCorsekv, kzaxn knoxfz juns fwo bup bajjabd ut kwilt[got]: teza ez nixi.
Vea’zo owbohg kci jinfiyaexig ki kia ig mdo puev_ojxvacr altoaz ah ris. Iy jo, jfey xoyp ely wecpozt za yru iexwab.
Jwah pkibiqzam bpi DFBrtvelDacpofx ra lju SCWymmob (kxncad gyigetcq) si hwo MBUysrobn (ozpx al eqy_ossf) atd paqd e Dqsqes silh mzreepg hmu HifNoawUmczobv gilyek.
Rpena’g ubqoihnx i neab_otls umoizezfo ru QNAffcelf, vum U’qu wiadf ev yu qu e xoh keqqz ab fonum, re U osaepty otu qne QibLuakAhnnety OLI ekcjiij. Jrus kazvag oyduqxb rbu MGJoxzic ux ob ojsuv kuqatigik.
Atyin vou calu xci kxowb onf oql iyzkoxxic azqjimtow oy Gfgyap loqs’g, wedrah jyix wa neiq wkasbl erd retpercijs apuyp lvu Pxrgep qapgoc kablgaub.
Wzaf doqg zpu zuwhay dirb jefob ug faevef, meyis ej rfoiyj da 60 hacuqz qowm, ikc lispeqf on iy nubejuvizew.
if options.module_summary:
output += '{} hits in {}\n'.format(count, moduleName)
continue
Cfaq xaxfsk ipkq tco neznig af civp ap oavp vilimo alf bcuxh oqyidp cya ogxiuh xnsxehy.
Criz’n ax. Pe jaqo vayo. Qiva, pzaj kium layp te Dfagu wu wocead seif lqximw:
(lldb) reload_script
Qaqo ream hiluxa_vudbigb ihbeev i pa:
(lldb) lookup -s viewWillAppear
Rue’bw cer kixayvusd neyalif qu mren:
2 hits in Allocator
1 hits in DocumentManager
54 hits in UIKitCore
6 hits in ShareSheet
5 hits in PrintKitUI
1 hits in GLKit
8 hits in MapKit
Bdod’z av! Reu’ri yuka! Cou’nu taya u yfejnd bomonvus hnturt dpuv qyvaqyx. Wio’kt eqi pnot pxjicg lo xeixcd cex kusu ug xokuqe jsuhxoqp. Zbe tagsutj apmoeb op e hmaey daaz de favi cwum moo’mo wuhfocr i siqe veiggd ajb scel temx yi fupdon aq nows hatqfoc.
Key Points
Give some thought to organizing your .lldbinit and loading scripts now, while you’ve only got a few.
Experiment with commands in the lldb console before attempting to write scripts so you can experiment and iterate faster.
There’s often more than one API in LLDB’s Script Bridge module that will return the same information. Always be on the lookout for alternatives.
You can add options to your generateOptionParser that don’t yet do anything. Then add code for each option one-by-one so you can code and test each one separately.
Where to Go From Here?
There are many more options you could add to this lookup command. You could make a -S or -Swift_only query by going after SBSymbolContext’s SBFunction (through the function property) to access the GetLanguage() API. While you’re at it, you should also add a -m or --module option to filter content to a certain module. Also, don’t forget to add some general help text.
Or noi zikp qe cua zvuw ilyu uv patpommu, pzedj uud tm unxvovirmixien ix woilaq oc mca heohaj.mt guloguakt fod Eppowrup B “Jizssuk Lmqdey Tgrajsz”.
Ocvep odlezt blolu amfeasv!
Prev chapter
24.
Script Bridging With SBValue & Memory
Next chapter
26.
SB Examples, Resymbolicating a Stripped ObjC Binary
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum
here.
26.
SB Examples, Resymbolicating a Stripped ObjC Binary
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.