Aprenda e pratique Hacking AWS:<imgsrc="/.gitbook/assets/arte.png"alt=""data-size="line">[**Treinamento HackTricks 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">[**Treinamento HackTricks 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 Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe truques de hacking enviando PRs para os repositórios** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
O Mach utiliza **tarefas** como a **unidade mais pequena** para compartilhar recursos, e cada tarefa pode conter **múltiplas threads**. Essas **tarefas e threads são mapeadas em um para um com processos e threads POSIX**.
A comunicação entre tarefas ocorre via Comunicação entre Processos Mach (IPC), utilizando canais de comunicação unidirecional. **As mensagens são transferidas entre portas**, que funcionam como **filas de mensagens** gerenciadas pelo kernel.
Cada processo possui uma **tabela IPC**, onde é possível encontrar as **portas mach do processo**. O nome de uma porta mach é na verdade um número (um ponteiro para o objeto do kernel).
Um processo também pode enviar um nome de porta com alguns direitos **para uma tarefa diferente** e o kernel fará com que essa entrada na **tabela IPC da outra tarefa** apareça.
Os direitos de porta, que definem quais operações uma tarefa pode realizar, são fundamentais para essa comunicação. Os possíveis **direitos de porta** são ([definições daqui](https://docs.darlinghq.org/internals/macos-specifics/mach-ports.html)):
* **Direito de Receber**, que permite receber mensagens enviadas para a porta. As portas Mach são filas MPSC (múltiplos produtores, um consumidor), o que significa que pode haver apenas **um direito de receber para cada porta** em todo o sistema (ao contrário de pipes, onde vários processos podem todos ter descritores de arquivo para a extremidade de leitura de um pipe).
* Uma **tarefa com o Direito de Receber** pode receber mensagens e **criar Direitos de Envio**, permitindo enviar mensagens. Originalmente, apenas a **própria tarefa tem o Direito de Receber sobre sua porta**.
* **Direito de Envio**, que permite enviar mensagens para a porta.
* O Direito de Envio pode ser **clonado** para que uma tarefa que possui um Direito de Envio possa clonar o direito e **concedê-lo a uma terceira tarefa**.
* **Direito de conjunto de portas**, que denota um _conjunto de portas_ em vez de uma única porta. Desenfileirar uma mensagem de um conjunto de portas desenfileira uma mensagem de uma das portas que ele contém. Os conjuntos de portas podem ser usados para escutar várias portas simultaneamente, muito parecido com `select`/`poll`/`epoll`/`kqueue` no Unix.
* **Nome morto**, que não é um direito de porta real, mas apenas um espaço reservado. Quando uma porta é destruída, todos os direitos de porta existentes para a porta se tornam nomes mortos.
**Tarefas podem transferir DIREITOS DE ENVIO para outros**, permitindo-lhes enviar mensagens de volta. **DIREITOS DE ENVIO também podem ser clonados, para que uma tarefa possa duplicar e dar o direito a uma terceira tarefa**. Isso, combinado com um processo intermediário conhecido como o **servidor de inicialização**, permite uma comunicação eficaz entre tarefas.
Portas de arquivo permitem encapsular descritores de arquivo em portas Mac (usando direitos de porta Mach). É possível criar um `fileport` a partir de um FD dado usando `fileport_makeport` e criar um FD a partir de um fileport usando `fileport_makefd`.
Como mencionado anteriormente, é possível enviar direitos usando mensagens Mach, no entanto, você **não pode enviar um direito sem já ter um direito** para enviar uma mensagem Mach. Então, como é estabelecida a primeira comunicação?
Para isso, o **servidor de inicialização** (**launchd** no Mac) está envolvido, pois **qualquer pessoa pode obter um DIREITO DE ENVIO para o servidor de inicialização**, é possível pedir a ele um direito para enviar uma mensagem para outro processo:
1. A Tarefa **A** cria uma **nova porta**, obtendo o **direito de RECEBER** sobre ela.
2. A Tarefa **A**, sendo a detentora do direito de RECEBER, **gera um DIREITO DE ENVIO para a porta**.
3. A Tarefa **A** estabelece uma **conexão** com o **servidor de inicialização**, e **envia a ele o DIREITO DE ENVIO** para a porta que gerou no início.
* Lembre-se de que qualquer pessoa pode obter um DIREITO DE ENVIO para o servidor de inicialização.
4. A Tarefa A envia uma mensagem `bootstrap_register` para o servidor de inicialização para **associar a porta fornecida a um nome** como `com.apple.taska`.
5. A Tarefa **B** interage com o **servidor de inicialização** para executar uma **busca de inicialização para o nome do serviço** (`bootstrap_lookup`). Para que o servidor de inicialização possa responder, a tarefa B enviará um **DIREITO DE ENVIO para uma porta que criou anteriormente** dentro da mensagem de busca. Se a busca for bem-sucedida, o **servidor duplica o DIREITO DE ENVIO** recebido da Tarefa A e **transmite para a Tarefa B**.
7. Para uma comunicação bidirecional, geralmente a tarefa **B** gera uma nova porta com um **direito de RECEBER** e um **DIREITO DE ENVIO**, e dá o **DIREITO DE ENVIO para a Tarefa A** para que ela possa enviar mensagens para a TAREFA B (comunicação bidirecional).
O servidor de inicialização **não pode autenticar** o nome do serviço reivindicado por uma tarefa. Isso significa que uma **tarefa** poderia potencialmente **falsificar qualquer tarefa do sistema**, como **reivindicar falsamente um nome de serviço de autorização** e então aprovar cada solicitação.
Em seguida, a Apple armazena os **nomes dos serviços fornecidos pelo sistema** em arquivos de configuração seguros, localizados em diretórios protegidos pelo SIP: `/System/Library/LaunchDaemons` e `/System/Library/LaunchAgents`. Ao lado de cada nome de serviço, o **binário associado também é armazenado**. O servidor de inicialização, criará e manterá um **direito de RECEBER para cada um desses nomes de serviço**.
Para esses serviços predefinidos, o **processo de busca difere ligeiramente**. Quando um nome de serviço está sendo procurado, o launchd inicia o serviço dinamicamente. O novo fluxo de trabalho é o seguinte:
* A Tarefa **B** inicia uma **busca de inicialização** para um nome de serviço.
* A Tarefa **A** (o serviço) executa um **check-in de inicialização** (`bootstrap_check_in()`). Aqui, o **servidor de inicialização** cria um DIREITO DE ENVIO, o retém e **transfere o DIREITO DE RECEBER para a Tarefa A**.
* launchd duplica o **DIREITO DE ENVIO e envia para a Tarefa B**.
* A Tarefa **B** gera uma nova porta com um **direito de RECEBER** e um **DIREITO DE ENVIO**, e dá o **DIREITO DE ENVIO para a Tarefa A** (o serviço) para que ela possa enviar mensagens para a TAREFA B (comunicação bidirecional).
No entanto, esse processo se aplica apenas a tarefas de sistema predefinidas. Tarefas não pertencentes ao sistema ainda operam conforme descrito originalmente, o que poderia potencialmente permitir a falsificação.
A função `mach_msg`, essencialmente uma chamada de sistema, é utilizada para enviar e receber mensagens Mach. A função requer que a mensagem seja enviada como argumento inicial. Esta mensagem deve começar com uma estrutura `mach_msg_header_t`, seguida pelo conteúdo real da mensagem. A estrutura é definida da seguinte forma:
Os processos que possuem um _**direito de recebimento**_ podem receber mensagens em uma porta Mach. Por outro lado, os **remetentes** recebem um _**direito de envio**_ ou um _**direito de envio único**_. O direito de envio único é exclusivamente para enviar uma única mensagem, após o que se torna inválido.
- Os **5 bits menos significativos do 2º byte** podem ser usados para **voucher**: outro tipo de porta para enviar combinações de chave/valor.
- Os **5 bits menos significativos do 3º byte** podem ser usados para **porta local**
- Os **5 bits menos significativos do 4º byte** podem ser usados para **porta remota**
Os tipos que podem ser especificados no voucher, portas locais e remotas são (de [**mach/message.h**](https://opensource.apple.com/source/xnu/xnu-7195.81.3/osfmk/mach/message.h.auto.html)):
```c
#define MACH_MSG_TYPE_MOVE_RECEIVE 16 /* Must hold receive right */
#define MACH_MSG_TYPE_MOVE_SEND 17 /* Must hold send right(s) */
#define MACH_MSG_TYPE_MOVE_SEND_ONCE 18 /* Must hold sendonce right */
#define MACH_MSG_TYPE_COPY_SEND 19 /* Must hold send right(s) */
#define MACH_MSG_TYPE_MAKE_SEND 20 /* Must hold receive right */
#define MACH_MSG_TYPE_MAKE_SEND_ONCE 21 /* Must hold receive right */
#define MACH_MSG_TYPE_COPY_RECEIVE 22 /* NOT VALID */
#define MACH_MSG_TYPE_DISPOSE_RECEIVE 24 /* must hold receive right */
#define MACH_MSG_TYPE_DISPOSE_SEND 25 /* must hold send right(s) */
#define MACH_MSG_TYPE_DISPOSE_SEND_ONCE 26 /* must hold sendonce right */
Por exemplo, `MACH_MSG_TYPE_MAKE_SEND_ONCE` pode ser usado para **indicar** que um **direito** de **envio-único** deve ser derivado e transferido para esta porta. Também pode ser especificado `MACH_PORT_NULL` para impedir que o destinatário possa responder.
Para alcançar uma **comunicação bidirecional** fácil, um processo pode especificar uma **porta mach** no cabeçalho da mensagem mach chamada _porta de resposta_ (**`msgh_local_port`**) onde o **receptor** da mensagem pode **enviar uma resposta** a esta mensagem.
Note que esse tipo de comunicação bidirecional é usado em mensagens XPC que esperam uma resposta (`xpc_connection_send_message_with_reply` e `xpc_connection_send_message_with_reply_sync`). Mas **geralmente são criadas portas diferentes** como explicado anteriormente para criar a comunicação bidirecional.
Note que **mensagens mach são enviadas por uma `porta mach`**, que é um canal de comunicação de **um único receptor**, **múltiplos remetentes** integrado no kernel mach. **Múltiplos processos** podem **enviar mensagens** para uma porta mach, mas em qualquer momento apenas **um único processo pode ler** dela.
As mensagens são então formadas pelo cabeçalho **`mach_msg_header_t`** seguido do **corpo** e do **trailer** (se houver) e pode conceder permissão para responder a ela. Nestes casos, o kernel só precisa passar a mensagem de uma tarefa para a outra.
Um **trailer** é **informação adicionada à mensagem pelo kernel** (não pode ser definida pelo usuário) que pode ser solicitada na recepção da mensagem com as flags `MACH_RCV_TRAILER_<trailer_opt>` (há diferentes informações que podem ser solicitadas).
#### Mensagens Complexas
No entanto, existem outras mensagens mais **complexas**, como as que passam direitos de porta adicionais ou compartilham memória, onde o kernel também precisa enviar esses objetos para o destinatário. Nestes casos, o bit mais significativo do cabeçalho `msgh_bits` é definido.
Os descritores possíveis para passar são definidos em [**`mach/message.h`**](https://opensource.apple.com/source/xnu/xnu-7195.81.3/osfmk/mach/message.h.auto.html):
O kernel copiará os descritores de uma tarefa para a outra, mas primeiro **criará uma cópia na memória do kernel**. Essa técnica, conhecida como "Feng Shui", tem sido abusada em vários exploits para fazer o **kernel copiar dados em sua memória**, fazendo com que um processo envie descritores para si mesmo. Em seguida, o processo pode receber as mensagens (o kernel as liberará).
Também é possível **enviar direitos de porta para um processo vulnerável**, e os direitos da porta simplesmente aparecerão no processo (mesmo que ele não os esteja manipulando).
Observe que as portas estão associadas ao namespace da tarefa, então para criar ou procurar uma porta, o namespace da tarefa também é consultado (mais em `mach/mach_port.h`):
* **`mach_port_allocate` | `mach_port_construct`**: **Criar** uma porta.
*`mach_port_allocate` também pode criar um **conjunto de portas**: direito de recebimento sobre um grupo de portas. Sempre que uma mensagem é recebida, é indicada a porta de onde ela veio.
*`mach_port_allocate_name`: Alterar o nome da porta (por padrão, inteiro de 32 bits)
*`mach_port_names`: Obter nomes de porta de um alvo
*`mach_port_type`: Obter direitos de uma tarefa sobre um nome
*`mach_port_rename`: Renomear uma porta (como dup2 para FDs)
* **`mach_msg`** | **`mach_msg_overwrite`**: Funções usadas para **enviar e receber mensagens mach**. A versão de sobrescrita permite especificar um buffer diferente para a recepção da mensagem (a outra versão apenas o reutilizará).
Como as funções **`mach_msg`** e **`mach_msg_overwrite`** são as usadas para enviar e receber mensagens, definir um ponto de interrupção nelas permitiria inspecionar as mensagens enviadas e recebidas.
Por exemplo, iniciar a depuração de qualquer aplicativo que você possa depurar, pois ele carregará **`libSystem.B` que usará essa função**.
<preclass="language-armasm"><codeclass="lang-armasm"><strong>(lldb) b mach_msg
</strong>Ponto de interrupção 1: onde = libsystem_kernel.dylib`mach_msg, endereço = 0x00000001803f6c20
quadro #9: 0x0000000181a1d5c8 dyld`função de invocação para bloco em dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const::$_0::operator()() const + 168
Para obter os argumentos de **`mach_msg`**, verifique os registradores. Estes são os argumentos (de [mach/message.h](https://opensource.apple.com/source/xnu/xnu-7195.81.3/osfmk/mach/message.h.auto.html)):
; 0x00131513 -> mach_msg_bits_t (msgh_bits) = 0x13 (MACH_MSG_TYPE_COPY_SEND) in local | 0x1500 (MACH_MSG_TYPE_MAKE_SEND_ONCE) in remote | 0x130000 (MACH_MSG_TYPE_COPY_SEND) in voucher
O **nome** é o nome padrão dado à porta (verifique como ele está **aumentando** nos primeiros 3 bytes). O **`ipc-object`** é o **identificador** único **ofuscado** da porta.\
Também é possível usar [**procesxp**](https://www.newosxbook.com/tools/procexp.html) para ver também os **nomes de serviço registrados** (com SIP desativado devido à necessidade de `com.apple.system-task-port`):
Pode instalar esta ferramenta no iOS fazendo o download em [http://newosxbook.com/tools/binpack64-256.tar.gz](http://newosxbook.com/tools/binpack64-256.tar.gz)
Observe como o **remetente****aloca** uma porta, cria um **direito de envio** para o nome `org.darlinghq.example` e o envia para o **servidor de inicialização** enquanto o remetente solicitou o **direito de envio** desse nome e o usou para **enviar uma mensagem**.
O `sender.c` é um exemplo simples de um programa que envia mensagens para um receptor usando IPC (Comunicação entre Processos) no macOS. Ele demonstra como enviar mensagens através de uma fila de mensagens POSIX.
Existem algumas portas especiais que permitem **realizar certas ações sensíveis ou acessar determinados dados sensíveis** caso uma tarefa tenha permissões de **ENVIO** sobre elas. Isso torna essas portas muito interessantes do ponto de vista de um atacante não apenas por causa das capacidades, mas também porque é possível **compartilhar permissões de ENVIO entre tarefas**.
Os direitos de **ENVIO** podem ser obtidos chamando **`host_get_special_port`** e os direitos de **RECEBIMENTO** chamando **`host_set_special_port`**. No entanto, ambas as chamadas requerem a porta **`host_priv`** que apenas o root pode acessar. Além disso, no passado, o root era capaz de chamar **`host_set_special_port`** e sequestrar arbitrariamente o que permitia, por exemplo, ignorar assinaturas de código sequestrando `HOST_KEXTD_PORT` (SIP agora impede isso).
Essas portas são divididas em 2 grupos: Os **primeiros 7 portas são de propriedade do kernel** sendo o 1 `HOST_PORT`, o 2 `HOST_PRIV_PORT`, o 3 `HOST_IO_MASTER_PORT` e o 7 é `HOST_MAX_SPECIAL_KERNEL_PORT`.\
Os que começam **a partir** do número **8** são **de propriedade dos daemons do sistema** e podem ser encontrados declarados em [**`host_special_ports.h`**](https://opensource.apple.com/source/xnu/xnu-4570.1.46/osfmk/mach/host\_special\_ports.h.auto.html).
* **Porta do Host**: Se um processo tem **privilégio de ENVIO** sobre esta porta, ele pode obter **informações** sobre o **sistema** chamando suas rotinas como:
*`host_processor_info`: Obter informações do processador
*`host_info`: Obter informações do host
*`host_virtual_physical_table_info`: Tabela de páginas virtual/física (requer MACH\_VMDEBUG)
*`host_statistics`: Obter estatísticas do host
*`mach_memory_info`: Obter layout de memória do kernel
* **Porta Priv do Host**: Um processo com direito de **ENVIO** sobre esta porta pode realizar **ações privilegiadas** como mostrar dados de inicialização ou tentar carregar uma extensão de kernel. O **processo precisa ser root** para obter essa permissão.
* Além disso, para chamar a API **`kext_request`** é necessário ter outras permissões **`com.apple.private.kext*`** que são concedidas apenas a binários da Apple.
*`host_processors`: Direito de envio para processadores do host
*`mach_vm_wire`: Tornar a memória residente
* Como o **root** pode acessar essa permissão, ele poderia chamar `host_set_[special/exception]_port[s]` para **sequestrar portas especiais ou de exceção do host**.
É possível **ver todas as portas especiais do host** executando:
Estas são portas reservadas para serviços conhecidos. É possível obtê-las/configurá-las chamando `task_[get/set]_special_port`. Elas podem ser encontradas em `task_special_ports.h`:
```c
typedef int task_special_port_t;
#define TASK_KERNEL_PORT 1 /* Represents task to the outside
world.*/
#define TASK_HOST_PORT 2 /* The host (priv) port for task. */
#define TASK_BOOTSTRAP_PORT 4 /* Bootstrap environment for task. */
#define TASK_WIRED_LEDGER_PORT 5 /* Wired resource ledger for task. */
#define TASK_PAGED_LEDGER_PORT 6 /* Paged resource ledger for task. */
```
De [aqui](https://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task\_get\_special\_port.html):
* **TASK\_KERNEL\_PORT**\[direito de envio de tarefa-self]: A porta usada para controlar esta tarefa. Usada para enviar mensagens que afetam a tarefa. Esta é a porta retornada por **mach\_task\_self (veja Portas de Tarefa abaixo)**.
* **TASK\_BOOTSTRAP\_PORT**\[direito de envio de inicialização]: A porta de inicialização da tarefa. Usada para enviar mensagens solicitando o retorno de outras portas de serviço do sistema.
* **TASK\_HOST\_NAME\_PORT**\[direito de envio de host-self]: A porta usada para solicitar informações do host contido. Esta é a porta retornada por **mach\_host\_self**.
* **TASK\_WIRED\_LEDGER\_PORT**\[direito de envio de livro-razão]: A porta que nomeia a fonte da qual esta tarefa retira sua memória com fio do kernel.
* **TASK\_PAGED\_LEDGER\_PORT**\[direito de envio de livro-razão]: A porta que nomeia a fonte da qual esta tarefa retira sua memória gerenciada por padrão.
Originalmente, o Mach não tinha "processos", tinha "tarefas", que eram consideradas mais como contêineres de threads. Quando o Mach foi mesclado com o BSD, **cada tarefa foi correlacionada com um processo BSD**. Portanto, cada processo BSD tem os detalhes necessários para ser um processo e cada tarefa Mach também tem seus mecanismos internos (exceto pelo pid inexistente 0, que é a `kernel_task`).
*`task_for_pid(porta_tarefa_alvo, pid, &porta_tarefa_do_pid)`: Obtenha um direito de envio para a porta da tarefa relacionada ao especificado pelo `pid` e dê-o à `porta_tarefa_alvo` indicada (que geralmente é a tarefa chamadora que usou `mach_task_self()`, mas poderia ser uma porta de envio sobre uma tarefa diferente).
Para realizar ações dentro da tarefa, a tarefa precisava de um direito de envio para si mesma chamando `mach_task_self()` (que usa o `task_self_trap` (28)). Com essa permissão, uma tarefa pode realizar várias ações como:
*`task_threads`: Obter direitos de envio sobre todas as portas de tarefa das threads da tarefa
*`task_info`: Obter informações sobre uma tarefa
*`task_suspend/resume`: Suspender ou retomar uma tarefa
*`task_[get/set]_special_port`
*`thread_create`: Criar uma thread
*`task_[get/set]_state`: Controlar o estado da tarefa
* e mais podem ser encontrados em [**mach/task.h**](https://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX11.3.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/mach/task.h)
Além disso, a porta da tarefa é também a **porta `vm_map`** que permite **ler e manipular memória** dentro de uma tarefa com funções como `vm_read()` e `vm_write()`. Isso basicamente significa que uma tarefa com direitos de envio sobre a porta da tarefa de uma tarefa diferente será capaz de **injetar código nessa tarefa**.
Lembre-se de que porque o **kernel também é uma tarefa**, se alguém conseguir obter permissões de **envio** sobre o **`kernel_task`**, será capaz de fazer o kernel executar qualquer coisa (jailbreaks).
* Chame `mach_task_self()` para **obter o nome** desta porta para a tarefa chamadora. Esta porta é **herdada** apenas através de **`exec()`**; uma nova tarefa criada com `fork()` obtém uma nova porta de tarefa (como caso especial, uma tarefa também obtém uma nova porta de tarefa após `exec()` em um binário suid). A única maneira de gerar uma tarefa e obter sua porta é realizar a ["dança de troca de portas"](https://robert.sesek.com/2014/1/changes\_to\_xnu\_mach\_ipc.html) enquanto faz um `fork()`.
* Se o aplicativo tiver a **permissão `com.apple.security.get-task-allow`**, processos do **mesmo usuário podem acessar a porta da tarefa** (comumente adicionado pelo Xcode para depuração). O processo de **notarização** não permitirá isso em lançamentos de produção.
* Aplicativos com a permissão **`com.apple.system-task-ports`** podem obter a **porta da tarefa para qualquer** processo, exceto o kernel. Em versões mais antigas, era chamado de **`task_for_pid-allow`**. Isso é concedido apenas a aplicativos da Apple.
* **Root pode acessar portas de tarefas** de aplicativos **não** compilados com um tempo de execução **fortificado** (e não da Apple).
**A porta do nome da tarefa:** Uma versão não privilegiada da _porta da tarefa_. Ela faz referência à tarefa, mas não permite controlá-la. A única coisa que parece estar disponível por meio dela é `task_info()`.
As threads também têm portas associadas, que são visíveis da tarefa chamando **`task_threads`** e do processador com `processor_set_threads`. Um direito de envio para a porta da thread permite usar a função do subsistema `thread_act`, como:
*`thread_terminate`
*`thread_[get/set]_state`
*`act_[get/set]_state`
*`thread_[suspend/resume]`
*`thread_info`
* ...
Qualquer thread pode obter esta porta chamando **`mach_thread_sef`**.
A Comunicação entre Processos (IPC) é um mecanismo essencial para que os processos em um sistema operacional possam trocar informações e coordenar suas atividades. No macOS, existem várias formas de IPC, como notificações distribuídas, Apple Events, XPC e IPC baseado em porta.
Os processos no macOS podem abusar dos mecanismos de IPC para obter privilégios elevados ou realizar ações maliciosas. É importante entender como os processos legítimos usam a IPC e monitorar atividades suspeitas para identificar possíveis abusos.
Para proteger um sistema macOS contra abusos de IPC, é fundamental implementar práticas de segurança, como restringir as permissões de IPC por meio de arquivos de entitlements e monitorar o uso de IPC por processos suspeitos.
Ao compreender os mecanismos de IPC no macOS e adotar medidas proativas para proteger contra abusos, é possível fortalecer a segurança do sistema e reduzir o risco de escalonamento de privilégios e atividades maliciosas.
**Compile** o programa anterior e adicione os **privilégios** para poder injetar código com o mesmo usuário (caso contrário, será necessário usar **sudo**).
No macOS, **threads** podem ser manipulados via **Mach** ou usando a **api posix `pthread`**. A thread que geramos na injeção anterior foi gerada usando a api Mach, então **não é compatível com posix**.
Foi possível **injetar um shellcode simples** para executar um comando porque **não precisava trabalhar com apis compatíveis com posix**, apenas com Mach. **Injeções mais complexas** precisariam que a **thread** também fosse **compatível com posix**.
Portanto, para **melhorar a thread**, ela deve chamar **`pthread_create_from_mach_thread`** que irá **criar um pthread válido**. Em seguida, este novo pthread poderia **chamar dlopen** para **carregar uma dylib** do sistema, então em vez de escrever um novo shellcode para realizar ações diferentes, é possível carregar bibliotecas personalizadas.
Ao chamar `task_for_pid` ou `thread_create_*`, um contador na estrutura de tarefa do kernel é incrementado, o qual pode ser acessado a partir do modo de usuário chamando task\_info(task, TASK\_EXTMOD\_INFO, ...)
Quando uma exceção ocorre em uma thread, esta exceção é enviada para a porta de exceção designada da thread. Se a thread não a manipular, então é enviada para as portas de exceção da tarefa. Se a tarefa não a manipular, então é enviada para a porta do host que é gerenciada pelo launchd (onde será reconhecida). Isso é chamado de triagem de exceção.
Observe que no final, geralmente, se não for manipulada corretamente, o relatório acabará sendo manipulado pelo daemon ReportCrash. No entanto, é possível para outra thread na mesma tarefa gerenciar a exceção, isso é o que ferramentas de relatório de falhas como `PLCrashReporter` fazem.
Qualquer usuário pode acessar informações sobre o relógio, no entanto, para definir a hora ou modificar outras configurações, é necessário ser root.
Para obter informações, é possível chamar funções do subsistema `clock` como: `clock_get_time`, `clock_get_attributtes` ou `clock_alarm`\
Para modificar valores, o subsistema `clock_priv` pode ser usado com funções como `clock_set_time` e `clock_set_attributes`
### Processadores e Conjunto de Processadores
As APIs de processador permitem controlar um único processador lógico chamando funções como `processor_start`, `processor_exit`, `processor_info`, `processor_get_assignment`...
Além disso, as APIs do **conjunto de processadores** fornecem uma maneira de agrupar vários processadores em um grupo. É possível recuperar o conjunto de processadores padrão chamando **`processor_set_default`**.\
Aqui estão algumas APIs interessantes para interagir com o conjunto de processadores:
*`processor_set_statistics`
*`processor_set_tasks`: Retorna uma matriz de direitos de envio para todas as tarefas dentro do conjunto de processadores
*`processor_set_threads`: Retorna uma matriz de direitos de envio para todas as threads dentro do conjunto de processadores
*`processor_set_stack_usage`
*`processor_set_info`
Conforme mencionado neste [**post**](https://reverse.put.as/2014/05/05/about-the-processor\_set\_tasks-access-to-kernel-memory-vulnerability/), no passado, isso permitia contornar a proteção mencionada anteriormente para obter portas de tarefa em outros processos para controlá-los chamando **`processor_set_tasks`** e obtendo uma porta de host em cada processo.\
Atualmente, é necessário ter privilégios de root para usar essa função e ela é protegida, então você só poderá obter essas portas em processos não protegidos.
Você pode tentar com:
<details>
<summary><strong>código de processor_set_tasks</strong></summary>
````c
// Maincpart fo the code from https://newosxbook.com/articles/PST2.html
//gcc ./port_pid.c -o port_pid
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sysctl.h>
#include <libproc.h>
#include <mach/mach.h>
#include <errno.h>
#include <string.h>
#include <mach/exception_types.h>
#include <mach/mach_host.h>
#include <mach/host_priv.h>
#include <mach/processor_set.h>
#include <mach/mach_init.h>
#include <mach/mach_port.h>
#include <mach/vm_map.h>
#include <mach/task.h>
#include <mach/task_info.h>
#include <mach/mach_traps.h>
#include <mach/mach_error.h>
#include <mach/thread_act.h>
#include <mach/thread_info.h>
#include <mach-o/loader.h>
#include <mach-o/nlist.h>
#include <sys/ptrace.h>
mach_port_t task_for_pid_workaround(int Pid)
{
host_t myhost = mach_host_self(); // host self is host priv if you're root anyway..
XPC, which stands for XNU (the kernel used by macOS) inter-Process Communication, is a framework for **communication between processes** on macOS and iOS. XPC provides a mechanism for making **safe, asynchronous method calls between different processes** on the system. It's a part of Apple's security paradigm, allowing for the **creation of privilege-separated applications** where each **component** runs with **only the permissions it needs** to do its job, thereby limiting the potential damage from a compromised process.
MIG was created to **simplify the process of Mach IPC** code creation. This is because a lot of work to program RPC involves the same actions (packing arguments, sending the msg, unpacking the data in the server...).
MIC basically **generates the needed code** for server and client to communicate with a given definition (in IDL -Interface Definition language-). Even if the generated code is ugly, a developer will just need to import it and his code will be much simpler than before.
Learn & practice AWS Hacking:<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">\
Learn & practice GCP Hacking: <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)
* 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.