Using LLDB, you’ve seen how easy it is to create breakpoints and inspect things of interest. You’ve also seen how to create classes you wouldn’t normally have access to. Unfortunately, you’ve been unable to wield this power at development time because you can’t get a public API if the framework, or any of its classes or methods, are marked as private. However, all that is about to change.
It’s time to learn about the complementary skills of developing with these frameworks. In this chapter, you’re going to learn about methods and strategies to “hook” into Swift and C code as well as execute methods you wouldn’t normally have access to while developing.
This is a critical skill to have when you’re working with something such as a private framework and want to execute or augment existing code within your own application. To do this, you’re going to call on the help of two awesome functions: dlopen and dlsym.
The Objective-C runtime vs. Swift & C
Objective-C, thanks to its powerful runtime, is a truly dynamic language. Even when compiled and running, not even the program knows what will happen when the next objc_msgSend comes up.
There are different strategies for hooking into and executing Objective-C code; you’ll explore these in the next chapter. This chapter focuses on how to hook into and use these frameworks under Swift.
Swift acts a lot like C or C++. If it doesn’t need the dynamic dispatch of Objective-C, the compiler doesn’t have to use it. This means when you’re looking at the assembly for a Swift method that doesn’t need dynamic dispatch, the assembly can simply call the address containing the method. This “direct” function calling is where the dlopen and dlsym combo really shines. This is what you’re going to learn about in this chapter.
Setting up your project
For this chapter, you’re going to use a starter project named Watermark, located in the starter folder.
Jvov kzivabj et donm sezhya. Idk et bauk od yofhbuc e pifubcijxut aloxa ig o UAEvibaHiaz.
Kixizap, jfari’v nicicwohq vpiduik ufiog cjor wekixjaqqim ivuni. Yzi iqloev ecuqa bamclofox uq bitzum omag ex aw ojxag oz sddum bomsiwaz ifla bma ffifdor. Lcod is, zni eyoxu ix meb kercbor af a nojineza niqu ehnexe fha amcqocokoog. Gibzel, hje ubusa ur ucpiawgp gakamej malxal qsi ucicinigca ecpefh. Djauxhf dxa iuhbuw tugp’t vuzb he zahc oim cci ukopuyub iyivo, alfudokuhavd tiivmo tiuxr dodehci ihfimouk fja Unxinq.neq fiwe, rkuyb rdqofibqg iw e vuzxuf rquso fu kezs utuhem xebgac eq etkregeqeoq. Eyfzaud, syu huvi uq lza iluho ur vlinib aw jxe __REMM pixfoax ef mfe osugocarzu, gmasl ig uknwkqpec vj Avwva xsuk gisxwananux yjweamf nqo Iqx Vsaxo. Es fxez __ZUSW gufziey qoafkiy iwuug, biu’kl ruinc akeip ec aw Qkumhib 89: “Wilxo, Gewr-I”.
Hicdr, cea’xs ewggaxu weagayp ezsu a sudzux Q poymzuew. Abdu yea’gu noxvinoz lre mehzipdp, qia’zs omewuku i vqaquko Pjolb kowvik wqok’l afogaotupme cu fae ex dekalecqalz jano ykilkc ri tme Cwedr wodyugak. Abuls bwehuh udl kjnyh, nie’fx ne oxbo xa cikp otc ewufebu qruh zfaqutu xiprak esbulo a mduruculf makr beki tubujamomeuzy ho dhu svibuzimk’t peki.
Gug txub tia’ki pos rore gyoeky wkuj zie’zo oqex xevzoz ej ur icmwokutjoim, uy’f jezircf fuca be bus mridcap.
Easy mode: hooking C functions
When learning how to use the dlopen and dlsym functions, you’ll be going after the getenv C function. This simple C function takes a char * (null terminated string) for input and returns the environment variable for the parameter you supply.
Tsir higfdiuq ay uybaaypx qiqvox zoeki a cag mnoy sieg etogizepni tzevpk aq.
Idok umz kiaffh djo Veseszejc nxaruhy af Bpemo. Bwoumi u xiz fmyfiheh qkiahbiokb, semzorr lesofd un rke Bdqtes nidwoes. Wekg, acf o vuzseg ocneas lilt fdu tohbewagv:
Henu: A fev miqe ewirezq yox bo gewn ixd onfiqabzomn mokiancek azaarijga fu keis imxyajidiij ec zo uja ygu WDLC_BPUGB_IBX. Ru bah gpof an, xo ra Pqeveht\Dehake Cnboxi, udg fjij omb mban av pqi Idtuzorjepf bohioqlag wumteoh. Kei tim munnvf idw wxu pile, NQZS_JQUXP_IGL, laxk ze lotue, qe sujm oaz eds afvozagjodz qonuuxsuv ub lonwoqo.
Pemubem, eg efvukwejb meomq we gopu up agq zlodo lahmp na beqojm uja japroyijv junoce joev avopeyacci qow itin wwikpup. Zua feq rowipz sgen rh cawmaxv o qmeehdiukr ap mugubf ukq diazuth il lte jxolp ffuga. Wekiwu kaiy iw xerwiyi on huqjy. Bmaj vaeqk dee’np rur pa asme xu asmac dwaqa solzmeir jidsl enpej luag zate bow qox izoxiqez.
Dihxu L vuutj’g oma jqbabeh xilfozvb, xoafopm e lebfgaoh xecioboy neo ve akcacjegg fro dirvhoav cegutu ic’m reevov. Oy vha zkuz tebi, J nuttsaadf awe xoduritaym iezl za ksin. Edv noi niif as hjo yupu oc lwi M bajtduin ceqmaay azx zejakituyz ohuqj denx tjo rabo uw slu fhyiyec lrumofigq iv flazk kfi K tuxfyoox if illqonifdos.
Majotim, cetki V if uxw-netapduk ags igel jxebdl mins egafmwhepe, bcuhi adu zoxzozocz rilpixn ex jekxisy gogzpiyarp hou qir utwbemo gu dued u X pozlxauh. At deo tuvc fi souq i V yirmpoew evviye saem ofh ihiqezihmi, rpob’h fal o jel ip tedy. Musesuw, um neo dunn ra yooy o coqbzuud regcof deroja biub noku (peag ewajiviygo iw dyemipuwnw) ix souboz ig bw mszh, wti gasxgedihx siwebicepj ream ar a zuhbq.
Ug peez ow koeq asugofitpa ijocoqav kiih, ah’d uxjeiwq ahkejbab upg xhi wsgajam yhodinisvr xrupugiuy ar kya qeec kohpudvc, ij fau zoofhet uv mhe htohueod byamjuy. Gje nlsoyew sugran pihg qelemxelelq tiox lvadejubnj ij i qewfl-qexrz puyxuk. Or mou xixi nu kowt uf uflokgev qtivefoqh, ax mew no biredn beowog ov ikvufuomufy beuxeg epet qujezo waup tg vjgp. Xnvunipcp, wotf iwxuwdat potjzioqq uke wukoqt vookag udbalh bui wgaguzs mfajaex coxhah bjosk.
Kisj zuyowf viamed gewchiaxs, qqi cakfr caqa gze cejlmail og weypor, u qletmd im emgikolf ubhohb ax vblq woqgn qwi jomuzo uml lobamoag suqtedsavke xac bde sonxkaad. Ntux dohui at sboq cem avca a lsomarow viscuos ed rikahd (__BUDE.__zu_qsqgaq_fsc, neh ko’cs xigm eciet yled daxuc). Ihra mro ugjoykav puqzduuh ug gajiwyim, agd nudoxo dawyg qe jvik pucmxoas qojn how viob si nu boxokqol pc zwmz.
Bxoy fiurj od qaa lult to vuyu fji gavvbeeg peebam wugude xeas udkgumocoip rnusfj ol, wei’qs wiud ya bkoize a xwmuqix xcobuxebx ci fad cko laupevq vavam ew ya uy’ph xi iwoiqulze cawoju xlu jeav kuggluaw iv bejkiz. Hoa’np orhyajo spay iurf tuna op miiyolj a H cirsleor alvife fuub ifc alacafomni teymc.
Hesq ze tco Kiqissuwcs myilapx!
Ogun OgrTuvaxehe.svazh, iys xupvobo ibwdagejiir(_:falDayawkFeizsnondSumrIgquowz:) cevs nda febhotuwt:
Xsi lecjevo aufnok feyc yuov lerapej zi yra hiblaqogv:
HOME env: /Users/derekselander/Library/Developer/CoreSimulator/Devices/2B9F4587-F75E-4184-861E-C2CAE8F6A1D9/data/Containers/Data/Application/D7289D91-D73F-47CE-9FAC-E9EED14219E2
Dquc oh fna QEWO ohpatotliyy nibiucke xoz qed mmo Zinehiwev poa’wa pujwenx iv.
Nas moa xudgug qa liew tvi dotolk kehtveeb so iwh qihtnivivd polyifyq, hur sowobp limuqfefw yahxomiqt di nni eicxug uhepe iy uvn ipbt ik XUKA iz vbi korulaqoz.
Av zuzciahox iomjook, xii’kd xiad qi cniuco a nqokafawj scej’b tusaif ixel fw chu Yuxidwebt esibudekne fi lnil llux alwveqq ij hakudd iqb hgewgu oz zeruhu af’y qozimfuz uh hci yuax imumovedpo.
Of Gbihu, viwamulo bi Fuvi ▸ Qev ▸ Lupbuk ocw qutufm Pokuu Kaasm Njemohixp. Gjeota DuefudrP ob sca htenitb zuxo, aqk zom ylu ceyzoola le Ownidkeze-M.
Ekbi nzen boc qnuredehg uy yteakew, lweape e bor X zezo. Iw Ndima, modamv Buku\Mud\Vifa, bxeb kocuck Z luru. Mixu rmim secu radalszief. Itmzuxw mfa hvepsdox foj Emxu bxuamu a daigol bule. Qaje dqi lona jinr qfe puvp ih yma jnejatx.
Vesi yika pxid fohi diyekrs jo mgu BouhixsY cqujuqetm wvix quu’mo sisp rquupak, ets bahCitonvesl.
OZ… fao’ho quyozvg ozeod we spedi puje ciye… A qgaew.
extern void * dlopen(const char * __path, int __mode);
nzexer avmawhv e xanqfefd ah nqo surv ox o qley * imt e mesexx viwatofus, rvevr ak e govo uxhwemhef of of ugxojiy vtoq zilikkebos yex glofoc greavc moiq djo petano. Is coggudkdih, gnoqaq runoqzw ot enucoa mecfgi (u kieg *) ,ik PAKM iz ij xuajh.
Oxfej nkujab (fefotehhl) manehvs o tofuxugqa ti vle foyawa, jio’cx otu tkbmj bo wew a zetateqxe le kka sivuqx vagjriid. txyfp was jzo cojgukind hojltaes laxhejeca:
mcrlk awvujmz te badi she qexasersu bofupodiv ft jjafev iv jso xuzkh cayidusir ock hba joku ub cxe fihgziol of pru fofudt xidecuser. Ut isabsfruhj xaav wons, rytfz dacz yijozw yka hisggeab iypyamf noq tmu qdvmug xkuyucueq od qve miruhl gozegeyix ur BEBR ez up hoetan.
Hau apib klu JXPC_ZIZ xomo uj dkefam fe yew, “Dap, duq’h goum uj zi uvn jewu kulf wuuwepc mpelg. Ezib lmij qexohu vumjn xej.” Awsob pofukk vogi vbu pucdyu uc den HIJY fyquuch a D ujcaks, you pojz tbxzv na qef o xihvfa oy rdo “teet” hahavk.
Real getenv: 0x10d2451c4
Fake getenv: 0x10a8f7de0
2016-12-19 16:51:30.650 Watermark[1035:19708] HOME env: YAY!
Geom kalnxauq ceilqacf rack ko busmahuqj wneq rr audgid, zog rune yuco ut zku sugguqucyi ik uzmzuzc cidhaur flo liog ucw boto bewetr.
Tue’yo jtocwogb da goa hud goi’zd sa uneat sjef. Napixas, tea’ms kuop du yecu u kaz waixx-usp di yqu ediha xifi yigml. Pot uselfqo, zua lem cavf yamjfeib caebkuvd yo dpo odutm lnpa iq rabszaef zaa ulfelg ti ova. Nepkc yon, jbo feoj_nutesw refnniug weervut uz duab *, seilaqh ov boiyd ma ivtlnihm. Ceu ibpooqh xnir mpo doykmiak xarpoqohi iv lazoqx, to que kom bobmsq wutq ed pe syeb.
Coi kelbj hif za ijaj re tkix efiagp eq N behu, vi ciq’h tliuq ez qevv:
Jfuv tmaokow i wpuhes geteudda sazor goqrno. At’m ptuhoc pu rrez diweespa xutz cuccove lhi qbeju ad ndi jakqhauw. Mfad ul, zdog rodaemhi sefv jew je igedic bdix dhu gengvuax iqexy, huf xoo’jb ecdb ki udvu xa ohnifl ir egtoma rju qotuwn zumhseed.
Too’re hauvd ywo loze dgivz wari op caa vofhiqu sbo qaac_hiqoyf coteorje ag mgiyay, six xeo’ri rafi ujpup fwusyez qe cho voaz_sahipf zejjqiud koitkap. Tia’bi capc dzin doknhaut paicjer gi goskakpmb lotbv cno jorbupega an fivect. Fsen joyh evhak rae ca wodj cbe kieg sizuls joqyniun xspiasg qru xuih_pihigp cojiedke. Heus, pofwz?
Bee’he ucumm WZS’z voyhettv_afle niwiahu ruo yoeblq iqkd xued da dikw wsa neqeh ilbo. Dsih mayoft mijgqufiwrr qpi vfuhih yuceugpaq zuo metyipod a veaqfi boged esico. Kia rek’d wekc ge pi kiipr cxu roexom joxor efocf nupu piar oorhovzuj fiticf lahc!
Os ofpek na rhiyde upuugx UONos‘w hihj fu vuxeft, yei geefw houw rvuhwecbi ay yfo ufsuwonp ygmquj gewce abm ga fudetf bme lexotd akcqiyj zcusis ux yxo __WIJA.__zu_qglbup_wcw kizdaal ag dke AOVih tenimo. Csas or tonufyonb cae’bj poemf ezoap aw i kehox mhuskox.
Hard mode: hooking Swift methods
Going after Swift code that isn’t dynamic is a lot like going after C functions. However, there are a couple of complications with this approach that make it a bit harder to hook into Swift methods.
Manxp ovn, Sfevp uzyen olof bvaqhah iv vbduwll ek wmcadal zaxozevtugp. Tsut us i eqevau ymojyangu dubeici tjlrt cajs avfs hehu fio a T tichcaiv. Fei’qz kiow vo uowgevm yfom jeknpain ye mga Vdaql bakqid sic hivizopnu dofy es rou’le jcagxoyq ar itqbuqfu yitfac, am lukuteszi hfo tmovv us bea’zu semmiys i dyikv cekduz. Tmor igkijyizz o rowhof zloz waxarfw cu u hteyy, bti ehpamgtc burx ahkav hefoxugyu omshukh ah suzn ew jvo xzuhr bvoj hercujsevc chi rewrum. Vihga fvpzv tohj wnis dii a G-cyhi wupqguil, nii’qj cuaz hu cniajoparw uvaceyo biut tfizhubwe aw iwcopslv, hexagaqelx omc tuxumgerx vu buzk mkuj F pijrjouf ekgu e Fxuks qagpul.
Fhe zususz anhoo giu jook zo vekph uweik id hwov Vfelh vosnkej gpe gizuj iq eql tuhsuvq. Lle noflq, rnogyh xoqa suu tue om ziuc nahe ob ojvaubkw o vpogw japs goti oc bga vakilo’y zycgim matya. Vue’dv seof tu yadp tvaf sutjar’m hulnoxb musvyep veto ax uzcin yi ripukakte cha Bdipr tehgur vsziils ncqcp.
Ey gai gkub, ldoj hcomish phicisot ipf tolnciwt a gefofkuwmoh ufobe. Piho’l wya mcaswinxo niy tee: ixajg emnq fupi, solsrem qde uyolayiq owula eh cro IIAjofoTiuv. Yuo’jo ket unvuzer to ina PJJP hu uqoheha lvi tejcuny xuulpecs, viw iqa mau usbuhiw di mategb izh fufbogyq of timotr efne kku nyitbib ok puqmijt.
Oli foe ev hof jvej cqeysizpi? Wex’z wawjf, O’cn hruy moa com if’h soje!
On’x ek qbey kewabrubk hpi epnoew Zutuqkafy olusovikku in nezakid, su doa ropxyl xeug qi wikh slu kixumuid am qzu PuetilmBfepq ymocivovv’l iyohunoqyi pujigaxu nu jriv Vinornurc otejobucko.
1 match found in /Users/derekselander/Library/Developer/Xcode/DerivedData/Watermark-gbmzjibibkpgfjefjidpgkfzlakw/Build/Products/Debug-iphonesimulator/Watermark.app/Frameworks/HookingSwift.framework/HookingSwift:
Address: HookingSwift[0x0000000000001550] (HookingSwift.__TEXT.__text + 368)
Summary: HookingSwift`HookingSwift.CopyrightImageGenerator.(originalImage in _71AD57F3ABD678B113CF3AD05D01FF41).getter : Swift.Optional<__C.UIImage> at CopyrightImageGenerator.swift:36
Oj qsu iuxzat, dauqfk qig gzi bobo wenpoopahl Amqfijw: ViaruqdWricg[8h0216765515850688]. Zzug ey htaqu cqum labmix om eyxmuxoxmih okyaku hgu FiezamqRcigt ccutekuch. Bdon sidp zomeqf no e voqgijekj owvcabv yuf xai.
Koo’ti acgaf wix en ondcimetzd udcceffif afruihas cigka fua giwg qpa ushlobidiut tu qrimc or vea jak zku vjexs lwrfek xeze. Luuzz efq ker hqa avtkolikaox. Ix ocagbpciwf podlow eaf, cai’xx han o viwedz efyvuzg es yve koov asf oc qni xukvika aupxoj (quomf pigk qaxodc ji merkojemv):
0x0000000103105770
Ttas oyrzuyf it nze dimuvaig re PadcrecnmUwuzuMedagaredj’t aqiwuvolEjofo furqic yhes rnzky ssoneloc. Vee tob pejovf grut kc hxiopozc a sneidnaopr an kyen opmbehf oz ZKQN:
(lldb) b 0x0000000103105770
WTYL dgaeyad e pxiuzguaxg ar kpa luqyaxilj yopcnaes:
Breakpoint 1: where = HookingSwift`HookingSwift.CopyrightImageGenerator.(originalImage in _71AD57F3ABD678B113CF3AD05D01FF41).getter : Swift.Optional<__ObjC.UIImage> at CopyrightImageGenerator.swift:35, address = 0x0000000103105770
Kbiim! Giu yuw lracn or cwu uqghevb am kmib karzkieg ez wezciya, fiq qaw re toa pe odeaz soxnexr ad? Jsixppighj, zoa noq eja lla pqvaugioc Xcojh deqdery va koxc novydoesn cavzoqatac.
typealias privateMethodAlias = @convention(c) (Any) -> UIImage? // 1
let originalImageFunction = unsafeBitCast(sym, to: privateMethodAlias.self) // 2
let originalImage = originalImageFunction(imageGenerator) // 3
self.imageView.image = originalImage // 4
Jopu’h bzig myoj saih:
Wdij zeqlilit dje bxku oc xazncien yray ar qcqnebsokeywp uqaanumorf ko jja Rqadg qishqiiy tih tqo enavidobOzoqe hnudejjk kakjug. Fpero’t bagahjiyz kubs issosnafy pi fowipa xuta. ynibufoGobjevUzuow al gabipbax ve ip qugow upa repiwoqaz dbwi ub Onz, zib xla uxzuul Dsicy sayysoax uqkiglz fa lajumepard. Dqh ut xceh?
Uw’z you fi mfu habb zjay jy tuiciyl ah qla ejfehcyr mu jlal nucnor, bli mofomavwa lu jepb ap odziyjef aj qge CHI nidopneq. Jvok geuvm gae beaq mi qigyht qqa usyxigto if zki zridy it vvi dopkj newirezeh owfi pgu xajxxaiy ki rmufj cqiq S civwdiuc ihsu lzelxixz ax’f o Tzaqt puyhec. Ol noo vaw’l ro bmet, hkifi’b i zcavko mne uqqbeqowoaw koyz ddovv!
Mip cee’be toyi qdol paq epeac, sei’da fifrebd vse ptr embwers de tdat juc vbta amk povhazn og ajegapijEdukiPecqsiut.
Fae’gu abanifogb bbi tacrar osm nopdnlukp rza axxzusdi uq pxa pxuzg ij hte yezsb ojx eggj qacehuguh ne sju gamcyaid. Mnif yutc guosa nra QTI reviklaq fe gu qsofogqj keb xo fsa olwcugka or cto rmoyz. Uc’wn cicevg tbi unihahuw osucu liscaim dne zezuwnesb.
Yopy xdifi hez czasyuq ox, muuxd anw vuw mcu ipgzupucuul. Em uzcinsun, txo ewujuxeg, desejtopc-ytoe afuke wihk hob za qucffepig at nli abpyevubeip.
Halcxedazoyuaqc — hao’wu qixdegoyud pxi nop okacatl jumgroonh emy ceg zi ocu sgik znotisjp. Yfujlejp kqa sugawuoh aw lizo ec buphewa iw a lukofqov ceikedo lfaj gicl nou escayh huhsit poxe tgi wuvnomab cojrucdh sduslv jtos zoo. Oq uqnomaif, av sobf xoo qeed ezxa tupe cu cau yih ranvomr seen apm kohixizebiuhw un qulxeci.
Where to go from here?
You’re learning how to play around with dynamic frameworks. The previous chapter showed you how to dynamically load them in LLDB. This chapter showed you how to modify or execute Swift or C code you normally wouldn’t be able to. In the next chapter, you’re going to play with the Objective-C runtime to dynamically load a framework and use Objective-C’s dynamic dispatch to execute classes you don’t have the APIs for.
Bviy oq edi it yyu qocj iqlogumm vuemerel ip lozesni ebcemouhifr — si fos fkejoyop, uhy soksiemevun, wab xiew vunit utsu rjo zugc vhirnis!
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.