⚠️ Attention :
Je suis un étudiant en cybersécurité. Ce post est personnel et non-professionnel. Mon analyse peut contenir des erreurs ou des imprécisions, je suis encore en apprentissage. Si vous constatez des erreurs ou si vous avez des suggestions, n’hésitez pas à me contacter !
1. Citizen Lab révèle l’affaire#
Le 12 juin 2025, Citizen Lab publie le rapport “First Forensic Confirmation of Paragon’s iOS Mercenary Spyware”.
Le rapport associe le spyware Graphite de Paragon à une attaque zero-click iMessage ciblant plusieurs journalistes européens.
Faits principaux :
- Une victime a reçu une threat notif d’Apple en avril 2025.
- Vecteur d’attaque : utilisation d’une attaque sophistiquée zero-click via iMessage.
Tout ça se termine le 11 juin 2025 (UTC), date à laquelle Apple publie iOS 18.3.1 avec la CVE-2025-43200 pour la correction.
2. CVE-2025-43200 & note d’Apple#
La note de sécurité d’Apple pour iOS 18.3.1 indique :
Impact : Un problème logique existait lors du traitement d’une photo ou d’une vidéo malicieusement conçue partagée via un lien iCloud. Apple est au courant d’un rapport selon lequel ce problème aurait été exploité dans une attaque extrêmement sophistiquée contre des individus ciblés.
Description : Ce problème a été résolu par une vérification améliorée.
CVE-2025-43200 - Apple.
Aucun chemin de fichier ni indication du binaire modifié. C’est là que le patch diffing entre en jeu !
3. ipsw-diffs entre 18.3 et 18.3.1#
Le diff automatisé de Blacktop montre 10 Mach-Os modifiés, dont trois seulement liés à iMessages :
- iMessage (
System/Library/Messages/PlugIns/iMessage.imservice/iMessage
) - SafetyMonitor (
System/Library/Messages/iMessageApps/SafetyMonitorMessages.bundle/SafetyMonitorMessages
) - identityservicesd (
System/Library/PrivateFrameworks/IDS.framework/identityservicesd.app/identityservicesd
)

Binaire | Pourquoi ce choix ? | Aperçu du diff |
---|---|---|
iMessage.imservice | Méthode interne d’iMessage | Important : nouvelle chaîne de log + vérification |
SafetyMonitorMessages | Pop-ups de sécurité de communication | Aucun delta fonctionnel vu avec le diffing tool |
identityservicesd | Daemon IDS/Push acheminant le trafic vers Messages | Aucun delta fonctionnel vu avec le diffing tool |
4. Récupération de 18.3 et 18.3.1#
Depuis iOS 18, Apple a ajouté les dmg.aea, rendant l’analyse différent si comme moi vous étiez habitué au dmg basique. Voici un micro-guide (si vous êtes uniquement intéressé à l’analyse technique passé à la partie 5.).
- Téléchargement des deux versions d’iOS
ipsw download ipsw --device iPhone17,1 --build 22D63
ipsw download ipsw --device iPhone17,1 --build 22D72
- Extraction du filesystem
ipsw extract --dmg fs iPhone17,1_18.3_22D63_Restore.ipsw
ipsw extract --dmg fs iPhone17,1_18.3.1_22D72_Restore.ipsw
- Extraction de la fcs-key et du dmg
ipsw extract --fcs-key iPhone17,1_18.3_22D63_Restore.ipsw
ipsw fw aea --pem '044-59182-075.dmg.aea.pem' '044-59515-074.dmg.aea' --output extracted/
# do this for the other one too
- Montage
ipsw mount fs --pem-db extracted/fcs-keys.json ../iPhone17,1_18.3_22D63_Restore.ipsw
If like me this doesn’t work for any reasons:
sudo apfs-fuse -o allow_other,uid=1001,gid=1001 extracted/044-59515-074.dmg /mnt/ios_old
- Copie des fichiers nécessaires
cp System/Library/PrivateFrameworks/IDS.framework/identityservicesd.app/identityservicesd ~/Documents/CVE-2025-43200/18.3.1/
cp System/Library/Messages/PlugIns/iMessage.imservice/iMessage ~/Documents/CVE-2025-43200/18.3.1/
cp System/Library/Messages/iMessageApps/SafetyMonitorMessages.bundle/SafetyMonitorMessages ~/Documents/CVE-2025-43200/18.3.1/
5. Différences dans iMessage.imservice#
Premièrement voici la similarité :
radiff2 -s 18.3/iMessage 18.3.1/iMessage
similarity: 0.977
distance: 49654
Ensuite nous pouvons creuser plus profondément avec IDA Pro et Diaphora script :

Nous pouvons voir un “partial match” pour-[MessageServiceSession _reAttemptMessageDeliveryForGUID: …]
.
Avec un nouveau log notable "Being requested to re-send a message that wasn't sent by me"
.

En analysant le code, on comprend à quoi sert tout cela. La méthode "_reAttemptMessageDeliveryForGUID:…" sert à décider si un message “iMessage” en échec doit être retenté ou s’il faut afficher une erreur.
En utilisant la Graph view nous pouvons clairement voir la nouvelle vérification :

Voici le changement important :
- Une nouvelle vérification de l’auteur
// APRÈS 18.3.1 - Bloque le renvoi des messages étrangers.
if (![message isFromMe]) { // message authored by someone else
os_log_info(MessageServiceLog,
"Being requested to re-send a message that wasn't sent by me");
return; // bail = exploit dies
}
Pourquoi ? - On peut supposer que la chaîne zéro-clic de Paragon a créé une trame de contrôle “renvoi” pointant vers une GUID dans la DB de discussion de la victime (où is_from_me == 0
). La protection unique ci-dessus rejette cette requête.
Nous pouvons voir ces informations dans la SMS.db:
CVE-2025-43200 est un correctif logique d’une seule ligne:
“Ne renvoie que les messages que tu as réellement écrits.”
L’exploit a fonctionné car cette invariant évidente n’était jamais appliquée dans l’helper de renvoi. Le correctif d’Apple consiste à :
if (!msg.isFromMe) return;
- Une instruction
os_log
pour le triage / log.
18.3 (vulnerable) 18.3.1 (patché)
┌───────────────────┐ ┌────────────────────────────────┐
│ … look-ups … │ │ … same … │
│ age-limit check │ │ age-limit check (unchanged) │
│ ──────────────────│ │────────────────────────────────│
│ NO author check │ │ if (!message.isFromMe) { │ ◄─ NEW
│ retry logic │ │ log "...not sent by me..." |
└───────────────────┘ │ return; │
│ } │
│ retry logic (unchanged) │
└────────────────────────────────┘
6. Cela dans CVE-2025-43200#
L’attaquant :
- Injectait ou rejouait une requête iMessage “renvoi” spécialement conçue pointant vers un GUID existant dans la base de données SQLite locale de la victime.
- Comme iOS 18.3 ne vérifiait pas
isFromMe
, la méthode_reAttemptMessageDeliveryForGUID:...
consommait un crédit de renvoi et réexpédiait le message étranger (ou sa pièce jointe) vers le contact contrôlé par l’attaquant.
Le correctif d’iOS 18.3.1 comble cette faille en exigeant que le bit isFromMe
du GUID soit vrai. Le message doit impérativement provenir de l’utilisateur local ; toute requête falsifiée référant à un message tiers déclenche désormais la nouvelle entrée de log et interrompt immédiatement le processus.
7. Attaque - Reconstruction plausible#
À ce jour, je n’ai pas identifié de scénario complet et convaincant montrant comment la CVE-2025-43200 s’insère exactement dans les cas documentés par Citizen Lab. Si vous avez d’autres idées ou des artefacts que j’aurais pu manquer, n’hésitez pas à me contacter.
Mon premier scénario envisageait que ce bug fournisse un canal d’exfiltration furtif. À y regarder de plus près, cela paraît peu probable : la primitive ne peut transmettre que des pièces jointes déjà présentes dans la sandbox de Messages. Elle ne permettrait pas, à elle seule, d’extraire des données arbitraires (bases Signal, WhatsApp, etc.).
Ma dernière théorie en date (les investigations continuent !) est la suivante :
- L’attaquant envoie une image ou photo contenant un payload inactif qui cible un parser
- Blastdoor n’élimine pas le payload (ce n’est pas son rôle) et la pièce jointe malveillante est sauvegardé sur le téléphone cible
- L’attaquant abuse de
_reAttemptMessageDeliveryForGUID:...
pour que la cible renvoie de lui même la pièce jointe malveillante, la faisant passer dans les parser et exploit hors sandbox

Faits :
- C’est le téléphone de l’éméteur qui fait les preview des pièces jointes (https://mysk.blog/2020/10/25/link-previews/)
- Les payloads inactifs pour bypass la sandbox de Blastdoor ont déjà été vu plusieurs fois :
- FORCEDENTRY (CVE-2021-30860)
- BLASTPASS (CVE-2023-41064 + 41061)
- Triangulation…
- schémas basés sur les travaux de Samuel Groß & Ian Beer (A Brief History of iMessage Exploitation & A Look at iMessage in iOS 14)
Questions :
- ai-je eu une mauvaise compréhension de la pipeline iMessage ?
- la pipeline est-elle toujours à jour ?
- la partie renvoie est-elle bien comme cela ?
- si ça fonctionne en 2 phases, cela veut dire que la cible reçoit une notif suspecte - est-ce okay d’un point de vu OPSEC pour l’attaquant ?
- peut-être que c’est en 1 phase, envoie de la pièce jointe malveillante + renvoi de message en même temps ?
- comment l’attaquant trouve la GUID du message malveillant pour le renvoyer (
_reAttemptMessageDeliveryForGUID:...
) ?- Il faudrait une autre vuln pour exfiltrer le GUID ? Pas la première fois que l’on voit quelque chose comme cela ? (cf. How to catch a wild triangle ou l’on voit
SELECT guid FROM attachment WHERE uti == "http://com.apple.watchface"....
) ?
- Il faudrait une autre vuln pour exfiltrer le GUID ? Pas la première fois que l’on voit quelque chose comme cela ? (cf. How to catch a wild triangle ou l’on voit
- s’il y a tout ça pourquoi un patch uniquement sur le
isFromMe
? Le patch parle bien uniquement de “logic check” et “This issue was addressed with improved checks.” ce qui colle bien avec ce qui a été trouvé. Quelle place au “maliciously crafted photo or video shared via an iCloud Link”? (cf. Apple security updates notes) ? Peut-être que le “malicious craft” = le fait de le faire en 1 phase ?
8. Forensique#
Étant donné que je n’ai pas accès aux données des iPhone compromis par Citizen Lab, tout ce qui suit est purement hypothétique ou fondé sur des déductions logiques.
1. Requêtes de logs unifiés dévoilant l’activité CVE-2025-43200 :
À rechercher | Pourquoi c’est important |
---|---|
"re-send a message that wasn't sent by me" | Nouvelle chaîne os_log introduite uniquement à partir d’iOS 18.3.1 ; sa présence indique que l’appareil a bloqué une tentative de renvoi falsifiée. |
stack traces _reAttemptMessageDeliveryForGUID (pré-patch) | Sur les appareils vulnérables (18.3/18.2.1), vous pouvez toujours trouver dans les logs de crash des références à ce sélecteur si l’exploit échoue. |
Attention : les logs unifiés rotate au bout d’environ 7 jours sur l’appareil ; pensez à extraire un sysdiagnose complet immédiatement.
2. Artefacts dans la base de chat (sms.db)
/* Possible duplicates: same GUID appears as both inbound (is_from_me = 0)
and outbound (is_from_me = 1) within a short window */
SELECT guid, date, is_from_me, text
FROM message
WHERE guid IN (
SELECT guid FROM message WHERE is_from_me = 0
)
ORDER BY date ASC;
- Un GUID dupliqué passant de
is_from_me = 0
➜1
sans action de l’utilisateur suggère fortement un abus du mécanisme de renvoi. - Recouper ce GUID avec la table attachments.
3. Traces IDS & livraison de messages :
- Emplacement (dump rooté ou système de fichiers complet iOS) :
/private/var/mobile/Library/Logs/CrashReporter/DiagnosticLogs/ids.*
- Rechercher dans les logs avec
grep
:"resend-request"
- valeurs de
"guid"
apparaissant également dans les doublons de sms.db
Ces trames de contrôle IDS en clair survivent souvent dans les logs de diagnostic même lorsque les logs unifiés ont été archivés.