Aprenda e pratique Hacking AWS:<imgsrc="../../../.gitbook/assets/arte.png"alt=""data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<imgsrc="../../../.gitbook/assets/arte.png"alt=""data-size="line">\
Aprenda e pratique Hacking GCP: <imgsrc="../../../.gitbook/assets/grte.png"alt=""data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<imgsrc="../../../.gitbook/assets/grte.png"alt=""data-size="line">](https://training.hacktricks.xyz/courses/grte)
* **Junte-se ao** 💬 [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga**-nos no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe 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:
* Este é o nível menos privilegiado e é usado para executar código de aplicativo regular.
* Aplicativos executando em EL0 são isolados uns dos outros e do software do sistema, aumentando a segurança e a estabilidade.
2.**EL1 - Modo do Kernel do Sistema Operacional**:
* A maioria dos kernels de sistemas operacionais opera neste nível.
* 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 de Hypervisor**:
* Este nível é usado para virtualização. Um hypervisor executando em EL2 pode gerenciar múltiplos sistemas operacionais (cada um em seu próprio EL1) rodando no mesmo hardware físico.
O uso desses níveis permite uma maneira estruturada e segura de gerenciar diferentes aspectos do sistema, desde aplicativos de usuário até o software do sistema mais privilegiado. A abordagem da ARMv8 em relação aos níveis de privilégio ajuda a isolar efetivamente diferentes componentes do sistema, aumentando assim a segurança e a robustez do sistema.
ARM64 possui **31 registradores de uso geral**, rotulados de `x0` a `x30`. Cada um pode armazenar um valor **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. Eles também são usados para chamadas de função indiretas e stubs da PLT (Tabela de Ligação de Procedimentos).
5.**`x18`** - **Registrador de Plataforma**. Pode ser usado como um registrador de uso geral, mas em algumas plataformas, este registrador é reservado para usos específicos da plataforma: Ponteiro para o bloco de ambiente de thread local no Windows, ou para apontar para a estrutura de tarefa **executando atualmente no kernel do linux**.
6.**`x19`** a **`x28`** - Estes são registradores salvos pelo chamado. Uma função deve preservar os valores desses registradores para seu chamador, então eles são armazenados na pilha e recuperados antes de voltar para o chamador.
7.**`x29`** - **Ponteiro de Quadro** 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 **novo** endereço do ponteiro de quadro é (**endereço `sp`**) **armazenado neste registrador**.
* Este registrador também pode ser usado como um **registrador de uso geral**, embora geralmente seja 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).
* O valor de **`sp`** deve sempre ser mantido em pelo menos um **alinhamento de quadword** ou uma exceção de alinhamento pode ocorrer.
10.**`pc`** - **Contador de Programa**, que aponta para a próxima instrução. Este registrador só pode ser atualizado através de gerações de exceção, retornos de exceção e branches. As únicas instruções ordinárias 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 **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 nenhum lugar (em **`xzr`**).
Além disso, existem outros **32 registradores de 128 bits** que podem ser usados em operações otimizadas de múltiplos dados de instrução única (SIMD) e para realizar aritmética de ponto flutuante. Estes 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 registradores do sistema**, também chamados de registradores de propósito especial (SPRs), usados para **monitorar** e **controlar** o comportamento dos **processadores**.\
Eles só podem ser lidos ou configurados usando as instruções especiais dedicadas **`mrs`** e **`msr`**.
Os registradores especiais **`TPIDR_EL0`** e **`TPIDDR_EL0`** são comumente encontrados ao realizar engenharia reversa. O sufixo `EL0` indica a **exceção mínima** a partir da qual o registrador pode ser acessado (neste caso, EL0 é o nível de exceção regular (privilégio) com o qual programas regulares são executados).\
Eles são frequentemente usados para armazenar o **endereço base da região de armazenamento local de thread** na memória. Geralmente, o primeiro é legível e gravável para programas executando em EL0, mas o segundo pode ser lido de EL0 e escrito de EL1 (como o kernel).
**PSTATE** contém vários componentes do processo serializados no registrador especial visível pelo sistema operacional **`SPSR_ELx`**, sendo X o **nível de permissão****da exceção acionada** (isso permite recuperar o estado do processo quando a exceção termina).\
* 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 do intervalo do tamanho de bits dado.
* 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 carry no caso de ser assinado ou não assinado.
Nem todas as instruções atualizam essas flags. Algumas como **`CMP`** ou **`TST`** fazem isso, e outras que têm um sufixo s como **`ADDS`** também o fazem.
* A **flag de largura de registrador atual (`nRW`)**: Se a flag tiver o valor 0, o programa será executado no estado de execução AArch64 uma vez retomado.
* O **Nível de Exceção atual** (**`EL`**): Um programa regular executando em EL0 terá o valor 0.
* A **flag de passo único** (**`SS`**): Usada por depuradores para executar um passo único definindo a flag SS para 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 **flag de estado de exceção ilegal** (**`IL`**): É usada para marcar quando um software privilegiado realiza uma transferência de nível de exceção inválida, essa flag é definida como 1 e o processador aciona uma exceção de estado ilegal.
* As flags **`DAIF`**: Essas flags permitem que um programa privilegiado oculte seletivamente certas exceções externas.
* Se **`A`** for 1, significa que **aborts assíncronos** serão acionados. O **`I`** configura para responder a **Solicitações de Interrupção de Hardware** (IRQs). e o F está relacionado a **Solicitações de Interrupção Rápida** (FIRs).
* As flags de seleção de ponteiro de pilha (**`SPS`**): Programas privilegiados executando em EL1 e acima podem alternar entre usar seu próprio registrador de ponteiro de pilha e o de modelo de usuário (por exemplo, entre `SP_EL1` e `EL0`). Essa troca é realizada escrevendo no registrador 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** para uma função são passados em registradores **`x0` a `x7`**. **Parâmetros adicionais** são passados na **pilha**. O **valor de retorno** é passado de volta no registrador **`x0`**, ou em **`x1`** também **se for longo de 128 bits**. Os registradores **`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 **registrador de destino** onde o resultado será armazenado, e **`src1`** e **`src2`** são os **registradores de origem**. Valores imediatos também podem ser usados no lugar de registradores de origem.
* **`ldp`**: **Carregar Par de Registradores**. Esta instrução **carrega dois registradores** de **localizações de memória** consecutivas. O endereço de memória é tipicamente formado adicionando um deslocamento ao valor em outro registrador.
* Exemplo: `ldp x0, x1, [x2]` — Isso carrega `x0` e `x1` das localizações de memória em `x2` e `x2 + 8`, respectivamente.
* **`stp`**: **Armazenar Par de Registradores**. Esta instrução **armazena dois registradores** em **localizações de memória** consecutivas. O endereço de memória é tipicamente formado adicionando um deslocamento ao valor em outro registrador.
* Exemplo: `stp x0, x1, [sp]` — Isso armazena `x0` e `x1` nas localizações de memória em `sp` e `sp + 8`, respectivamente.
*`stp x0, x1, [sp, #16]!` — Isso armazena `x0` e `x1` nas localizações de memória em `sp+16` e `sp + 24`, respectivamente, e atualiza `sp` com `sp+16`.
* **`add`**: **Adicionar** os valores de dois registradores e armazenar o resultado em um registrador.
* **Deslocamento lógico à esquerda**: Adiciona 0s do final movendo os outros bits para frente (multiplica por n vezes 2).
* **Deslocamento lógico à direita**: Adiciona 1s no início movendo os outros bits para trás (divide por n vezes 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).
* **Rotacionar à direita**: Como **`lsr`**, mas o que for removido da direita é anexado à esquerda.
* **Rotacionar à 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 **`#r`** a **quantidade de rotação à direita**.
* Movimento de campo de bits: `BFM Xd, Xn, #r`.
* Movimento de campo de bits assinado: `SBFM Xd, Xn, #r, #s`.
* Movimento de campo de bits não assinado: `UBFM Xd, Xn, #r, #s`.
* **Extração e Inserção de Campo de Bits:** Copia um campo de bits de um registrador e o copia para outro registrador.
* **`BFI X1, X2, #3, #4`** Insere 4 bits de X2 a partir do 3º bit de X1.
* **`BFXIL X1, X2, #3, #4`** Extrai do 3º bit de X2 quatro bits e os copia para X1.
* **`SBFIZ X1, X2, #3, #4`** Estende o sinal de 4 bits de X2 e os insere em X1 começando na posição do bit 3 zerando os bits à direita.
* **`SBFX X1, X2, #3, #4`** Extrai 4 bits começando no bit 3 de X2, estende o sinal e coloca o resultado em X1.
* **`UBFIZ X1, X2, #3, #4`** Estende 4 bits de X2 e os insere em X1 começando na posição do bit 3 zerando os bits à direita.
* **`UBFX X1, X2, #3, #4`** Extrai 4 bits começando no bit 3 de X2 e coloca o resultado estendido a zero em X1.
* **Extensão de Sinal para X:** Estende o sinal (ou adiciona apenas 0s na versão não assinada) de um valor para poder realizar operações com ele:
* **`SXTB X1, W2`** Estende o sinal de um byte **de W2 para X1** (`W2` é metade de `X2`) para preencher os 64 bits.
* **`SXTH X1, W2`** Estende o sinal de um número de 16 bits **de W2 para X1** para preencher os 64 bits.
* **`SXTW X1, W2`** Estende o sinal de um byte **de W2 para X1** para preencher os 64 bits.
* **`UXTB X1, W2`** Adiciona 0s (não assinado) a um byte **de W2 para X1** para preencher os 64 bits.
* **`extr`:** Extrai bits de um **par de registradores especificados concatenados**.
* Exemplo: `EXTR W3, W2, W1, #3` Isso irá **concatenar W1+W2** e obter **do bit 3 de W2 até o bit 3 de W1** e armazená-lo em W3.
* **`cmp`**: **Comparar** dois registradores e definir flags de condição. É um **alias de `subs`** definindo o registrador de destino como o registrador zero. Útil para saber se `m == n`.
* Suporta a **mesma sintaxe que `subs`**.
* Exemplo: `cmp x0, x1` — Isso compara os valores em `x0` e `x1` e define as flags de condição de acordo.
* **`cmn`**: **Comparar o operando negativo**. Neste caso, é um **alias de `adds`** e suporta a mesma sintaxe. Útil para saber se `m == -n`.
* **`ccmp`**: Comparação condicional, é uma comparação que será realizada apenas se uma comparação anterior foi verdadeira e definirá especificamente os bits nzcv.
*`cmp x1, x2; ccmp x3, x4, 0, NE; blt _func` -> se x1 != x2 e x3 <x4,salteparafunc.
* Isso ocorre porque **`ccmp`** só será executado se a **comparação anterior `cmp` foi um `NE`**, se não foi, 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` (o mesmo, mas negativo, como `cmp` vs `cmn`).
* **`tst`**: Verifica se algum dos valores da comparação é 1 (funciona como um ANDS sem armazenar o resultado em nenhum lugar). É útil para verificar um registrador com um valor e verificar se algum dos bits do registrador indicado no valor é 1.
* Exemplo: `tst X1, #7` Verifica se algum dos últimos 3 bits de X1 é 1.
* **`teq`**: Operação XOR descartando o resultado.
* **`b`**: Branch incondicional.
* Exemplo: `b myFunction`.
* Note que isso não preencherá o registrador de link com o endereço de retorno (não é adequado para chamadas de sub-rotina que precisam retornar).
* **`bl`**: **Branch** com link, usado para **chamar** uma **sub-rotina**. Armazena o **endereço de retorno em `x30`**.
* Exemplo: `bl myFunction` — Isso chama a função `myFunction` e armazena o endereço de retorno em `x30`.
* Note que isso não preencherá o registrador de link com o endereço de retorno (não é adequado para chamadas de sub-rotina que precisam retornar).
* **`blr`**: **Branch** com Link para Registrador, usado para **chamar** uma **sub-rotina** onde o alvo é **especificado** em um **registrador**. Armazena o endereço de retorno em `x30`. (Isso é
* **`b.ne`**: **Branch se Não Igual**. 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, ela faz um branch para um rótulo ou endereço.
* **`cbz`**: **Comparar e Branch em Zero**. Esta instrução compara um registrador com zero, e se forem iguais, faz um branch para um rótulo ou endereço.
* **`cbnz`**: **Comparar e Branch em Não Zero**. Esta instrução compara um registrador com zero, e se não forem iguais, faz um branch para um rótulo ou endereço.
* Exemplo: `cbnz x0, label` — Se o valor em `x0` for não zero, isso salta para `label`.
* **`tbnz`**: Testa o bit e faz branch em não zero.
* Exemplo: `tbnz x0, #8, label`.
* **`tbz`**: Testa o bit e faz branch em zero.
* Exemplo: `tbz x0, #8, label`.
* **Operações de seleção condicional**: Estas são operações cujo comportamento varia dependendo dos bits condicionais.
* Exemplo: `ldrsw x0, [x1]` — Isso carrega um valor assinado de 32 bits da localização de memória apontada por `x1`, estende-o para 64 bits e o armazena em `x0`.
* **`stur`**: **Armazenar um valor de registrador em uma localização de memória**, usando um deslocamento de outro registrador.
* Exemplo: `stur x0, [x1, #4]` — Isso armazena o valor em `x0` na localização de memória que é 4 bytes maior do que o endereço atualmente em `x1`.
* **`svc`** : Faz uma **chamada de sistema**. Significa "Supervisor Call". Quando o processador executa esta instrução, ele **muda do modo de usuário para o modo de kernel** e salta para um local específico na memória onde o **código de manipulação de chamadas de sistema do kernel** está localizado.
Armv8-A suporta a execução de programas de 32 bits. **AArch32** pode operar 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 nível de privilégio inferior de 32 bits.\
Note 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 de****`SPSR_ELx`** registro especial **para 1** quando o thread do processo `AArch32` está pronto para ser executado e o restante de `SPSR_ELx` armazena o **`AArch32`** CPSR. Em seguida, o processo privilegiado chama a instrução **`ERET`** para que o processador transite 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 definir o **bit mais baixo como 1** para indicar que o conjunto de instruções é T32.\
Isso é configurado durante as **instruções de ramificação interworking**, mas também pode ser configurado diretamente com outras instruções quando o PC é definido como o registrador 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 geralmente são reservados:
Além disso, os registradores são salvos em **`registros bancados`**. Que são lugares 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 registradores manualmente toda vez.\
Isso é feito **salvando o estado do processador do `CPSR` para o `SPSR`** do modo do processador ao qual a exceção é gerada. Ao retornar da exceção, o **`CPSR`** é restaurado do **`SPSR`**.
Em AArch32, o CPSR funciona de forma semelhante ao **`PSTATE`** em AArch64 e também é armazenado em **`SPSR_ELx`** quando uma exceção é gerada para restaurar a execução posteriormente:
* As flags **`N`**, **`Z`**, **`C`**, **`V`** (assim como em AArch64)
* A flag **`Q`**: É definida como 1 sempre que **ocorre saturação inteira** durante a execução de uma instrução aritmética de saturação especializada. Uma vez definida como **`1`**, manterá o valor até que seja manualmente definida 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 (Instrução Única, Múltiplos Dados), como "adição paralela" e "subtração paralela". Essas operações permitem processar múltiplos 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 aquele par de bytes **transbordou**.
* Os bits **`J`** e **`T`**: **`J`** deve ser 0 e se **`T`** for 0, o conjunto de instruções A32 é usado, e se for 1, o T32 é usado.
* **Registro de Estado do Bloco IT** (`ITSTATE`): Esses são os bits de 10-15 e 25-26. Eles armazenam condições para instruções dentro de um grupo prefixado por **`IT`**.
* Bit **`E`**: Indica a **endianness**.
* **Bits de Modo e Máscara de Exceção** (0-4): Eles determinam o estado de execução atual. O **5º** indica se o programa está sendo executado como 32 bits (um 1) ou 64 bits (um 0). Os outros 4 representam o **modo de exceção atualmente em uso** (quando uma exceção ocorre e está sendo tratada). O número definido **indica a prioridade atual** caso outra exceção seja 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 **aborts assíncronos** serão acionados. O **`I`** configura para responder a **Solicitações de Interrupção** de hardware externo (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 **menos**: **`_kernelrpc_mach_vm_allocate_trap`** é **`-10`**.
Você também pode verificar **`libsystem_kernel.dylib`** em um desassemblador para encontrar como chamar essas (e BSD) chamadas de sistema:
À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 syscalls (BSD e Mach) é gerado via scripts (ver comentários no código-fonte), enquanto na dylib você pode encontrar o que está sendo chamado.
XNU suporta outro tipo de chamadas chamadas dependentes de máquina. Os números dessas chamadas dependem da arquitetura e nem as chamadas nem os números são garantidos para permanecer constantes.
Esta é uma página de memória de propriedade do kernel que está mapeada no espaço de endereços de cada processo de usuário. É destinada a tornar a transição do modo usuário para o espaço do kernel mais rápida do que usar syscalls para serviços do kernel que são usados tanto que essa transição seria muito ineficiente.
Então, se você colocar um breakpoint antes do ramo para esta função, pode facilmente encontrar o que está sendo invocado no lldb com (neste exemplo, o objeto chama um objeto de `NSConcreteTask` que irá executar um comando):
Definindo a variável de ambiente **`NSObjCMessageLoggingEnabled=1`** é possível registrar quando essa função é chamada em um arquivo como `/tmp/msgSends-pid`.
Além disso, definindo **`OBJC_HELP=1`** e chamando qualquer binário, você pode ver outras variáveis de ambiente que poderia usar para **logar** quando certas ações Objc-C ocorrem.
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 (que na memória significa uma pilha dos endereços).
Bind shell de [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**
Aprenda e pratique Hacking AWS:<imgsrc="../../../.gitbook/assets/arte.png"alt=""data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<imgsrc="../../../.gitbook/assets/arte.png"alt=""data-size="line">\
Aprenda e pratique Hacking GCP: <imgsrc="../../../.gitbook/assets/grte.png"alt=""data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<imgsrc="../../../.gitbook/assets/grte.png"alt=""data-size="line">](https://training.hacktricks.xyz/courses/grte)
* Confira os [**planos de assinatura**](https://github.com/sponsors/carlospolop)!
* **Junte-se ao** 💬 [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga**-nos no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe 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.