Aller au contenu

FCSC 2025 - iOS Forensic

·10 mins· loading · loading · ·
FCSC 2025 IOS Writeup
Sommaire

Scénario
#

Lors d’un passage de douane, le douanier vous demande de lui remettre votre tĂ©lĂ©phone ainsi que son code de dĂ©verrouillage. Le tĂ©lĂ©phone vous est rendu quelques heures plus tard 
 Suspicieux, vous envoyez votre tĂ©lĂ©phone pour analyse au CERT-FR de l’ANSSI. Les analystes du CERT-FR effectuent une collecte sur le tĂ©lĂ©phone, composĂ©e d’un sysdiagnose et d’un backup. Ces Ă©preuves font partie d’une sĂ©rie. Les Ă©preuves sont indĂ©pendantes sauf iBackdoor 2/2 qui dĂ©pend de iBackdoor 1/2 : iForensics - iCrash iForensics - iDevice iForensics - iWiFi iForensics - iTreasure iForensics - iNvisible iForensics - iBackdoor 1/2 iForensics - iBackdoor 2/2 iForensics - iC2 iForensics - iCompromise

On a donc une backup.tar.xz (logique) et des sysdiagnose & crashes !

Setup
#

Pour ces challenges nous allons utiliser :

  • DB Browser for SQLite
  • EC-DIGIT-CSIRC/sysdiagnose
  • iLEAPP
  • Autopsy

On peut aussi s’aider de cheatsheets telles que :

On pourrait aussi utiliser des tools et mĂ©thodologies plus “pro” (via Plaso etc.) mais dans le contexte du CTF (fait en retard) je n’ai pas pris le temps de le faire. đŸ€ 

Intro - iForensics - iCrash
#

Il semblerait qu’un flag se soit cachĂ© Ă  l’endroit oĂč sont stockĂ©s les crashes sur le tĂ©lĂ©phone 


Ici trĂšs simple. On sait que les crashs se trouvent dans l’archive sysdiagnose_and_crashes.tar.xz. On l’extrait donc :

tar -xf sysdiagnose_and_crashes.tar.xz 

Ici on peut trouver de plusieurs maniĂšres, un simple grep grep -r "FCSC{", se balader dans les logs de crash etc.

Si on se rend dans sysdiagnose_and_crashes/private/var/mobile/Library/Logs/CrashReporter/ on trouve le fichier fcsc_intro.txt avec le flag.

Flag : FCSC{7a1ca2d4f17d4e1aa8936f2e906f0be8}

⭐ - iForensics - iDevice
#

Pour commencer, trouvez quelques informations d’intĂ©rĂȘt sur le tĂ©lĂ©phone : version d’iOS et identifiant du modĂšle de tĂ©lĂ©phone. Le flag est au format FCSC{<identifiant du modĂšle>|<numĂ©ro de build>}. Par exemple, pour un iPhone 14 Pro Max en iOS 18.4 (22E240) : FCSC{iPhone15,3|22E240}.

Pour rĂ©pondre Ă  cette question il faut savoir de quoi est constituĂ© une backup iOS. J’ai parlĂ© plus haut de backup “logique”. Cela a une importance car si on regarde Ă  l’intĂ©rieur de la backup on ne voit que des dossiers bizarres :

En fait il faut reconstruire la structure et noms de dossiers / fichiers. Pour cela il faut utiliser la Manifest.db (iOS 10+) en faisant la correspondance entre les RelativePath et les FileID.

NĂ©anmoins on voit aussi des fichiers avec des noms normaux dont Info.plist. C’est ici qu’Apple conserve les metadata clĂ©s concernant l’appareil :

  • Product Type (identifiant du modĂšle, ex. iPhone12,3),
  • Product Version (version d’iOS, ex. 16.0),
  • Build Version (numĂ©ro de build, ex. 20A362),
  • Divers identifiants (IMEI, MEID, Serial Number, GUID
),
  • Date du dernier backup, applications installĂ©es, etc.

On a donc tout ce qu’il nous faut pour faire le flag :

Flag : FCSC{iPhone12,3|20A362}

Si reconstruire l’arbo vous intĂ©resse voici pour la dĂ©monstration :

PremiÚrement regardons de quoi est constitué Manifest.db :

TrĂšs direct, on peut donc scripter facilement la reconstruction comme cela :

#!/bin/bash
BACKUP="/mnt/hgfs/backup/backup"
OUT="/mnt/hgfs/backup/reconstructed-backup"

mkdir -p "$OUT"

# on utilise -separator '|' pour que SQLite nous renvoie directement fileID|domain|relativePath
sqlite3 -separator '|' "$BACKUP/Manifest.db" \
"SELECT fileID, domain, COALESCE(relativePath,'') FROM Files;" \
| while IFS="|" read -r FILEID DOMAIN RELPATH; do

  # Si relativePath est vide, on saute (ce sont souvent des entrées de dossier sans chemin)
  [[ -z "$RELPATH" ]] && continue

  # Chemins de sortie pour recréer l'arborescence
  DEST_DIR="$OUT/$DOMAIN/$(dirname "$RELPATH")"
  DEST_PATH="$OUT/$DOMAIN/$RELPATH"

  mkdir -p "$DEST_DIR"
  ln -s "$BACKUP/$FILEID" "$DEST_PATH" 2>/dev/null || true
done

Et voilĂ  :

⭐ - iForensics - iWiFi
#

Pour continuer, trouvez quelques informations d’intĂ©rĂȘt sur le tĂ©lĂ©phone : SSID et BSSID du rĂ©seau WiFi sur lequel le tĂ©lĂ©phone est connectĂ© ainsi que le compte iCloud associĂ© au tĂ©lĂ©phone. Le flag est au format FCSC{||}. Par exemple, si le tĂ©lĂ©phone est connectĂ© sur le rĂ©seau WiFi example, qui a pour BSSID 00:11:22:33:44:55 et que le compte iCloud associĂ© est example@example.com : FCSC{example|00:11:22:33:44:55|example@example.com}.

Afin d’accĂ©lĂ©rer l’extraction des informations Wi-Fi et iCloud, on peut utiliser iLEAPP (iOS Logs, Events, and Protobuf Parser) : il va collecter et organiser automatiquement pour nous pleins d’artefacts et faire un rapport.

Bref aprĂšs avoir fait passĂ© l’ILEAPP on trouve le SSID & BSSID ici :

Pour le compte iCloud plusieurs maniÚres mais une façon assez direct avec iLEAPP et de regarder par quel compte les apps ont-elles été installé :

Flag : FCSC{FCSC|66:20:95:6c:9b:37|robertswigert@icloud.com}

⭐⭐ - iForensics - iTreasure
#

Avant la remise du tĂ©lĂ©phone Ă  la douane, le propriĂ©taire du tĂ©lĂ©phone a eu le temps d’envoyer un trĂ©sor. Retrouvez ce trĂ©sor.

Ici plusieurs maniĂšres rapide de le trouver. En effet le scĂ©nario parle d’un envoi. On pense directement au SMS.

iLEAPP parse cela donc on peut aller checker directement :

On peut aussi le faire ingĂ©rer Ă  Autopsy avec le module “Logical File Analysis”. GrĂące Ă  cela, Autopsy va scanner tous les fichiers et, d’aprĂšs leurs en-tĂȘtes (magic bytes), il va regrouper certains des mĂ©dias (JPEG, PNG, etc.) sous l’onglet “User Content Suspected” car le Chemin d’accĂšs est localisĂ© dans HomeDomain/Media/DCIM/
. Il considĂšre donc qu’il s’agit d’un contenu utilisateur (photo prise ou importĂ©e)

Flag : FCSC{511773550dca}

⭐⭐ - iForensics - iNvisible
#

Il semblerait qu’un message n’ait pas pu s’envoyer 
 Retrouvez le destinataire de ce message. Le flag est au format FCSC{}. Par exemple, si le destinataire est example@example.com : FCSC{example@example.com}.

Ici trĂšs rapide, on peut directement aller chercher dans la DB sms.db. C’est cette base qui contient toutes les conversations (iMessage et SMS), avec les tables principales message (headers, Ă©tat, texte, etc.) et handle (liste des correspondants, numĂ©ros / adresses).

Ne faites pas l’erreur d’aller chercher dans la table “message”. En effet, on ne retrouve que les iMessage ici. Pour les SMS il faut aller dans la table “chat”.

Flag : FCSC{kristy.friedman@outlook.com}

⭐⭐ - iForensics - iBackdoor 1/2
#

Vous continuez vos analyses afin de trouver la backdoor sur le tĂ©lĂ©phone. Vous finissez par vous rendre compte qu’une application est compromise et que le tĂ©lĂ©phone Ă©tait infectĂ© au moment de la collecte 
 Trouvez l’identifiant de l’application compromise ainsi que l’identifiant de processus (PID) du malware.

Le flag est au format FCSC{|}. Par exemple, si l’application compromise est Example (com.example) et que le PID est 1337 : FCSC{com.example|1337}.

Ici on va devoir s’appuyer sur les sysdiagnose (/sysdiagnose_and_crashes/private/var/mobile/Library/Logs/CrashReporter/DiagnosticLogs/sysdiagnose/sysdiagnose_2025.04.07_08-06-18-0700_iPhone-OS_iPhone_20A362).

Mais avant c’est quoi les sysdiagnose ? C’est une archive gĂ©nĂ©rĂ©e par iOS qui regroupe automatiquement les logs systĂšme, rapports de crash, Ă©tats rĂ©seau et informations de configuration au moment de la capture. Il sert principalement Ă  diagnostiquer des problĂšmes de performance ou de stabilitĂ© en fournissant un instantanĂ© complet de l’appareil. Mais il est aussi trĂšs utile d’un point de vu forensic aprĂšs une compromission.

Pour ĂȘtre un minimum pro et gagner du temps je vais utiliser le superbe tool EC-DIGIT-CSIRC/sysdiagnose https://github.com/EC-DIGIT-CSIRC/sysdiagnose.

┌──(venv)─(kali㉿kali)-[~/sysdiagnose]
└─$ sysdiag create /mnt/hgfs/backup/sysdiagnose_and_crashes/private/var/mobile/Library/Logs/CrashReporter/DiagnosticLogs/sysdiagnose/sysdiagnose_2025.04.07_08-06-18-0700_iPhone-OS_iPhone_20A362.tar.gz 

Sysdiagnose file has been processed: /mnt/hgfs/backup/sysdiagnose_and_crashes/private/var/mobile/Library/Logs/CrashReporter/DiagnosticLogs/sysdiagnose/sysdiagnose_2025.04.07_08-06-18-0700_iPhone-OS_iPhone_20A362.tar.gz
Case 'C39ZL6V1N6Y6_20250407_080618' created successfully from '/mnt/hgfs/backup/sysdiagnose_and_crashes/private/var/mobile/Library/Logs/CrashReporter/DiagnosticLogs/sysdiagnose/sysdiagnose_2025.04.07_08-06-18-0700_iPhone-OS_iPhone_20A362.tar.gz'

On voit bien que la case a été créé :

On fait passer le parser “ps” car trĂšs utile dans ce contexte. En effet analyser le contenu de ps.txt (le listing des processus) permet :

  • D’avoir une visibilitĂ© sur tous les processus en cours :

Le ps.txt fournit un instantanĂ© de tout ce qui tourne sur l’iPhone (y compris les exĂ©cutables cachĂ©s ou lancĂ©s par des services systĂšme). Sans ce listing, un malware qui se dissimule derriĂšre un nom trompeur ou dans un rĂ©pertoire non standard pourrait passer inaperçu.

  • DĂ©tection d’anomalies dans les privilĂšges

En regardant les colonnes user/uid et ppid, on repĂšre rapidement quand un processus tiers (par exemple extrait d’une app tierce) s’exĂ©cute sous l’utilisateur root (UID 0). Or, une app normale ne devrait jamais obtenir un tel niveau de privilĂšges sans passer par un mĂ©canisme officiel.

  • Identification de commandes et arguments suspects

Le champ command montre l’exĂ©cutable et ses arguments. Tout binaire inconnu (comme ce qu’on verra par la suite) ou toute URL codĂ©e (Base64 ou autre) est immĂ©diatement visible et peut ĂȘtre dĂ©codĂ©/inspectĂ©.

  • Tracking temporel et contexte

Avec la date/heure (started, datetime) et les champs de performance (%cpu, %mem), on sait si un processus a dĂ©marrĂ© anormalement tĂŽt (au boot) ou s’il consomme des ressources pour exfiltrer des donnĂ©es, mĂȘme si ça reste Ă  0 % pour masquer son activitĂ©.

  • Corroboration avec d’autres modules de sysdiagnose

Le ps.txt s’intĂšgre Ă  l’ensemble des autres dumps (rĂ©seau, fichiers ouverts, configurations). On peut croiser : “X processus root vers IP Y” + “connexion rĂ©seau vers Y” + “fichiers créés dans Z” pour construire un fil d’attaque.

On voit donc ceci :

root     
   279     1  
 /var/containers/Bundle/Application/
/Signal.app/mussel dGNwOi8vOTguNjYuMTU0LjIzNToyOTU1Mg==
root     
   330     1  
 /var/containers/Bundle/Application/
/Signal.app/mussel dGNwOi8vOTguNjYuMTU0LjIzNToyOTU1Mg==
root     
   345   344  
 /var/containers/Bundle/Application/
/Signal.app/mussel dGNwOi8vOTguNjYuMTU0LjIzNToyOTU1Mg==

1. Binaire “mussel” – Un fichier mussel embarquĂ© dans l’app Signal est inhabituel : ce n’est pas un dĂ©mon standard d’iOS.

2. ExĂ©cution en root – Il tourne avec l’UID 0 (root), ce qui est extrĂȘmement suspect pour un composant d’application tierce.

3. Argument codĂ© en Base64 – dGNwOi8vOTguNjYuMTU0LjIzNToyOTU1Mg== est une chaĂźne Base64 qui, dĂ©codĂ©e, donne tcp://98.66.154.235:29552, un canal TCP vers une IP externe, sans doute un C2.

4. Comportement typique d’un spyware – Un dĂ©mon inconnu qui s’exĂ©cute en root et ouvre une connexion vers un hĂŽte externe ressemble fortement Ă  un implant malveillant ou spyware.

Answer : FCSC{org.whispersystems.signal|345}

⭐⭐ - iForensics - iBackdoor 2/2
#

Maintenant que vous savez quelle application a Ă©tĂ© compromise, retrouvez comment est-ce que l’attaquant a rĂ©cupĂ©rĂ© l’application lĂ©gitime, prĂ©alablement Ă  l’infection. Il vous faudra retrouver :

  • L’identifiant de l’application utilisĂ©e pour rĂ©cupĂ©rer l’application lĂ©gitime;
  • Le chemin utilisĂ© pour stocker l’application lĂ©gitime;
  • La date de dĂ©sinstallation de l’application lĂ©gitime (en heure locale).

Le flag est au format FCSC{||}. Par exemple, si l’application utilisĂ©e est Example (com.example), que le chemin est /private/var/tmp/test.xyz et que la date de dĂ©sinstallation est 2025-01-01 01:00:00 : FCSC{com.example|/private/var/tmp/test.xyz|2025-01-01 01:00:00}.

Remettons les choses Ă  plat :

  • on sait que c’est Signal l’app en question
  • on sait qu’elle a Ă©tĂ© lancĂ© vers 7:47AM
  • on doit trouver le chemin de l’app, ce qui a “rĂ©cupĂ©rĂ©” / installĂ© l’app lĂ©gitime et la date de dĂ©sinstallation

Pour cela je me suis directement dirigé vers les mobileinstallation.

En effet, c’est la couche d’iOS responsable de l’installation, la mise Ă  jour et dĂ©sinstallation des apps.

On pourra y retrouver :

  • les timestamps prĂ©cis (timestamp + datetime)
  • les bundle id
  • les dĂ©tails du process d’uninstall
  • les erreurs et leur contexte

Bingo :

// à 07:40:47-07:00, premiÚre désinstallation de Signal
{
  "datetime": "2025-04-07T07:40:47.000000-07:00",
  "event_type": "MIClientConnection _uninstallIdentities",
  "message": "Uninstall requested by installcoordinationd ... for identity [org.whispersystems.signal]"
}
// Ă  la mĂȘme seconde, on dĂ©truit ses containers :
"message": "Destroying container org.whispersystems.signal ... at /private/var/containers/Bundle/Application/1EC20F02-..."

// à 07:43:55, désinstallation de l'outil com.fiore.trolldecrypt
{
  "datetime": "2025-04-07T07:43:55.000000-07:00",
  "message": "Uninstalling identifier com.fiore.trolldecrypt"
  // puis destruction du bundle container correspondant
}

On sait donc maintenant que l’attaquant a utilisĂ© TrollDecrypt qui est utilitaire opensource destinĂ© aux appareils iOS Ă©quipĂ©s de TrollStore. Il permet de dĂ©chiffrer Ă  la volĂ©e les applications installĂ©es (IPA protĂ©gĂ©es par FairPlay DRM) directement sur l’appareil, sans nĂ©cessiter de jailbreak. ConcrĂštement, il :

  • scanne la liste des apps installĂ©es sur l’iDevice via TrollStore
  • dĂ©chiffre le binaire FairPlay de l’application ciblĂ©e
  • emballe le rĂ©sultat dans un fichier .ipa exploitable (pour analyses, rĂ©installations, sideloading, etc.)

TrollStore exploite une faille CoreTrust pour signer Ă  vie n’importe quelle IPA. TrollDecrypt s’appuie dessus pour lancer l’app ciblĂ©e, dumper sa mĂ©moire et sortir un IPA FairPlay free. D’oĂč la prĂ©sence du dossier /Library/TrollDecrypt/decrypted/.

J’avoue qu’il y aurait mille façons intelligentes de pivoter, analyser et trouver le path de stockage de l’app lĂ©gitime mais il y a plus rapide. Dans un contexte de CTF ça compte.

Chercher un .ipa tout simplement.

Ce qui donne pour une timeline trĂšs succincte :

  1. 07h40m47s : désinstallation de Signal (log MI)
  2. 07h40–42m : dump → Signal_7.53_decrypted.ipa (fslisting)
  3. 07h43m55s : désinstallation de TrollDecrypt (log MI)
  4. 07h47mxxs : lancement de l’IPA repackĂ©e (unified log)

On a désormais tout pour créer le flag.

Flag : FCSC{com.fiore.trolldecrypt|/private/var/mobile/Library/TrollDecrypt/decrypted/Signal_7.53_decrypted.ipa|2025-04-07 07:40:47}

⭐⭐⭐ - iForensics - iC2
#

Retrouvez le nom de l’outil malveillant dĂ©ployĂ© sur le tĂ©lĂ©phone, ainsi que le protocole, l’adresse IP et le port de communication vers le serveur C2.

Le flag est au format FCSC{|||}. Par exemple, si l’outil est Cobalt Strike, le protocole TCP, l’adresse IP 127.0.0.1 et le port 1337 : FCSC{Cobalt Strike|TCP|127.0.0.1|1337}.

Je me suis donc renseigné davantage sur TrollStore et les actualités intéressantes liées. Je suis tombé sur cette article : https://idevicecentral.com/news/ios-malware-makes-trollstore-users-vulnerable-to-monitoring-file-extraction-remote-control-on-ios-14-ios-17/

On a dĂ©jĂ  rĂ©cupĂ©rĂ© le protocol, l’IP et le port plus tĂŽt donc c’est simple :

Flag : FCSC{SeaShell|TCP|98.66.154.235|29552}