Introduction to ARM64v8
Last updated
Last updated
Учите и практикујте AWS хаковање:HackTricks Training AWS Red Team Expert (ARTE) Учите и практикујте GCP хаковање: HackTricks Training GCP Red Team Expert (GRTE)
У ARMv8 архитектури, нивои извршења, познати као нивои изузетака (EL), дефинишу ниво привилегија и способности извршног окружења. Постоје четири нивоа изузетака, од EL0 до EL3, од којих сваки служи различитој сврси:
EL0 - Кориснички режим:
Ово је најмање привилегован ниво и користи се за извршавање редовног кода апликација.
Апликације које раде на EL0 су изоловане једна од друге и од системског софтвера, што побољшава безбедност и стабилност.
EL1 - Режим језгра оперативног система:
Већина језгара оперативних система ради на овом нивоу.
EL1 има више привилегија од EL0 и може приступити системским ресурсима, али уз нека ограничења ради очувања интегритета система.
EL2 - Режим хипервизора:
Овај ниво се користи за виртуализацију. Хипервизор који ради на EL2 може управљати више оперативних система (сваки у свом EL1) који раде на истом физичком хардверу.
EL2 пружа функције за изолацију и контролу виртуализованих окружења.
EL3 - Режим сигурног монитора:
Ово је најпривилегованији ниво и често се користи за сигурно покретање и поверење у извршна окружења.
EL3 може управљати и контролисати приступе између сигурних и несигурних стања (као што су сигурно покретање, поверење у ОС, итд.).
Користење ових нивоа омогућава структурисан и сигуран начин управљања различитим аспектима система, од корисничких апликација до најпривилегованијег системског софтвера. Приступ ARMv8 нивима привилегија помаже у ефикасном изоловању различитих компоненти система, чиме се побољшава безбедност и робусност система.
ARM64 има 31 регистар опште намене, обележен x0
до x30
. Сваки може да чува 64-битну (8-бајтну) вредност. За операције које захтевају само 32-битне вредности, исти регистри могу бити доступни у 32-битном режиму користећи имена w0 до w30.
x0
до x7
- Ови се обично користе као регистри за привремене податке и за пренос параметара у подпрограме.
x0
такође носи повратне податке функције
x8
- У Linux језгру, x8
се користи као број системског позива за svc
инструкцију. У macOS, x16 је тај који се користи!
x9
до x15
- Више привремених регистара, често се користе за локалне променљиве.
x16
и x17
- Регистри за позиве унутар процедура. Привремени регистри за одмах вредности. Такође се користе за индиректне позиве функција и PLT (Табела повезивања процедура).
x16
се користи као број системског позива за svc
инструкцију у macOS.
x18
- Регистар платформе. Може се користити као регистар опште намене, али на неким платформама, овај регистар је резервисан за платформски специфичне намене: Показивач на блок окружења тренутне нит у Windows-у, или да укаже на тренутну структуру извршавања задатка у linux језгру.
x19
до x28
- Ово су регистри које чува позвана функција. Функција мора да очува вредности ових регистара за свог позиваоца, тако да се чувају на стеку и опорављају пре него што се врати позиваоцу.
x29
- Показивач оквира за праћење оквира стека. Када се креира нови оквир стека јер је функција позвана, x29
регистар се чува на стеку и нова адреса показивача оквира (sp
адреса) се чува у овом регистру.
Овај регистар се такође може користити као регистар опште намене иако се обично користи као референца на локалне променљиве.
x30
или lr
- Регистар за повратак. Држи адресу повратка када се извршава BL
(Гранка са повратком) или BLR
(Гранка са повратком у регистар) инструкција чувајући pc
вредност у овом регистру.
Може се користити и као било који други регистар.
Ако тренутна функција позива нову функцију и стога ће преоптеретити lr
, чуваће је на стеку на почетку, ово је епилог (stp x29, x30 , [sp, #-48]; mov x29, sp
-> Чува fp
и lr
, генерише простор и добија нови fp
) и опорављаће је на крају, ово је пролог (ldp x29, x30, [sp], #48; ret
-> Опоравља fp
и lr
и враћа).
sp
- Показивач стека, користи се за праћење врха стека.
Вредност sp
треба увек да буде одржавана на најмање квадратно поредио или може доћи до изузетка у поређењу.
pc
- Бројач програма, који указује на следећу инструкцију. Овај регистар може бити ажуриран само кроз генерисање изузетака, повратке изузетака и гране. Једине обичне инструкције које могу читати овај регистар су инструкције гране са повратком (BL, BLR) да чувају pc
адресу у lr
(Регистар за повратак).
xzr
- Нулти регистар. Такође се зове wzr
у 32-битном регистарном облику. Може се користити за лако добијање нулте вредности (обична операција) или за извршавање поређења користећи subs
као subs XZR, Xn, #10
чувајући резултујуће податке нигде (у xzr
).
Регистри Wn
су 32-битна верзија регистара Xn
.
Штавише, постоји још 32 регистра дужине 128бит који се могу користити у оптимизованим операцијама једне инструкције више података (SIMD) и за извршавање аритметике покретних тачака. Ови се зову Vn регистри иако могу радити и у 64-битном, 32-битном, 16-битном и 8-битном режиму и тада се зову Qn
, Dn
, Sn
, Hn
и Bn
.
Постоје стотине системских регистара, такође познатих као регистри специјалне намене (SPRs), који се користе за праћење и контролу понашања процесора.
Могу се читати или постављати само помоћу посебних инструкција mrs
и msr
.
Посебни регистри TPIDR_EL0
и TPIDDR_EL0
се често налазе током реверзног инжењеринга. Суфикс EL0
указује на минимално изузеће из ког се регистар може приступити (у овом случају EL0 је редован ниво изузећа (привилегија) на коме редовни програми раде).
Често се користе за чување основне адресе области локалне меморије. Обично је први читљив и записив за програме који раде у EL0, али други се може читати из EL0 и записивати из EL1 (као језгро).
mrs x0, TPIDR_EL0 ; Чита TPIDR_EL0 у x0
msr TPIDR_EL0, X0 ; Записује x0 у TPIDR_EL0
PSTATE садржи неколико компоненти процеса серијализованих у регистру специјалне намене видљивом оперативном систему SPSR_ELx
, где је X ниво дозволе изазваног изузећа (ово омогућава опоравак стања процеса када изузеће заврши).
Ово су доступна поља:
N
, Z
, C
и V
условне заставице:
N
значи да је операција дала негативан резултат
Z
значи да је операција дала нулу
C
значи да је операција пренела
V
значи да је операција дала потписано преливање:
Збир два позитивна броја даје негативан резултат.
Збир два негативна броја даје позитиван резултат.
У одузимању, када се велики негативан број одузима од мањег позитивног броја (или обрнуто), а резултат не може бити представљен у опсегу дате величине бита.
Очигледно, процесор не зна да ли је операција потписана или не, па ће проверити C и V у операцијама и указати да ли је дошло до преноса у случају да је било потписано или непотписано.
Нису све инструкције ажурирале ове заставице. Неке као CMP
или TST
то раде, а друге које имају s суфикс као ADDS
такође то раде.
Тренутна заставица ширине регистра (nRW
): Ако застава држи вредност 0, програм ће се извршавати у AArch64 извршном стању када се поново покрене.
Тренутни Ниво изузетака (EL
): Редован програм који ради у EL0 ће имати вредност 0
Заставица појединачног корака (SS
): Користи се од стране дебагера за појединачно корачење постављајући SS заставицу на 1 унутар SPSR_ELx
кроз изузеће. Програм ће извршити корак и изазвати изузеће појединачног корака.
Заставица нелегалног изузетка (IL
): Користи се за означавање када привилегисани софтвер изврши неважећи пренос нивоа изузетка, ова застава се поставља на 1 и процесор активира нелегално стање изузетка.
DAIF
заставице: Ове заставице омогућавају привилегисаном програму да селективно маскира одређена спољна изузећа.
Ако је A
1, то значи да ће бити активирани асинхрони прекиди. I
конфигурише одговор на спољне захтеве за прекид хардвера (IRQ). и F је повезан са брзим захтевима за прекид (FIR).
Заставице избора показивача стека (SPS
): Привилегисани програми који раде у EL1 и изнад могу да прелазе између коришћења свог регистара показивача стека и корисничког модела (нпр. између SP_EL1
и EL0
). Ова прелазак се изводи писањем у SPSel
посебан регистар. Ово не може бити учињено из EL0.
ARM64 конвенција позива спецификује да се првих осам параметара функције преноси у регистрима x0
до x7
. Додатни параметри се преносе на стеку. Вредност повратка се враћа у регистар x0
, или у x1
ако је дужине 128 бит. Регистри x19
до x30
и sp
морају бити очувани током позива функција.
Када читате функцију у асемблеру, потражите пролог и епилог функције. Пролог обично укључује чување показивача оквира (x29
), постављање новог показивача оквира, и алокацију простора на стеку. Епилог обично укључује враћање сачуваног показивача оквира и враћање из функције.
Swift има своју конвенцију позива која се може наћи на https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64
ARM64 инструкције обично имају формат opcode dst, src1, src2
, где је opcode
операција која се извршава (као што су add
, sub
, mov
, итд.), dst
је регистар дестинације у који ће бити сачуван резултат, а src1
и src2
су изворни регистри. Одмах вредности се такође могу користити уместо изворних регистара.
mov
: Премести вредност из једног регистра у други.
Пример: mov x0, x1
— Ово премешта вредност из x1
у x0
.
ldr
: Учитај вредност из меморије у регистар.
Пример: ldr x0, [x1]
— Ово учитава вредност из меморијске локације на коју указује x1
у x0
.
Режим офсет: Офсет који утиче на оригинални показивач је назначен, на пример:
ldr x2, [x1, #8]
, ово ће учитати у x2 вредност из x1 + 8
ldr x2, [x0, x1, lsl #2]
, ово ће учитати у x2 објекат из низа x0, из позиције x1 (индекс) * 4
Режим пред-индикатора: Ово ће применити израчунавања на оригинал, добити резултат и такође сачувати нови оригинал у оригиналу.
ldr x2, [x1, #8]!
, ово ће учитати x1 + 8
у x2
и сачувати у x1 резултат x1 + 8
str lr, [sp, #-4]!
, Сачувајте регистар за повратак у sp и ажурирајте регистар sp
Режим пост-индикатора: Ово је као претходни, али се меморијска адреса приступа и затим се офсет израчунава и чува.
ldr x0, [x1], #8
, учитајте x1
у x0
и ажурирајте x1 са x1 + 8
PC-релативно адресирање: У овом случају адреса за учитавање се израчунава релативно на PC регистар
ldr x1, =_start
, Ово ће учитати адресу где симбол _start
почиње у x1 у односу на тренутни PC.
str
: Сачувајте вредност из регистра у меморију.
Пример: str x0, [x1]
— Ово чува вредност у x0
у меморијској локацији на коју указује x1
.
ldp
: Учитај пар регистара. Ова инструкција учитава два регистра из узастопних меморијских локација. Меморијска адреса се обично формира додавањем офсета вредности у другом регистру.
Пример: ldp x0, x1, [x2]
— Ово учитава x0
и x1
из меморијских локација на x2
и x2 + 8
, респективно.
stp
: Сачувај пар регистара. Ова инструкција сачува два регистра у узастопне меморијске локације. Меморијска адреса се обично формира додавањем офсета вредности у другом регистру.
Пример: stp x0, x1, [sp]
— Ово чува x0
и x1
у меморијским локацијама на sp
и sp + 8
, респективно.
stp x0, x1, [sp, #16]!
— Ово чува x0
и x1
у меморијским локацијама на sp+16
и sp + 24
, респективно, и ажурира sp
са sp+16
.
add
: Додајте вредности два регистра и сачувајте резултат у регистру.
Синтакса: add(s) Xn1, Xn2, Xn3 | #imm, [shift #N | RRX]
Xn1 -> Дестинација
Xn2 -> Операнд 1
Xn3 | #imm -> Операнд 2 (регистар или одмах)
[shift #N | RRX] -> Извршите померање или позовите RRX
Пример: add x0, x1, x2
— Ово додаје вредности у x1
и x2
и чува резултат у x0
.
add x5, x5, #1, lsl #12
— Ово је једнако 4096 (1 померач 12 пута) -> 1 0000 0000 0000 0000
adds
Ово извршава add
и ажурира заставице
sub
: Одузмите вредности два регистра и сачувајте резултат у регистру.
Проверите add
синтаксу.
Пример: sub x0, x1, x2
— Ово одузима вредност у x2
од x1
и чува резултат у x0
.
subs
Ово је као sub али ажурира заставицу
mul
: Множење вредности два регистра и чување резултата у регистру.
Пример: mul x0, x1, x2
— Ово множење вредности у x1
и x2
и чува резултат у x0
.
div
: Делите вредност једног регистра са другим и чувајте резултат у регистру.
Пример: div x0, x1, x2
— Ово дели вредност у x1
са x2
и чува резултат у x0
.
lsl
, lsr
, asr
, ror
, rrx
:
Логичко померање налево: Додајте 0 из краја померајући остале битове напред (множите са n-пута 2)
Логичко померање удесно: Додајте 1 на почетку померајући остале битове назад (делите са n-пута 2 у непотписаним)
Аритметичко померање удесно: Као lsr
, али уместо додавања 0, ако је најзначајнији бит 1, додају се 1 (делите са n-пута 2 у потписаним)
Померите удесно: Као lsr
али шта год да се уклони с десне стране, додаје се с леве
Померите удесно са проширењем: Као ror
, али са заставицом преноса као "најзначајнији бит". Дакле, преносна застава се помера на бит 31, а уклоњени бит у преносну заставу.
bfm
: Премештање битова, ове операције копирају битове 0...n
из вредности и стављају их у позиције m..m+n
. #s
одређује леву најзначајнију позицију бита, а #r
количину ротације удесно.
Премештање битова: BFM Xd, Xn, #r
Потписано премештање битова: SBFM Xd, Xn, #r, #s
Непотписано премештање битова: UBFM Xd, Xn, #r, #s
Извлачење и уметање битова: Копира битно поље из регистра и копира га у други регистар.
BFI X1, X2, #3, #4
Уметните 4 бита из X2 из 3. бита X1
BFXIL X1, X2, #3, #4
Извлачи из 3. бита X2 четири бита и копира их у X1
SBFIZ X1, X2, #3, #4
Потписано проширује 4 бита из X2 и умета их у X1 почињући на позицији бита 3 нулирајући десне битове
SBFX X1, X2, #3, #4
Извлачи 4 бита почињући на биту 3 из X2, потписано их проширује и ставља резултат у X1
UBFIZ X1, X2, #3, #4
Нулира 4 бита из X2 и умета их у X1 почињући на позицији бита 3 нулирајући десне битове
UBFX X1, X2, #3, #4
Извлачи 4 бита почињући на биту 3 из X2 и ставља нулирано проширени резултат у X1.
Проширите знак на X: Проширите знак (или само додајте 0 у непотписаној верзији) вредности да бисте могли да извршите операције с њом:
SXTB X1, W2
Проширите знак байта из W2 у X1 (W2
је половина X2
) да попуните 64 бита
SXTH X1, W2
Проширите знак 16-битног броја из W2 у X1 да попуните 64 бита
SXTW X1, W2
Проширите знак байта из W2 у X1 да попуните 64 бита
UXTB X1, W2
Додаје 0 (непотписано) на байт из W2 у X1 да попуните 64 бита
extr
: Извлачи битове из одређеног пара регистара конкатенисаних.
Пример: EXTR W3, W2, W1, #3
Ово ће конкатенисати W1+W2 и добити од бита 3 W2 до бита 3 W1 и сачувати у W3.
cmp
: Поређење два регистра и постављање условних заставица. То је алиас subs
постављајући регистар дестинације на нулти регистар. Корисно за проверу да ли је m == n
.
Подржава исту синтаксу као subs
Пример: cmp x0, x1
— Ово пореди вредности у x0
и x1
и поставља условне заставице у складу с тим.
cmn
: Поређење негативног операнда. У овом случају је алиас adds
и подржава исту синтаксу. Корисно за проверу да ли је m == -n
.
ccmp
: Условно поређење, то је поређење које ће бити извршено само ако је претходно поређење било тачно и конкретно ће поставити nzcv битове.
cmp x1, x2; ccmp x3, x4, 0, NE; blt _func
-> ако x1 != x2 и x3 < x4, скочи на func
Ово је зато што ће ccmp
бити извршено само ако је претходни cmp
био NE
, ако није, битови nzcv
ће бити постављени на 0 (што неће задовољити blt
поређење).
Ово се може користити и као ccmn
(исто али негативно, као cmp
против cmn
).
tst
: Проверава да ли су било које од вредности поређења обе 1 (ради као ANDS без чувања резултата било где). Корисно је проверити регистар са вредношћу и проверити да ли је било који од битова регистра назначених у вредности 1.
Пример: tst X1, #7
Проверава да ли је било који од последња 3 бита X1 1
teq
: XOR операција без чувања резултата
b
: Непосредна грана
Пример: b myFunction
Имајте на уму да ово неће попунити регистар за повратак са адресом повратка (није прикладно за позиве подпрограма који треба да се врате)
bl
: Гранка са повратком, користи се за позив подпрограма. Чува адресу повратка у x30
.
Пример: bl myFunction
— Ово позива функцију myFunction
и чува адресу повратка у x30
.
Имајте на уму да ово неће попунити регистар за повратак са адресом повратка (није прикладно за позиве подпрограма који треба да се врате)
blr
: Гранка са повратком у регистар, користи се за позив подпрограма где је циљ наведен у регистру. Чува адресу повратка у x30
. (Ово је
Пример: blr x1
— Ово позива функцију чија адреса је садржана у x1
и чува адресу повратка у x30
.
ret
: Врати се из подпрограма, обично користећи адресу у x30
.
Пример: ret
— Ово се враћа из тренутног подпрограма користећи адресу повратка у x30
.
b.<cond>
: Условне гране
b.eq
: Гранка ако је једнако, на основу претходне cmp
инструкције.
Пример: b.eq label
— Ако је претходна cmp
инструкција пронашла две једнаке вредности, ово скочи на label
.
b.ne
: Гранка ако није једнако. Ова инструкција проверава условне заставице (које су постављене претходном инструкцијом поређења), и ако упоређиване вредности нису једнаке, грана се на ознаку или адресу.
Пример: Након cmp x0, x1
инструкције, b.ne label
— Ако вредности у x0
и x1
нису једнаке, ово скочи на label
.
cbz
: Поређење и гранање на нулу. Ова инструкција пореди регистар са нулом, и ако су једнаке, грана се на ознаку или адресу.
Пример: cbz x0, label
— Ако је вредност у x0
нула, ово скочи на label
.
cbnz
: Поређење и гранање на ненуло. Ова инструкција пореди регистар са нулом, и ако нису једнаке, грана се на ознаку или адресу.
Пример: cbnz x0, label
— Ако је вредност у x0
ненула, ово скочи на label
.
tbnz
: Тестирај бит и гранај на ненуло
Пример: tbnz x0, #8, label
tbz
: Тестирај бит и гранај на нулу
Пример: tbz x0, #8, label
Условне операције избора: Ово су операције чије понашање варира у зависности од условних битова.
csel Xd, Xn, Xm, cond
-> csel X0, X1, X2, EQ
-> Ако је тачно, X0 = X1, ако није, X0 = X2
csinc Xd, Xn, Xm, cond
-> Ако је тачно, Xd = Xn, ако није, Xd = Xm + 1
cinc Xd, Xn, cond
-> Ако је тачно, Xd = Xn + 1, ако није, Xd = Xn
csinv Xd, Xn, Xm, cond
-> Ако је тачно, Xd = Xn, ако није, Xd = NOT(Xm)
cinv Xd, Xn, cond
-> Ако је тачно, Xd = NOT(Xn), ако није, Xd = Xn
csneg Xd, Xn, Xm, cond
-> Ако је тачно, Xd = Xn, ако није, Xd = - Xm
cneg Xd, Xn, cond
-> Ако је тачно, Xd = - Xn, ако није, Xd = Xn
cset Xd, Xn, Xm, cond
-> Ако је тачно, Xd = 1, ако није, Xd = 0
csetm Xd, Xn, Xm, cond
-> Ако је тачно, Xd = <сви 1>, ако није, Xd = 0
adrp
: Израчунати адресу странице симбола и сачувати је у регистру.
Пример: adrp x0, symbol
— Ово израчунава адресу странице симбола symbol
и чува је у x0
.
ldrsw
: Учитајте потписану 32-битну вредност из меморије и потписано проширите на 64 бита.
Пример: ldrsw x0, [x1]
— Ово учитава потписану 32-битну вредност из меморијске локације на коју указује x1
, потписано је проширује на 64 бита и чува у x0
.
stur
: Сачувајте вредност регистра на меморијској локацији, користећи офсет из другог регистра.
Пример: stur x0, [x1, #4]
— Ово чува вредност у x0
у меморијској адреси која је 4 бајта већа од адресе која се тренутно налази у x1
.
svc
: Извршите системски позив. Ово значи "Позив супервизора". Када процесор извршава ову инструкцију, прелази из корисничког режима у режим језгра и скочи на одређену локацију у меморији где се налази код за обраду системских позива језгра.
Пример:
Сачувајте регистар за повратак и показивач оквира на стеку:
Postavite novi pokazivač okvira: mov x29, sp
(postavlja novi pokazivač okvira za trenutnu funkciju)
Dodelite prostor na steku za lokalne promenljive (ako je potrebno): sub sp, sp, <size>
(gde je <size>
broj bajtova koji su potrebni)
Dealokacija lokalnih promenljivih (ako su dodeljene): add sp, sp, <size>
Obnovite registrator veze i pokazivač okvira:
Povratak: ret
(vraća kontrolu pozivaocu koristeći adresu u link registru)
Armv8-A podržava izvršavanje 32-bitnih programa. AArch32 može raditi u jednom od dva skupa instrukcija: A32
i T32
i može prebacivati između njih putem interworking
.
Privilegovani 64-bitni programi mogu zakazati izvršavanje 32-bitnih programa izvršavanjem prenosa nivoa izuzetka na niže privilegovane 32-bitne.
Napomena: prelazak sa 64-bitnog na 32-bitni se dešava sa smanjenjem nivoa izuzetka (na primer, 64-bitni program u EL1 pokreće program u EL0). Ovo se postiže postavljanjem bita 4 SPSR_ELx
specijalnog registra na 1 kada je AArch32
procesna nit spremna za izvršavanje, a ostatak SPSR_ELx
čuva AArch32
programe CPSR. Zatim, privilegovani proces poziva ERET
instrukciju tako da procesor prelazi na AArch32
ulazeći u A32 ili T32 u zavisnosti od CPSR**.**
Interworking
se dešava korišćenjem J i T bitova CPSR. J=0
i T=0
znači A32
i J=0
i T=1
znači T32. Ovo se suštinski prevodi na postavljanje najnižeg bita na 1 da označi da je skup instrukcija T32.
Ovo se postavlja tokom interworking grana instrukcija, ali se takođe može postaviti direktno sa drugim instrukcijama kada je PC postavljen kao registar odredišta. Primer:
Još jedan primer:
Postoji 16 32-bitnih registara (r0-r15). Od r0 do r14 mogu se koristiti za bilo koju operaciju, međutim neki od njih su obično rezervisani:
r15
: Program counter (uvek). Sadrži adresu sledeće instrukcije. U A32 trenutni + 8, u T32, trenutni + 4.
r11
: Frame Pointer
r12
: Intra-procedural call register
r13
: Stack Pointer
r14
: Link Register
Pored toga, registri su podržani u banked registries
. To su mesta koja čuvaju vrednosti registara, omogućavajući brzo prebacivanje konteksta u obradi izuzetaka i privilegovanih operacija kako bi se izbegla potreba za ručnim čuvanjem i vraćanjem registara svaki put.
To se postiže čuvanjem stanja procesora iz CPSR
u SPSR
režima procesora u kojem se izuzetak dešava. Kada se izuzetak vrati, CPSR
se vraća iz SPSR
.
U AArch32 CPSR funkcioniše slično PSTATE
u AArch64 i takođe se čuva u SPSR_ELx
kada se izuzetak dešava kako bi se kasnije obnovila izvršenja:
Polja su podeljena u nekoliko grupa:
Registro statusa aplikacionog programa (APSR): Aritmetičke zastavice i dostupne iz EL0
Registrovi stanja izvršenja: Ponašanje procesa (u upravljanju od strane OS-a).
Zastavice N
, Z
, C
, V
(poput AArch64)
Zastavica Q
: Postavlja se na 1 kada god dođe do saturacije celih brojeva tokom izvršenja specijalizovane aritmetičke instrukcije sa saturacijom. Kada se postavi na 1
, zadržaće tu vrednost dok se ručno ne postavi na 0. Pored toga, ne postoji nijedna instrukcija koja implicitno proverava njenu vrednost, to se mora uraditi čitanjem ručno.
GE
(Veće ili jednako) Zastavice: Koriste se u SIMD (Jedna instrukcija, više podataka) operacijama, kao što su "paralelno sabiranje" i "paralelno oduzimanje". Ove operacije omogućavaju obradu više tačaka podataka u jednoj instrukciji.
Na primer, instrukcija UADD8
sabira četiri para bajtova (iz dva 32-bitna operanda) paralelno i čuva rezultate u 32-bitnom registru. Zatim postavlja GE
zastavice u APSR
na osnovu ovih rezultata. Svaka GE zastavica odgovara jednom od sabiranja bajtova, ukazujući da li je sabiranje za taj par bajtova prelilo.
Instrukcija SEL
koristi ove GE zastavice za izvršavanje uslovnih akcija.
Zastavice J
i T
: J
treba da bude 0, a ako je T
0 koristi se skup instrukcija A32, a ako je 1, koristi se T32.
IT Block State Register (ITSTATE
): Ovo su bitovi od 10-15 i 25-26. Čuvaju uslove za instrukcije unutar grupe sa prefiksom IT
.
E
bit: Ukazuje na endianness.
Bitovi režima i maske izuzetaka (0-4): Određuju trenutno stanje izvršenja. 5. označava da li program radi kao 32bit (1) ili 64bit (0). Ostala 4 predstavljaju režim izuzetka koji se trenutno koristi (kada se izuzetak dešava i obrađuje). Broj postavljen ukazuje na trenutni prioritet u slučaju da se drugi izuzetak pokrene dok se ovaj obrađuje.
AIF
: Određeni izuzeci mogu biti onemogućeni korišćenjem bitova A
, I
, F
. Ako je A
1, to znači da će asinkroni aborti biti pokrenuti. I
konfiguriše odgovor na spoljne hardverske Interrupts Requests (IRQs). a F se odnosi na Fast Interrupt Requests (FIRs).
Pogledajte syscalls.master. BSD syscalls će imati x16 > 0.
Pogledajte u syscall_sw.c mach_trap_table
i u mach_traps.h prototipove. Maksimalni broj Mach traps je MACH_TRAP_TABLE_COUNT
= 128. Mach traps će imati x16 < 0, tako da treba da pozovete brojeve iz prethodne liste sa minusom: _kernelrpc_mach_vm_allocate_trap
je -10
.
Takođe možete proveriti libsystem_kernel.dylib
u disassembleru da biste saznali kako da pozovete ove (i BSD) syscalls:
Napomena da Ida i Ghidra takođe mogu dekompilirati specifične dylibs iz keša jednostavno prolazeći kroz keš.
Ponekad je lakše proveriti dekompilirani kod iz libsystem_kernel.dylib
nego proveravati izvorni kod jer se kod nekoliko syscalls (BSD i Mach) generiše putem skripti (proverite komentare u izvoru) dok u dylib-u možete pronaći šta se poziva.
XNU podržava još jedan tip poziva koji se naziva zavistan od mašine. Broj ovih poziva zavisi od arhitekture i ni pozivi ni brojevi nisu garantovani da ostanu konstantni.
Ovo je stranica memorije koju poseduje kernel i koja je mapirana u adresni prostor svakog korisničkog procesa. Namenjena je da ubrza prelazak iz korisničkog moda u kernel prostor brže nego korišćenje syscalls za kernel usluge koje se toliko koriste da bi ovaj prelazak bio veoma neefikasan.
Na primer, poziv gettimeofdate
čita vrednost timeval
direktno sa comm stranice.
Veoma je uobičajeno pronaći ovu funkciju korišćenu u Objective-C ili Swift programima. Ova funkcija omogućava pozivanje metode objekta Objective-C.
Parametri (više informacija u dokumentaciji):
x0: self -> Pokazivač na instancu
x1: op -> Selektor metode
x2... -> Ostatak argumenata pozvane metode
Dakle, ako stavite breakpoint pre grananja na ovu funkciju, lako možete pronaći šta se poziva u lldb sa (u ovom primeru objekat poziva objekat iz NSConcreteTask
koji će izvršiti komandu):
Postavljanjem env varijable NSObjCMessageLoggingEnabled=1
moguće je logovati kada se ova funkcija poziva u datoteci kao što je /tmp/msgSends-pid
.
Pored toga, postavljanjem OBJC_HELP=1
i pozivanjem bilo kog binarnog fajla možete videti druge varijable okruženja koje možete koristiti da log kada se određene Objc-C akcije dešavaju.
Kada se ova funkcija pozove, potrebno je pronaći pozvanu metodu označene instance, za to se vrše različite pretrage:
Izvršiti optimističku pretragu u kešu:
Ako je uspešno, gotovo
Zauzeti runtimeLock (čitanje)
Ako (realize && !cls->realized) realizovati klasu
Ako (initialize && !cls->initialized) inicijalizovati klasu
Pokušati keš klase:
Ako je uspešno, gotovo
Pokušati listu metoda klase:
Ako je pronađeno, popuniti keš i gotovo
Pokušati keš superklase:
Ako je uspešno, gotovo
Pokušati listu metoda superklase:
Ako je pronađeno, popuniti keš i gotovo
Ako (resolver) pokušati metodu resolver, i ponoviti od pretrage klase
Ako ste još ovde (= sve ostalo je propalo) pokušati forwarder
Za kompajliranje:
Da biste izvukli bajtove:
За новије macOS:
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)