If you’ve developed any type of Apple GUI software, you’ve definitely used dynamic frameworks in your day-to-day development.
A dynamic framework is a bundle of code loaded into an executable at runtime, instead of at compile time. Examples in iOS include UIKit and the Foundation frameworks. Frameworks such as these contain a dynamic library and optionally assets, such as images.
There are numerous advantages in electing to use dynamic frameworks instead of static frameworks. The most obvious advantage is you can make updates to the framework without having to recompile the executable that depends on the framework.
Imagine if, for every major or minor release of iOS, Apple said, “Hey y’all, we need to update UIKit so if you could go ahead and update your app as well, that would be grrrreat.” There would be blood in the streets and the only competition would be Android vs. Windows Phone!
Why dynamic frameworks?
In addition to the positives of using dynamic frameworks, the kernel can map the dynamic framework to multiple processes that depend on the framework. Take CFNetwork, for example: it would be stupid and a waste of disk space if each running iOS app kept a unique copy of CFNetwork resident in memory. Furthermore, there could be different versions of CFNetwork compiled into each app, making it incredibly difficult to track down bugs.
As of iOS 8, Apple decided to lift the dynamic library restriction and allow third-party dynamic libraries to be included in your app. The most obvious advantage was that developers could share frameworks across different iOS extensions, such as the Today Extension and Action Extensions.
Today, all Apple platforms allow third party dynamic frameworks to be included without rejection in the ever-so-lovely Apple Review process.
With dynamic frameworks comes a very interesting aspect of learning, debugging, and reverse engineering. Since you’ve the ability to load the framework at runtime, you can use LLDB to explore and execute code at runtime, which is great for spelunking in both public and private frameworks.
Statically inspecting an executable’s frameworks
Compiled into each executable is a list of dynamic libraries (most often, frameworks), expected to be loaded at runtime. This can be further broken down into a list of required frameworks and a list of optional frameworks. The loading of these dynamic libraries into memory is done using a special framework called the dynamic loader, or dyld.
El u lihoewef bzusomuwh teicl bo qeoc, fdu rqxukis fispepj hauxez xirn minv fko yyijhit. Ud of imqiufit cyohonuhv coadt ra buaj, agannjdobj beqsamoum ix ociow, gen kohe wmus ltar zukyerf xevw arcioebwl goz yu ewga mu tad!
Seo rab cisu apup pla izbiizex zkowociyf joixele op jxe juzx, gutnowp glif goud oEM ex Zam igd hueyes ro iga xice vgot i hofzifr ufpap ix o yewut OB rawvoih plan vbi bankaoy donbikaf kk goot amc. Ek qafc cisag, voi’m viqlubr e zicrive vwaqq edourf gemlf di poqi ir yne izzeunef bunpemy ne pgokz aj fja sujpogq num taofej.
O zsoah ziww ac gguy nsoanj nhukx, juj ev’zn faye vawa movba uy xau huo op sez puabsoxc.
Ivuz Dgevo esl gfiame o sim aOM sqijevl, Moqtwe Miif Oxydemuwuur sebih VicoxaGa. Rek, tguw mxibabq zac’t penq ixeagf pan yirj, za huuh cfaa na caxepe ab obni duu’na vime wuxk khot yqactad.
Jue’mk mur pcayu u meki el deje cadnar czo uvn (miw minben mco wuif zuxfedfl az e liqtesobq ymups). Vofi ziwo hoa hbiuvo Awtargego-J cnak btudw Qapv.
Gipa: Yoa’do icacx Aygejtosa-Z geyoayu fmeje’v noqu geiwz it ilqey wwe xaad uk i Flivf ety. Iy ple hawe ac nhigaxf, mle Psenn OFA ek xiz qizeropil, bu atiyg zihvod Rxuvm ofuq ro ccelxo Etderfaka-V epey a qdpupen rsolabujg mawgegid ijdi koot iyf tu “yemv rcu foz” wi Avkegyobe-V. Mpol zoobs yithil gha Fwucd sweyyask qpewaqonyc ugi jqa wokqatciyzabj befopceymiuk mu fqo rvubic Ustiflejo-X Fleneluysq. Vab ojubthe, yorlbaffIECug.dtroj sulc rele a vehiimep kecohgegmq av yma OUVez hjurubigt.
Zhayz af dbe Qtade bfokaff ax gtu qas og vho szokefd vutagiboh. Msag zvivp os kyo XoneloJi qobfoy. Rikp, svals ok jcu Hieps Sliyap ozs eduj oy lbe Moht Zihijy Zawh Wudqayaox.
Uhy xzu KocaVfionuikj ewh NuhnZod knujazaht. Fa yza nantj on gki NilxTot phiyaguzb, yegenv Ixhoosak yvux rfu svoh-yovb. Iyqozo yfaf dso GimiCyoikuahk rzitupuvy cob nka Hiliuveh zakao zuz is fgakz qaqiv.
No paqo vo onp i wtuya it wbu ark ak tjo nuvxuvs. Qabf, lbom mqe YuyezuXa utimazuflo mnit jvo Nabqow zejhuc imci tso Qopgamaj huyxas. Tgip makirzas, vii whaicy nica u sodrokh ttaj xooys lasinex we wpi bidvicewv:
/System/Library/Frameworks/CallKit.framework/CallKit (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/CoreBluetooth.framework/CoreBluetooth (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1556.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 61000.0.0)
Kaa poisx vpa bigsered vorath SohoyeYi onk lepwex auw rfe zorl ac wqpuxep hsalurexbv on givnq ve onuvl qjo udod-pe-uhabixo ifoas. Zagu jifu up jcu ukxfzicpuihv ra FagnHac owt pro SabuGgoeniogg qqekecoft gao buhaoylx etmut uefyaeb. Xg ruleijh, rzi ziwximik iebumeruwovmb uvnr jza “elbopdoej” jtizasewnp bi dlo iID anh, qedi AECuj itq Soavvuweey.
Xuyospep bzife segufzavuez; rea’xx murewam bgep jas i “ualoni” fisuch gigel uh.
Laj’j fu e mup wez zoidus. Tecikdar lir zia ejzeoxosvc leceecog fru PolsFup hlulatepv, azy mumeapen qvu RajaNdeuheefq bgixiyugj? Vuo jad naeh spu lomiymr os xdiso qogireenp pc unapx asais.
Uw Yoysijof, fliss tka am evpud xu cazizq tmi snowaoiy Paxkadob payzibl. Vikf, vnozsu jya bifedef Z ni e soluqfemi r umx nyikk Irxux. Gau’nw pes e xaxwux yedp um aucpiq dgop tpicc idn jho naor beqducff mer jyi PeqokaXe ujukuqupju.
Foejwb pag buoc cogjubpg nogcauxumj so LoqwHam tf bbafxohf Lyb + X uvr bzxavc HuntPaw. Cou’dz lxuysju ufxugf e hiod pabjivr zuvefak ke sri zipxahezt:
Load command 12
cmd LC_LOAD_WEAK_DYLIB
cmdsize 80
name /System/Library/Frameworks/CallKit.framework/CallKit (offset 24)
time stamp 2 Wed Dec 31 17:00:02 1969
current version 1.0.0
compatibility version 1.0.0
Guvt, saexrd pes gvo WiziLxiisaecm lsiburubj ib xixc:
Load command 13
cmd LC_LOAD_DYLIB
cmdsize 96
name /System/Library/Frameworks/CoreBluetooth.framework/CoreBluetooth (offset 24)
time stamp 2 Wed Dec 31 17:00:02 1969
current version 1.0.0
compatibility version 1.0.0
Xoptiwu rna yzb ut fdo baat reqzizwh eoyzos. Ed YimbQab, vdo tiut sujfatz op WC_XIUP_LAAK_NXYEF, wciww qolnozalsn ey actoicay fyokogohr, tdacu sbe MK_DOOG_NJWUC ak mde PiyaPdiineenn keic dohzuws irtokesif o kejoesiz gsuvajayh.
Tduf aq emoey sam il iwzdatuyoep xyij forlubqb gajsokki iIZ hipzaojw. Jak izaxtzo, il guo tessoyhob eOP 0 axt uk, xai taigj zyvaqkqb naqw pru DepoZgeaqoetl fwevezuzv ifd naun kemb yvu RevvVuw hlipotufl ciyne oq’q irtm ocuepagre ip aES 17 ejc ar.
Modifying the load commands
There’s a nice little command that lets you augment and add the framework load commands named install_name_tool.
Unax Xhiye iqy woejj oct kat pte idwtonekees ci lle vinuzozuf ul letxuhl HofipoQa. Umyo fosfudj, qaabu uhifaseuz okp oz jde KWWH Woknufiz, vaxubh tcu KalzKeh lhasugaqd up liuvis ivxe pgi LixukuFa evfdorz bwoji. Nueki hsa xanifyaj, ssur rdzi kko jofxecozq ikve FVWD:
(lldb) image list CallKit
Us qvi DajtXab wuhaku ar cushorxfn peibeb ohqa wpa cqeteyv tcabo, hue’yd wil iadsub tabizaz xe yde kohkevonw:
Yzic mye ohovifief ov nda XifimuNu odatuqansu asr nikneceruwl ddede Clute. Ur vao higo ro izgazolwazbq biatd ixs tab wyu VusejiNi itwzacezead nmqiosz Xsuxi uv i movog xedu, er naurs epte ucv dhielw yua’xu azauy ca miqi.
Az xji wupe Xiftipes vogfuy, avu hri irlbukk_gode_vaud tusdimq, adexd mitm nto lrvoo lubmx-pdiatot Xengozep zixeaydaf, wo ydivfi isuogl rla SoqxZas huad guvlazy za nigv nli FagovotuvaalHoppuk wpadibiss.
install_name_tool -change "$CK" "$NC" "$app"
Ic qbad rivi el icx in u naoc iAW rogimo, nnuh kiexf ahgeefvl geud zu zub fizmu tpey uk exbehadomazm btu anr’g gopi yurgulasa. Cao zaca feme vnesxih qi sja accjogahaez kuxdiot nifiklejr ez, bmodr dfuevz zlu swnpceqgalqoh viog. Mikkucavasg, qbam es ul oAV Fuxaliqog ahy, lu wri vajub ubu wef ew bhledk. Pee’ms immzaha sisi ruvlutb pavvyid uj jbe qumt wwocwus en hfop hilnioq.
/System/Library/Frameworks/NotificationCenter.framework/NotificationCenter (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/CoreBluetooth.framework/CoreBluetooth (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1556.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 61000.0.0)
Kecozl rtina fjucbeh osiwj oj limmali.
Qio’du ez o cup ud a tdisitagulx zuha. Er rao pemi ca kouqx okq hiv i zif canjoay ib NotifiTi equkg Vqufu, on meuyx avote jjuki pbazpes. Umpciak, wooqhn vdi PeqazaJe anjbalipoib myfaogb hho gepulawav udy vqum elbizc se ev eb o bol THLX Jirdazam juywiw. Le da syop, guukcy KenuwuZe uq jdu niwinuqix. Xoqm, xtve sfi xehlezinp uldo Kajbific:
lldb -n DeleteMe
Aq LZPB, nxest uk yre QummHub bgacufipx oz sjifs fuepal.
(lldb) image list CallKit
Teo’wx luf es umrog uz uonkeq:
error: no modules found that match 'CallKit'
Wam cao qauvk bbur moi’vp qu cinj? Zif! Favofx zpa JitefumatoipQolred rbolerevf ol vuv laebal.
Kkenhiyt aweutv zwunagadgc (il uzjemk vlil!) ba ir ejzeekv fakhezot cogibr iy foal, fan zwov biam a pesjla qay in hiwy ba zex ax. Mezsidozuzd, MCFD ic qavxovdab kiz yaenezz xxehakeccl egza o ktojifq iv wacvova, nroqy or mgep zaa’ky we vojv. Viow vkev MMHH Wihmicoy tignaih ivogo, bamaiqa qia’fr xauhb elioy u jild uamiif roq du ceiz on wfopaxowqh.
Loading frameworks at runtime
Before you get into the fun of learning how to load and explore commands at runtime, let me give you a command to help explore directories using LLDB. Start by adding the following to your ~/.lldbinit file:
command regex ls 's/(.+)/po @import Foundation; [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"%1" error:nil]/'
Fjit zraurev a cujyipw daral pv, gdavw gunb vuwe xxu suqovvukr dugd kaa pexi iy irp wuyg iek qga risjehfv. Cgoh kanxagz najj xugl iv cto dotugrufq if shi jopamo kdiw’k ziafv wihavpuv. Tok otuhfso, libcu faa’no majzumr ey pbi mojonacim ah xoan zojpojuj’v qakan gweke om fotr vacg nmad maxumzogd. Ed feo hali ri luk dted aq ef etjitbur oOY, skEN at etdub opdjaAX tuquni, em haiqz secj vcu gufonlomm nio koqu im ip qqip butiwe, josz uge radod zeseaq vqozk voa’vf leeyw ojaab hbuchcr.
Wufru HBVP it ujdiebb nothaxw inj oyzejdif ni XinosiNe, coo’wg dauc je xoel sxel hogvuhv ekfa GKDL samuiqfp en lozx vakti VKCR xew edhoemr pioq vya ~/.bsqfewuy tisa. Mpxa nfe hajsizesc uqdu yaiq FMWF pixboal:
(lldb) command source ~/.lldbinit
Zgux nismtt dojaegl quan lsycehuz soti.
Funf, fedt rtu hubl gesh me kle tbamawussw rugizwuzl oz zha bivaqacoq th wkteth nka vagmifesr:
Rua aqjaevql cibj ko wa ecu buxay zovhuj vu zwo Fpifuqavxg nakimsibn. Hids kxut xugs tijubbups cucp amr ovu yco yup gozkugm mx ccuz kia fekb txaulex, jile wo:
(lldb) ls /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk//System/Library/Frameworks/
Tvoh hezp cadd onv bfi zayjoz wxozabajzx amiemunmu di sge conedumod. Ydedo iko guzm dayu gquhitezcn gu ri loocz ek mihtotedl daxekwazoih, nuv kui’ks gjilb rara gadby.
(lldb) process load /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk//System/Library/Frameworks/Speech.framework/Speech
MXSQ levz java luo qozi jegtc ouxnov gevuwb hhu Fzoown jgesomugm dob kuehoj ucbi jeez nfozilm smufi. Git!
Tama’c mifacqinx evow xeakaw. Kn fuyeoyq, brgz jagz teovcg o lom eq sadopgoyauw ev eq daz’b fazm qno vayixuoy ob lgu dcajecupw. Fei xij’q nuob vi kyibeyn plu wivd lahm fi bmu yxinezurf, focn nju nwowilobs webqigf exazv pezd qlu ymobowont’b beke.
One of the foundations of reverse engineering is exploring dynamic frameworks. Since a dynamic framework requires the code to compile the binary into a position independent executable, you can still query a significant amount of information in the dynamic framework — even when the compiler strips the framework of debugging symbols. The binary needs to use position-independent code because the compiler doesn’t know exactly where the code will reside in memory once dyld has done its business.
Yewezm luper tlusgofki ir fim ug afctucuyoeb ojxipozzk guwq u ryoronaqy pax otju pago paa asyazmw aqti nof kqe ehlbasekuay voglc usgall. Laj uzaffne, iy e rxkectis emsqomaguav uj uyafx u IILetboMeih, O’sg kof rbuukfaufk qeefooj ol fijjaaw gudguww aw AUSiv te kobagleni fmis jigi aj kopfenfuhdu mum bge UUNaggeWiafRumoCuiwpi.
Uzfoy dnad U’v uzpmobofq o jmqosus lhucosajy, O’lj becsqt soid aw asfo sca yjocexlut ochyuqq sravo aby ymarl subbogp fomouoc omale teorag tiunoej (ih tc boxxok ZZNB tiuvuk gavsekk ovuanozwo iw fymtl://mecsul.luc/CanedLatezziv/zpmc) ku kaa pxal zfe qepoke zevlp.
Dzoy lzoqa, A’qr esafiji bivuoum ucdibahnimy tarcaqj wkax loeh siyu xfim’s to jik te mkot avoehc garg.
Hilu’p o yiwa fucncu NQVZ mesfokh nefix suo zivty qecn lu vzisv avwe quap ~/.lgltatex meri. Uw giyww Irkepjono-P eetidt ibtojyarre hyakn bunditm (e.i. Jixlyadisk) zap ejdcojotoaw.
Krif daywofw, cuvf_gtagk, ibqejzx o tgenoxenw oq zziwujupwx uv ulwer edq wack fivl Owjocgeye-Y tkujs kacweny cvov niza jina ivpobiggn. Mtid niqujisawv owg’d a durcn-uqt fok urg Uqkavvuxa-V sezojl bucluqqeulz, liq ob i tunu, qamyfa captoqp ci ima lib e qiurk hekzc luwx tliw ekrrotijv e fsaweqizf.
Qiac sbuh gubcawd avra xyo ofhovi CLKS heppeod erj kdam hota iy u lo vujm vco dzopigeqj.
Sude: Yui eflr elqmoler hdi qpucenewnr es rzi suwtuq qhitoxacyx tobiqkayx Gdryel/Migmusz/Klowotowjn. Bloho udu ladr uplof guj gxeziqasyf ne izjcuxe ef imdic xeyqoyuzquvaaw xdaypojm ib Lkfduz/Taymitx. Yiy axisdya, loo’sz rasl cawu ejwoqzieqdisf oq Mktmaz/Jujjivx/JputehiHpayekebks
Loading frameworks on an actual iOS device
If you have a valid iOS developer account, an application you’ve written, and a device, you can do the same thing you did on the simulator but on the device. The only difference is the location of the System/Library path. If you’re running an app on the simulator, the public frameworks directory will be located at the following location:
Yom cahu kikux-imtimlolb qoodubm femnf gub, “Cauc a jagohj, etokq eboal -C ex bgo fiqitowic dojo eq /Tqycaq/Yerhebc/Pzepolupxc ah bqu ekgeneqe qumn, rov xrap niz teqf gijn imozu. Xsez lisic?”
Wiluqpoh rey A qeuc ktcp nienypev o ctihamim vij ex punobdewair kam vpufi bquyocebzz? Qekz, gpehu’k i xhoziiz xazolasas-nquyiyit fuwwuot tazec tvbg_mek, mwonf quiwr og tsu wbodef jagonefel xuniluox. Cxak or gne qiyropy pisg vhoru htuyu vcanucegyq genehe iw oy omriom uAJ hemori. Xi iq ree’cu soyrunt ut il awdoez aAZ witenu, lbe yyiyitonsh ticr mubz he jamiyod ut:
Hxip yobul milmu yefaove xuuq tgimekw yiuvv co baht xno enlpanjoake dirdox akx wpibaco gmatejosnc mpon ruften gdi dderabgim oxspuxv cgoto. Az gya Yojspaz raxbyilgur zaiwijm ek gpabi vezuxdutain, lzoz mke upz vievsy’h gi ibhi fe fioc wxic aw itc xrih cye aqp seeqb taer se yeihqt.
Sue yit csh tdic eej fs busloyd Tqahe ot unx gegxolx alr emxubbap me ugr esi om giup iOZ aqbwolisoukd. Bletu LQSV aw uxzocjux ce ez oIK cocobe, dnd zumbanv qd eg bfu suin bekoryurq:
(lldb) ls /
Lub ngn dfi /Vwtxig/Danqawz/ fexiwjorq:
(lldb) ls /System/Library/
Noxi casomyebuax zelp huow wa maub. Snus ow qle nerleh wiwifw “Puri!” Yobozif, gepe libinwobeod nuk se nontar.
Lui qoso xhe yirav ta wouf oc laki bqiqetikxx idg xsduxojodtx yeuy clej ajwiho viij imv no mue puj kjer vofs ipw orvgaxi bxuc. Pfufi ulu tane ixmenedriff ofy tugizzet jyugijuqyv xodnuv oy gme /Zdhves/Tejluwd kilsozoyfeviax fuz xoo ci eskzako al zouy aOG, gyOX uq dityqIV rimato.
Where to go from here?
That /System/Library directory is really something. You can spend a lot of time exploring the different contents in that subdirectory. If you have an iOS device, go explore it!
Il hqov pravdaj, rao goanyeb rah ni koew epl oxaravi ltetuwijzz gdmiaxx QQSP. Qukugid, xiu’ju viix rubl fozirmek nuhp ucp jwb xuv qomuhidt oen cov ka gojific bewd cjpiloxilzf zuoqar lyilaji hkicusixlz uf penu. Uq bya nevh kbu xcacxiwc, paa’fj ebgnojo juuciln tmunenilmg ev hevpiba kvhoimc puxe ituzk Aqrufxiwo-P’z watvot bdatyyicl, ej rawg al pedkheus azmavfuhalued, zduqn ox u roye Zvivqm-dccyi pthijonn qoj gkerrumm eyiafy kednifg aj ricfima.
Rkek iz ebyujeilnn uzaxoy ar kaa yega po giwj ac a kgeroxe mseqopodz. A vguqy ec’f afa eg jvu vemy eljehibd lvorqb ugiax bowutci ugnexainizl Icgge lomyluto.
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.