
Mergulho educacional aprofundado em app bundles do macOS, arquivos plist e comportamento do processo launchd, com notas de segurança ofensiva sobre empacotar payloads como arquivos .app e evadir o monitoramento da árvore de processos.
Fazer a transição do Linux ou Windows para o macOS pode parecer andar por uma terra estranha e desconhecida. Como o Linux é open-source e o Windows é bem documentado e muito popular (e o macOS não é exatamente nenhum dos dois), o macOS pode ser desafiador às vezes. Neste post, pretendo discutir algumas das primeiras coisas que você pode notar no macOS - Apps, Apps em todos os lugares!
Para quem vem de um ambiente Windows ou Linux, o conceito de Apps pode parecer estranho. Todos sabemos que threads são "unidades de execução" e que processos são contêineres para threads com seu próprio espaço de endereçamento -- o que há mais além disso? Bem, processos raramente são distribuídos em arquivos únicos. Tanto no Windows quanto no Linux, há muitas coisas das quais o código pode precisar para funcionar. Algumas delas são:
.dll, .so). Por exemplo, a biblioteca de runtime C (msvcr<version>.dll no Windows, libc-<version>.so) e outras dependências.PE, que possui diretórios - um deles é o diretório de recursos (até certo ponto documentado aqui) que pode conter recursos (imagens, strings e outros). Recursos também podem ser carregados do disco dinamicamente, é claro.PE (leia aqui) ou em arquivos de catálogo (ou seja, externamente).xml, ini, json) e o Registro do Windows.Bem, o macOS dá grande ênfase a Application Bundles. A ideia é empacotar (quase) tudo o que é necessário para o programa rodar em uma estrutura de diretórios - incluindo recursos, informações de localização, etc. Claro, nem tudo pode ser empacotado de forma organizada (como a biblioteca de runtime C, por exemplo) - mas ainda assim significa que as coisas ficam empacotadas de forma organizada - sem necessidade de navegar em um Registro enorme ou ler páginas de manual para localizações obscuras de arquivos de configuração. Application bundles são apenas diretórios que terminam com .app - embora a interface oculte a extensão .app (e o fato de ser um diretório).
Da perspectiva de um atacante, isso é interessante - já que um Application Bundle pode ter ícones arbitrários e esconde a extensão .app - a entrega de malware pode ser alcançada enganando um usuário desprevenido para clicar em tal app. Por exemplo, pense em um arquivo Resume.app com um ícone de PDF.
A estrutura de diretórios de um Application Bundle pode ser facilmente examinada, obviamente pela App Calculator embutida:
jbo@McJbo ~ % cd /System/Applications/Calculator.app
jbo@McJbo Calculator.app % ll
total 0
drwxr-xr-x 3 root wheel 96 Mar 17 21:34 .
drwxr-xr-x 43 root wheel 1376 Mar 17 21:34 ..
drwxr-xr-x 9 root wheel 288 Mar 17 21:34 Contents
jbo@McJbo Calculator.app % cd Contents
jbo@McJbo Contents % ll
total 16
drwxr-xr-x 9 root wheel 288 Mar 17 21:34 .
drwxr-xr-x 3 root wheel 96 Mar 17 21:34 ..
-rw-r--r-- 1 root wheel 2147 Mar 17 21:34 Info.plist
drwxr-xr-x 3 root wheel 96 Mar 17 21:34 MacOS
-rw-r--r-- 204 root wheel 8 Mar 17 21:34 PkgInfo
drwxr-xr-x 4 root wheel 128 Mar 17 21:34 PlugIns
drwxr-xr-x 54 root wheel 1728 Mar 17 21:34 Resources
drwxr-xr-x 3 root wheel 96 Mar 17 21:34 _CodeSignature
-rw-r--r-- 1 root wheel 461 Mar 17 21:34 version.plist
jbo@McJbo Contents % cd MacOS
jbo@McJbo MacOS % ll
total 344
drwxr-xr-x 3 root wheel 96 Mar 17 21:34 .
drwxr-xr-x 9 root wheel 288 Mar 17 21:34 ..
-rwxr-xr-x 1 root wheel 540912 Mar 17 21:34 Calculator
jbo@McJbo MacOS %
Como você pode ver, Calculator.app é um diretório. Dentro dele há um único item - outro diretório chamado Contents.
Dentro de Contents há vários itens:
Info.plist - contém metadados sobre a App. Mais sobre isso depois.MacOS - contém o executável principal da App (como pode ser visto na terceira listagem de diretórios).PkgInfo - não obrigatório. Um arquivo binário que contém informações do pacote.PlugIns - não obrigatório. Um diretório que pode conter plugins para a App. A Calculator tem dois - um para "Basic and Scientific" e outro para "Hexadecimal" (eu realmente não sei por que fizeram essa separação, nem me importo).Resources - não obrigatório. Como o nome sugere, contém recursos. Você pode encontrar vários itens lá, incluindo um arquivo .icns com ícones, bem como diretórios com o sufixo .lprroj relacionados à localização._CodeSignature - não obrigatório. Como o nome sugere - contém informações de assinatura de código.version.plist - não obrigatório, contém informações de versão.Observe que são muito poucos os itens oficialmente necessários. Na verdade, podemos criar nossa primeira App sem nem compilar nada!
Mas primeiro precisamos discutir o arquivo Info.plist.
Quanto mais você olha para o macOS, mais encontra esses arquivos estranhos. Eles nada mais são do que arquivos de configuração glorificados.
Eles sempre terão a extensão .plist, que é apenas uma forma abreviada de se referir ao seu nome formal: arquivos Property list.
Infelizmente, existem 3 formatos plist diferentes mantidos pela Apple:
xml, legível por humanos.json, não muito usado.bplist como magic number.Felizmente, existe um utilitário chamado plutil que suporta todos os formatos. Para exibir um arquivo plist, basta usar plutil -p. Por exemplo:
jbo@McJbo Contents % plutil -p Info.plist | head -n 20
{
"BuildMachineOSBuild" => "22A380007"
"CFBundleDevelopmentRegion" => "English"
"CFBundleExecutable" => "Calculator"
"CFBundleGetInfoString" => "10.14, Copyright © 2000-2018, Apple Inc."
"CFBundleHelpBookFolder" => "Calculator.help"
"CFBundleHelpBookName" => "com.apple.Calculator.help"
"CFBundleIconFile" => "AppIcon"
"CFBundleIconName" => "AppIcon"
"CFBundleIdentifier" => "com.apple.calculator"
"CFBundleInfoDictionaryVersion" => "6.0"
"CFBundleName" => "Calculator"
"CFBundlePackageType" => "APPL"
"CFBundleShortVersionString" => "10.16"
"CFBundleSignature" => "????"
"CFBundleSupportedPlatforms" => [
0 => "MacOSX"
]
"CFBundleVersion" => "223"
"CTIgnoreUserFonts" => 1
jbo@McJbo Contents %
Há também funcionalidades de conversão embutidas no plutil - não vamos demonstrá-las agora.
A Apple documenta vários requisitos no Info.plist de uma App, mas são muito poucos os campos realmente obrigatórios. Aqui estão alguns campos interessantes:
CFBundleExecutable - o nome do executável principal, esperado no diretório MacOS.CFBundleIconFile - o nome do arquivo de ícone. Não obrigatório.CFBundleIdentifier - um identificador para o App Bundle. A Apple recomenda usar a notação DNS reversa (ex.: com.apple.calculator).CFBundleName - o nome do bundle.Com isso em mente, podemos criar nossa primeira app incrível, sem nem programar! Dê uma olhada: