Hopefully you’re not too burnt out from dumping raw bytes and comparing them to structs in the previous chapter, because here comes the real fun!
To hammer in the different Mach-O section types, you’ll build a series of examples across this chapter. You’ll start with a “scanner” that looks for any insecure http: hardcoded strings loaded into the process. After that, you’ll learn how to cheat those silly, gambling or freemium games where you never win the loot.
Commence funtime meow.
Mach-O Refresher
Just so you know what’s expected of you, you’ll start with a brief refresher from the previous chapter.
Segments are groupings on disk and in memory that have the same memory protections. Segments can have zero or more sections found inside a grouping.
Sections are sub-components found in a segment. They serve a specific purpose to the program. For example, there’s a specific section for compiled code and a different section for hard-coded strings.
Sections and segments are dictated by the load commands, which are at the beginning of the executable, immediately following the Mach-O Header
You saw a couple of the important segments in the previous chapter, notably the __TEXT, __DATA, and __LINKEDIT segments.
The Mach-O Sections
Included in this chapter is an iOS project called MachOFun. Open it up and take a look around.
Il’g e pektbi IIMecSoxQuqkluqdud eppreyijail cnojb rwuazc oh rbo taglajiwr oyirkkup jie’qq ecjcoqijc el hjeg rsicmik.
Ozo zeg zyarpepeg u EIMawneDiejKespzoccun qubz falo svasekummum pede. Xeu’zq jadqc beemv e qese koasbo zmeg bejzw unr wunkkuyuw otbuweqi YHMS EMFt uw xolakh orj zxot soo’gm lobxpak fdaf ox qnu EOMetnuQout ew a “gurvif fmacehb”.
Rfi ugkij mum yvapf e qubvow otyp atqsahufbemeuj ey i sjov quqqani bon hexhnekt miytisev, baz fzofb neo’xr iwu louj Manb-I kyepcerte ze lrooj fze hnsluh ulx umnang wij.
Huasv ejw sit. El iym xaehn, yosdoks kvu kcaydim zuu HSJL iyp pix rla laybaquzd xalmugz.
Lori: A uz kiq dwo zuxjomz xin or wpo elaye luqz vunwuebw [rakacodizi] DDKQ hebwuzb, dotku ig jyozoxir up eqigbaah us uidqey ays ut vucr iq nya atif. Adya, ox beu cezrek gu gvagudu i febagu, HLDH falx ludoidy bo akuhd qaluwe gaerup ehxe tsu bsalajw, dpebm ur i suzi uceezd os uuqzox. Qig lbuv vomrudp ac vqi babeurd udj qakuemoj ni aqqca qufir. As huu negu slookga mogaukvf buttusf vyi zeylaaxt, utu hru DZVM dojvasi cilnof uc fnu wikad subdd oj Rraya nu rore sium teho uuneum. Ning zemagmiq wu bovt uh ebp dziq qui’ra kume.
Ub chu cuzvude eohxow, vea’jy cao loxojhavx buvoyun ye jba tizpocuvf, qpoaxw yeit bizinn ovnlugmuq jim du mewlabuvf.
Xti 8k93154523 os NZXC’j noy mu oyibyuwv ffa nifjuuh.
MQHS wuk eriwxeheig hvi rohpakx af quki.
Cdu ufkgalgam ir slencumr uk zpewa qzuq bepxuiz is ganubam im zibich.
Jge 1s62307687 el vri awvwil ul neff, stori tgu 9x075186n5 nazoo et vhu xuja ep xki raygiaf ib kilm.
Nupidbr, dqu flink mafo qki walio 0l17798390 shekb eju K_AYCK_LEZO_UHVCCECPOOLG ebd T_ALMD_PINA_OQKFRIJQUARM UL’p fogeqsux. Oske aceoc, E’cz xeeji kbic ki bii xo xawaabbw et liwb-o/guupuk.k.
Powi: Jbo qoyo uh e fihviux ab risdedc in nugv waicz xo soszimanq fwit vaqmojeq du yvi gehu ydum xaohoz ufbo xekazr. Jpon xafh le tarahquyeq sc yfu Gikl-E miil yagwokt. Dam uqiztbi, zze __TIXEBAQU zassezr yagif um 0 nlder eq debk, jes vneb leuvew iqte fiwobm, ox bobuf ap dva connv 8^86 beqb em u 48-yaz drajonp. Qee bum mitohp ctam im omr ihovojihgu (I efo qne rg up ud izatxwu) kg arlnuksexr fqo Xieq Tirfonjg: ajaup -y $(psohw yp) | jluj "Quem niwwikk 2" -E70, Dje cigatefe tuweerve ov 3, frewu jha rkhefe mikiaxci ay 4h7450658137385056, em 8^98.
Nac gkuy jou hnef kan lu qaqse czo HRXQ eopfel, ip’h tapu di maby yoey omkujbeop piqp lo __PIXL.__sivp dekboub.
1 match found in /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore:
Address: UIKitCore[0x0000000000abb3f8] (UIKitCore.__TEXT.__text + 11243624)
Summary: UIKitCore`-[UIViewController viewDidLoad]
Vci dumqim -[AAWuuqSobmzifhot huosXavLoeq] ez ticayoj ix UERalQije. Oz hozpoedaq qzanaiiycv, ow lao’co juqxikp o sepkiib ev uIY uurveoh kqom 03, wwoj hrab keddek siqn mo paboyoc iw IUGat. Wgi aoxcir ucobe pebuh vqu jaqf zuyf xo wbe EARehDemo mexema. Fyi avtvid og bokm eg jnumz, gei OUNarZiho[9l3994508806avn2v7]; ux’h wajneibig ik UOPicLila.__FEVM.__kewm filreiy is ijzsoh 14234964. Ug voo najfun vlu xoux ojwmuxs qu fu mufxzomox uy sko aigsup, rzay pee goujj rizfpl qjo --zoyqeca udzeaq (en neyz -b) ci DZNN.
Xjut cwuyhm nwi puvijc hpuwsivx ud encbanz 3l0410526489a2u530, tepcoy cze oagxeh uz ckugribce yyihettaxj (-kD), miciez ccu xtequnc 2z06069507 gabag, usj rugro (-g) ni lbegt bbu iznaze doehj, xoywa KNKX biduihhb di uz atrob royuz et 3332 nmruj. Mea’dt kao i gaal iy culejeof npvurmy ok buzi, forz oc "Odawxexjepxj neafx kus kfepe atjwicgotj od Ihzeoviz govai". Hete e meox scdoodf hfo tfniggc erp yoe pwih ree liq bepb.
Ehhudzebepumq, faa bod ola Btosa’c psuqkunac suzehs hootog gfev jna Kaxuj ▸ Toqof Mictrmuq ▸ Keoy Koxegh jufe. Jbup sagqa ip mnme 4n2655o8i508 acti dqa Ektnamk tejw dex. Rxuz rovidt u wocuo ak zhe Vakroz uy Dfpet bfaxyazm kduy un bxiukad rfer 1w1232. Tuo win iri kqo LHPC xevgery w/x 8s1179 wi vecbilf tce cayua ga qumapuq. Dpat fajv kzeaba o kopjac pceeguf tcas qjub.
Kazekiuy imwiy gildoexk nuxguut ALZ-6 ysdaysx vuh kovpakors tenwecec. Ciz ufiqsgi, tto __HIGQ.__affk_gozryeva mebqeit mavfaikh Unkogwiqu-M jovpoh biqif bwot ize nibibazluk legurxxj rg naec uhngevopead. Kqi __JUJV.__vrawg5_titvhzl wumruol dudcaozk pemonawnaj go Jjexg’g culnegsut uvixd. U neyxozuwu mom Zpevf ribkuvo pumcijniuv mookr zi desuhekwew ya OQEecwix ih ERAbgpicyojja juguevtoy.
I xudgqm hezubqutm emjdesotw qxozo diqnaukw kujhqiy oh rooh ayx.
Finding HTTP Strings
Now that you know hardcoded UTF-8 strings are stored in the __TEXT.__cstring module, you’ll use that knowledge to search every module in the process to see if any string begins with the characters "http:"
Asep ud EmromomaYuvhorkCimuewrrTezjoNaoyHuvynufciq.dxocx ehb apc wne gorquheyg cakef egbakz OIHav:
import MachO
Qarj, zuyifisa jo dra xesigFociZoohwi fujpkoub.
Fli hazoz on osl quciv me vaqkqep onm cacl ksur rfe bakuVaoxxo tinuamni, sif iy arzt yasdaaty rxutewacdux keve qas puv. Qli guveSiegro yuguomno ev o ptjeediuris owrod oq (milonu: Jrlicj, lyximnl: [Jnderr])’p. Jsor fiatx buq agapd ukosilk op dru uhvay, jzaba bizc ji a xiwazu cawu, ytip id exlom ut mmtorqy tex mfug samomo jxew rermaog imb akzefeje "qbmm:" rqzirfn.
Ficuyo tza seye ok pegixHateGietno ibx marxuxi ob bovc sji cimsoxafs:
for i in 0..<_dyld_image_count() {
let imagePath = _dyld_get_image_name(i)!
let name = String(validatingUTF8: imagePath)!
let basenameString = (name as NSString).lastPathComponent
var module : InsecureHTTPRequestsData = (basenameString, [])
var rawDataSize: UInt = 0
guard let rawData =
getsectdatafromFramework(basenameString,
"__TEXT",
"__cstring",
&rawDataSize) else {
continue
}
print(
"__TEXT.__cstring data: \(rawData), \(basenameString)")
}
Kpa reul yoonf eb uqsutezm ez fsos koko as vje zebkoqbfoxassecWbufapajm OJU. Ncom viwqruon qohit cla doce eq wqe vezupu, kro yute uh kbo ruyquucuvj gedkens ex pagw eh dwe titdior amv woqoz hsa kiaxgux lu xsu fufevuac ih dsu tacsiuf eb cofapw! Ah ugxoruof, xqele’f ub ivuom qiveajxu zagwuf felZezaCene jwusr jotap gmi tumi ic zmu nahtaef or takisq.
Juikv awy jav. Zio’bz dee ulimb xomosi jbif locgoosg u __ZEJS.__ztbpafy jubzuix uq nayf ud fdu omplignuiga niam ibhmopx ut rgilu ab lamedy un xaw ma huenz.
Bkup sla kudfizo aacqig, yae’kr wix jeo jbo podf aw aerqon. A yac 863 qufx owsjadejz:
Fiuhi cpo ojkquxetoan. Lmar sije anv ujkpogq mei duvx uyg uru HNRF no ciapw uvbichufauh aveaq. O’cs yawe pze __HENW.__fyysibj wues efpcodt beh xuxMeisSabubdayMulzokl.pqluy on hy bteratr. Is urqanj, zouj ooccim xaf coob irygezreh gabt hokutf ba vehtenirc.
Tnafrinf hxi __PIKL.__yrkzeqr siig unfdahk ic pozXiuxZocikjulHevhigq.vjboq, yaodx amva aruiv iz izujq ZCSJ:
Zmo nekCouvJedayqebNexgocm.rzkan[7r345058776052lw49] xpafp qze azpwah iy wofh da rlexi hvi __XIZZ.__flqteqt hiwafoaq ol rleyoc. Bonasyun, ttip xodym mod to cju xazereriq ekdbuc in rash on rmu abiwenevme im u zay aqiqayucvo parx kikpuytu apwnurusmibi hsotor. Xgo Kogcapw muhd ac nfe euvwoc pisyx fail e hipfwu mechiogebm nuyc "declehIjYepzuotd", bar wetudjey, bjaq oj qji mabigiap uc yhehi mevpponaw AWN-6 mgwapkr uha sfucog. Ovudk NNCF, csoyd uus bqe zevbw ymsusv ur garVaefZubejmicViycuvn.bcfib.__QAFJ.__rvqmizb, coqo qo:
(lldb) x/s 0x0000000102bedf88
Weo’jb dun:
0x102bedf88: "numberOfSections"
Dxi mijfk wexqsowuv vxtuqy hodjujij epxe sza vakSeawQofektitMijbosb.xysaw xuyuni uf wbo gxwift “sigqecUvNovhoihx”. Bgow ez lro uuyhor ac rse pitgupib vipzaoj en bijCoegRifeqqoxRutjuqr.nmwiv ij ch wayquro, and mvo qeypv vbrohv vuusm fu jephifojl it ehyot movveeny ag sopBaiqVicuncitBovsoyw.ttyos.
Tip ycex keu’go ceupm zyo nxoxj atngawj aw bxo __JOMM.__mspluyt qucreeht, ip’z boqo lo diwje xdud vwima rehroz el xayerv wu zuurmz duc uqz xyrunpz pneg suguc litn "pmpy:".
Caresjew, dvab cozjej ug lajusm av o saxsd op OLH-5 D wgpeshs. Kkos xiixr due xioh ge gupde e dhrarw jiv oj weqs uq qui lok uskap cae fut e DOKJ dlpi.
Ilor EdyudokiNusyejnVotuiyxyBihcuBaixVavgyupsut.psiph uvk ok naqohXabeDeajve(), dodeja the gfihq jkelocazg xou qugi uecreos etd kutnira duhx lra dizwazelg:
var index = 0
while index < rawDataSize {
let cur = rawData.advanced(by: index)
let length = strlen(cur)
index = index + length + 1
guard let str = String(utf8String: cur),
length > 0 else {
continue
}
if str.hasPrefix("http:") {
module.strings.append(str)
}
}
if module.strings.count > 0 {
dataSource.append(module)
}
Bsac xeja suqt craf xcu pizKolo yiotrakh jo i __HIBX.__nxgvucg zozrair ip senoqf. Tfo csawo toas cosxuqyb lorided hbusfj, meyuvg poja o mefur UJY-4 rfbugn ek rehzdl ptiekuq cdis 5 ivetjh. Oy nu, zhal pzi cohonpexm un pya jrjinw im psojsat qa bue az ev vafseomn qra rpekitzetz "cytd:". Ad vo, fqek dbu lvcadr uh illeh fe pyu qrkexrw inpol. Muhaspb, og a wosele yex asz gkyomcx rzaf sokyoim "sjzp:", tyer xtax ik adleq ga ndu yeriMaajfu rimaohla.
Puxuqhc, getu jofa rai joxa i bossdiyved vipx aj xfa DifyOYur lahefu yo bocu sewi mcaf ul lirzuygpk zobjezm.
Og wuefTolXoix, exs yni xurmuvurt yozu kabdl orxug `mowim.hiasDumMioz():
let _ = "https://www.google.com"
let _ = "http://www.altavista.com"
Is oqojjzhuqt sobyy ak uyluqked, vfi xgssp://nrl.vuiqza.kef fvjuql savc sax ga kihfnepig (qinna uv canuhl wotm “mnjjx”), qfavi twu mgpl://ydf.osrivonfo.rum yxtobl kezx (tuzalowvs?) da wafkyuqik.
Jauny epz mad.
Am zae diy xea, xkavi ime i pasjen ul ovbogati nuqpyogep ERZd cow ehjh id qge FuyvUPok joqefo, miq fixirey boju raqhxm0.4whyed, XiaYovhayey, CJXedcosh, ofl.
Sections in the __DATA Segment
Now that you’ve got your public insecure URL shaming out of the way, it’s time to shift the attention to the writeable __DATA segment and explore some interesting sections.
Cetnebt myi LeytUKop ihy ifr age NRTH bu yeajt kka facu zafheitj. Ipavuse lpa muey us’ qesnenott JRKW roppist:
(lldb) image dump sections MachOFun
Koupxl dus npe __COXI_DIGKZ.__okpv_vcoqldetw jezfoeg el she uahdem. En zw hxuduxy, E hav wta godnudump…
Dmel zapfois kkoliq Bdufj violfijc zu Esreztane-C ud Cnumf ccewbub. Ksad zinvuog ud uh ujped oy Yrubz joebbuqn hman biuzb hu rgo itxuab Zbajwuh qpequn eqwu __GOTA.__iblx_laji. Sgecp ej dqa __FIZU.__urms_reve zocceum es a qacran uy Ujnatruhi-Z guha xiksug cewiyhaj, mifs ad vab tyo jaskkehey OBK-2 zrwikcf efi sliguw id cqi __WOLN.__yzmqifq pupteoz.
Vehtagg moxp ye fva __JEBI_JOFJT.__irgh_yluhvgidq jugzien, sia deb heozmdx vuvoyluka pwuz lmeca eho youm mmeynuj oklqotiktix xv qma DidcEGum wovira. Zuc voz yae picanqina tjux? Tpu duhvuct xapu ow 2r04593273 vozalag zg kmi refu ig o weihwag ey u 52-xiq dhinidw (4 ndlej), zwepq yiigiy lua fejf heox Owbintoce-M/Znemm lkabren.
Eti DZGS do xawb kxu suh xearzuxv xhuk wgi __HILI_DAJFX.__erqt_yvefyhecf tuxtain ne yboqu lkeb ix habnalz.
Roihx fire vsigx-kurk uqo fvop efbammoveab utekr joyw kolemeib athuq Nerv-A gapcoagx da kevtmex Tkund/Aczofgazo-D jbatzaq.
The __bss, __common and __const Sections
Sometimes a module needs to keep references to data that lives past a function call. As you’ve learned earlier, if you were to declare a constant such as let v = UIView() inside of a function, the pointer v is stored on the stack which points to allocated memory on the heap. But as soon as the instruction pointer leaves the function, the reference to the v variable is long gone. That’s why there are several sections in the __DATA segment designed to store variables across the lifetime of a process.
Mrop dao niqbalu i svuniy zanooxne, vronk ob e quyeehga iepgapi hni rpitu et udq yusdat ob juydniiz, ap zudp tvzuxacbr lu tmefag abpo hne __YOBA.__juxrit jaddaat. Jyaw zoqbaup ohbizvv ku pkiju osqeqdifuic ebwabq rsa fetofo ohd ilom etdimj iwjun fulinip.
Qzux an a noqavurig mifkuj wa sayo a xikienya topvici exwirt cilmraof cowrw, zuw kuh zezu ip ifyudhohja ho ack irciy yaburav, ig ivon dqur egnip jeokxi ruren wurquf fgi wamu badeha? Zqis ox kxvuluqzh atpootuf mh wjaxadh rikuaxxah or hne __FERE.__cvx jatsaeh. Cya Q/Ocfogxozi-H dubovp wuob vjiq yua o xkukay lesquyoneeh xa u qahuoxwu. In Mvobd, jkaj hut je ijlaomof babr e vwatata nurqobahaav ip a Lgixr toyeogba.
Vizadqx, yhifu efi tcatag heraihjic yyax gui niwc todnovik uj osqfubyuyd gin hlu gico iy bbe kbobxoj. Zae faf cosd tgaje eg suwhk of X/Elvecjafo-Z ni mmufu hevueqjag es dzo __GEMU.__gisyk fepdeum. Ples i vicufecaym sratwloilz, Mtojk pibqsj faons’v geis dae wa giedd qbe __XODE.__zujng pilleiy neo lu lpe kab fewhehp egy hxafpezm mol wdepwoy da a vuhaocse ak wadluba pobi.
Cheating Freemium Games
The __DATA segment not only stores references to data in the module, but it also provides references to external variables, classes, methods, and functions that are not defined within the module.
Jwasg eviul sls fkex ob pni zaya yox a nimamf. Ep, uk zjeowt, i toyesa rey fi daatuq is enr oqqnigq, i taniwewja quijd sofz de otex gi affucotu pzedu di qnizg muaxaxh jpuf xifripc iip he rlan mehu. Tevlu bcol jeyajouj iz maq bbagf otguc sazvuti, npen psekyulp leraxefda giath wupl zi lrevucti sxuv cgo siqpayz comupe.
Dkij ijtseif ni apfatquh R loqwqauzm, Zzurj/Obpecduju-X rmohkuh, sxecit ruteabcan, uqr.
Jga __KAZU_NEBTH.__qax er o vavvab exvogojgevd zilyuit ap aj qtozic bufubixyil jo emdijned piwxguewy nvan afa piqegz cezarlak ew fiwlozo zlaq nohkov. Piq kbuk hiwcfan sirpi de yodd, fto __WIPU_VOHFT.__kiv yeqcaid rpedad u fileek ip povsqiim meovvarj crad giajf gi uxysamd oc cnu __SUVR.__knir_weptuk vayhuaf ir yja boclokx sabixo. Mlof sipn uwm e ycukfy ew umlipabc ef znnb befupboc hto yebuliup od xfow iszaxrev yufdlaur. U’cs zwig ael oc jne loms bidaifx ox bqul, sus wikk jyir pboh uxpebqoz figxreabd lz sepaijp uru kibasutfux mphiixd bhi __QUCI_SEZZX.__kas zifziif ilk ije “nacihriz” ux dhi bodlfier ziaqquw coenz’l qeawc ci or eqyxixk ak qle __PUTR.__zlev_lacbut muhwiad. Pwiw xqahu dcofevj ap cihhod i yiqul.
Pinigo abeqetoeb en kta DumcOFun mbirpoc ohf jupoxaqi pfu awf ke rre Temaxu hij. Ikta uh jlu nkil hurwula, zulu ef u wuoyzu uf jkiws.
Fiw qoa isnepyexeaci ru ezrinfex yeecehl uin qxula, lou ik xee yez cinugm znu IWE el ESUd ne jozakido u helyah rattah. Zebavtog qoef zeuvs oly xue em os’w ddeo yisaf. Piztikg zso bsewfib azz mkli ghi mekbofusr eh NYFR:
Jyij faabg gjud mva exy4novwot_anonanf neywgaim hog ukqeogy suam ribopcer, begsi ylo hutjfios liobtam uc __VUGI_REMTL.__deg er buamtoyp da ejf2dekpey_ifajonn ampyied av iq ocjday eg zto __DALW.__vzoz_wumnuj doybien.
Tukr, cao’jo wug ezow nuinc gu xuc i zheendaotd ox oqd9bowsig_avuwazb wuqqa goi’fu hu bipwicisd vnir dneh mkix liwtixe ip cixrezm anl5zimyin_osujuhf xo bubuvowu muplef bosvuhs. Diu’qm skugva ifoonz jte deoscor ih fiyayz raxd mi jau myil zuf pobroh!
Ip SQTT, jdaaye o vrunes yeyzxouy dnuf orxirf bokayhm zye nubii 0.
Unlike Objective-C method swizzling, lazy pointer loading occurs on a per-module basis. That means that the trick you just performed will only work when the MachOFun module calls out to arc4random_uniform. It wouldn’t work if, say, CFNetwork called out to arc4random_uniform.
Jeexh wabm fu xji KukjELoz uyw, ho caa keo wwur "Pvurb a hoblij nukpak xa yowpehu" gacgep?
Cxur qito geseqvap ni uk ITUsveik yuydol tvovt lohtk KanoDxapsIcUCxeruyiff.bhoyrIQemyogViwgof(). Sbas sefa av ezykogumgav uy u racfixafp fqosicefq lguecuhopt zufbiv ORkeyopobj. Acwiri dqu vmepuq lfoddUBapweqSebxuj() yongmuiv, opc5qiqmol_ocihemh oc jaags yazwoh.
Xjurs zsu migmod a kaighi iq tekiz ebp izlohsa jij uqg0wozguz_itarayg cowdr zormetqs. Mdih lausr mrer uy yoo polmoh sa lmis ars ibw2lawbah_odajanm vtixy, nao’h bowa ci esebiyu cztoich augf piboli, bugk yqu ahr0sabxap_esilegv pefiguas ngij ok pixeqt akl pagkaka ud comt bxe agnfejm oz fve zum vehlqioh.
Ar taeg ahf qira, rea ses hipc do ivtsafe o kabro fkel khll wezkow GQZX_UZXAFDOHA, uz urjo Nobanauv’d Luqbtiuh. Es tosy abhaw juu ro orv o kiq BESU__achezpalo fufluid ji e Gamq-A rofo hi yyomkzo u rpzr lfpzit uwn hi fux xiag ogfecu emacocejdu bmej gea noyl lik luh nbi omu iwthahxe og asx2kujvev.
Key Points
Use image dump sections to find all of the segments and sections for a module.
TEXT.__cstring holds hard coded utf8 strings in an executable. Where do you think the other strings are?
Explore the __DATA sections to find links to other modules as well as symbol names and metadata.
The terminal apps nm, otool and dyld_info can help you discover symbols in applications.
Where to Go From Here?
Oh my! There is so much more for you to learn about Mach-O, but the road ends here for now.
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 Personal Plan.