Tuesday, December 11, 2018

Adventures in Video Conferencing Part 3: The Even Wilder World of WhatsApp

Posted by Natalie Silvanovich, Project Zero

WhatsApp is anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r application that supports video conferencing that does not use WebRTC as its core implementation. Instead, it uses PJSIP, which contains some WebRTC code, but also contains a substantial amount of ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r code, and predates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WebRTC project. I fuzzed this implementation to see if it had similar results to WebRTC and FaceTime.

Fuzzing Set-up

PJSIP is open source, so it was easy to identify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PJSIP code in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Android WhatsApp binary (libwhatsapp.so). Since PJSIP uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 open source library libsrtp, I started off by opening cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 binary in IDA and searching for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 string srtp_protect, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 name of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function libsrtp uses for encryption. This led to a log entry emitted by a function that looked like srtp_protect. There was only one function in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 binary that called this function, and called memcpy soon before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call. Some log entries before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call contained cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 file name srtp_transport.c, which exists in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PJSIP repository. The log entries in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WhatsApp binary say that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function being called is transport_send_rtp2 and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PJSIP source only has a function called transport_send_rtp, but it looks similar to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 function calling srtp_protect in WhatsApp, in that it has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same number of calls before and after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memcpy. Assuming that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code in WhatsApp is some variation of that code, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memcpy copies cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entire unencrypted packet right before it is encrypted.

Hooking this memcpy seemed like a possible way to fuzz WhatsApp video calling. I started off by hooking memcpy for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 entire app using a tool called Frida. This tool can easily hook native function in Android applications, and I was able to see calls to memcpy from WhatsApp within minutes. Unfortunately though, video conferencing is very performance sensitive, and a delay sending video packets actually influences cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 contents of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next packet, so hooking every memcpy call didn’t seem practical. Instead, I decided to change cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 single memcpy to point to a function I wrote.

I started off by writing a function in assembly that loaded a library from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filesystem using dlopen, retrieved a symbol by calling dlsym and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n called into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 library. Frida was very useful in debugging this, as it could hook calls to dlopen and dlsym to make sure cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were being called correctly. I overwrote a function in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WhatsApp GIF transcoder with this function, as it is only used in sending text messages, which I didn’t plan to do with this altered version. I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memcpy call to point to this function instead of memcpy, using this online ARM branch finder.

sub_2F8CC
MOV             X21, X30
MOV             X22, X0
MOV             X23, X1
MOV             X20, X2
MOV             X1, #1
ADRP            X0, #aDataDataCom_wh@PAGE ; "/data/data/com.whatsapp/libn.so"
ADD             X0, X0, #aDataDataCom_wh@PAGEOFF ; "/data/data/com.whatsapp/libn.so"
BL              .dlopen
ADRP            X1, #aApthread@PAGE ; "apthread"
ADD             X1, X1, #aApthread@PAGEOFF ; "apthread"
BL              .dlsym
MOV             X8, X0
MOV             X0, X22
MOV             X1, X23
MOV             X2, X20
NOP
BLR             X8
MOV             X30, X21
RET
The library loading function

I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n wrote a library for Android which had cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same parameters as memcpy, but fuzzed and copied cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer instead of just copying it, and put it on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 filesystem where it would be loaded by dlopen. I cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n tried making a WhatsApp call with this setup. The video call looked like it was being fuzzed and crashed in roughly fifteen minutes.

Replay Set-up


To replay cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packets I added logging to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 library, so that each buffer that was altered would also be saved to a file. Then I created a second library that copied cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logged packets into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer being copied instead of altering it. This required modifying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 WhatsApp binary slightly, because cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logged packet will usually not be cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same size as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet currently being sent. I changed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 hooked memcpy to be passed by reference instead of by value, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n had cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 library change cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logged packet. This changed cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length so that it would be correct for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 call to srtp_protect. Luckily, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet is copied into is a fixed length, so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re is no concern that a valid packet will overflow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buffer length. This is a common design pattern in RTP processing that improves performance by reducing length checks. It was also helpful in modifying FaceTime to replay packets of varying length, as described in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 previous post.

This initial replay setup did not work, and looking at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 logged packets, it turned out that WhatsApp uses four streams with different SSRCs for video conferencing (possibly one for video, one for audio, one for synchronization and one for good luck). The streams each had only one payload type, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y were all different, so it was fairly easy to map each SSRC to its stream. So I modified cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 replay library to determine cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current SSRC for each stream based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 payload types of incoming packets, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n to replace cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SSRC of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 replayed packets with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 correct one based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir payload type. This reliably replayed a WhatsApp call. I was cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n able to fuzz and reproduce crashes on WhatsApp.

Results

Using this setup, I reported one heap corruption issue on WhatsApp, CVE-2018-6344. This issue has since been fixed. After this issue was resolved, fuzzing did not yield any additional crashes with security impact, and we moved on to ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r methodologies. Part 4 will describe our ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r (unsuccessful) attempts to find vulnerabilities in WhatsApp.

1 comment:

  1. I've been enjoying cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 series quite a bit. Out of curiosity, did you use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same fuzz function used in part 1?
    Do you have any thoughts cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tradeoffs between writing a quick fuzzer than just randomizes data and something a little bit more advanced that might try certain magic values for something like this?

    ReplyDelete