34 KiB
Applications macOS - Inspection, débogage et fuzzing
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- Travaillez-vous dans une entreprise de cybersécurité ? Voulez-vous voir votre entreprise annoncée dans HackTricks ? ou voulez-vous avoir accès à la dernière version de PEASS ou télécharger HackTricks en PDF ? Consultez les PLANS D'ABONNEMENT !
- Découvrez The PEASS Family, notre collection exclusive de NFTs
- Obtenez le swag officiel PEASS & HackTricks
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez moi sur Twitter 🐦@carlospolopm.
- Partagez vos astuces de piratage en soumettant des PR au repo hacktricks et au repo hacktricks-cloud.
Analyse statique
otool
otool -L /bin/ls #List dynamically linked libraries
otool -tv /bin/ps #Decompile application
objdump
Description
objdump
is a command-line utility that allows you to inspect the contents of an executable file. It can display information about the file's sections, symbols, and relocations. It can also disassemble the file's machine code into assembly language.
Usage
$ objdump -h <executable>
$ objdump -d <executable>
Example
$ objdump -h /Applications/Calculator.app/Contents/MacOS/Calculator
/Applications/Calculator.app/Contents/MacOS/Calculator: file format Mach-O 64-bit x86-64
Sections:
Idx Name Size Address Type
0 __text 0000d000 0000000100001000 TEXT
1 __stubs 00000080 000000010000e000 TEXT
2 __stub_helper 00000030 000000010000e080 TEXT
3 __cstring 00000a1c 000000010000e0b0 DATA
4 __unwind_info 000002d8 000000010000f0cc DATA
5 __DATA 00000020 0000000100010000 DATA
6 __got 00000008 0000000100010020 DATA
7 __la_symbol_p 00000008 0000000100010028 DATA
8 __mod_init_f 00000008 0000000100010030 DATA
9 __mod_term_f 00000008 0000000100010038 DATA
10 __const 00000008 0000000100010040 DATA
11 __bss 00000008 0000000100010048 BSS
$ objdump -d /Applications/Calculator.app/Contents/MacOS/Calculator
/Applications/Calculator.app/Contents/MacOS/Calculator: file format Mach-O 64-bit x86-64
Disassembly of section __text:
0000000100001000 <_start>:
100001000: 55 push %rbp
100001001: 48 89 e5 mov %rsp,%rbp
100001004: 48 83 ec 10 sub $0x10,%rsp
100001008: 48 8d 05 8d 00 00 00 lea 0x8d(%rip),%rax # 10000109c <_dyld_private>
10000100f: 48 89 45 f8 mov %rax,-0x8(%rbp)
100001013: 48 8b 05 7e 00 00 00 mov 0x7e(%rip),%rax # 100001096 <_dyld_func_lookup>
10000101a: 48 8d 55 f8 lea -0x8(%rbp),%rdx
10000101e: 48 89 d6 mov %rdx,%rsi
100001021: ff d0 callq *%rax
100001023: 48 8d 05 6d 00 00 00 lea 0x6d(%rip),%rax # 100001096 <_dyld_func_lookup>
10000102a: 48 8d 55 f8 lea -0x8(%rbp),%rdx
10000102e: 48 89 d6 mov %rdx,%rsi
100001031: ff d0 callq *%rax
100001033: 48 8d 05 5b 00 00 00 lea 0x5b(%rip),%rax # 100001094 <_dyld_register_func_for_remove_image>
10000103a: 48 8d 55 f8 lea -0x8(%rbp),%rdx
10000103e: 48 89 d6 mov %rdx,%rsi
100001041: ff d0 callq *%rax
100001043: 48 8d 05 49 00 00 00 lea 0x49(%rip),%rax # 100001093 <_dyld_register_func_for_add_image>
10000104a: 48 8d 55 f8 lea -0x8(%rbp),%rdx
10000104e: 48 89 d6 mov %rdx,%rsi
100001051: ff d0 callq *%rax
100001053: 48 8d 05 37 00 00 00 lea 0x37(%rip),%rax # 100001091 <_dyld_image_count>
10000105a: 48 8d 55 f8 lea -0x8(%rbp),%rdx
10000105e: 48 89 d6 mov %rdx,%rsi
100001061: ff d0 callq *%rax
100001063: 48 8d 05 25 00 00 00 lea 0x25(%rip),%rax # 10000108f <_dyld_get_image_name>
10000106a: 48 8d 55 f8 lea -0x8(%rbp),%rdx
10000106e: 48 89 d6 mov %rdx,%rsi
100001071: ff d0 callq *%rax
100001073: 48 8d 05 13 00 00 00 lea 0x13(%rip),%rax # 100001087 <_dyld_get_image_header>
10000107a: 48 8d 55 f8 lea -0x8(%rbp),%rdx
10000107e: 48 89 d6 mov %rdx,%rsi
100001081: ff d0 callq *%rax
100001083: 31 c0 xor %eax,%eax
100001085: c9 leaveq
100001086: c3 retq
100001087: 55 push %rbp
100001088: 48 89 e5 mov %rsp,%rbp
10000108b: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 100001092 <_dyld_image_header_containing_address>
100001092: c9 leaveq
100001093: c3 retq
100001094: 55 push %rbp
100001095: c9 leaveq
100001096: c3 retq
100001097: 55 push %rbp
100001098: c9 leaveq
100001099: c3 retq
10000109a: 55 push %rbp
10000109b: c9 leaveq
10000109c: 2f 75 73 72 2f 62 69 6e 2f 65 6e 76 20 20 20 20 /usr/bin/env
1000010ac: 2d 73 68 0a -sh.
Remarks
objdump
is a powerful tool for inspecting the contents of an executable file. It can be used to analyze the file's structure and to disassemble its machine code. This can be useful for reverse engineering and vulnerability research. However, it should be used with caution, as it can also be used by attackers to analyze and exploit vulnerabilities in a target application.
objdump -m --dylibs-used /bin/ls #List dynamically linked libraries
objdump -m -h /bin/ls # Get headers information
objdump -m --syms /bin/ls # Check if the symbol table exists to get function names
objdump -m --full-contents /bin/ls # Dump every section
objdump -d /bin/ls # Dissasemble the binary
jtool2
L'outil peut être utilisé en remplacement de codesign, otool et objdump, et offre quelques fonctionnalités supplémentaires.
# Install
brew install --cask jtool2
jtool2 -l /bin/ls # Get commands (headers)
jtool2 -L /bin/ls # Get libraries
jtool2 -S /bin/ls # Get symbol info
jtool2 -d /bin/ls # Dump binary
jtool2 -D /bin/ls # Decompile binary
# Get signature information
ARCH=x86_64 jtool2 --sig /System/Applications/Automator.app/Contents/MacOS/Automator
Codesign
Codesign est un outil de ligne de commande fourni avec Xcode qui permet de signer numériquement les fichiers exécutables et les bibliothèques partagées. La signature numérique permet de garantir l'authenticité et l'intégrité du fichier signé. Les développeurs peuvent utiliser codesign pour signer leurs applications macOS avant de les distribuer aux utilisateurs finaux. Les administrateurs système peuvent également utiliser codesign pour vérifier l'authenticité des applications installées sur un système macOS.
# Get signer
codesign -vv -d /bin/ls 2>&1 | grep -E "Authority|TeamIdentifier"
# Check if the app’s contents have been modified
codesign --verify --verbose /Applications/Safari.app
# Get entitlements from the binary
codesign -d --entitlements :- /System/Applications/Automator.app # Check the TCC perms
# Check if the signature is valid
spctl --assess --verbose /Applications/Safari.app
# Sign a binary
codesign -s <cert-name-keychain> toolsdemo
SuspiciousPackage
SuspiciousPackage est un outil utile pour inspecter les fichiers .pkg (installateurs) et voir ce qu'il y a à l'intérieur avant de l'installer.
Ces installateurs ont des scripts bash preinstall
et postinstall
que les auteurs de logiciels malveillants utilisent généralement pour persister le logiciel malveillant.
hdiutil
Cet outil permet de monter les images disque Apple (.dmg) pour les inspecter avant d'exécuter quoi que ce soit :
hdiutil attach ~/Downloads/Firefox\ 58.0.2.dmg
Il sera monté dans /Volumes
Objective-C
Lorsqu'une fonction est appelée dans un binaire qui utilise Objective-C, le code compilé, au lieu d'appeler cette fonction, appellera objc_msgSend
. Qui appellera la fonction finale :
Les paramètres que cette fonction attend sont :
- Le premier paramètre (self) est "un pointeur qui pointe vers l'instance de la classe qui doit recevoir le message". Ou plus simplement, c'est l'objet sur lequel la méthode est invoquée. Si la méthode est une méthode de classe, il s'agira d'une instance de l'objet de classe (dans son ensemble), tandis que pour une méthode d'instance, self pointera vers une instance instanciée de la classe en tant qu'objet.
- Le deuxième paramètre, (op), est "le sélecteur de la méthode qui gère le message". Encore une fois, plus simplement, il s'agit simplement du nom de la méthode.
- Les paramètres restants sont toutes les valeurs requises par la méthode (op).
Argument | Registre | (pour) objc_msgSend |
---|---|---|
1er argument | rdi | self : objet sur lequel la méthode est invoquée |
2ème argument | rsi | op : nom de la méthode |
3ème argument | rdx | 1er argument de la méthode |
4ème argument | rcx | 2ème argument de la méthode |
5ème argument | r8 | 3ème argument de la méthode |
6ème argument | r9 | 4ème argument de la méthode |
7ème+ argument | rsp+ |
5ème+ argument de la méthode |
Binaires compressés
- Vérifier l'entropie élevée
- Vérifier les chaînes (s'il n'y a presque aucune chaîne compréhensible, compressée)
- Le packer UPX pour MacOS génère une section appelée "__XHDR"
Analyse dynamique
{% hint style="warning" %}
Notez que pour déboguer des binaires, SIP doit être désactivé (csrutil disable
ou csrutil enable --without debug
) ou pour copier les binaires dans un dossier temporaire et supprimer la signature avec codesign --remove-signature <chemin-du-binaire>
ou autoriser le débogage du binaire (vous pouvez utiliser ce script)
{% endhint %}
{% hint style="warning" %}
Notez que pour instrumenter les binaires système (tels que cloudconfigurationd
) sur macOS, SIP doit être désactivé (la simple suppression de la signature ne fonctionnera pas).
{% endhint %}
Hopper
Panneau de gauche
Dans le panneau de gauche de Hopper, il est possible de voir les symboles (Labels) du binaire, la liste des procédures et fonctions (Proc) et les chaînes (Str). Ce ne sont pas toutes les chaînes, mais celles définies dans plusieurs parties du fichier Mac-O (comme cstring ou objc_methname
).
Panneau central
Dans le panneau central, vous pouvez voir le code désassemblé. Et vous pouvez le voir sous forme de désassemblage brut, sous forme de graphique, sous forme de décompilé et sous forme binaire en cliquant sur l'icône respective :
En cliquant avec le bouton droit de la souris sur un objet de code, vous pouvez voir les références à/depuis cet objet ou même changer son nom (cela ne fonctionne pas dans le pseudocode décompilé) :
De plus, dans le milieu en bas, vous pouvez écrire des commandes python.
Panneau de droite
Dans le panneau de droite, vous pouvez voir des informations intéressantes telles que l'historique de navigation (pour savoir comment vous êtes arrivé à la situation actuelle), le graphique d'appel où vous pouvez voir toutes les fonctions qui appellent cette fonction et toutes les fonctions que cette fonction appelle, et les informations sur les variables locales.
dtruss -c ls #Get syscalls of ls
dtruss -c -p 1000 #get syscalls of PID 1000
ktrace
Vous pouvez utiliser celui-ci même avec SIP activé.
ktrace trace -s -S -t c -c ls | grep "ls("
dtrace
Il permet aux utilisateurs d'accéder aux applications à un niveau extrêmement bas et fournit un moyen aux utilisateurs de tracer les programmes et même de changer leur flux d'exécution. Dtrace utilise des sondes qui sont placées dans tout le noyau et se trouvent à des emplacements tels que le début et la fin des appels système.
DTrace utilise la fonction dtrace_probe_create
pour créer une sonde pour chaque appel système. Ces sondes peuvent être déclenchées au point d'entrée et de sortie de chaque appel système. L'interaction avec DTrace se fait via /dev/dtrace qui n'est disponible que pour l'utilisateur root.
Les sondes disponibles de dtrace peuvent être obtenues avec:
dtrace -l | head
ID PROVIDER MODULE FUNCTION NAME
1 dtrace BEGIN
2 dtrace END
3 dtrace ERROR
43 profile profile-97
44 profile profile-199
Le nom de la sonde se compose de quatre parties : le fournisseur, le module, la fonction et le nom (fbt:mach_kernel:ptrace:entry
). Si vous ne spécifiez pas une partie du nom, Dtrace l'appliquera comme un joker.
Pour configurer DTrace afin d'activer les sondes et de spécifier les actions à effectuer lorsqu'elles se déclenchent, nous devrons utiliser le langage D.
Une explication plus détaillée et plus d'exemples peuvent être trouvés dans https://illumos.org/books/dtrace/chp-intro.html
Exemples
Exécutez man -k dtrace
pour lister les scripts DTrace disponibles. Exemple : sudo dtruss -n binary
- En ligne
#Count the number of syscalls of each running process
sudo dtrace -n 'syscall:::entry {@[execname] = count()}'
- script
syscall:::entry
/pid == $1/
{
}
#Log every syscall of a PID
sudo dtrace -s script.d 1234
syscall::open:entry
{
printf("%s(%s)", probefunc, copyinstr(arg0));
}
syscall::close:entry
{
printf("%s(%d)\n", probefunc, arg0);
}
#Log files opened and closed by a process
sudo dtrace -s b.d -c "cat /etc/hosts"
syscall:::entry
{
;
}
syscall:::return
{
printf("=%d\n", arg1);
}
#Log sys calls with values
sudo dtrace -s syscalls_info.d -c "cat /etc/hosts"
ProcessMonitor
ProcessMonitor est un outil très utile pour vérifier les actions liées aux processus qu'un processus effectue (par exemple, surveiller les nouveaux processus qu'un processus crée).
FileMonitor
FileMonitor permet de surveiller les événements de fichiers (tels que la création, la modification et la suppression) en fournissant des informations détaillées sur ces événements.
fs_usage
Permet de suivre les actions effectuées par les processus :
fs_usage -w -f filesys ls #This tracks filesystem actions of proccess names containing ls
fs_usage -w -f network curl #This tracks network actions
TaskExplorer
Taskexplorer est utile pour voir les bibliothèques utilisées par un binaire, les fichiers qu'il utilise et les connexions réseau.
Il vérifie également les processus binaires avec virustotal et affiche des informations sur le binaire.
lldb
lldb est l'outil de débogage binaire de macOS de facto.
lldb ./malware.bin
lldb -p 1122
lldb -n malware.bin
lldb -n malware.bin --waitfor
Commande (lldb) | Description |
---|---|
run (r) | Démarre l'exécution, qui se poursuivra sans interruption jusqu'à ce qu'un point d'arrêt soit atteint ou que le processus se termine. |
continue (c) | Continue l'exécution du processus en cours de débogage. |
nexti (n / ni) | Exécute l'instruction suivante. Cette commande sautera les appels de fonction. |
stepi (s / si) | Exécute l'instruction suivante. Contrairement à la commande nexti, cette commande entrera dans les appels de fonction. |
finish (f) | Exécute le reste des instructions dans la fonction ("frame") actuelle, retourne et s'arrête. |
control + c | Interrompt l'exécution. Si le processus a été exécuté (r) ou continué (c), cela provoquera l'arrêt du processus ... où qu'il soit en train d'être exécuté. |
breakpoint (b) | b main b -[NSDictionary objectForKey:] b 0x0000000100004bd9 br l #Liste des points d'arrêt br e/dis <num> #Activer/Désactiver le point d'arrêt breakpoint delete <num> |
help | help breakpoint #Obtenir de l'aide sur la commande breakpoint help memory write #Obtenir de l'aide pour écrire dans la mémoire |
reg | reg read reg read $rax reg write $rip 0x100035cc0 |
x/s <reg/memory address> | Affiche la mémoire sous forme de chaîne terminée par un caractère nul. |
x/i <reg/memory address> | Affiche la mémoire sous forme d'instruction d'assemblage. |
x/b <reg/memory address> | Affiche la mémoire sous forme de byte. |
print object (po) | Cela affichera l'objet référencé par le paramètre po $raw
Notez que la plupart des API ou méthodes Objective-C d'Apple renvoient des objets et doivent donc être affichées via la commande "print object" (po). Si po ne produit pas de sortie significative, utilisez |
memory | memory read 0x000.... |
disassembly | dis #Désassemble la fonction actuelle |
parray | parray 3 (char **)$x1 # Vérifiez le tableau de 3 composants dans le registre x1 |
{% hint style="info" %}
Lors de l'appel de la fonction objc_sendMsg
, le registre rsi contient le nom de la méthode sous forme de chaîne terminée par un caractère nul ("C"). Pour afficher le nom via lldb, faites :
(lldb) x/s $rsi: 0x1000f1576: "startMiningWithPort:password:coreCount:slowMemory:currency:"
(lldb) print (char*)$rsi:
(char *) $1 = 0x00000001000f1576 "startMiningWithPort:password:coreCount:slowMemory:currency:"
(lldb) reg read $rsi: rsi = 0x00000001000f1576 "startMiningWithPort:password:coreCount:slowMemory:currency:"
{% endhint %}
Anti-Analyse Dynamique
Détection de la VM
- La commande
sysctl hw.model
renvoie "Mac" lorsque l'hôte est un MacOS, mais quelque chose de différent lorsqu'il s'agit d'une VM. - En jouant avec les valeurs de
hw.logicalcpu
ethw.physicalcpu
, certains malwares essaient de détecter s'il s'agit d'une VM. - Certains malwares peuvent également détecter si la machine est basée sur VMware en fonction de l'adresse MAC (00:50:56).
- Il est également possible de savoir si un processus est en cours de débogage avec un code simple tel que :
if(P_TRACED == (info.kp_proc.p_flag & P_TRACED)){ //processus en cours de débogage }
- Il peut également invoquer l'appel système
ptrace
avec le drapeauPT_DENY_ATTACH
. Cela empêche un débogueur de s'attacher et de tracer.- Vous pouvez vérifier si la fonction
sysctl
ouptrace
est importée (mais le malware pourrait l'importer dynamiquement) - Comme indiqué dans cet article, "Defeating Anti-Debug Techniques: macOS ptrace variants":
"Le message Process # exited with status = 45 (0x0000002d) est généralement un signe révélateur que la cible de débogage utilise PT_DENY_ATTACH"
- Vous pouvez vérifier si la fonction
Fuzzing
ReportCrash
ReportCrash analyse les processus en cours de plantage et enregistre un rapport de plantage sur le disque. Un rapport de plantage contient des informations qui peuvent aider un développeur à diagnostiquer la cause d'un plantage.
Pour les applications et autres processus exécutés dans le contexte de lancement par utilisateur, ReportCrash s'exécute en tant que LaunchAgent et enregistre les rapports de plantage dans ~/Library/Logs/DiagnosticReports/
de l'utilisateur.
Pour les démons, les autres processus exécutés dans le contexte de lancement système et les autres processus privilégiés, ReportCrash s'exécute en tant que LaunchDaemon et enregistre les rapports de plantage dans /Library/Logs/DiagnosticReports
du système.
Si vous êtes préoccupé par le fait que les rapports de plantage soient envoyés à Apple, vous pouvez les désactiver. Sinon, les rapports de plantage peuvent être utiles pour déterminer comment un serveur a planté.
#To disable crash reporting:
launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist
#To re-enable crash reporting:
launchctl load -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist
Sommeil
Lors du fuzzing sur un MacOS, il est important de ne pas permettre au Mac de dormir :
- systemsetup -setsleep Never
- pmset, Préférences Système
- KeepingYouAwake
Déconnexion SSH
Si vous faites du fuzzing via une connexion SSH, il est important de s'assurer que la session ne va pas se terminer. Pour cela, modifiez le fichier sshd_config avec :
- TCPKeepAlive Yes
- ClientAliveInterval 0
- ClientAliveCountMax 0
sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist
Gestionnaires internes
Consultez la page suivante pour savoir comment trouver quelle application est responsable de la gestion du schéma ou du protocole spécifié :
{% content-ref url="../macos-file-extension-apps.md" %} macos-file-extension-apps.md {% endcontent-ref %}
Énumération des processus réseau
Il est intéressant de trouver les processus qui gèrent les données réseau :
dtrace -n 'syscall::recv*:entry { printf("-> %s (pid=%d)", execname, pid); }' >> recv.log
#wait some time
sort -u recv.log > procs.txt
cat procs.txt
Ou utilisez netstat
ou lsof
Fuzzers
AFL++
Fonctionne pour les outils CLI
Litefuzz
Il fonctionne "juste" avec les outils GUI de macOS. Notez que certaines applications macOS ont des exigences spécifiques telles que des noms de fichiers uniques, la bonne extension, la nécessité de lire les fichiers à partir du sandbox (~/Library/Containers/com.apple.Safari/Data
)...
Quelques exemples:
{% code overflow="wrap" %}
# iBooks
litefuzz -l -c "/System/Applications/Books.app/Contents/MacOS/Books FUZZ" -i files/epub -o crashes/ibooks -t /Users/test/Library/Containers/com.apple.iBooksX/Data/tmp -x 10 -n 100000 -ez
# -l : Local
# -c : cmdline with FUZZ word (if not stdin is used)
# -i : input directory or file
# -o : Dir to output crashes
# -t : Dir to output runtime fuzzing artifacts
# -x : Tmeout for the run (default is 1)
# -n : Num of fuzzing iterations (default is 1)
# -e : enable second round fuzzing where any crashes found are reused as inputs
# -z : enable malloc debug helpers
# Font Book
litefuzz -l -c "/System/Applications/Font Book.app/Contents/MacOS/Font Book FUZZ" -i input/fonts -o crashes/font-book -x 2 -n 500000 -ez
# smbutil (using pcap capture)
litefuzz -lk -c "smbutil view smb://localhost:4455" -a tcp://localhost:4455 -i input/mac-smb-resp -p -n 100000 -z
# screensharingd (using pcap capture)
litefuzz -s -a tcp://localhost:5900 -i input/screenshared-session --reportcrash screensharingd -p -n 100000
{% endcode %}
Plus d'informations sur le fuzzing MacOS
- https://www.youtube.com/watch?v=T5xfL9tEg44
- https://github.com/bnagy/slides/blob/master/OSXScale.pdf
- https://github.com/bnagy/francis/tree/master/exploitaben
- https://github.com/ant4g0nist/crashwrangler
Références
- OS X Incident Response: Scripting and Analysis
- https://www.youtube.com/watch?v=T5xfL9tEg44
- https://taomm.org/vol1/analysis.html
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- Travaillez-vous dans une entreprise de cybersécurité ? Voulez-vous voir votre entreprise annoncée dans HackTricks ? ou voulez-vous avoir accès à la dernière version de PEASS ou télécharger HackTricks en PDF ? Consultez les PLANS D'ABONNEMENT !
- Découvrez The PEASS Family, notre collection exclusive de NFT
- Obtenez le swag officiel PEASS & HackTricks
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez moi sur Twitter 🐦@carlospolopm.
- Partagez vos astuces de piratage en soumettant des PR au repo hacktricks et au repo hacktricks-cloud.