{"id":281,"date":"2025-02-06T20:59:18","date_gmt":"2025-02-06T20:59:18","guid":{"rendered":"https:\/\/tolva.fr\/?p=281"},"modified":"2025-02-06T20:59:25","modified_gmt":"2025-02-06T20:59:25","slug":"survol-de-la-fonctionnalite-dappel-vocal-de-lapplication-seatalk","status":"publish","type":"post","link":"https:\/\/tolva.fr\/index.php\/2025\/02\/06\/survol-de-la-fonctionnalite-dappel-vocal-de-lapplication-seatalk\/","title":{"rendered":"Survol de la fonctionnalit\u00e9 d&rsquo;appel vocal de l&rsquo;application SeaTalk"},"content":{"rendered":"\n<p>En plus de permettre d&rsquo;\u00e9changer des messages texte, l&rsquo;application SeaTalk permet aussi de passer des appels vocaux.<\/p>\n\n\n\n<p>J&rsquo;ai donc tent\u00e9 d&rsquo;interpr\u00e9ter le trafic r\u00e9seau auquel donne lieu un appel vocal, et j&rsquo;ai jet\u00e9 un \u0153il \u00e0 l&rsquo;impl\u00e9mentation sous-jacente.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Le trafic induit par un appel vocal<\/strong><\/h4>\n\n\n\n<p>Pour se faire une premi\u00e8re id\u00e9e de la cin\u00e9matique d&rsquo;un appel, on r\u00e9alise diff\u00e9rentes captures r\u00e9seau.<\/p>\n\n\n\n<p>Regardons les serveurs TLS contact\u00e9s lorsque aucun appel n&rsquo;est effectu\u00e9 :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>$ tshark -r captures\/seatalk_nocall.pcap -Y tls.handshake.type==1 -T fields -e tls.handshake.extensions_server_name | grep -vE '^$' | sort -u\napi.haiserve.com\nedge-co.haiserve.com\noa.haiserve.com\ns.haiserve.com<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>$ tshark -r captures\/seatalk_call_failure_1.pcap -Y tls.handshake.type==1 -T fields -e tls.handshake.extensions_server_name | grep -vE '^$' | sort -u\napi.haiserve.com\ncall.haiserve.com\nedge-co.haiserve.com\noa.haiserve.com\nplay.googleapis.com\ns.haiserve.com\nwww.google.com<\/code><\/pre>\n\n\n\n<p>Regardons ensuite ce qui se produit lorsqu&rsquo;un appel est effectu\u00e9 mais que le correspondant ne d\u00e9croche pas :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>$ tshark -r captures\/seatalk_call_failure_2.pcap -Y tls.handshake.type==1 -T fields -e tls.handshake.extensions_server_name | grep -vE '^$' | sort -u\napi.haiserve.com\ncall.haiserve.com\nedge-co.haiserve.com\noa.haiserve.com\ns.haiserve.com<\/code><\/pre>\n\n\n\n<p>Enfin, lorsqu&rsquo;une communication vocale est r\u00e9ellement \u00e9tablie :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>$ tshark -r captures\/seatalk_call_success_1.pcap -Y tls.handshake.type==1 -T fields -e tls.handshake.extensions_server_name | grep -vE '^$' | sort -u\napi.haiserve.com\ncall.haiserve.com\nedge-co.haiserve.com\nf.haiserve.com\noa.haiserve.com\ns.haiserve.com<\/code><\/pre>\n\n\n\n<p>En conclusion, on constate que du trafic est initi\u00e9 avec le serveur <code>call.haiserve.com<\/code> par un terminal lorsqu&rsquo;il initie un appel.<\/p>\n\n\n\n<p>De plus (et cela n&rsquo;appara\u00eet pas dans ces <code>grep<\/code>), on constate que du trafic UDP est \u00e9chang\u00e9 lorsque le correspondant d\u00e9croche : le trafic vocal proprement dit est donc tr\u00e8s probablement transport\u00e9 par ce canal.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Trafic \u00e9chang\u00e9 avec call.haiserve.com<\/strong><\/h4>\n\n\n\n<p>Int\u00e9ressons-nous d&rsquo;un peu plus pr\u00e8s au trafic \u00e9chang\u00e9 avec <code>call.haiserve.com<\/code> lorsqu&rsquo;un appel est initi\u00e9.<\/p>\n\n\n\n<p>Pour cela, lan\u00e7ons l&rsquo;application en interceptant le trafic avec Burp.<\/p>\n\n\n\n<p>L&rsquo;\u00e9change HTTPS avec <code>call.haiserve.com<\/code> se r\u00e9duit \u00e0 un unique couple requ\u00eate-r\u00e9ponse :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"480\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/request_call_dot_haiserve-1.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-285\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/request_call_dot_haiserve-1.png 1920w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/request_call_dot_haiserve-1-300x75.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/request_call_dot_haiserve-1-768x192.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/request_call_dot_haiserve-1-1536x384.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>Cette requ\u00eate sert donc \u00e0 \u00e9tablir une session websocket avec <code>call.haiserve.com<\/code>.<\/p>\n\n\n\n<p>Une fois la websocket \u00e9tablie, on peut voir dans l&rsquo;Interceptor de Burp qu&rsquo;elle est visiblement utilis\u00e9e pour \u00e9changer de la signalisation :<\/p>\n\n\n\n<p>Commande <code>RING<\/code> :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_1.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-288\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_1.png 1920w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_1-300x169.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_1-768x432.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_1-1536x864.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>Commande <code>JOIN<\/code> :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_2.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-289\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_2.png 1920w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_2-300x169.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_2-768x432.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_2-1536x864.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>Commande <code>STATE<\/code> :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_3.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-290\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_3.png 1920w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_3-300x169.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_3-768x432.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_3-1536x864.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>R\u00e9ponse du serveur \u00e0 la commande <code>RING<\/code> :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_4.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-291\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_4.png 1920w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_4-300x169.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_4-768x432.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_4-1536x864.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>R\u00e9ponse du serveur \u00e0 la commande <code>JOIN<\/code> :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_5.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-292\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_5.png 1920w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_5-300x169.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_5-768x432.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_5-1536x864.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>Dans cette r\u00e9ponse, on observe la pr\u00e9sence d&rsquo;un token.<\/p>\n\n\n\n<p>R\u00e9ponse du serveur \u00e0 la commande <code>STATE<\/code> :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_6.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-293\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_6.png 1920w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_6-300x169.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_6-768x432.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_6-1536x864.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>Certaines r\u00e9ponses du serveur informent le client de certains \u00e9v\u00e9nements concernant le correspondant, par exemple lorsque son t\u00e9l\u00e9phone sonne :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_11.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-294\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_11.png 1920w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_11-300x169.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_11-768x432.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_11-1536x864.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>ou lorsqu&rsquo;il d\u00e9croche :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_12.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-295\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_12.png 1920w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_12-300x169.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_12-768x432.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_12-1536x864.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>Des messages qui semblent \u00eatre des <em>heartbeats<\/em> sont r\u00e9guli\u00e8rement \u00e9chang\u00e9s (message <code>SignalRTT<\/code>).<\/p>\n\n\n\n<p>Ces messages comportent un champ <code>ts<\/code> (vraisemblablement pour timestamp), dont la valeur est strictement croissante :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_31.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-296\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_31.png 1920w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_31-300x169.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_31-768x432.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/websocket_31-1536x864.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>Ces messages de <em>heartbeat<\/em> sont \u00e9chang\u00e9s tout au long de l&rsquo;appel.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Le <em>Software-Defined-Network<\/em> agora<\/strong><\/h4>\n\n\n\n<p>Diff\u00e9rents indices indiquent que SeaTalk utilise le SDK agora (https:\/\/www.agora.io), du moins au plus probant :<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>le mot \u00ab\u00a0agora\u00a0\u00bb dans la r\u00e9ponse \u00e0 la commande <code>JOIN<\/code> (voir plus haut),<\/li>\n\n\n\n<li>la tr\u00e8s grande quantit\u00e9 de classes dans le package <code>io.agora.*<\/code> :<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1860\" height=\"952\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/soMuchAgora.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-297\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/soMuchAgora.png 1860w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/soMuchAgora-300x154.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/soMuchAgora-768x393.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/soMuchAgora-1536x786.png 1536w\" sizes=\"auto, (max-width: 1860px) 100vw, 1860px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>les tr\u00e8s nombreuses biblioth\u00e8ques partag\u00e9es <code>libagora*.so<\/code> :<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code alignwide has-small-font-size\"><code>$ find SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/ -type f -name \"*libagora*so\" -exec ls -lh {} \\;\n-rw-r--r-- 1 thomas thomas 2,9M 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora_ai_noise_suppression_extension.so\n-rw-r--r-- 1 thomas thomas 679K 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora-fdkaac.so\n-rw-r--r-- 1 thomas thomas 174K 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora-soundtouch.so\n-rw-r--r-- 1 thomas thomas 1,4M 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora_video_encoder_extension.so\n-rw-r--r-- 1 thomas thomas 23M 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora-rtc-sdk.so\n-rw-r--r-- 1 thomas thomas 3,0M 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora_udrm3_extension.so\n-rw-r--r-- 1 thomas thomas 1,9M 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora_audio_beauty_extension.so\n-rw-r--r-- 1 thomas thomas 1,3M 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora_clear_vision_extension.so\n-rw-r--r-- 1 thomas thomas 895K 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora_video_decoder_extension.so\n-rw-r--r-- 1 thomas thomas 191K 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora_drm_loader_extension.so\n-rw-r--r-- 1 thomas thomas 1011K 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora_video_quality_analyzer_extension.so\n-rw-r--r-- 1 thomas thomas 2,9M 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora_segmentation_extension.so\n-rw-r--r-- 1 thomas thomas 1,2M 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora_face_detection_extension.so\n-rw-r--r-- 1 thomas thomas 5,9M 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora-ffmpeg.so\n-rw-r--r-- 1 thomas thomas 488K 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora-core.so\n-rw-r--r-- 1 thomas thomas 3,9M 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora_ai_echo_cancellation_extension.so\n-rw-r--r-- 1 thomas thomas 4,5M 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora_spatial_audio_extension.so\n-rw-r--r-- 1 thomas thomas 379K 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora_screen_capture_extension.so\n-rw-r--r-- 1 thomas thomas 1,7M 25 nov.  21:44 SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora_content_inspect_extension.so<\/code><\/pre>\n\n\n\n<p>Le sdk agora est d\u00e9velopp\u00e9 par l&rsquo;entreprise de m\u00eame nom (<code>agora.io<\/code>) et permet d&rsquo;ajouter rapidement \u00e0 une application des fonctionnalit\u00e9s d&rsquo;appels vocaux ou vid\u00e9os. Ces appels transitent par l&rsquo;agora SD-RTN (Software-Defined Real-Time Network) : Le client d&rsquo;agora n&rsquo;a pas \u00e0 mettre en place une infrastructure d&rsquo;acheminement du flux vocal, c&rsquo;est l&rsquo;infrastructure agora qui fait ce travail.<\/p>\n\n\n\n<p>Le mod\u00e8le \u00e9conomique de Agora est de<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>mettre gratuitement \u00e0 disposition le SDK pour la plateforme de votre choix (https:\/\/docs.agora.io\/en\/sdks?platform=android),<\/li>\n\n\n\n<li>facturer au d\u00e9veloppeur l&rsquo;usage du SD-RTN fait par son application.<\/li>\n<\/ul>\n\n\n\n<p>Un client de agora aura un <code>APP_ID<\/code>, qui est un identifiant propre \u00e0 chaque client, destin\u00e9 \u00e0 des fins de facturation et divers services statistiques.<\/p>\n\n\n\n<p>Ce client aura \u00e9galement acc\u00e8s \u00e0 un <em>agora_certificate<\/em> qui est une cha\u00eene de caract\u00e8res \u00e0 partir de laquelle le backend du client calculera les tokens (observ\u00e9 dans la r\u00e9ponse de <code>call.haiserve.com<\/code> \u00e0 la commande <code>JOIN<\/code> dans le trafic de signalisation) en utilisant les snippets de code fournis par agora.<\/p>\n\n\n\n<p>Le token est communiqu\u00e9 par le backend client \u00e0 ses utilisateurs, et est construit cryptographiquement \u00e0 partir d&rsquo;un timestamp, de l&rsquo;<code>APP_ID<\/code> et de l&rsquo;<em>agora_certificate<\/em>.<\/p>\n\n\n\n<p>Apr\u00e8s avoir \u00e9t\u00e9 communiqu\u00e9 par le backend du d\u00e9veloppeur \u00e0 l&rsquo;application cliente, le token est ensuite transmis avec l&rsquo;<code>APP_ID<\/code> au SDN agora comme \u00e9l\u00e9ment d&rsquo;authentification.<\/p>\n\n\n\n<p>Une vuln\u00e9rabilit\u00e9 a \u00e9t\u00e9 d\u00e9couverte en 2020 par McAfee (CVE-2020-25605) : l&rsquo;<code>APP_ID<\/code> et le token d&rsquo;authentification transitaient en clair dans le trafic entre l&rsquo;application cliente et le SDN agora.<\/p>\n\n\n\n<p>Dans SeaTalk, l&rsquo;<code>APP_ID<\/code> est cod\u00e9 en dur dans un appel \u00e0 la m\u00e9thode <code>RtcEngine.create<\/code> dans <code>RtcEngineInstance<\/code> :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1179\" height=\"684\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/app_id_location.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-298\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/app_id_location.png 1179w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/app_id_location-300x174.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/app_id_location-768x446.png 768w\" sizes=\"auto, (max-width: 1179px) 100vw, 1179px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Chiffrement du flux vocal<\/strong><\/h4>\n\n\n\n<p>Dans l&rsquo;architecture con\u00e7ue par Agora, il est possible de prot\u00e9ger cryptographiquement le flux vocal entre l&rsquo;appelant et l&rsquo;appel\u00e9.<\/p>\n\n\n\n<p>Dans ce cas, la distribution du mat\u00e9riel cryptographique (une cl\u00e9 et un sel) incombe au backend client.<\/p>\n\n\n\n<p>Concr\u00e8tement, l&rsquo;activation du chiffrement passe par un appel \u00e0 la m\u00e9thode <code>enableEncryption<\/code> de la classe <code>RtcEngine<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide has-small-font-size\"><code>@Override\npublic void onClick(View v) {\n    if (v.getId() == R.id.btn_join) {\n        if (!joined) {\n            if (encry_mode.getSelectedItem().toString().equals(getString(R.string.custom))) {\n                enablePacketProcessor(true);\n            } else {\n                \/\/ Creates an EncryptionConfig instance.\n                EncryptionConfig config = new EncryptionConfig();\n                \/\/ Sets the encryption mode as AES_128_XTS.\n                config.encryptionMode = EncryptionConfig.EncryptionMode.valueOf(encry_mode.getSelectedItem().toString());\n                \/\/ Sets the encryption key.\n                config.encryptionKey = et_password.getText().toString();\n                System.arraycopy(getKdfSaltFromServer(), 0, config.encryptionKdfSalt, 0, config.encryptionKdfSalt.length);\n                \/\/ Enables the built-in encryption.\n                engine.enableEncryption(true, config);\n            }<\/code><\/pre>\n\n\n\n<p>Le code de l&rsquo;application comporte bien une m\u00e9thode <code>enableEncryption<\/code>, qui fait appel \u00e0 la m\u00e9thode native correspondante <code>nativeEnableEncryption<\/code> :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1318\" height=\"192\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/enableEncryption2.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-299\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/enableEncryption2.png 1318w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/enableEncryption2-300x44.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/enableEncryption2-768x112.png 768w\" sizes=\"auto, (max-width: 1318px) 100vw, 1318px\" \/><\/figure>\n\n\n\n<p>Toutefois, la m\u00e9thode <code>enableEncryption<\/code> n&rsquo;est jamais appel\u00e9e :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1610\" height=\"246\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/enableEncryption1.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-300\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/enableEncryption1.png 1610w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/enableEncryption1-300x46.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/enableEncryption1-768x117.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/enableEncryption1-1536x235.png 1536w\" sizes=\"auto, (max-width: 1610px) 100vw, 1610px\" \/><\/figure>\n\n\n\n<p>Par cons\u00e9quent, tracer la m\u00e9thode <code>enableEncryption<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>$ frida-trace -U -p $(frida-ps -U | grep SeaTalk | awk -F ' ' '{print $1}') -j '*!*enableEncryption*'\nInstrumenting...                                                        \nRtcEngineImpl.enableEncryption: Auto-generated handler at \"\/home\/thomas\/tools\/dirsearch\/__handlers__\/io.agora.rtc2.internal.RtcEngineImpl\/enableEncryption.js\"\nRtcEngine.enableEncryption: Auto-generated handler at \"\/home\/thomas\/tools\/dirsearch\/__handlers__\/io.agora.rtc2.RtcEngine\/enableEncryption.js\"\nStarted tracing 2 functions. Press Ctrl+C to stop<\/code><\/pre>\n\n\n\n<p>ou bien la m\u00e9thode native correspondante <code>nativeEnableEncryption<\/code> :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>$ frida-trace -U -p $(frida-ps -U | grep SeaTalk | awk -F ' ' '{print $1}') -i '*nativeEnableEncryption*'\nInstrumenting...                                                        \nJava_io_agora_rtc2_internal_RtcEngineImpl_nativeEnableEncryption: Auto-generated handler at \"\/home\/thomas\/tools\/dirsearch\/__handlers__\/libagora_rtc_sdk.so\/Java_io_agora_rtc2_internal_RtcE_8d545876.js\"\nStarted tracing 1 function. Press Ctrl+C to stop.<\/code><\/pre>\n\n\n\n<p>Ne donne lieu \u00e0 aucune trace, configurant que ces fonctions ne sont effectivement jamais appel\u00e9es.<\/p>\n\n\n\n<p>L&rsquo;application SeaTalk ne suit donc pas les conseils d&rsquo;utilisation prodigu\u00e9s par agora, mais cela ne signifie pas n\u00e9cessairement l&rsquo;absence totale de chiffrement : il est possible que les flux entre l&rsquo;application et le SDN agora soient de toute fa\u00e7on chiffr\u00e9s, auquel cas l&rsquo;absence d&rsquo;utilisation de la fonction <code>enableEncryption<\/code> aurait pour cons\u00e9quence l&rsquo;absence de chiffrement de bout en bout entre deux utilisateurs de SeaTalk.<\/p>\n\n\n\n<p>Tout ceci reste cependant de l&rsquo;ordre de l&rsquo;hypoth\u00e8se, et demanderait une \u00e9tude approfondie du SDK agora pour \u00eatre confirm\u00e9 ou non.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Par o\u00f9 commencer ?<\/strong><\/h4>\n\n\n\n<p>Comme on l&rsquo;a vu plus haut, le volume de code repr\u00e9sent\u00e9 par les diff\u00e9rentes biblioth\u00e8ques partag\u00e9es du SDK agora embarqu\u00e9es par l&rsquo;application est relativement important.<\/p>\n\n\n\n<p>En particulier, les deux biblioth\u00e8ques libagora-rtc-sdk.so et libagora-core.so exportent un nombre consid\u00e9rable de fonctions :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>$ aarch64-linux-gnu-objdump -T SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora-rtc-sdk.so | grep 'DF .text' | sort -u | wc -l\n517<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>$ aarch64-linux-gnu-objdump -T SeaTalk_3.49.1_APKPure.xapk.out\/unknown\/config.arm64_v8a\/lib\/arm64-v8a\/libagora-core.so | grep 'DF .text' | sort -u | wc -l\n462<\/code><\/pre>\n\n\n\n<p>D\u00e8s lors, par quel bout d\u00e9buter l&rsquo;analyse de l&rsquo;application ?<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Les fonctions natives<\/strong><\/h4>\n\n\n\n<p>On peut commencer par lister les m\u00e9thodes java natives, qui sont des wrappers vers des m\u00e9thodes impl\u00e9ment\u00e9es dans une des biblioth\u00e8ques partag\u00e9es embarqu\u00e9es par l&rsquo;application.<\/p>\n\n\n\n<p>Ces m\u00e9thodes sont pr\u00e9fix\u00e9es par le mot-cl\u00e9 <em>native<\/em> :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1908\" height=\"925\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/nativeMethodsJava.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-301\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/nativeMethodsJava.png 1908w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/nativeMethodsJava-300x145.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/nativeMethodsJava-768x372.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/nativeMethodsJava-1536x745.png 1536w\" sizes=\"auto, (max-width: 1908px) 100vw, 1908px\" \/><\/figure>\n\n\n\n<p>Comme on peut le voir, toutes ces m\u00e9thodes ont des noms d\u00e9butant par \u00ab\u00a0native\u00a0\u00bb.<\/p>\n\n\n\n<p>On peut donc, pour les diff\u00e9rents packages de l&rsquo;application, tracer les m\u00e9thodes dont le nom contient le mot \u00ab\u00a0native\u00a0\u00bb :<\/p>\n\n\n\n<p>Le package le plus prometteur est io.agora.rtc2, qui embarquent 367 m\u00e9thodes \u00ab\u00a0<em>native<\/em>\u00ab\u00a0.<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>frida-trace -U -p $(frida-ps -U | grep SeaTalk | awk -F ' ' '{print $1}') -j 'io.agora.rtc2*!*native*'\n(...)<\/code><\/pre>\n\n\n\n<p>La fonction la plus int\u00e9ressante est peut-\u00eatre <code>nativeJoinChannel<\/code> (dont le pendant natif s&rsquo;appelle <code>Java_io_agora_rtc2_internal_RtcEngineImpl_nativeJoinChannel<\/code> dans libagora-rtc-sdk.so) : En tra\u00e7ant cette fonction on constate que son deuxi\u00e8me argument est un token (similaire \u00e0 celui retourn\u00e9 par le backend de l&rsquo;application et observ\u00e9 dans les \u00e9changes de signalisation sur websocket), tandis que le dernier argument est l&rsquo;identifiant num\u00e9rique de l&rsquo;utilisateur :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>(...)\n18119 ms  RtcEngineImpl.nativeJoinChannel(\"-5476376667000352608\", \"0067656ab67ab154d18a1cf32bfb01446d1IADobfyXeZRJlhohshNaJrj+JfDA3se\/T5Umq14gOoyzoQGMrchm26d2IgDLh8gDb+WEZwQAAQAfvoNnAgAfvoNnAwAfvoNnBAAfvoNn\", \"01JHCZKDS9GWSC9TD8HSJQHZWH\", \"\", 641926)\n(...)<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>logcat et server hello<\/strong><\/h4>\n\n\n\n<p>La journalisation logcat contient de nombreuses r\u00e9f\u00e9rences \u00e0 agora, symptomatiques de diff\u00e9rents appels de fonctions, et constitue donc une source d&rsquo;information appr\u00e9ciable.<\/p>\n\n\n\n<p>Une entr\u00e9e particuli\u00e8rement int\u00e9ressante est celle mentionnant la r\u00e9ception d&rsquo;un message \u00ab\u00a0server hello\u00a0\u00bb :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1749\" height=\"595\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/LogcatServerHello.png\" alt=\"\" class=\"wp-image-302\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/LogcatServerHello.png 1749w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/LogcatServerHello-300x102.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/LogcatServerHello-768x261.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/LogcatServerHello-1536x523.png 1536w\" sizes=\"auto, (max-width: 1749px) 100vw, 1749px\" \/><\/figure>\n\n\n\n<p>La cha\u00eene de caract\u00e8res en question est pr\u00e9sente dans la biblioth\u00e8que libagora-rtc-sdk.so :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1524\" height=\"135\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/GhidraServerHelloString.png\" alt=\"\" class=\"wp-image-303\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/GhidraServerHelloString.png 1524w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/GhidraServerHelloString-300x27.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/GhidraServerHelloString-768x68.png 768w\" sizes=\"auto, (max-width: 1524px) 100vw, 1524px\" \/><\/figure>\n\n\n\n<p>Dans cette librairie, cette cha\u00eene de caract\u00e8res n&rsquo;est utilis\u00e9e que par la fonction <code>FUN_008232f0<\/code> :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full has-custom-border\"><img loading=\"lazy\" decoding=\"async\" width=\"1540\" height=\"939\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/ServerHelloHandlingFunction.png\" alt=\"\" class=\"has-border-color has-foreground-border-color wp-image-304\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/ServerHelloHandlingFunction.png 1540w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/ServerHelloHandlingFunction-300x183.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/ServerHelloHandlingFunction-768x468.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/ServerHelloHandlingFunction-1536x937.png 1536w\" sizes=\"auto, (max-width: 1540px) 100vw, 1540px\" \/><\/figure>\n\n\n\n<p>Interceptons donc les appels \u00e0 cette fonction avec frida :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const ghidraImageBase = 0x00100000\nconst libagoraBaseAddr = Module.findBaseAddress('libagora-rtc-sdk.so');\n\nconst FUN_008232f0_RealAddr = libagoraBaseAddr.add(0x008232f0 - ghidraImageBase);<\/code><\/pre>\n\n\n\n<p>Le hook positionn\u00e9 est configur\u00e9 pour dumper les arguments d&rsquo;appel de la fonction et lister la pile d&rsquo;appel \u00e0 la fonction :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide has-small-font-size\"><code>Interceptor.attach(FUN_008232f0_RealAddr, {\n    onEnter: function(args) {\n        console.log(\"entering the server hello-related function\");\n\n        console.log('FUN_008232f0 called from:\\n' +\n            Thread.backtrace(this.context, Backtracer.ACCURATE)\n            .map(DebugSymbol.fromAddress).join('\\n') + '\\n');\n\n        console.log('x0:' + this.context.x0.toString());\n        console.log('x1:' + this.context.x1.toString());\n        console.log('x2:' + this.context.x2.toString());\n        console.log('x3:' + this.context.x3.toString());\n        console.log('x4:' + this.context.x3.toString());\n\n        console.log('content at x0 : ' + hexdump(Memory.readByteArray(this.context.x0, 256)));\n        console.log('content at x1 : ' + hexdump(Memory.readByteArray(this.context.x1, 256)));\n        console.log('content at x2 : ' + hexdump(Memory.readByteArray(this.context.x2, 256)));\n        console.log('content at x3 : ' + hexdump(Memory.readByteArray(this.context.x3, 256)));\n        console.log('content at x4 : ' + hexdump(Memory.readByteArray(this.context.x4, 256)));\n    }\n});<\/code><\/pre>\n\n\n\n<p>On r\u00e9p\u00e8te la d\u00e9marche pour les appelants successifs de <code>FUN_008232f0<\/code>.<\/p>\n\n\n\n<p>La \u00ab\u00a05\u00e8me fonction appelante\u00a0\u00bb (la \u00ab\u00a01\u00e8re fonction appelante\u00a0\u00bb \u00e9tant une fonction appelant directement <code>FUN_008232f0<\/code>, la \u00ab\u00a02\u00e8me fonction appelante\u00a0\u00bb \u00e9tant une fonction appelant une fonction qui appelle <code>FUN_008232f0<\/code>, et ainsi de suite) est la fonction <code>FUN_0079786c<\/code>.<\/p>\n\n\n\n<p>Il appara\u00eet que le 3\u00e8me argument de cette fonction est un paquet qui peut \u00e9galement \u00eatre observ\u00e9 dans une capture r\u00e9seau, tandis que le 4\u00e8me argument est la taille du paquet en question :<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>&#91;Pixel 7a::PID::20321 ]-&gt; entering the server hello-related function 5th caller\nFUN_0079786c called from:\n0x78524f3fb0 libagora-rtc-sdk.so!0x695fb0\n0x78524f3fb0 libagora-rtc-sdk.so!0x695fb0\n0x78524f14c8 libagora-rtc-sdk.so!0x6934c8\n0x7852b8c008 libagora-rtc-sdk.so!0xd2e008\n0x7852c8df4c libagora-rtc-sdk.so!0xe2ff4c\n0x7852c8e8b4 libagora-rtc-sdk.so!0xe308b4\n0x78d1b24228 libagora-core.so!0x13228\n0x78d1b21ed8 libagora-core.so!0x10ed8\n0x78d1b26d88 libagora-core.so!0x15d88\n0x78d1b29170 libagora-core.so!0x18170\n0x78d1b282f0 libagora-core.so!0x172f0\n0x78d1b39254 libagora-core.so!0x28254\n0x7cd6cf3fc0 libc.so!_ZL15__pthread_startPv+0xd0\n0x7cd6ce5d64 libc.so!__start_thread+0x44\n\nx0:0xb400007b1b839590\nx1:0xb400007a6aceed10\nx2:0xb400007b4ad003a0\nx3:0xc2\ncontent at x2 :            0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF\n00000000  02 1f cd 26 fc 5c 6b bb 56 6e af e1 00 00 23 00  ...&amp;.\\k.Vn....#.\n00000010  83 53 19 00 01 43 50 54 4f a7 00 4e 4f 4e 43 20  .S...CPTO..NONC \n00000020  00 03 e8 e8 32 ec b3 f2 f2 d3 0b 97 b8 22 a7 6f  ....2........\".o\n00000030  67 7a a7 87 f2 32 2d 56 40 79 3c b6 19 b7 28 f5  gz...2-V@y&lt;...(.\n00000040  bf 41 45 41 44 04 00 41 45 53 47 53 43 49 44 20  .AEAD..AESGSCID \n00000050  00 70 33 71 a9 c5 2e 35 bc fe 7e e5 b0 a7 12 a5  .p3q...5..~.....\n00000060  de 1f 9d e7 aa 7c 8a b7 c9 f4 50 8e bc 7b 1a f0  .....|....P..{..\n00000070  6a 50 55 42 53 41 00 04 22 41 a2 5e 24 f7 b5 e3  jPUBSA..\"A.^$...\n00000080  20 49 c6 4f d7 0c 9e a8 99 64 0e 54 47 c8 b6 fc   I.O.....d.TG...\n00000090  23 12 98 eb 87 a5 53 52 a7 3c 11 52 cf 95 81 14  #.....SR.&lt;.R....\n000000a0  4e bb 31 39 18 7e 27 61 af 06 ab f6 08 60 30 f6  N.19.~'a.....`0.\n000000b0  03 aa dc ff 9a 3b 7b d3 4b 45 58 53 04 00 50 32  .....;{.KEXS..P2\n000000c0  35 36                                            56<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1574\" height=\"728\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/serverHelloInPcap.png\" alt=\"\" class=\"wp-image-305\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/serverHelloInPcap.png 1574w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/serverHelloInPcap-300x139.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/serverHelloInPcap-768x355.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/serverHelloInPcap-1536x710.png 1536w\" sizes=\"auto, (max-width: 1574px) 100vw, 1574px\" \/><\/figure>\n\n\n\n<p>Dans les journaux logcat on retrouve aussi trace de messages \u00ab\u00a0client hello\u00a0\u00bb :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1716\" height=\"384\" src=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/LogcatClientHello.png\" alt=\"\" class=\"wp-image-306\" srcset=\"https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/LogcatClientHello.png 1716w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/LogcatClientHello-300x67.png 300w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/LogcatClientHello-768x172.png 768w, https:\/\/tolva.fr\/wp-content\/uploads\/2025\/02\/LogcatClientHello-1536x344.png 1536w\" sizes=\"auto, (max-width: 1716px) 100vw, 1716px\" \/><\/figure>\n\n\n\n<p>Cette terminologie laisse penser qu&rsquo;on a affaire \u00e0 un protocole de transport s\u00e9curis\u00e9 inspir\u00e9 de TLS. <\/p>\n\n\n\n<p>Si c&rsquo;est le cas, le server hello est alors re\u00e7u par le client avant que la n\u00e9gociation d&rsquo;algorithmes et de secrets cryptographiques communs n&rsquo;ait \u00e9t\u00e9 termin\u00e9e.<\/p>\n\n\n\n<p>Le message server hello serait alors pleinement manipulable par un attaquant (pas de hmac ou de tag gcm emp\u00eachant de le modifier !) et pourrait \u00eatre utilis\u00e9 comme vecteur d&rsquo;attaque pour d\u00e9clencher une vuln\u00e9rabilit\u00e9 pr\u00e9sentes dans une des fonctions traitant ce server hello.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>En plus de permettre d&rsquo;\u00e9changer des messages texte, l&rsquo;application SeaTalk permet aussi de passer des appels vocaux. J&rsquo;ai donc tent\u00e9 d&rsquo;interpr\u00e9ter le trafic r\u00e9seau auquel donne lieu un appel vocal, et j&rsquo;ai jet\u00e9 un \u0153il \u00e0 l&rsquo;impl\u00e9mentation sous-jacente. Le trafic induit par un appel vocal Pour se faire une premi\u00e8re id\u00e9e de la cin\u00e9matique d&rsquo;un [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-281","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/posts\/281","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/comments?post=281"}],"version-history":[{"count":9,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/posts\/281\/revisions"}],"predecessor-version":[{"id":311,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/posts\/281\/revisions\/311"}],"wp:attachment":[{"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/media?parent=281"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/categories?post=281"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tolva.fr\/index.php\/wp-json\/wp\/v2\/tags?post=281"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}