Introduction to ARM64v8
Last updated
Last updated
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
In ARMv8 argitektuur, definieer uitvoeringsvlakke, bekend as Uitsondering Vlakke (ELs), die voorregvlak en vermoëns van die uitvoeringsomgewing. Daar is vier uitsondering vlakke, wat wissel van EL0 tot EL3, elk met 'n ander doel:
EL0 - Gebruikersmodus:
Dit is die minste voorreg vlak en word gebruik om gewone toepassingskode uit te voer.
Toepassings wat op EL0 loop, is van mekaar en van die stelselsagteware geïsoleer, wat sekuriteit en stabiliteit verbeter.
EL1 - Bedryfstelsel Kernel Modus:
Meeste bedryfstelsel kerne loop op hierdie vlak.
EL1 het meer voorregte as EL0 en kan toegang tot stelselhulpbronne hê, maar met sekere beperkings om stelselintegriteit te verseker.
EL2 - Hypervisor Modus:
Hierdie vlak word gebruik vir virtualisering. 'n Hypervisor wat op EL2 loop, kan verskeie bedryfstelsels bestuur (elke in sy eie EL1) wat op dieselfde fisiese hardeware loop.
EL2 bied kenmerke vir isolasie en beheer van die gevirtualiseerde omgewings.
EL3 - Veilige Monitor Modus:
Dit is die mees voorregte vlak en word dikwels gebruik vir veilige opstart en vertroude uitvoeringsomgewings.
EL3 kan toegang en beheer tussen veilige en nie-veilige toestande bestuur (soos veilige opstart, vertroude OS, ens.).
Die gebruik van hierdie vlakke stel 'n gestruktureerde en veilige manier in om verskillende aspekte van die stelsel te bestuur, van gebruikers toepassings tot die mees voorregte stelselsagteware. ARMv8 se benadering tot voorregte vlakke help om verskillende stelselskomponente effektief te isoleer, wat die sekuriteit en robuustheid van die stelsel verbeter.
ARM64 het 31 algemene registers, gemerk x0
tot x30
. Elke kan 'n 64-bit (8-byte) waarde stoor. Vir operasies wat slegs 32-bit waardes vereis, kan dieselfde registers in 'n 32-bit modus toeganklik wees met die name w0 tot w30.
x0
tot x7
- Hierdie word tipies gebruik as skrap registers en om parameters aan subrutines oor te dra.
x0
dra ook die terugdata van 'n funksie
x8
- In die Linux-kernel, word x8
gebruik as die stelselaanroepnommer vir die svc
instruksie. In macOS is dit x16 wat gebruik word!
x9
tot x15
- Meer tydelike registers, dikwels gebruik vir plaaslike veranderlikes.
x16
en x17
- Intra-prosedurele Oproep Registers. Tydelike registers vir onmiddellike waardes. Hulle word ook gebruik vir indirekte funksie oproepe en PLT (Procedure Linkage Table) stubs.
x16
word gebruik as die stelselaanroepnommer vir die svc
instruksie in macOS.
x18
- Platform register. Dit kan as 'n algemene register gebruik word, maar op sommige platforms is hierdie register gereserveer vir platform-spesifieke gebruike: Punter na die huidige draad-omgewing blok in Windows, of om na die huidige uitvoerende taakstruktuur in die linux kernel te verwys.
x19
tot x28
- Hierdie is kalteer-bewaar registers. 'n Funksie moet hierdie registers se waardes vir sy oproeper behou, so hulle word in die stapel gestoor en herwin voordat hulle teruggaan na die oproeper.
x29
- Raamwyser om die stapelraam te volg. Wanneer 'n nuwe stapelraam geskep word omdat 'n funksie opgeroep word, word die x29
register in die stapel gestoor en die nuwe raamwyser adres is (sp
adres) in hierdie register gestoor.
Hierdie register kan ook as 'n algemene register gebruik word alhoewel dit gewoonlik as 'n verwysing na lokale veranderlikes gebruik word.
x30
of lr
- Link register. Dit hou die terugadres wanneer 'n BL
(Branch with Link) of BLR
(Branch with Link to Register) instruksie uitgevoer word deur die pc
waarde in hierdie register te stoor.
Dit kan ook soos enige ander register gebruik word.
As die huidige funksie 'n nuwe funksie gaan oproep en dus lr
gaan oorskryf, sal dit dit aan die begin in die stapel stoor, dit is die epiloog (stp x29, x30 , [sp, #-48]; mov x29, sp
-> Stoor fp
en lr
, genereer ruimte en kry nuwe fp
) en dit aan die einde herwin, dit is die proloog (ldp x29, x30, [sp], #48; ret
-> Herwin fp
en lr
en keer terug).
sp
- Stapelwyser, gebruik om die bokant van die stapel te volg.
die sp
waarde moet altyd ten minste 'n quadword uitlijning of 'n uitlijningsfout mag voorkom.
pc
- Program teller, wat na die volgende instruksie wys. Hierdie register kan slegs opgedateer word deur uitsondering generasies, uitsondering terugkeerde, en takke. Die enigste gewone instruksies wat hierdie register kan lees, is tak met link instruksies (BL, BLR) om die pc
adres in lr
(Link Register) te stoor.
xzr
- Nul register. Ook genoem wzr
in sy 32-bit register vorm. Kan gebruik word om die nul waarde maklik te kry (gewone operasie) of om vergelykings te doen met subs
soos subs XZR, Xn, #10
wat die resulterende data nêrens stoor (in xzr
).
Die Wn
registers is die 32bit weergawe van die Xn
register.
Boonop is daar nog 32 registers van 128bit lengte wat gebruik kan word in geoptimaliseerde enkele instruksie meervoudige data (SIMD) operasies en vir die uitvoering van drijvende-komma rekenkunde. Hierdie word die Vn registers genoem alhoewel hulle ook in 64-bit, 32-bit, 16-bit en 8-bit kan werk en dan word hulle Qn
, Dn
, Sn
, Hn
en Bn
genoem.
Daar is honderde stelselsregisters, ook bekend as spesiale-doel registers (SPRs), wat gebruik word vir monitering en beheer van prosessor gedrag.
Hulle kan slegs gelees of gestel word met die toegewyde spesiale instruksie mrs
en msr
.
Die spesiale registers TPIDR_EL0
en TPIDDR_EL0
word algemeen aangetref wanneer omgekeerde ingenieurswese gedoen word. Die EL0
agtervoegsel dui die minimale uitsondering aan waaruit die register toeganklik is (in hierdie geval is EL0 die gewone uitsondering (voorreg) vlak waaroor gewone programme loop).
Hulle word dikwels gebruik om die basisadres van die draad-lokale berging geheue streek te stoor. Gewoonlik is die eerste een leesbaar en skryfbaar vir programme wat in EL0 loop, maar die tweede kan van EL0 gelees en van EL1 geskryf word (soos kernel).
mrs x0, TPIDR_EL0 ; Lees TPIDR_EL0 in x0
msr TPIDR_EL0, X0 ; Skryf x0 in TPIDR_EL0
PSTATE bevat verskeie proses komponente wat in die bedryfstelsel-sigbare SPSR_ELx
spesiale register geserialiseer is, wat X die toestemming vlak van die geaktiveerde uitsondering aandui (dit stel in staat om die proses toestand te herstel wanneer die uitsondering eindig).
Hierdie is die toeganklike velde:
Die N
, Z
, C
en V
toestand vlae:
N
beteken die operasie het 'n negatiewe resultaat opgelewer
Z
beteken die operasie het nul opgelewer
C
beteken die operasie het 'n dra oor
V
beteken die operasie het 'n onderteken oorloop opgelewer:
Die som van twee positiewe getalle lewer 'n negatiewe resultaat.
Die som van twee negatiewe getalle lewer 'n positiewe resultaat.
In aftrekking, wanneer 'n groot negatiewe getal van 'n kleiner positiewe getal (of omgekeerd) afgetrek word, en die resultaat nie binne die reeks van die gegewe bitgrootte verteenwoordig kan word nie.
Dit is duidelik dat die prosessor nie weet of die operasie onderteken is of nie, so dit sal C en V in die operasies nagaan en aandui of 'n dra plaasgevind het in die geval dit onderteken of nie-onderteken was.
Nie alle instruksies werk hierdie vlae op nie. Sommige soos CMP
of TST
doen, en ander wat 'n s agtervoegsel het soos ADDS
doen dit ook.
Die huidige register breedte (nRW
) vlag: As die vlag die waarde 0 hou, sal die program in die AArch64 uitvoeringsstaat loop sodra dit hervat word.
Die huidige Uitsondering Vlak (EL
): 'n Gewone program wat in EL0 loop, sal die waarde 0 hê
Die enkele stap vlag (SS
): Gebruik deur debuggers om enkelstap deur die SS vlag op 1 in SPSR_ELx
deur 'n uitsondering te stel. Die program sal 'n stap uitvoer en 'n enkele stap uitsondering uitreik.
Die onwettige uitsondering toestand vlag (IL
): Dit word gebruik om aan te dui wanneer 'n voorregte sagteware 'n ongeldige uitsondering vlak oordrag uitvoer, hierdie vlag word op 1 gestel en die prosessor aktiveer 'n onwettige toestand uitsondering.
Die DAIF
vlae: Hierdie vlae stel 'n voorregte program in staat om selektief sekere eksterne uitsonderings te masker.
As A
1 is, beteken dit dat asynchrone afbrake geaktiveer sal word. Die I
stel in om te reageer op eksterne hardeware Interrupts Requests (IRQs). en die F is verwant aan Fast Interrupt Requests (FIRs).
Die stapelwyser seleksie vlae (SPS
): Voorregte programme wat in EL1 en hoër loop, kan tussen die gebruik van hul eie stapelwyser register en die gebruikersmodel een (bv. tussen SP_EL1
en EL0
) wissel. Hierdie skakeling word uitgevoer deur na die SPSel
spesiale register te skryf. Dit kan nie van EL0 gedoen word nie.
Die ARM64 oproep konvensie spesifiseer dat die eerste agt parameters aan 'n funksie in registers x0
tot x7
oorgedra word. Addisionele parameters word op die stapel oorgedra. Die terug waarde word teruggegee in register x0
, of in x1
as dit ook 128 bits lank is. Die x19
tot x30
en sp
registers moet bewaar word oor funksie oproepe.
Wanneer 'n funksie in assembly gelees word, soek na die funksie proloog en epiloog. Die proloog behels gewoonlik die stoor van die raamwyser (x29
), opstelling van 'n nuwe raamwyser, en toewysing van stapelruimte. Die epiloog behels gewoonlik die herstel van die gestoor raamwyser en terugkeer van die funksie.
Swift het sy eie oproep konvensie wat gevind kan word in https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64
ARM64 instruksies het oor die algemeen die formaat opcode dst, src1, src2
, waar opcode
die operasie is wat uitgevoer moet word (soos add
, sub
, mov
, ens.), dst
is die bestemmings register waar die resultaat gestoor sal word, en src1
en src2
is die bron registers. Onmiddellike waardes kan ook in plaas van bron registers gebruik word.
mov
: Beweeg 'n waarde van een register na 'n ander.
Voorbeeld: mov x0, x1
— Dit beweeg die waarde van x1
na x0
.
ldr
: Laai 'n waarde van geheue in 'n register.
Voorbeeld: ldr x0, [x1]
— Dit laai 'n waarde van die geheue ligging wat deur x1
aangedui word in x0
.
Offset modus: 'n offset wat die oorspronklike punter beïnvloed, word aangedui, byvoorbeeld:
ldr x2, [x1, #8]
, dit sal die waarde van x1 + 8 in x2 laai
ldr x2, [x0, x1, lsl #2]
, dit sal 'n objek van die array x0 in x2 laai, vanaf die posisie x1 (indeks) * 4
Pre-geïndekseerde modus: Dit sal berekeninge op die oorspronklike toepas, die resultaat kry en ook die nuwe oorspronklike in die oorspronklike stoor.
ldr x2, [x1, #8]!
, dit sal x1 + 8
in x2
laai en in x1
die resultaat van x1 + 8
stoor
str lr, [sp, #-4]!
, Stoor die link register in sp en werk die register sp op
Post-geïndekseerde modus: Dit is soos die vorige een, maar die geheue adres word toeganklik gemaak en dan word die offset bereken en gestoor.
ldr x0, [x1], #8
, laai x1
in x0
en werk x1 op met x1 + 8
PC-relatiewe adressering: In hierdie geval word die adres om te laai bereken relatief tot die PC register
ldr x1, =_start
, Dit sal die adres waar die _start
simbool begin in x1 laai relatief tot die huidige PC.
str
: Stoor 'n waarde van 'n register in geheue.
Voorbeeld: str x0, [x1]
— Dit stoor die waarde in x0
in die geheue ligging wat deur x1
aangedui word.
ldp
: Laai Paar Registers. Hierdie instruksie laai twee registers van aaneengeskakelde geheue liggings. Die geheue adres word tipies gevorm deur 'n offset by die waarde in 'n ander register te voeg.
Voorbeeld: ldp x0, x1, [x2]
— Dit laai x0
en x1
van die geheue liggings by x2
en x2 + 8
, onderskeidelik.
stp
: Stoor Paar Registers. Hierdie instruksie stoor twee registers na aaneengeskakelde geheue liggings. Die geheue adres word tipies gevorm deur 'n offset by die waarde in 'n ander register te voeg.
Voorbeeld: stp x0, x1, [sp]
— Dit stoor x0
en x1
na die geheue liggings by sp
en sp + 8
, onderskeidelik.
stp x0, x1, [sp, #16]!
— Dit stoor x0
en x1
na die geheue liggings by sp+16
en sp + 24
, onderskeidelik, en werk sp
op met sp+16
.
add
: Voeg die waardes van twee registers by en stoor die resultaat in 'n register.
Sintaksis: add(s) Xn1, Xn2, Xn3 | #imm, [shift #N | RRX]
Xn1 -> Bestemming
Xn2 -> Operand 1
Xn3 | #imm -> Operando 2 (register of onmiddellik)
[shift #N | RRX] -> Voer 'n verskuiwing uit of bel RRX
Voorbeeld: add x0, x1, x2
— Dit voeg die waardes in x1
en x2
saam en stoor die resultaat in x0
.
add x5, x5, #1, lsl #12
— Dit is gelyk aan 4096 (1 verskuiwer 12 keer) -> 1 0000 0000 0000 0000
adds
Dit voer 'n add
uit en werk die vlae op
sub
: Trek die waardes van twee registers af en stoor die resultaat in 'n register.
Kyk na add
sintaksis.
Voorbeeld: sub x0, x1, x2
— Dit trek die waarde in x2
van x1
af en stoor die resultaat in x0
.
subs
Dit is soos sub maar werk die vlag op
mul
: Vermenigvuldig die waardes van twee registers en stoor die resultaat in 'n register.
Voorbeeld: mul x0, x1, x2
— Dit vermenigvuldig die waardes in x1
en x2
en stoor die resultaat in x0
.
div
: Deel die waarde van een register deur 'n ander en stoor die resultaat in 'n register.
Voorbeeld: div x0, x1, x2
— Dit deel die waarde in x1
deur x2
en stoor die resultaat in x0
.
lsl
, lsr
, asr
, ror
, rrx
:
Logiese verskuiwing links: Voeg 0s van die einde by en beweeg die ander bits vorentoe (vermenigvuldig met n-keer 2)
Logiese verskuiwing regs: Voeg 1s aan die begin by en beweeg die ander bits agtertoe (deel deur n-keer 2 in nie-onderteken)
Arithmetiese verskuiwing regs: Soos lsr
, maar in plaas daarvan om 0s by te voeg, as die mees betekenisvolle bit 'n 1 is, word 1s bygevoeg (deel deur n-keer 2 in onderteken)
Draai regs: Soos lsr
maar wat ook al van die regterkant verwyder word, word aan die linkerkant bygevoeg
Draai Regs met Uitbreiding: Soos ror
, maar met die dra vlag as die "mees betekenisvolle bit". So die dra vlag word na die bit 31 verskuif en die verwyderde bit na die dra vlag.
bfm
: Bit Veld Beweeg, hierdie operasies kopieer bits 0...n
van 'n waarde en plaas hulle in posisies m..m+n
. Die #s
spesifiseer die linkerste bit posisie en #r
die draai regs hoeveelheid.
Bitfiled beweeg: BFM Xd, Xn, #r
Onderteken Bitfield beweeg: SBFM Xd, Xn, #r, #s
Ononderteken Bitfield beweeg: UBFM Xd, Xn, #r, #s
Bitfield Uittrek en Invoeg: Kopieer 'n bitveld van 'n register en kopieer dit na 'n ander register.
BFI X1, X2, #3, #4
Voeg 4 bits van X2 vanaf die 3de bit van X1 in
BFXIL X1, X2, #3, #4
Trek 4 bits vanaf die 3de bit van X2 uit en kopieer dit na X1
SBFIZ X1, X2, #3, #4
Onderteken-uitbrei 4 bits van X2 en voeg dit in X1 in wat by bit posisie 3 begin en die regter bits nulmaak
SBFX X1, X2, #3, #4
Trek 4 bits vanaf bit 3 van X2 uit, onderteken uitbrei dit, en plaas die resultaat in X1
UBFIZ X1, X2, #3, #4
Nul-uitbrei 4 bits van X2 en voeg dit in X1 in wat by bit posisie 3 begin en die regter bits nulmaak
UBFX X1, X2, #3, #4
Trek 4 bits vanaf bit 3 van X2 uit en plaas die nul-uitgebreide resultaat in X1.
Onderteken Uitbrei na X: Brei die teken uit (of voeg net 0s in die ononderteken weergawe) van 'n waarde om operasies daarmee uit te voer:
SXTB X1, W2
Brei die teken van 'n byte van W2 na X1 uit (W2
is die helfte van X2
) om die 64bits te vul
SXTH X1, W2
Brei die teken van 'n 16bit getal van W2 na X1 uit om die 64bits te vul
SXTW X1, W2
Brei die teken van 'n byte van W2 na X1 uit om die 64bits te vul
UXTB X1, W2
Voeg 0s (ononderteken) by 'n byte van W2 na X1 om die 64bits te vul
extr
: Trek bits uit 'n gespesifiseerde paar registers gekombineer.
Voorbeeld: EXTR W3, W2, W1, #3
Dit sal W1+W2 kombineer en van bit 3 van W2 tot bit 3 van W1 kry en dit in W3 stoor.
cmp
: Vergelyk twee registers en stel toestand vlae. Dit is 'n alias van subs
wat die bestemming register na die nul register stel. Nuttig om te weet of m == n
.
Dit ondersteun die dieselfde sintaksis as subs
Voorbeeld: cmp x0, x1
— Dit vergelyk die waardes in x0
en x1
en stel die toestand vlae ooreenkomstig op.
cmn
: Vergelyk negatiewe operand. In hierdie geval is dit 'n alias van adds
en ondersteun die dieselfde sintaksis. Nuttig om te weet of m == -n
.
ccmp
: Voorwaardelike vergelyking, dit is 'n vergelyking wat slegs uitgevoer sal word as 'n vorige vergelyking waar was en sal spesifiek nzcv bits stel.
cmp x1, x2; ccmp x3, x4, 0, NE; blt _func
-> as x1 != x2 en x3 < x4, spring na func
Dit is omdat ccmp
slegs uitgevoer sal word as die vorige cmp
'n NE
was, as dit nie was nie, sal die bits nzcv
op 0 gestel word (wat nie die blt
vergelyking sal bevredig nie).
Dit kan ook as ccmn
gebruik word (dieselfde maar negatief, soos cmp
teenoor cmn
).
tst
: Dit kyk of enige van die vergelykings se waardes albei 1 is (dit werk soos 'n ANDS sonder om die resultaat nêrens te stoor). Dit is nuttig om 'n register met 'n waarde te kontroleer en te kyk of enige van die bits van die register wat in die waarde aangedui word, 1 is.
Voorbeeld: tst X1, #7
Kyk of enige van die laaste 3 bits van X1 1 is
teq
: XOR operasie wat die resultaat verwerp
b
: Onvoorwaardelike Tak
Voorbeeld: b myFunction
Let daarop dat dit nie die link register met die terugadres sal vul nie (nie geskik vir subrutine oproepe wat terug moet keer nie)
bl
: Tak met link, gebruik om 'n subrutine te noem. Stoor die terugadres in x30
.
Voorbeeld: bl myFunction
— Dit noem die funksie myFunction
en stoor die terugadres in x30
.
Let daarop dat dit nie die link register met die terugadres sal vul nie (nie geskik vir subrutine oproepe wat terug moet keer nie)
blr
: Tak met Link na Register, gebruik om 'n subrutine te noem waar die teiken in 'n register gespesifiseer is. Stoor die terugadres in x30
. (Dit is
Voorbeeld: blr x1
— Dit noem die funksie waarvan die adres in x1
bevat is en stoor die terugadres in x30
.
ret
: Keer terug van subrutine, tipies met die adres in x30
.
Voorbeeld: ret
— Dit keer terug van die huidige subrutine met die terugadres in x30
.
b.<cond>
: Voorwaardelike takke
b.eq
: Tak as gelyk, gebaseer op die vorige cmp
instruksie.
Voorbeeld: b.eq label
— As die vorige cmp
instruksie twee gelyke waardes gevind het, spring dit na label
.
b.ne
: Tak as Nie Gelyk. Hierdie instruksie kyk die toestand vlae (wat deur 'n vorige vergelyking instruksie gestel is), en as die vergelykte waardes nie gelyk was nie, tak dit na 'n etiket of adres.
Voorbeeld: Na 'n cmp x0, x1
instruksie, b.ne label
— As die waardes in x0
en x1
nie gelyk was nie, spring dit na label
.
cbz
: Vergelyk en Tak op Nul. Hierdie instruksie vergelyk 'n register met nul, en as hulle gelyk is, tak dit na 'n etiket of adres.
Voorbeeld: cbz x0, label
— As die waarde in x0
nul is, spring dit na label
.
cbnz
: Vergelyk en Tak op Nie-Nul. Hierdie instruksie vergelyk 'n register met nul, en as hulle nie gelyk is nie, tak dit na 'n etiket of adres.
Voorbeeld: cbnz x0, label
— As die waarde in x0
nie nul is nie, spring dit na label
.
tbnz
: Toets bit en tak op nie-nul
Voorbeeld: tbnz x0, #8, label
tbz
: Toets bit en tak op nul
Voorbeeld: tbz x0, #8, label
Voorwaardelike seleksie operasies: Dit is operasies waarvan die gedrag wissel, afhangende van die voorwaardelike bits.
csel Xd, Xn, Xm, cond
-> csel X0, X1, X2, EQ
-> As waar, X0 = X1, as vals, X0 = X2
csinc Xd, Xn, Xm, cond
-> As waar, Xd = Xn, as vals, Xd = Xm + 1
cinc Xd, Xn, cond
-> As waar, Xd = Xn + 1, as vals, Xd = Xn
csinv Xd, Xn, Xm, cond
-> As waar, Xd = Xn, as vals, Xd = NOT(Xm)
cinv Xd, Xn, cond
-> As waar, Xd = NOT(Xn), as vals, Xd = Xn
csneg Xd, Xn, Xm, cond
-> As waar, Xd = Xn, as vals, Xd = - Xm
cneg Xd, Xn, cond
-> As waar, Xd = - Xn, as vals, Xd = Xn
cset Xd, Xn, Xm, cond
-> As waar, Xd = 1, as vals, Xd = 0
csetm Xd, Xn, Xm, cond
-> As waar, Xd = <alle 1>, as vals, Xd = 0
adrp
: Bereken die blad adres van 'n simbool en stoor dit in 'n register.
Voorbeeld: adrp x0, symbol
— Dit bereken die blad adres van symbol
en stoor dit in x0
.
ldrsw
: Laai 'n onderteken 32-bit waarde van geheue en onderteken-uitbrei dit na 64 bits.
Voorbeeld: ldrsw x0, [x1]
— Dit laai 'n onderteken 32-bit waarde van die geheue ligging wat deur x1
aangedui word, onderteken-uitbrei dit na 64 bits, en stoor dit in x0
.
stur
: Stoor 'n register waarde na 'n geheue ligging, met 'n offset van 'n ander register.
Voorbeeld: stur x0, [x1, #4]
— Dit stoor die waarde in x0
in die geheue adres wat 4 bytes groter is as die adres wat tans in x1
is.
svc
: Maak 'n stelselaanroep. Dit staan vir "Supervisor Call". Wanneer die prosessor hierdie instruksie uitvoer, skakel dit van gebruikersmodus na kernelmodus en spring na 'n spesifieke ligging in geheue waar die kernel se stelselaanroep hantering kode geleë is.
Voorbeeld:
Stoor die link register en raamwyser in die stapel:
Stel die nuwe raamwyser op: mov x29, sp
(stel die nuwe raamwyser op vir die huidige funksie)
Toewys ruimte op die stapel vir plaaslike veranderlikes (indien nodig): sub sp, sp, <size>
(waar <size>
die aantal bytes is wat benodig word)
Deallocate plaaslike veranderlikes (indien enige toegeken is): add sp, sp, <size>
Herstel die skakelregister en raamwyser:
Return: ret
(gee beheer terug aan die oproeper met behulp van die adres in die skakelregister)
Armv8-A ondersteun die uitvoering van 32-bis programme. AArch32 kan in een van twee instruksiesette loop: A32
en T32
en kan tussen hulle skakel via interworking
.
Bevoorregte 64-bis programme kan die uitvoering van 32-bis programme skeduleer deur 'n uitsonderingsvlak oordrag na die laer bevoorregte 32-bis uit te voer.
Let daarop dat die oorgang van 64-bis na 32-bis plaasvind met 'n verlaging van die uitsonderingsvlak (byvoorbeeld 'n 64-bis program in EL1 wat 'n program in EL0 aktiveer). Dit word gedoen deur die bit 4 van SPSR_ELx
spesiale register na 1 te stel wanneer die AArch32
prosesdraad gereed is om uitgevoer te word en die res van SPSR_ELx
stoor die AArch32
programme CPSR. Dan roep die bevoorregte proses die ERET
instruksie aan sodat die verwerker oorgaan na AArch32
wat in A32 of T32 ingaan, afhangende van CPSR**.**
Die interworking
vind plaas met behulp van die J en T bits van CPSR. J=0
en T=0
beteken A32
en J=0
en T=1
beteken T32. Dit beteken basies om die laagste bit na 1 te stel om aan te dui dat die instruksieset T32 is.
Dit word tydens die interworking takinstruksies gestel, maar kan ook direk met ander instruksies gestel word wanneer die PC as die bestemmingsregister gestel word. Voorbeeld:
Nog 'n voorbeeld:
Daar is 16 32-bit registers (r0-r15). Van r0 tot r14 kan hulle gebruik word vir enige operasie, maar sommige daarvan is gewoonlik gereserveer:
r15
: Programma teller (altyd). Bevat die adres van die volgende instruksie. In A32 huidige + 8, in T32, huidige + 4.
r11
: Raamwyser
r12
: Intra-prosedure oproep register
r13
: Stapelwyser
r14
: Skakel register
Boonop word registers gebackup in banked registries
. Dit is plekke wat die registerwaardes stoor wat dit moontlik maak om vinnige kontekstuswisseling in uitsondering hantering en bevoorregte operasies uit te voer om die behoefte om registers elke keer handmatig te stoor en te herstel te vermy.
Dit word gedoen deur die verwerker toestand van die CPSR
na die SPSR
van die verwerker modus waarheen die uitsondering geneem word, te stoor. By die uitsondering terugkeer, word die CPSR
van die SPSR
herstel.
In AArch32 werk die CPSR soortgelyk aan PSTATE
in AArch64 en word ook gestoor in SPSR_ELx
wanneer 'n uitsondering geneem word om later die uitvoering te herstel:
Die velde is in 'n paar groepe verdeel:
Aansoek Program Status Register (APSR): Aritmetiese vlae en toeganklik vanaf EL0
Uitvoeringsstaat Registers: Proses gedrag (geadministreer deur die OS).
Die N
, Z
, C
, V
vlae (net soos in AArch64)
Die Q
vlag: Dit word op 1 gestel wanneer heelgetal saturasie plaasvind tydens die uitvoering van 'n gespesialiseerde saturerende aritmetiese instruksie. Sodra dit op 1
gestel is, sal dit die waarde behou totdat dit handmatig op 0 gestel word. Boonop is daar geen instruksie wat sy waarde implisiet nagaan nie, dit moet gedoen word deur dit handmatig te lees.
GE
(Groter as of gelyk aan) Vlaggies: Dit word gebruik in SIMD (Enkele Instruksie, Meervoudige Data) operasies, soos "parallel byvoeg" en "parallel aftrek". Hierdie operasies stel in staat om verskeie datapunte in 'n enkele instruksie te verwerk.
Byvoorbeeld, die UADD8
instruksie voeg vier pare bytes (van twee 32-bit operand) parallel by en stoor die resultate in 'n 32-bit register. Dit stel dan die GE
vlae in die APSR
op grond van hierdie resultate. Elke GE vlag kom ooreen met een van die byte byvoegings, wat aandui of die byvoeging vir daardie byte paar oorloop.
Die SEL
instruksie gebruik hierdie GE vlae om voorwaardelike aksies uit te voer.
Die J
en T
bits: J
moet 0 wees en as T
0 is, word die instruksieset A32 gebruik, en as dit 1 is, word die T32 gebruik.
IT Blok Staat Register (ITSTATE
): Dit is die bits van 10-15 en 25-26. Hulle stoor toestande vir instruksies binne 'n IT
voorvoegsel groep.
E
bit: Dui die endianness aan.
Modus en Uitsondering Masker Bits (0-4): Hulle bepaal die huidige uitvoeringsstaat. Die 5de dui aan of die program as 32bit (n 1) of 64bit (n 0) loop. Die ander 4 verteenwoordig die uitsondering modus wat tans gebruik word (wanneer 'n uitsondering plaasvind en dit hanteer word). Die nommer wat gestel word dui die huidige prioriteit aan in die geval dat 'n ander uitsondering geaktiveer word terwyl dit hanteer word.
AIF
: Sekere uitsonderings kan gedeaktiveer word deur die bits A
, I
, F
. As A
1 is, beteken dit dat asynchrone aborts geaktiveer sal word. Die I
stel in om te reageer op eksterne hardeware Interrupts Requests (IRQs). en die F is verwant aan Fast Interrupt Requests (FIRs).
Kyk na syscalls.master. BSD syscalls sal x16 > 0 hê.
Kyk na syscall_sw.c die mach_trap_table
en in mach_traps.h die prototipes. Die maksimum aantal Mach traps is MACH_TRAP_TABLE_COUNT
= 128. Mach traps sal x16 < 0 hê, so jy moet die nommers van die vorige lys met 'n minus aanroep: _kernelrpc_mach_vm_allocate_trap
is -10
.
Jy kan ook libsystem_kernel.dylib
in 'n disassembler nagaan om te vind hoe om hierdie (en BSD) syscalls aan te roep:
Let daarop dat Ida en Ghidra ook spesifieke dylibs uit die cache kan dekompileer net deur die cache te oorhandig.
Soms is dit makliker om die gedekompleerde kode van libsystem_kernel.dylib
te kontroleer as om die bronkode te kontroleer omdat die kode van verskeie syscalls (BSD en Mach) via skripte gegenereer word (kyk kommentaar in die bronkode) terwyl jy in die dylib kan vind wat aangeroep word.
XNU ondersteun 'n ander tipe oproepe wat masjienafhanklik genoem word. Die getalle van hierdie oproepe hang af van die argitektuur en geen van die oproepe of getalle is gewaarborg om konstant te bly nie.
Dit is 'n kern eienaar geheue bladsy wat in die adresruimte van elke gebruiker se proses gemap is. Dit is bedoel om die oorgang van gebruikersmodus na kernruimte vinniger te maak as om syscalls te gebruik vir kern dienste wat so baie gebruik word dat hierdie oorgang baie ondoeltreffend sou wees.
Byvoorbeeld, die oproep gettimeofdate
lees die waarde van timeval
direk van die comm bladsy.
Dit is baie algemeen om hierdie funksie in Objective-C of Swift programme te vind. Hierdie funksie stel jou in staat om 'n metode van 'n Objective-C objek aan te roep.
Parameters (meer inligting in die dokumentasie):
x0: self -> Wys na die instansie
x1: op -> Selektor van die metode
x2... -> Res van die argumente van die aangeroepte metode
So, as jy 'n breekpunt voor die tak na hierdie funksie plaas, kan jy maklik vind wat in lldb aangeroep word (in hierdie voorbeeld roep die objek 'n objek van NSConcreteTask
aan wat 'n opdrag sal uitvoer):
Deur die omgewing veranderlike NSObjCMessageLoggingEnabled=1
in te stel, is dit moontlik om te log wanneer hierdie funksie in 'n lêer soos /tmp/msgSends-pid
aangeroep word.
Boonop, deur OBJC_HELP=1
in te stel en enige binêre aan te roep, kan jy ander omgewing veranderlikes sien wat jy kan gebruik om log te maak wanneer sekere Objc-C aksies plaasvind.
Wanneer hierdie funksie aangeroep word, is dit nodig om die aangeroepde metode van die aangeduide instansie te vind, hiervoor word verskillende soektogte gedoen:
Voer optimistiese kassoektog uit:
As suksesvol, klaar
Verkry runtimeLock (lees)
As (realize && !cls->realized) besef klas
As (initialize && !cls->initialized) inisieer klas
Probeer klas se eie kas:
As suksesvol, klaar
Probeer klas metode lys:
As gevind, vul kas en klaar
Probeer superklas kas:
As suksesvol, klaar
Probeer superklas metode lys:
As gevind, vul kas en klaar
As (resolver) probeer metode resolver, en herhaal vanaf klas soektog
As jy steeds hier is (= alles anders het gefaal) probeer forwarder
Om te kompileer:
Om die bytes te onttrek:
Vir nuwer macOS:
Leer & oefen AWS Hacking:HackTricks Opleiding AWS Red Team Expert (ARTE) Leer & oefen GCP Hacking: HackTricks Opleiding GCP Red Team Expert (GRTE)