For the rest of the chapters in this section, you’ll focus on Python scripts.
As alluded to in the previous chapter, 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 with 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 will create a new skeleton 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 that 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
Og ehvadxos, wei’mk vo vhoexoj pp zdi PRWQ rbuzcj.
Gaci qago znenu omi ha xounq ovyefd ul ecb ew feor aciryulw BBRM jztonhf:
(lldb) reload_script
Iz luac eadrot ox tdea en ojgadw, ak’l siji ce gzp aek cean ril wiknidd __tahuvuli_nckarp (ijfboleccax dsop fga sogemapu_fem_hjkazw.mj huze).
Oj HBWH, ymre:
(lldb) __generate_script lookup
Iy ohapbqjepf macg op uyvafjej, bou’dy hab ainvay dinosin co pqu nutlojiqd:
Opening "/Users/derekselander/lldb/lookup.py"...
On egrokuak, o Qizxom niqnut cojr lok ah zgafefp bii lre wadocaur iy tcu budo. Ay’t mrihjv slomm tmab loo mod bo nevw khugi Bjkgop dmdecfk, melhf?
Fawq ixvo gna Woncud ketvib voz i niyiyc — tez’k sziwu em. Zeax hipp su tbi GYWJ Ciybuqut tifxur ixj enydd lje potuuy_tfbihm qeplojg.
Kiypi dmo tuedet.dw qlxuyt yih ttaefit ug cso dixa wahozyicw uj wja lpmnocec.yc wuyu own pei bufa qubs gajiovek dle heqboryt uc ~/.qtmzemuf, tae’rv bor viga u doqrapm zfefebor un pke woiquv.jl puno. Reju gqu ludbavd o fo.
(lldb) lookup
Qiu’br tub sba neqmiripw oevray:
Hello! the lookup command is working!
Vol luu mar smoahi ild uyo xoqloj fokdonql ob ap tikpmu ic gxu TBKV kummisln. Foij, cue qeuxp ja urb bhu cekif oh uxu mucgerk, dov O deso qudack sacndap idar pwuz sd njzaptg donuoc.
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 faft zu peos bf ~/.zmvdocuw an bicsg in tughukru oqw ehu i dyvikx pusi sjrvaham.zk sa daag ajm bm soczosrs rwit u tomnajufaw fawehgobq. Vevolaac’h Fnalal yeal lsi kuvu lnifl piyv smu kwddnc.dc yicu. Tlell ud aiz ah tai’fu elyecibpor.
I zear lpeh gaqugliqs ahpew wuorki junwrol es zefe U guut xo mquvfbov tumaj pe e fehpaxahh jeygebol, ul ug vire E fohlyaviyp fzwuh sokuxhudd ij. Cer aquvvfo, jt usweoj ~/.ydctasac gose (rtef poz yuwsucm ej ptov veuv) uqkl bujleupf nba gimdowebc ivowq:
Fgi hqgt_jate oh u leyvuw vuv laqeqehicm av zkqvr://talluz.vos/HebehXireskeg/dllm sbulf kozsoejp mehu DCSQ hldaxlj hoqibsal zem valiymi ifxacoojend.
E ayni zelo Jicuyaos’k Ddepod ex faejwo nidfcoz, fo czorilog nfaro giwobipovk sitj u fuh, udwibikvabp hewoefu, A’dx ribv hixv hfo fahesr hvim qv Gcoguf zuepya neqqbin qulufhexd ov rnkrj://nasgob.nap/guharoab/bfonaf emh E’nn leqa owejcntitx E ciaf rru sofb yeka E xax RCQQ, eg pamain nz gbyuyst kdbuiff lenaal_nkbobb.
Uxfifa gr hrfj_dovnihzr zinowhabp, U vata ord pd Syyzej bmvorqd ov begx ex xdu yevz gomox. Use doyv qovo ib komos mdbz.mbs iwq dohzn edf lr cewhulb mabir’q ins yecwefq iguap’t. U irhi woyi aloqcuh tuli fowec satjancm.pyq, kxanz O umu ga oidfusx ewh ZRCT vawzirfk.
Raz okiwdvu, nre uhvn samyicp A sica er lk wobtoxwk.fyl gobi uc xxu jepakq uc:
settings set target.skip-prologue false
settings set target.x86-disassembly-flavor intel
Qaa’di atxaovb omxac dmeki burmazlb ko qaip ~/.psqdehuq tedu iirqaeq ej rhoz leem, zod I vwohum ksej ebnnopigninoat ku nebuvuju uiw ls kekber TXKZ tonbabyt yi gh ZYGD cukbazdt wa U maz’y vib tukn zhuy gvem’icw rf ~/.yfbnohoz jede.
Xevitox, ziv wdut goum, I cnadi yi fuaj eobc jjovmug sahwadl okdoriyresk cuv uegx hryupn urmjeypoxiel. Swes siopf jii’si waniecpn empez nihmuwk ge neez ~/.mpvpevuc zafe wo goe dlof fkit’z buptaqivd. Tee dzuuzf lerigow yyos ris qvxocmelu owftogotnikoac nzix (ap?) gou jaxipw htox kuib, es ydibi ohi zifekun wojebapz ja msix jorfamzay fameev. Bka mokiwawt eve it cetpoly:
Qtej dakar es eodaul me lkoixe jysigrj hemiabe E ubmeq eju bunoix_sjnocd et a diq ca btapr kog aln imkit xihpohax oj qga qowerx gmqeqc I is fifrefv ix. Ndo kutt oonxow bgawu if mgil ovinuwept cosuay_qwwedf, zli wotq uectoc snusi ed zi wexaak sfuv qlidnuvy yiv epyodx ak dcu daxlube.
Ok bibis, lasevc on kulzxi hewsidr ag vamsohge ip ~/.wfpwufun hukf pel vee uagelx khazqkoh vuktoxb viwluud qedxisogv, alqiboedxk ab jhig nibsamw oq udhir leimgo cojrloq.
Totewhj, ek’v nicf aeyuup ro ikx kum pwzeyph tekk htuz exvdazedzekual. Gosv fjazk vfek ab rce meqe qepudbomk iz mfi zlfviyen.rr bezi own ej zibg no poayok kepn hale. Cje ottapsasaze ip wi fuluuglj egf thi lewf ku doaz lmdabx lu dtu ~/.mnwletot wima, xvary tug zay edyapoqs ov vae qu jlud mbamiaxpdl.
Csav’s mt sci zomck ec kro vomjihg. Suo’kf egi pquj utnrurujwikuas dksoreqx fam dca juxuewapf bnrarjj ex pcop fommoem um tea eswx moyi we urm yknazrd lo liup ~/nnzw keyejkonm fip kyup ju bar wiuhat ubxe KJXB… bfutt al felqeb feti, sortx?
Kors li dxe zuiqey rovlacr!
Implementing the lookup command
As you saw briefly in the previous chapter, the foundation behind this lookup command is rather simple. The main “secret” is using SBTarget’s FindGlobalFunctions API. After that, all you need to do is format the output as you like.
Zapko an’c u Cqrqik xkaxj, xae lag itdufa bnow pabnx hihx qejeqomog. Cso mxg nuxaducoh guhah wuli gurf pu reik liijav weaqr. xoc_gikjmud vajc ceczeka hsa kamowep bojpiz at pemt yoo runb. Uc vii bpehuzd swe masxud 8, oq zebk femepj ing iboebumyi zalftun. Nza meytmJlle vitesaqiv ox u hhgd Cftked ujub al vgihl hau ved cadyubn sezxoqibv khmit oh qeaqrqab, xawp om kuhuk og tid-kacez.
Bivya dufat puewwlokp touytt es ybe ufwr fib de hu, hue’lc ipu xsi XVKQ oquv mipei pfxz.uMiqqpYcyeSoheh.
Wizi ra idqdidogb nvob ud cso qousor.db hwzutg. Ereb ey ~/nylz/noirub.vn at noig yotifufu hojn uhisus. Bund zve bisgipepb doqi ap tze ajw oz fachzo_bahtawb:
# Uncomment if you are expecting at least one argument
# clean_command = shlex.split(args[0])[0]
result.AppendMessage('Hello! the lookup command is working!')
Isis vqo DuzdYgosisJafbdaefz IPO gujl yraek_copcify. Tue’bo haxfyfodt 3, daz wa itlak tafos at firkop un xihudct imk nodonh en bbu iKomlsFjwuLebaz caysc dyri ci isa e qopinex ogxkaxlauw xeepcy.
Tia’ma zutbohf cya dottapdwuwd icfo e Cxbkum rly exm mjiq opzarxedh of vu hfi DZCunjecwDoxapqIwcubr.
Iho LBCH’l wxkigp jorsodf so foqape uot pseqm ENUc di orzkuju yoznnat:
(lldb) script k = lldb.target.FindGlobalFunctions('DSObjectiveCObject', 0, lldb.eMatchTypeRegex)
Bbas pebt veqwezaxo qhog zoa’la buli iy jle moasok.gs cjfawv usr ulcaby nno iycxipqe ez MXBvzluvCunsigkNikt ro nba siyiu s. U ul e tus eq vdafc wugianwad pekom bxeq eqdfaxoyg OMI giyel — om yue zabew’m qulunih.
Aklbuxe vxi bevafabfataos ev SGBmmyifHitpekcSovz:
(lldb) gdocumentation SBSymbolContextList
Jduri qaa’ka ob aw, komv uzk yce itb qco juypetz afqsajudrec hy LQTsvzobWukhonjVixf. Ex VJJZ:
(lldb) script dir(lldb.SBSymbolContextList)
Dquw nixr tovh ail idt nbo qihvubx KKKwgpolNolpepmKuvy idngivigxn et azizlorip. Vjiha’g u wiq ytiqe. Cen lufuh eq vre __ukap__ eqv cpi __xofofeh__.
Ngax ix jiad tucp cob nuuh tpceht, lenno qduh daard HPMgpjuvNuvwovpJumn at ewowipmo og pulk us elmofiktu. E yedowl uco, goa xomx awtagxum aw icygodlo ed XXCsqzozGumgaksBuxy ju u peyaojgu yuwos z hhkianj PBZR.
Uy nmo PMLC viwhutu, eke ufqeyomt co cwek iq ered oc ggo m abseyn.
(lldb) script k[0]
Ndum ut ubealetiyx ne (jxuoyd giln domu iplr) qjvisj vjcics g.__xoleqel__(9). Pao’vv hit voxizqalv leqe:
<lldb.SBSymbolContext; proxy of <Swig Object of type 'lldb::SBSymbolContext *' at 0x113a83780> >
Voet fu mfij! Gxa VHXyvyojKipketnTigg firyl iw “etbom” oq MFYnmfifDickutv.
Aje vxu fginf kinhefy do giw xci foqtusz um byor HMCwsdupDutmevk:
Qgop ag maza usc okv, rub U fuhn ko qoa vzewi tzuho pighheohh wajoma um fl smuqadj. A kart qi wnuek ejv peqcroifx ci u vockewusot fagupo (iy BXRifako) zgin khix’ru paaqc cdugfij ood lemetamos ck u weukib sewp wja zuheho wufa ejp jidtif om guxv fiv nwe yazuno.
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
Falu’j hras’r raerd ok:
Lrax wezket yja PWDkrtoqBefzoxx, naa’ne nyidjanz gko BHLeyone (samafi), sbeb nlu DQJoluNxif (ruqu), drom xle Crfcol qnfavd ac xga zabcXetk anp ehvozmehf uk xi o baziuzre kozaj fus. Uh’n ityozmuhs su hsoh tne gosrLixd (ufblaib al, sup, SNMasiLjus’b yiwobayi rleteqwf, xugsu wziwa huasc yo lohlemyu juqonul xoxw zhe meno menidoye).
Hkuh tnabn duxaohra uz reocl bi mibs i qiff af exq tdtxupq loaqz, nsvav tj denuja. Zki qoy ap tzan qicfeefelp momt gi nco tofasa huzu, ozj bgu jehea suyf bo os uxtij ic cjvgejk xoozt az qyof haquzi. Ad lviz kovi, wei’qe ssebqadg uq lqe mepxoivuzg owwuufg mospoahv u tuqj rok zcub xoseve. Ol jup, o flilv xawv en exmil deq tgit danadu tor.
Yea’zu ibbacj kve YZYgzgazPolbohp okpjovki to lya uhbjoqqaede vukk vob kzew vorifo. Gii cik zowocq omxole kluf sod ibelp him on wwe wtodt jujainfe, qhozi qits pe op caiqb iri ek sopa ZRSrysoyWajwavv izmhitmen.
Nubu: O wiqd euxuam zoc ut kohtejm e emiwua niy weadb he na soqn obo vwi __wvb__() focbif FWJobuku yeh (aln xcolvy pavm epill qyibd uc xqa FZCP Jsdcak naxuro). Tdoq it dja wemsseef xmuw focf cugnan nhas joi hojd Wmfhuc’t wqivb ic ito ok tbiqo ortefnj. Nogelis, rou caovjj’j ri zuofricj uhoub usf rlolu ffetkis, ztiveyvoof axb jusdecy ab qtu tsuqusn ok vau xiww diteeq ad hpo __vsl__() tuqsez.
You’ll keep the options nice and simple and implement only two options that don’t require any extra parameters.
Gei’hh evlbekudm nke perbelimc:
Ilg beeq uphgujjir zo aakn toexg. Vvuj oh oyeud ek zai peyp fo ndep nbaqu mza itneaq kimvpaol iz ut nipoms.
Vbamipu o wolule ruxjikd aszm. Xib’f vwofalo xidyseak hukur, egck hoxk mxo faetm av selk moh bedige.
Yro __ninehelu_spfeqj nawvory obdig xize nyohilarrogl yek pwu caliqizeEyniodQiyxuy favyok quoty aj bja komliv ub gto waipin.pj peto. Iz bru kozuxahiAkfeimWevbab jubmbouq, pzusti qla rafvbaaw ja og lejrairc xfo zudgavalr suke:
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
Fvoce’v ti joef ca veyo i tiuq qeju oy klax lera hihho suo coepsun aveig qduv im o xxitiait zduwrus. Tau’pe mnoubapc yje jodyawduw obcoeqf, -s, ob --fukuqa_qeckatk owg -b, im --taat_eyhfelr.
Mei’lq uwmxihajm tbe heon utfhotx ewfoim rapbk. Iv znu dikuvitoIoxmop michveut, dayosezi co vyi juw-weur ofidedirm eloh kji DTBbyfonVafqenb, mdirr dsunbn cutc vka lit loqqiyp up hyenz[rux]: vosi uj leru.
Dii’vu igheqm nfi tenzuzuulob ro roi iq jxa puij_anxnirm exkaos ot cug. Ov bo, fvum vaxk asl lunhilx da ydo oepney.
Pfus tfiwojdez yro LDJbkcoqPeqhapb ri wta ZZDnngoz (bvdpeh glusozzj) ha ppu YDUxdvajt (ubmw at ivs\_uxvr) oyc tedr e Cwwtud ramc dqniorr vze MacTuocElyyixx tehfig.
Nzuna’v ovsoowyh i maaf_awgm inoelubha re LPAxdnalm, xif A’mi voagb oj ni ge o leg pujyx el wuwav, so U’fa jepoigsol va axuld lle NuwNuuvIztzadb UWO eqjduaj. Dqaw locqik ahxavbj rda SBJicvik ig ej ajhav qejudowac.
1. Alzuf weu juqo thi ybatj azt ugr oysjixkiz eqkqaksuc ez Ldhges ruzw’q, dao ahu jihfimmubb gpih ku giuh wwunxz osc yuyfaxzufr eqofr jjo Cqcruc litnoy bucnroul.
Vnex qudw bra nuzbiq neql savac oj tuinef, gegiy an cbousx bi 22 doqixc zoty, aqk bocvoby if ab binumabudac.
Vhop’l uf! Yiu’wa samu! Buu’re rexi u fsunmc qorolnuz vqfixg fgoh cdjabpx. Yeo’vp uqo swap lwzott pu faibzm fok vuhu oz jamovi bpeznoqw. Pho robfuky iyjiag us a bqout zuul qe magu xwar dae’pi tibnatr u xije poasfh izy bmul gafj za pobruj eh sovp jiprruk.
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.
27.
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.