diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 27f33cff3..2062b6f9d 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -61,6 +61,7 @@ - [Deofuscation vbs (cscript.exe)](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/desofuscation-vbs-cscript.exe.md) - [Discord Cache Forensics](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/discord-cache-forensics.md) - [Local Cloud Storage](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/local-cloud-storage.md) + - [Mach O Entitlements And Ipsw Indexing](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md) - [Office file analysis](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/office-file-analysis.md) - [PDF File analysis](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/pdf-file-analysis.md) - [PNG tricks](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/png-tricks.md) diff --git a/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/README.md b/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/README.md index 734bae1fd..0e5fe7fb5 100644 --- a/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/README.md +++ b/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/README.md @@ -1,4 +1,4 @@ -# Truques Específicos de Software/Tipos de Arquivo +# Truques específicos para tipos de arquivo/software {{#include ../../../banners/hacktricks-training.md}} @@ -54,4 +54,9 @@ video-and-audio-file-analysis.md zips-tricks.md {{#endref}} + +{{#ref}} +mach-o-entitlements-and-ipsw-indexing.md +{{#endref}} + {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md b/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md new file mode 100644 index 000000000..451e1b569 --- /dev/null +++ b/src/generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md @@ -0,0 +1,213 @@ +# Extração de Entitlements de Mach-O & Indexação de IPSW + +{{#include ../../../banners/hacktricks-training.md}} + +## Visão geral + +Esta página explica como extrair entitlements de binários Mach-O programaticamente percorrendo LC_CODE_SIGNATURE e analisando o code signing SuperBlob, e como escalar isso em firmwares IPSW da Apple montando e indexando seus conteúdos para busca/diff forense. + +Se precisar de uma revisão sobre o formato Mach-O e code signing, veja também: macOS code signing and SuperBlob internals. +- Consulte os detalhes de macOS code signing (SuperBlob, Code Directory, special slots): [macOS Code Signing](../../../macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md) +- Consulte estruturas gerais do Mach-O / load commands: [Universal binaries & Mach-O Format](../../../macos-hardening/macos-security-and-privilege-escalation/macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md) + + +## Entitlements no Mach-O: onde residem + +Entitlements são armazenados dentro dos dados de code signature referenciados pelo load command LC_CODE_SIGNATURE e colocados no segmento __LINKEDIT. A assinatura é um CS_SuperBlob contendo múltiplos blobs (code directory, requirements, entitlements, CMS, etc.). O blob de entitlements é um CS_GenericBlob cujo dado é um Apple Binary Property List (bplist00) que mapeia chaves de entitlements para valores. + +Key structures (from xnu): +```c +/* mach-o/loader.h */ +struct mach_header_64 { +uint32_t magic; +cpu_type_t cputype; +cpu_subtype_t cpusubtype; +uint32_t filetype; +uint32_t ncmds; +uint32_t sizeofcmds; +uint32_t flags; +uint32_t reserved; +}; + +struct load_command { +uint32_t cmd; +uint32_t cmdsize; +}; + +/* Entitlements live behind LC_CODE_SIGNATURE (cmd=0x1d) */ +struct linkedit_data_command { +uint32_t cmd; /* LC_CODE_SIGNATURE */ +uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */ +uint32_t dataoff; /* file offset of data in __LINKEDIT */ +uint32_t datasize; /* file size of data in __LINKEDIT */ +}; + +/* osfmk/kern/cs_blobs.h */ +typedef struct __SC_SuperBlob { +uint32_t magic; /* CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0 */ +uint32_t length; +uint32_t count; +CS_BlobIndex index[]; +} CS_SuperBlob; + +typedef struct __BlobIndex { +uint32_t type; /* e.g., CSMAGIC_EMBEDDED_ENTITLEMENTS = 0xfade7171 */ +uint32_t offset; /* offset of entry */ +} CS_BlobIndex; + +typedef struct __SC_GenericBlob { +uint32_t magic; /* same as type when standalone */ +uint32_t length; +char data[]; /* Apple Binary Plist containing entitlements */ +} CS_GenericBlob; +``` +Constantes importantes: +- LC_CODE_SIGNATURE cmd = 0x1d +- CS SuperBlob magic = 0xfade0cc0 +- Entitlements blob type (CSMAGIC_EMBEDDED_ENTITLEMENTS) = 0xfade7171 +- DER entitlements may be present via special slot (e.g., -7), see the macOS Code Signing page for special slots and DER entitlements notes + +Nota: Binários multi-arch (fat) contêm múltiplos Mach-O slices. Você deve escolher o slice da arquitetura que quer inspecionar e então percorrer seus load commands. + + +## Etapas de extração (genéricas, praticamente sem perda) + +1) Analise o cabeçalho Mach-O; itere pelos registros load_command conforme ncmds. +2) Localize LC_CODE_SIGNATURE; leia linkedit_data_command.dataoff/datasize para mapear o Code Signing SuperBlob colocado em __LINKEDIT. +3) Valide CS_SuperBlob.magic == 0xfade0cc0; itere pelas count entradas de CS_BlobIndex. +4) Localize index.type == 0xfade7171 (embedded entitlements). Leia o CS_GenericBlob apontado e parseie seus dados como um plist binário Apple (bplist00) para chaves/valores de entitlements. + +Notas de implementação: +- As estruturas de code signature usam campos big-endian; troque a ordem de bytes ao parsear em hosts little-endian. +- Os dados do GenericBlob de entitlements em si são um plist binário (tratado por bibliotecas padrão de plist). +- Alguns binários iOS podem conter DER entitlements; também alguns stores/slots diferem entre plataformas/versões. Verifique tanto os entitlements padrão quanto os DER conforme necessário. +- Para binários fat, use os fat headers (FAT_MAGIC/FAT_MAGIC_64) para localizar o slice e offset corretos antes de percorrer os Mach-O load commands. + + +## Esboço mínimo de parsing (Python) + +O seguinte é um esboço compacto mostrando o fluxo de controle para encontrar e decodificar entitlements. Intencionalmente omite verificações robustas de limites e suporte completo a fat binaries por brevidade. +```python +import plistlib, struct + +LC_CODE_SIGNATURE = 0x1d +CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0 +CSMAGIC_EMBEDDED_ENTITLEMENTS = 0xfade7171 + +# all code-signing integers are big-endian per cs_blobs.h +be32 = lambda b, off: struct.unpack_from(">I", b, off)[0] + +def parse_entitlements(macho_bytes): +# assume already positioned at a single-arch Mach-O slice +magic, = struct.unpack_from(" +``` +- Percorra volumes montados para localizar arquivos Mach-O (verifique magic e/ou use file/otool) e, em seguida, analise entitlements e frameworks importados. +- Persista uma visão normalizada em um banco de dados relacional para evitar crescimento linear através de milhares de IPSWs: +- executables, operating_system_versions, entitlements, frameworks +- many-to-many: executable↔OS version, executable↔entitlement, executable↔framework + +Exemplo de query para listar todas as versões do OS que contenham um determinado nome de executável: +```sql +SELECT osv.version AS "Versions" +FROM device d +LEFT JOIN operating_system_version osv ON osv.device_id = d.id +LEFT JOIN executable_operating_system_version eosv ON eosv.operating_system_version_id = osv.id +LEFT JOIN executable e ON e.id = eosv.executable_id +WHERE e.name = "launchd"; +``` +Notas sobre portabilidade de DB (se você implementar seu próprio indexador): +- Use um ORM/abstraction (e.g., SeaORM) para manter o código DB-agnostic (SQLite/PostgreSQL). +- SQLite requer AUTOINCREMENT apenas em um INTEGER PRIMARY KEY; se você quiser i64 PKs em Rust, gere entidades como i32 e converta tipos, SQLite armazena INTEGER como inteiro com sinal de 8 bytes internamente. + + +## Open-source tooling and references for entitlement hunting + +- Firmware mount/download: https://github.com/blacktop/ipsw +- Entitlement databases and references: +- Jonathan Levin’s entitlement DB: https://newosxbook.com/ent.php +- entdb: https://github.com/ChiChou/entdb +- Large-scale indexer (Rust, self-hosted Web UI + OpenAPI): https://github.com/synacktiv/appledb_rs +- Apple headers for structures and constants: +- loader.h (Mach-O headers, load commands) +- cs_blobs.h (SuperBlob, GenericBlob, CodeDirectory) + +For more on code signing internals (Code Directory, special slots, DER entitlements), see: [macOS Code Signing](../../../macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md) + + +## References + +- [appledb_rs: a research support tool for Apple platforms](https://www.synacktiv.com/publications/appledbrs-un-outil-daide-a-la-recherche-sur-plateformes-apple.html) +- [synacktiv/appledb_rs](https://github.com/synacktiv/appledb_rs) +- [blacktop/ipsw](https://github.com/blacktop/ipsw) +- [Jonathan Levin’s entitlement DB](https://newosxbook.com/ent.php) +- [ChiChou/entdb](https://github.com/ChiChou/entdb) +- [XNU cs_blobs.h](https://github.com/apple-oss-distributions/xnu/blob/main/osfmk/kern/cs_blobs.h) +- [XNU mach-o/loader.h](https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/loader.h) +- [SQLite Datatypes](https://sqlite.org/datatype3.html) + +{{#include ../../../banners/hacktricks-training.md}} diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md index d13312c17..14d64bf95 100644 --- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md +++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md @@ -2,47 +2,47 @@ {{#include ../../../banners/hacktricks-training.md}} -## Informações Básicas +## Basic Information -Os binários do Mac OS geralmente são compilados como **universal binaries**. Um **universal binary** pode **suportar múltiplas arquiteturas no mesmo arquivo**. +Binários do macOS geralmente são compilados como **universal binaries**. Um **universal binary** pode **suportar múltiplas arquiteturas no mesmo arquivo**. -Esses binários seguem a **estrutura Mach-O**, que é basicamente composta por: +Esses binários seguem a **estrutura Mach-O** que basicamente é composta por: - Cabeçalho -- Comandos de Carregamento +- Comandos de carregamento - Dados ![https://alexdremov.me/content/images/2022/10/6XLCD.gif](<../../../images/image (470).png>) -## Cabeçalho Fat +## Fat Header -Procure pelo arquivo com: `mdfind fat.h | grep -i mach-o | grep -E "fat.h$"` +Procure o arquivo com: `mdfind fat.h | grep -i mach-o | grep -E "fat.h$"`
#define FAT_MAGIC	0xcafebabe
 #define FAT_CIGAM	0xbebafeca	/* NXSwapLong(FAT_MAGIC) */
 
 struct fat_header {
-	uint32_t	magic;		/* FAT_MAGIC ou FAT_MAGIC_64 */
-	uint32_t	nfat_arch;	/* número de structs que seguem */
+	uint32_t	magic;		/* FAT_MAGIC or FAT_MAGIC_64 */
+	uint32_t	nfat_arch;	/* number of structs that follow */
 };
 
 struct fat_arch {
-cpu_type_t	cputype;	/* especificador de cpu (int) */
-cpu_subtype_t	cpusubtype;	/* especificador de máquina (int) */
-uint32_t	offset;		/* deslocamento do arquivo para este arquivo objeto */
-uint32_t	size;		/* tamanho deste arquivo objeto */
-uint32_t	align;		/* alinhamento como uma potência de 2 */
+cpu_type_t	cputype;	/* cpu specifier (int) */
+cpu_subtype_t	cpusubtype;	/* machine specifier (int) */
+uint32_t	offset;		/* file offset to this object file */
+uint32_t	size;		/* size of this object file */
+uint32_t	align;		/* alignment as a power of 2 */
 };
 
-O cabeçalho tem os bytes **mágicos** seguidos pelo **número** de **arquiteturas** que o arquivo **contém** (`nfat_arch`) e cada arquitetura terá uma struct `fat_arch`. +O header tem os bytes **magic** seguidos pelo **número** de **archs** que o arquivo **contém** (`nfat_arch`) e cada arch terá uma struct `fat_arch`. Verifique com:
% file /bin/ls
-/bin/ls: Mach-O universal binary com 2 arquiteturas: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
-/bin/ls (para arquitetura x86_64):	Mach-O 64-bit executable x86_64
-/bin/ls (para arquitetura arm64e):	Mach-O 64-bit executable arm64e
+/bin/ls: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
+/bin/ls (for architecture x86_64):	Mach-O 64-bit executable x86_64
+/bin/ls (for architecture arm64e):	Mach-O 64-bit executable arm64e
 
 % otool -f -v /bin/ls
 Fat headers
@@ -68,11 +68,11 @@ ou usando a ferramenta [Mach-O View](https://sourceforge.net/projects/machoview/
 
 
-Como você pode estar pensando, geralmente um universal binary compilado para 2 arquiteturas **dobra o tamanho** de um compilado para apenas 1 arquitetura. +Como você pode imaginar, geralmente um universal binary compilado para 2 arquiteturas **dobra o tamanho** de um compilado para apenas 1 arch. -## **Cabeçalho Mach-O** +## **Mach-O Header** -O cabeçalho contém informações básicas sobre o arquivo, como bytes mágicos para identificá-lo como um arquivo Mach-O e informações sobre a arquitetura de destino. Você pode encontrá-lo em: `mdfind loader.h | grep -i mach-o | grep -E "loader.h$"` +O header contém informações básicas sobre o arquivo, como bytes magic para identificá-lo como um arquivo Mach-O e informações sobre a arquitetura alvo. Você pode encontrá-lo em: `mdfind loader.h | grep -i mach-o | grep -E "loader.h$"` ```c #define MH_MAGIC 0xfeedface /* the mach magic number */ #define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */ @@ -99,19 +99,19 @@ uint32_t flags; /* flags */ uint32_t reserved; /* reserved */ }; ``` -### Tipos de Arquivo Mach-O +### Mach-O File Types -Existem diferentes tipos de arquivos, que podem ser encontrados definidos no [**código-fonte, por exemplo aqui**](https://opensource.apple.com/source/xnu/xnu-2050.18.24/EXTERNAL_HEADERS/mach-o/loader.h). Os mais importantes são: +Existem diferentes tipos de arquivo — você pode encontrá-los definidos no [**source code for example here**](https://opensource.apple.com/source/xnu/xnu-2050.18.24/EXTERNAL_HEADERS/mach-o/loader.h). Os mais importantes são: - `MH_OBJECT`: Arquivo objeto relocável (produtos intermediários da compilação, ainda não executáveis). - `MH_EXECUTE`: Arquivos executáveis. -- `MH_FVMLIB`: Arquivo de biblioteca VM fixa. -- `MH_CORE`: Dumps de código. -- `MH_PRELOAD`: Arquivo executável pré-carregado (não mais suportado no XNU). -- `MH_DYLIB`: Bibliotecas dinâmicas. -- `MH_DYLINKER`: Linker dinâmico. -- `MH_BUNDLE`: "Arquivos de plugin". Gerados usando -bundle no gcc e carregados explicitamente por `NSBundle` ou `dlopen`. -- `MH_DYSM`: Arquivo companion `.dSym` (arquivo com símbolos para depuração). +- `MH_FVMLIB`: Arquivo de biblioteca de VM fixa. +- `MH_CORE`: Despejos de código +- `MH_PRELOAD`: Arquivo executável pré-carregado (não é mais suportado no XNU) +- `MH_DYLIB`: Bibliotecas dinâmicas +- `MH_DYLINKER`: Ligador dinâmico +- `MH_BUNDLE`: "Plugin files". Gerados usando -bundle no gcc e carregados explicitamente por `NSBundle` ou `dlopen`. +- `MH_DYSM`: Arquivo acompanhante `.dSym` (arquivo com símbolos para depuração). - `MH_KEXT_BUNDLE`: Extensões do Kernel. ```bash # Checking the mac header of a binary @@ -120,54 +120,54 @@ Mach header magic cputype cpusubtype caps filetype ncmds sizeofcmds flags MH_MAGIC_64 ARM64 E USR00 EXECUTE 19 1728 NOUNDEFS DYLDLINK TWOLEVEL PIE ``` -Ou usando [Mach-O View](https://sourceforge.net/projects/machoview/): +Or using [Mach-O View](https://sourceforge.net/projects/machoview/):
-## **Flags Mach-O** +## **Flags do Mach-O** O código-fonte também define várias flags úteis para carregar bibliotecas: -- `MH_NOUNDEFS`: Sem referências indefinidas (totalmente vinculado) -- `MH_DYLDLINK`: Vinculação Dyld +- `MH_NOUNDEFS`: Sem referências indefinidas (totalmente vinculadas) +- `MH_DYLDLINK`: Ligação pelo dyld - `MH_PREBOUND`: Referências dinâmicas pré-vinculadas. -- `MH_SPLIT_SEGS`: O arquivo divide segmentos r/o e r/w. -- `MH_WEAK_DEFINES`: O binário tem símbolos definidos fracos -- `MH_BINDS_TO_WEAK`: O binário usa símbolos fracos -- `MH_ALLOW_STACK_EXECUTION`: Torna a pilha executável -- `MH_NO_REEXPORTED_DYLIBS`: Biblioteca não possui comandos LC_REEXPORT -- `MH_PIE`: Executável Independente de Posição -- `MH_HAS_TLV_DESCRIPTORS`: Há uma seção com variáveis locais de thread +- `MH_SPLIT_SEGS`: Arquivo divide segmentos r/o e r/w. +- `MH_WEAK_DEFINES`: Binário possui símbolos definidos fracos +- `MH_BINDS_TO_WEAK`: Binário usa símbolos fracos +- `MH_ALLOW_STACK_EXECUTION`: Tornar a pilha executável +- `MH_NO_REEXPORTED_DYLIBS`: Biblioteca sem comandos LC_REEXPORT +- `MH_PIE`: Executável independente de posição +- `MH_HAS_TLV_DESCRIPTORS`: Há uma seção com variáveis thread-local - `MH_NO_HEAP_EXECUTION`: Sem execução para páginas de heap/dados -- `MH_HAS_OBJC`: O binário tem seções oBject-C -- `MH_SIM_SUPPORT`: Suporte a simulador -- `MH_DYLIB_IN_CACHE`: Usado em dylibs/frameworks no cache de biblioteca compartilhada. +- `MH_HAS_OBJC`: Binário possui seções oBject-C +- `MH_SIM_SUPPORT`: Suporte ao simulador +- `MH_DYLIB_IN_CACHE`: Usado em dylibs/frameworks no cache de bibliotecas compartilhadas. -## **Comandos de carregamento Mach-O** +## **Comandos de carregamento do Mach-O** -O **layout do arquivo na memória** é especificado aqui, detalhando a **localização da tabela de símbolos**, o contexto da thread principal no início da execução e as **bibliotecas compartilhadas** necessárias. Instruções são fornecidas ao carregador dinâmico **(dyld)** sobre o processo de carregamento do binário na memória. +A **disposição do arquivo na memória** é especificada aqui, detalhando a **localização da tabela de símbolos**, o contexto da thread principal no início da execução e as **bibliotecas compartilhadas** necessárias. São fornecidas instruções para o loader dinâmico **(dyld)** sobre o processo de carregamento do binário na memória. -O utiliza a estrutura **load_command**, definida no mencionado **`loader.h`**: +Ele usa a estrutura **load_command**, definida no mencionado **`loader.h`**: ```objectivec struct load_command { uint32_t cmd; /* type of load command */ uint32_t cmdsize; /* total size of command in bytes */ }; ``` -Existem cerca de **50 tipos diferentes de comandos de carga** que o sistema trata de maneira diferente. Os mais comuns são: `LC_SEGMENT_64`, `LC_LOAD_DYLINKER`, `LC_MAIN`, `LC_LOAD_DYLIB` e `LC_CODE_SIGNATURE`. +Existem cerca de **50 tipos diferentes de comandos de carregamento** que o sistema trata de forma diferente. Os mais comuns são: `LC_SEGMENT_64`, `LC_LOAD_DYLINKER`, `LC_MAIN`, `LC_LOAD_DYLIB`, and `LC_CODE_SIGNATURE`. ### **LC_SEGMENT/LC_SEGMENT_64** > [!TIP] -> Basicamente, este tipo de Comando de Carga define **como carregar o \_\_TEXT** (código executável) **e \_\_DATA** (dados para o processo) **segmentos** de acordo com os **offsets indicados na seção de Dados** quando o binário é executado. +> Basicamente, esse tipo de Comando de carregamento define **como carregar os \_\_TEXT** (código executável) **e \_\_DATA** (dados do processo) **segmentos** de acordo com os **offsets indicados na seção de dados** quando o binário é executado. Esses comandos **definem segmentos** que são **mapeados** no **espaço de memória virtual** de um processo quando ele é executado. -Existem **diferentes tipos** de segmentos, como o **\_\_TEXT** segmento, que contém o código executável de um programa, e o **\_\_DATA** segmento, que contém dados usados pelo processo. Esses **segmentos estão localizados na seção de dados** do arquivo Mach-O. +Existem **diferentes tipos** de segmentos, como o segmento **\_\_TEXT**, que contém o código executável de um programa, e o segmento **\_\_DATA**, que contém dados usados pelo processo. Esses **segmentos estão localizados na seção de dados** do arquivo Mach-O. -**Cada segmento** pode ser ainda **dividido** em múltiplas **seções**. A **estrutura do comando de carga** contém **informações** sobre **essas seções** dentro do respectivo segmento. +**Cada segmento** pode ser ainda **dividido** em múltiplas **seções**. A **estrutura do load command** contém **informações** sobre **essas seções** dentro do respectivo segmento. -No cabeçalho, primeiro você encontra o **cabeçalho do segmento**: +No cabeçalho, primeiro você encontra o **segment header**:
struct segment_command_64 { /* for 64-bit architectures */
 uint32_t	cmd;		/* LC_SEGMENT_64 */
@@ -184,11 +184,11 @@ int32_t		initprot;	/* initial VM protection */
 };
 
-Exemplo de cabeçalho de segmento: +Exemplo de segment header:
-Este cabeçalho define o **número de seções cujos cabeçalhos aparecem depois** dele: +Esse cabeçalho define o **número de seções cujos cabeçalhos aparecem após** ele: ```c struct section_64 { /* for 64-bit architectures */ char sectname[16]; /* name of this section */ @@ -205,62 +205,62 @@ uint32_t reserved2; /* reserved (for count or sizeof) */ uint32_t reserved3; /* reserved */ }; ``` -Exemplo de **cabeçalho de seção**: +Exemplo de **section header**:
-Se você **adicionar** o **deslocamento da seção** (0x37DC) + o **deslocamento** onde a **arquitetura começa**, neste caso `0x18000` --> `0x37DC + 0x18000 = 0x1B7DC` +Se você **somar** o **section offset** (0x37DC) + o **offset** onde a **arch** começa, neste caso `0x18000` --> `0x37DC + 0x18000 = 0x1B7DC`
-Também é possível obter **informações de cabeçalhos** a partir da **linha de comando** com: +Também é possível obter **headers information** pela **command line** com: ```bash otool -lv /bin/ls ``` -Segmentos comuns carregados por este cmd: +Common segments loaded by this cmd: -- **`__PAGEZERO`:** Instruí o kernel a **mapear** o **endereço zero** para que **não possa ser lido, escrito ou executado**. As variáveis maxprot e minprot na estrutura são definidas como zero para indicar que **não há direitos de leitura-gravação-execução nesta página**. -- Esta alocação é importante para **mitigar vulnerabilidades de desreferência de ponteiro NULL**. Isso ocorre porque o XNU impõe uma página zero rígida que garante que a primeira página (apenas a primeira) da memória seja inacessível (exceto em i386). Um binário poderia atender a esses requisitos criando um pequeno \_\_PAGEZERO (usando o `-pagezero_size`) para cobrir os primeiros 4k e tendo o restante da memória de 32 bits acessível tanto em modo de usuário quanto em modo kernel. -- **`__TEXT`**: Contém **código** **executável** com permissões de **leitura** e **execução** (sem permissões de escrita)**.** Seções comuns deste segmento: +- **`__PAGEZERO`:** Instrui o kernel a **mapear** o **endereço zero** de modo que **não possa ser lido, escrito ou executado**. As variáveis `maxprot` e `minprot` na estrutura são definidas como zero para indicar que **não há permissões de leitura-escrita-execução nesta página**. +- Esta alocação é importante para **mitigar vulnerabilidades de desreferência de ponteiro NULL**. Isso porque XNU aplica uma hard page zero que garante que a primeira página (apenas a primeira) da memória seja inacessível (exceto em i386). Um binário poderia satisfazer esse requisito criando um pequeno \_\_PAGEZERO (usando o `-pagezero_size`) para cobrir os primeiros 4k e deixando o restante da memória 32bit acessível tanto em modo usuário quanto em modo kernel. +- **`__TEXT`**: Contém **código** **executável** com permissões de **leitura** e **execução** (não gravável). Seções comuns deste segmento: - `__text`: Código binário compilado - `__const`: Dados constantes (somente leitura) -- `__[c/u/os_log]string`: Constantes de string C, Unicode ou logs do os -- `__stubs` e `__stubs_helper`: Envolvidos durante o processo de carregamento da biblioteca dinâmica -- `__unwind_info`: Dados de desempilhamento. -- Note que todo esse conteúdo é assinado, mas também marcado como executável (criando mais opções para exploração de seções que não necessariamente precisam desse privilégio, como seções dedicadas a strings). -- **`__DATA`**: Contém dados que são **legíveis** e **graváveis** (sem executável)**.** -- `__got:` Tabela de Deslocamento Global -- `__nl_symbol_ptr`: Ponteiro de símbolo não preguiçoso (vinculado na carga) -- `__la_symbol_ptr`: Ponteiro de símbolo preguiçoso (vinculado no uso) -- `__const`: Deve ser dados somente leitura (não realmente) +- `__[c/u/os_log]string`: Constantes de string C, Unicode ou de logs do os +- `__stubs` and `__stubs_helper`: Envolvidas durante o processo de carregamento de bibliotecas dinâmicas +- `__unwind_info`: Dados de unwind da pilha +- Note que todo esse conteúdo é assinado, mas também marcado como executável (criando mais opções para exploração de seções que nem necessariamente precisam desse privilégio, como seções dedicadas a strings). +- **`__DATA`**: Contém dados que são **legíveis** e **graváveis** (não executáveis). +- `__got:` Global Offset Table +- `__nl_symbol_ptr`: Ponteiro de símbolo non-lazy (bind at load) +- `__la_symbol_ptr`: Ponteiro de símbolo lazy (bind on use) +- `__const`: Deveria ser dados somente leitura (na prática não é) - `__cfstring`: Strings do CoreFoundation - `__data`: Variáveis globais (que foram inicializadas) - `__bss`: Variáveis estáticas (que não foram inicializadas) -- `__objc_*` (\_\_objc_classlist, \_\_objc_protolist, etc): Informações usadas pelo runtime do Objective-C -- **`__DATA_CONST`**: \_\_DATA.\_\_const não é garantido que seja constante (permissões de escrita), nem outros ponteiros e a GOT. Esta seção torna `__const`, alguns inicializadores e a tabela GOT (uma vez resolvida) **somente leitura** usando `mprotect`. -- **`__LINKEDIT`**: Contém informações para o linker (dyld), como entradas de tabela de símbolos, strings e relocação. É um contêiner genérico para conteúdos que não estão em `__TEXT` ou `__DATA` e seu conteúdo é descrito em outros comandos de carregamento. -- Informações do dyld: Rebase, opcodes de vinculação não preguiçosa/preguiçosa/fraca e informações de exportação -- Inícios de funções: Tabela de endereços de início de funções -- Dados em Código: Ilhas de dados em \_\_text -- Tabela de Símbolos: Símbolos no binário -- Tabela de Símbolos Indiretos: Símbolos de ponteiro/stub -- Tabela de Strings -- Assinatura de Código -- **`__OBJC`**: Contém informações usadas pelo runtime do Objective-C. Embora essas informações também possam ser encontradas no segmento \_\_DATA, dentro de várias seções em \_\_objc\_\*. -- **`__RESTRICT`**: Um segmento sem conteúdo com uma única seção chamada **`__restrict`** (também vazia) que garante que, ao executar o binário, ele ignorará variáveis de ambiente DYLD. +- `__objc_*` (\_\_objc_classlist, \_\_objc_protolist, etc): Informações usadas pelo runtime Objective-C +- **`__DATA_CONST`**: \_\_DATA.\_\_const não é garantidamente constante (tem permissões de escrita), nem outros ponteiros e o GOT. Esta seção torna `__const`, alguns inicializadores e a tabela GOT (uma vez resolvida) **somente leitura** usando `mprotect`. +- **`__LINKEDIT`**: Contém informações para o linker (dyld) tais como entradas de tabelas de símbolos, strings e relocação. É um contêiner genérico para conteúdos que não estão em `__TEXT` ou `__DATA` e seu conteúdo é descrito em outros load commands. +- Informação do dyld: Rebase, opcodes de binding Non-lazy/lazy/weak e informações de exportação +- Functions starts: Tabela de endereços iniciais das funções +- Data In Code: Ilhas de dados em \_\_text +- Symbol Table: Símbolos no binário +- Indirect Symbol Table: Símbolos de ponteiro/stub +- String Table +- Code Signature +- **`__OBJC`**: Contém informações usadas pelo runtime Objective-C. Embora essas informações também possam ser encontradas no segmento \_\_DATA, dentro de várias seções \_\_objc\_\*. +- **`__RESTRICT`**: Um segmento sem conteúdo com uma única seção chamada **`__restrict`** (também vazia) que assegura que, ao executar o binário, ele irá ignorar as variáveis de ambiente do DYLD. -Como foi possível ver no código, **os segmentos também suportam flags** (embora não sejam muito usadas): +As it was possible to see in the code, **segments also support flags** (although they aren't used very much): -- `SG_HIGHVM`: Apenas núcleo (não usado) +- `SG_HIGHVM`: Somente core (não usado) - `SG_FVMLIB`: Não usado -- `SG_NORELOC`: O segmento não tem relocação -- `SG_PROTECTED_VERSION_1`: Criptografia. Usado, por exemplo, pelo Finder para criptografar o segmento `__TEXT`. +- `SG_NORELOC`: Segment has no relocation +- `SG_PROTECTED_VERSION_1`: Encryption. Used for example by Finder to encrypt text `__TEXT` segment. ### **`LC_UNIXTHREAD/LC_MAIN`** -**`LC_MAIN`** contém o ponto de entrada no **atributo entryoff.** No momento do carregamento, **dyld** simplesmente **adiciona** esse valor à (em memória) **base do binário**, então **salta** para essa instrução para iniciar a execução do código do binário. +**`LC_MAIN`** contains the entrypoint in the **entryoff attribute.** At load time, **dyld** simply **adds** this value to the (in-memory) **base of the binary**, then **jumps** to this instruction to start execution of the binary’s code. -**`LC_UNIXTHREAD`** contém os valores que o registrador deve ter ao iniciar a thread principal. Isso já foi descontinuado, mas **`dyld`** ainda o utiliza. É possível ver os valores dos registradores definidos por isso com: +**`LC_UNIXTHREAD`** contains the values the register must have when starting the main thread. This was already deprecated but **`dyld`** still uses it. It's possible to see the vlaues of the registers set by this with: ```bash otool -l /usr/lib/dyld [...] @@ -286,34 +286,39 @@ cpsr 0x00000000 ``` ### **`LC_CODE_SIGNATURE`** -Contém informações sobre a **assinatura de código do arquivo Macho-O**. Ele contém apenas um **offset** que **aponta** para o **blob de assinatura**. Isso geralmente está no final do arquivo.\ -No entanto, você pode encontrar algumas informações sobre esta seção em [**este post do blog**](https://davedelong.com/blog/2018/01/10/reading-your-own-entitlements/) e este [**gists**](https://gist.github.com/carlospolop/ef26f8eb9fafd4bc22e69e1a32b81da4). +{{#ref}} +../../../generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md +{{#endref}} + + +Contains information about the **code signature of the Macho-O file**. It only contains an **offset** that **points** to the **signature blob**. This is typically at the very end of the file.\ +However, you can find some information about this section in [**this blog post**](https://davedelong.com/blog/2018/01/10/reading-your-own-entitlements/) and this [**gists**](https://gist.github.com/carlospolop/ef26f8eb9fafd4bc22e69e1a32b81da4). ### **`LC_ENCRYPTION_INFO[_64]`** -Suporte para criptografia binária. No entanto, claro, se um atacante conseguir comprometer o processo, ele poderá despejar a memória sem criptografia. +Suporte para criptografia de binários. No entanto, claro, se um atacante conseguir comprometer o processo, ele poderá extrair a memória sem criptografia. ### **`LC_LOAD_DYLINKER`** -Contém o **caminho para o executável do linker dinâmico** que mapeia bibliotecas compartilhadas no espaço de endereço do processo. O **valor é sempre definido como `/usr/lib/dyld`**. É importante notar que no macOS, o mapeamento de dylib acontece em **modo de usuário**, não em modo de kernel. +Contém o **caminho para o executável do dynamic linker** que mapeia bibliotecas compartilhadas no espaço de endereços do processo. O **valor é sempre definido para `/usr/lib/dyld`**. É importante notar que no macOS, o mapeamento de dylib ocorre em **modo de usuário**, não em modo kernel. ### **`LC_IDENT`** -Obsoleto, mas quando configurado para gerar dumps em pânico, um core dump Mach-O é criado e a versão do kernel é definida no comando `LC_IDENT`. +Obsoleto, mas quando configurado para gerar dumps em panic, um core dump Mach-O é criado e a versão do kernel é definida no comando `LC_IDENT`. ### **`LC_UUID`** -UUID aleatório. É útil para qualquer coisa diretamente, mas o XNU o armazena em cache com o resto das informações do processo. Pode ser usado em relatórios de falhas. +UUID aleatório. Não é útil diretamente para muita coisa, mas o XNU o armazena em cache com o resto das informações do processo. Pode ser usado em crash reports. ### **`LC_DYLD_ENVIRONMENT`** -Permite indicar variáveis de ambiente para o dyld antes que o processo seja executado. Isso pode ser muito perigoso, pois pode permitir a execução de código arbitrário dentro do processo, então este comando de carga é usado apenas em dyld construído com `#define SUPPORT_LC_DYLD_ENVIRONMENT` e restringe ainda mais o processamento apenas para variáveis da forma `DYLD_..._PATH` especificando caminhos de carga. +Permite indicar variáveis de ambiente para o dyld antes do processo ser executado. Isso pode ser muito perigoso, pois pode permitir executar código arbitrário dentro do processo, então esse load command é usado apenas em builds do dyld com `#define SUPPORT_LC_DYLD_ENVIRONMENT` e restringe o processamento apenas às variáveis da forma `DYLD_..._PATH` que especificam caminhos de carregamento. ### **`LC_LOAD_DYLIB`** -Este comando de carga descreve uma **dependência de biblioteca** **dinâmica** que **instrui** o **loader** (dyld) a **carregar e vincular a referida biblioteca**. Há um comando de carga `LC_LOAD_DYLIB` **para cada biblioteca** que o binário Mach-O requer. +This load command describes a **dynamic** **library** dependency which **instructs** the **loader** (dyld) to **load and link said library**. There is a `LC_LOAD_DYLIB` load command **for each library** that the Mach-O binary requires. -- Este comando de carga é uma estrutura do tipo **`dylib_command`** (que contém uma struct dylib, descrevendo a biblioteca dinâmica dependente real): +- This load command is a structure of type **`dylib_command`** (which contains a struct dylib, describing the actual dependent dynamic library): ```objectivec struct dylib_command { uint32_t cmd; /* LC_LOAD_{,WEAK_}DYLIB */ @@ -330,7 +335,7 @@ uint32_t compatibility_version; /* library's compatibility vers number*/ ``` ![](<../../../images/image (486).png>) -Você também pode obter essas informações pelo cli com: +Você também pode obter essa informação pelo cli com: ```bash otool -L /bin/ls /bin/ls: @@ -338,54 +343,54 @@ otool -L /bin/ls /usr/lib/libncurses.5.4.dylib (compatibility version 5.4.0, current version 5.4.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0) ``` -Algumas bibliotecas potenciais relacionadas a malware são: +Algumas bibliotecas potencialmente relacionadas a malware são: -- **DiskArbitration**: Monitoramento de drives USB +- **DiskArbitration**: Monitoramento de unidades USB - **AVFoundation:** Captura de áudio e vídeo -- **CoreWLAN**: Scans de Wifi. - -> [!NOTE] -> Um binário Mach-O pode conter um ou **mais** **construtores**, que serão **executados** **antes** do endereço especificado em **LC_MAIN**.\ -> Os offsets de quaisquer construtores são mantidos na seção **\_\_mod_init_func** do segmento **\_\_DATA_CONST**. - -## **Dados Mach-O** - -No núcleo do arquivo está a região de dados, que é composta por vários segmentos conforme definido na região de comandos de carregamento. **Uma variedade de seções de dados pode ser abrigada dentro de cada segmento**, com cada seção **mantendo código ou dados** específicos a um tipo. +- **CoreWLAN**: Varreduras Wifi. > [!TIP] -> Os dados são basicamente a parte que contém todas as **informações** que são carregadas pelos comandos de carregamento **LC_SEGMENTS_64** +> Um binário Mach-O pode conter um ou **mais** **constructors**, que serão **executados** **antes** do endereço especificado em **LC_MAIN**.\ +> Os offsets de quaisquer constructors são mantidos na seção **\_\_mod_init_func** do segmento **\_\_DATA_CONST**. + +## **Mach-O Data** + +No núcleo do arquivo encontra-se a região de dados, que é composta por vários segmentos conforme definidos na região de load-commands. **Uma variedade de seções de dados pode ser alojada em cada segmento**, com cada seção **contendo código ou dados** específicos a um tipo. + +> [!TIP] +> Os dados são basicamente a parte que contém todas as **informações** que são carregadas pelos load commands **LC_SEGMENTS_64** ![https://www.oreilly.com/api/v2/epubs/9781785883378/files/graphics/B05055_02_38.jpg](<../../../images/image (507) (3).png>) -Isso inclui: +Isto inclui: -- **Tabela de funções:** Que contém informações sobre as funções do programa. -- **Tabela de símbolos**: Que contém informações sobre a função externa usada pelo binário +- **Function table:** Que armazena informações sobre as funções do programa. +- **Symbol table**: Que contém informações sobre as funções externas usadas pelo binário - Também pode conter nomes de funções internas, variáveis e mais. -Para verificar, você pode usar a ferramenta [**Mach-O View**](https://sourceforge.net/projects/machoview/): +Para verificar isso você pode usar a ferramenta [**Mach-O View**](https://sourceforge.net/projects/machoview/):
-Ou a partir da cli: +Ou pelo cli: ```bash size -m /bin/ls ``` -## Seções Comuns do Objective-C +## Seções comuns do Objective-C No segmento `__TEXT` (r-x): - `__objc_classname`: Nomes de classes (strings) - `__objc_methname`: Nomes de métodos (strings) -- `__objc_methtype`: Tipos de métodos (strings) +- `__objc_methtype`: Tipos de método (strings) No segmento `__DATA` (rw-): - `__objc_classlist`: Ponteiros para todas as classes Objective-C -- `__objc_nlclslist`: Ponteiros para classes Objective-C Não-Lazy -- `__objc_catlist`: Ponteiro para Categorias -- `__objc_nlcatlist`: Ponteiro para Categorias Não-Lazy -- `__objc_protolist`: Lista de Protocolos +- `__objc_nlclslist`: Ponteiros para classes Objective-C Non-Lazy +- `__objc_catlist`: Ponteiro para Categories +- `__objc_nlcatlist`: Ponteiro para Categories Non-Lazy +- `__objc_protolist`: Lista de protocolos - `__objc_const`: Dados constantes - `__objc_imageinfo`, `__objc_selrefs`, `objc__protorefs`... diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md index e4db8d2df..3fc95ccf1 100644 --- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md +++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md @@ -1,15 +1,20 @@ -# macOS Code Signing +# Assinatura de Código do macOS {{#include ../../../banners/hacktricks-training.md}} ## Informações Básicas -Binaries Mach-o contêm um comando de carregamento chamado **`LC_CODE_SIGNATURE`** que indica o **offset** e **tamanho** das assinaturas dentro do binário. Na verdade, usando a ferramenta GUI MachOView, é possível encontrar no final do binário uma seção chamada **Code Signature** com essas informações: +{{#ref}} +../../../generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md +{{#endref}} + + +Binários Mach-O contêm um load command chamado **`LC_CODE_SIGNATURE`** que indica o **offset** e o **size** das assinaturas dentro do binário. Na prática, usando a ferramenta GUI MachOView, é possível encontrar no fim do binário uma seção chamada **Code Signature** com essa informação:
-O cabeçalho mágico da Code Signature é **`0xFADE0CC0`**. Então você tem informações como o comprimento e o número de blobs do superBlob que os contém.\ -É possível encontrar essas informações no [código-fonte aqui](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L276): +O magic header da Code Signature é **`0xFADE0CC0`**. Em seguida há informações como o comprimento e o número de blobs do superBlob que os contém.\ +É possível encontrar essa informação no [source code here](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L276): ```c /* * Structure of an embedded-signature SuperBlob @@ -38,14 +43,14 @@ char data[]; } CS_GenericBlob __attribute__ ((aligned(1))); ``` -Blobs comuns contidos são Diretório de Código, Requisitos e Direitos e uma Sintaxe de Mensagem Criptográfica (CMS).\ +Os blobs comuns contêm Code Directory, Requirements and Entitlements e uma Sintaxe de Mensagem Criptográfica (CMS).\ Além disso, note como os dados codificados nos blobs são codificados em **Big Endian.** Além disso, assinaturas podem ser destacadas dos binários e armazenadas em `/var/db/DetachedSignatures` (usado pelo iOS). -## Blob do Diretório de Código +## Code Directory Blob -É possível encontrar a declaração do [Blob do Diretório de Código no código](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L104): +É possível encontrar a declaração do [Code Directory Blob in the code](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L104): ```c typedef struct __CodeDirectory { uint32_t magic; /* magic number (CSMAGIC_CODEDIRECTORY) */ @@ -101,12 +106,12 @@ char end_withLinkage[0]; } CS_CodeDirectory __attribute__ ((aligned(1))); ``` -Note que existem diferentes versões desta estrutura onde as antigas podem conter menos informações. +Observe que existem diferentes versões desta struct onde as antigas podem conter menos informação. -## Páginas de Assinatura de Código +## Assinando Páginas de Código -Hashing o binário completo seria ineficiente e até inútil se ele for carregado na memória apenas parcialmente. Portanto, a assinatura do código é na verdade um hash de hashes onde cada página binária é hashada individualmente.\ -Na verdade, no código anterior do **Diretório de Código**, você pode ver que o **tamanho da página é especificado** em um de seus campos. Além disso, se o tamanho do binário não for um múltiplo do tamanho de uma página, o campo **CodeLimit** especifica onde está o final da assinatura. +Calcular o hash do binário completo seria ineficiente e até inútil se ele for carregado em memória apenas parcialmente. Portanto, a assinatura de código é, na verdade, um hash de hashes onde cada página do binário é hasheada individualmente.\ +Na verdade, no código anterior do **Code Directory** você pode ver que o **tamanho da página é especificado** em um de seus campos. Além disso, se o tamanho do binário não for múltiplo do tamanho de uma página, o campo **CodeLimit** especifica onde termina a assinatura. ```bash # Get all hashes of /bin/ps codesign -d -vvvvvv /bin/ps @@ -144,25 +149,25 @@ openssl sha256 /tmp/*.page.* ``` ## Entitlements Blob -Note que as aplicações também podem conter um **entitlement blob** onde todos os direitos são definidos. Além disso, alguns binários do iOS podem ter seus direitos específicos no slot especial -7 (em vez de no slot especial -5). +Note que aplicações podem também conter um **entitlement blob** onde todos os entitlements são definidos. Além disso, alguns binários iOS podem ter seus entitlements específicos no special slot -7 (em vez do special slot -5 de entitlements). ## Special Slots -As aplicações do MacOS não têm tudo o que precisam para executar dentro do binário, mas também usam **recursos externos** (geralmente dentro do **bundle** das aplicações). Portanto, existem alguns slots dentro do binário que conterão os hashes de alguns recursos externos interessantes para verificar se não foram modificados. +Aplicações macOS não têm tudo o que precisam para executar dentro do binário; elas também usam **external resources** (normalmente dentro do **bundle** da aplicação). Portanto, existem alguns slots dentro do binário que conterão os hashes de alguns recursos externos interessantes para verificar se não foram modificados. -Na verdade, é possível ver nas estruturas do Code Directory um parâmetro chamado **`nSpecialSlots`** indicando o número dos slots especiais. Não existe um slot especial 0 e os mais comuns (de -1 a -6) são: +Na verdade, é possível ver nas structs do Code Directory um parâmetro chamado **`nSpecialSlots`** indicando o número de special slots. Não existe um special slot 0 e os mais comuns (de -1 a -6) são: -- Hash de `info.plist` (ou o que está dentro de `__TEXT.__info__plist`). -- Hash dos Requisitos -- Hash do Resource Directory (hash do arquivo `_CodeSignature/CodeResources` dentro do bundle). -- Específico da aplicação (não utilizado) -- Hash dos direitos -- Assinaturas de código DMG apenas -- Direitos DER +- Hash of `info.plist` (ou o que está dentro de `__TEXT.__info__plist`). +- Has of the Requirements +- Hash of the Resource Directory (hash do arquivo `_CodeSignature/CodeResources` dentro do bundle). +- Application specific (unused) +- Hash of the entitlements +- DMG code signatures only +- DER Entitlements ## Code Signing Flags -Cada processo tem um bitmask relacionado conhecido como `status`, que é iniciado pelo kernel e alguns deles podem ser substituídos pela **assinatura de código**. Essas flags que podem ser incluídas na assinatura de código são [definidas no código](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L36): +Cada processo tem associada uma bitmask conhecida como `status`, que é iniciada pelo kernel e alguns bits podem ser sobrescritos pela **code signature**. Essas flags que podem ser incluídas na code signing estão [definidas no código](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L36): ```c /* code signing attributes of a process */ #define CS_VALID 0x00000001 /* dynamically valid */ @@ -207,15 +212,15 @@ CS_RESTRICT | CS_ENFORCEMENT | CS_REQUIRE_LV | CS_RUNTIME | CS_LINKER_SIGNED) #define CS_ENTITLEMENT_FLAGS (CS_GET_TASK_ALLOW | CS_INSTALLER | CS_DATAVAULT_CONTROLLER | CS_NVRAM_UNRESTRICTED) ``` -Note que a função [**exec_mach_imgact**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_exec.c#L1420) também pode adicionar os flags `CS_EXEC_*` dinamicamente ao iniciar a execução. +Note que a função [**exec_mach_imgact**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_exec.c#L1420) também pode adicionar as flags `CS_EXEC_*` dinamicamente ao iniciar a execução. ## Requisitos de Assinatura de Código -Cada aplicativo armazena alguns **requisitos** que deve **satisfazer** para poder ser executado. Se os **requisitos do aplicativo não forem satisfeitos**, ele não será executado (pois provavelmente foi alterado). +Cada aplicação armazena alguns **requisitos** que deve **satisfazer** para poder ser executada. Se os **requisitos contidos na aplicação não forem satisfeitos**, ela não será executada (pois provavelmente foi alterada). -Os requisitos de um binário usam uma **gramática especial** que é um fluxo de **expressões** e são codificados como blobs usando `0xfade0c00` como o mágico cujo **hash é armazenado em um slot de código especial**. +Os requisitos de um binário usam uma **gramática especial**, que é um fluxo de **expressões**, e são codificados como blobs usando `0xfade0c00` como número mágico, cujo **hash é armazenado em um slot de código especial**. -Os requisitos de um binário podem ser vistos executando: +Os requisitos de um binário podem ser vistos ao executar: ```bash codesign -d -r- /bin/ls Executable=/bin/ls @@ -225,8 +230,8 @@ codesign -d -r- /Applications/Signal.app/ Executable=/Applications/Signal.app/Contents/MacOS/Signal designated => identifier "org.whispersystems.signal-desktop" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = U68MSDN6DR ``` -> [!NOTE] -> Observe como essas assinaturas podem verificar coisas como informações de certificação, TeamID, IDs, direitos e muitos outros dados. +> [!TIP] +> Observe como essas assinaturas podem verificar coisas como informações de certificação, TeamID, IDs, entitlements e muitos outros dados. Além disso, é possível gerar alguns requisitos compilados usando a ferramenta `csreq`: ```bash @@ -242,55 +247,55 @@ od -A x -t x1 /tmp/output.csreq ``` É possível acessar essas informações e criar ou modificar requisitos com algumas APIs do `Security.framework`, como: -#### **Verificando a Validade** +#### **Verificação de Validade** -- **`Sec[Static]CodeCheckValidity`**: Verifica a validade de SecCodeRef por Requisito. -- **`SecRequirementEvaluate`**: Valida o requisito no contexto do certificado. -- **`SecTaskValidateForRequirement`**: Valida um SecTask em execução contra o requisito `CFString`. +- **`Sec[Static]CodeCheckValidity`**: Verifica a validade de SecCodeRef por Requirement. +- **`SecRequirementEvaluate`**: Valida um requirement no contexto de certificados. +- **`SecTaskValidateForRequirement`**: Valida um SecTask em execução contra um requirement em `CFString`. -#### **Criando e Gerenciando Requisitos de Código** +#### **Criação e Gerenciamento de Requisitos de Código** -- **`SecRequirementCreateWithData`:** Cria um `SecRequirementRef` a partir de dados binários representando o requisito. -- **`SecRequirementCreateWithString`:** Cria um `SecRequirementRef` a partir de uma expressão de string do requisito. -- **`SecRequirementCopy[Data/String]`**: Recupera a representação de dados binários de um `SecRequirementRef`. -- **`SecRequirementCreateGroup`**: Cria um requisito para a associação de grupo de aplicativos. +- **`SecRequirementCreateWithData`:** Cria um `SecRequirementRef` a partir de dados binários que representam o requirement. +- **`SecRequirementCreateWithString`:** Cria um `SecRequirementRef` a partir de uma expressão string do requirement. +- **`SecRequirementCopy[Data/String]`**: Recupera a representação em dados binários de um `SecRequirementRef`. +- **`SecRequirementCreateGroup`**: Cria um requirement para membership de app-group. #### **Acessando Informações de Assinatura de Código** -- **`SecStaticCodeCreateWithPath`**: Inicializa um objeto `SecStaticCodeRef` a partir de um caminho do sistema de arquivos para inspecionar assinaturas de código. +- **`SecStaticCodeCreateWithPath`**: Inicializa um objeto `SecStaticCodeRef` a partir de um caminho no sistema de arquivos para inspecionar assinaturas de código. - **`SecCodeCopySigningInformation`**: Obtém informações de assinatura de um `SecCodeRef` ou `SecStaticCodeRef`. #### **Modificando Requisitos de Código** -- **`SecCodeSignerCreate`**: Cria um objeto `SecCodeSignerRef` para realizar operações de assinatura de código. -- **`SecCodeSignerSetRequirement`**: Define um novo requisito para o signatário de código aplicar durante a assinatura. -- **`SecCodeSignerAddSignature`**: Adiciona uma assinatura ao código que está sendo assinado com o signatário especificado. +- **`SecCodeSignerCreate`**: Cria um objeto `SecCodeSignerRef` para realizar operações de code signing. +- **`SecCodeSignerSetRequirement`**: Define um novo requirement para o signer aplicar durante o signing. +- **`SecCodeSignerAddSignature`**: Adiciona uma assinatura ao código sendo assinado com o signer especificado. #### **Validando Código com Requisitos** - **`SecStaticCodeCheckValidity`**: Valida um objeto de código estático contra requisitos especificados. -#### **APIs Úteis Adicionais** +#### **APIs Adicionais Úteis** -- **`SecCodeCopy[Internal/Designated]Requirement`: Obter SecRequirementRef de SecCodeRef** -- **`SecCodeCopyGuestWithAttributes`**: Cria um `SecCodeRef` representando um objeto de código com base em atributos específicos, útil para sandboxing. -- **`SecCodeCopyPath`**: Recupera o caminho do sistema de arquivos associado a um `SecCodeRef`. -- **`SecCodeCopySigningIdentifier`**: Obtém o identificador de assinatura (por exemplo, Team ID) de um `SecCodeRef`. -- **`SecCodeGetTypeID`**: Retorna o identificador de tipo para objetos `SecCodeRef`. +- **`SecCodeCopy[Internal/Designated]Requirement`: Get SecRequirementRef from SecCodeRef** +- **`SecCodeCopyGuestWithAttributes`**: Cria um `SecCodeRef` representando um objeto de código baseado em atributos específicos, útil para sandboxing. +- **`SecCodeCopyPath`**: Recupera o caminho no sistema de arquivos associado a um `SecCodeRef`. +- **`SecCodeCopySigningIdentifier`**: Obtém o signing identifier (ex.: Team ID) de um `SecCodeRef`. +- **`SecCodeGetTypeID`**: Retorna o type identifier para objetos `SecCodeRef`. - **`SecRequirementGetTypeID`**: Obtém um CFTypeID de um `SecRequirementRef`. #### **Flags e Constantes de Assinatura de Código** - **`kSecCSDefaultFlags`**: Flags padrão usadas em muitas funções do Security.framework para operações de assinatura de código. -- **`kSecCSSigningInformation`**: Flag usada para especificar que as informações de assinatura devem ser recuperadas. +- **`kSecCSSigningInformation`**: Flag usada para especificar que informações de signing devem ser recuperadas. -## Aplicação de Assinatura de Código +## Aplicação da Assinatura de Código -O **kernel** é quem **verifica a assinatura do código** antes de permitir que o código do aplicativo seja executado. Além disso, uma maneira de conseguir escrever e executar novo código na memória é abusar do JIT se `mprotect` for chamado com a flag `MAP_JIT`. Note que a aplicação precisa de um direito especial para poder fazer isso. +O **kernel** é quem **verifica a assinatura de código** antes de permitir que o código do app seja executado. Além disso, uma forma de conseguir escrever e executar novo código em memória é abusar do JIT se `mprotect` for chamado com a flag `MAP_JIT`. Note que a aplicação precisa de um entitlement especial para poder fazer isso. ## `cs_blobs` & `cs_blob` -[**cs_blob**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/ubc_internal.h#L106) a struct contém as informações sobre o direito do processo em execução sobre ele. `csb_platform_binary` também informa se a aplicação é um binário de plataforma (o que é verificado em diferentes momentos pelo OS para aplicar mecanismos de segurança, como proteger os direitos de SEND para as portas de tarefa desses processos). +[**cs_blob**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/ubc_internal.h#L106) struct contém as informações sobre o entitlement do processo em execução armazenadas nele. `csb_platform_binary` também indica se a aplicação é um binário de plataforma (o que é verificado em diferentes momentos pelo OS para aplicar mecanismos de segurança, como proteger os SEND rights aos task ports desses processos). ```c struct cs_blob { struct cs_blob *csb_next;