Since TCP is considered the “Trusted channel” used by Zoom servers, it seems that one may be able to hit various function IDs in this message handler with “untrusted” UDP packets sent by the client, since at this point, Zoom is not checking where the crafted message came from. One thing you may have realized about this design, is that UDP and TCP data are both read by “ process_io_event” and eventually posted to the same handler. So I will spare going into that part as it’s not vital to explaining this specific vulnerability. Most of the cases will craft yet-another-message which will be posted to another messaging queue, get processed by different handlers that branch into a dll I won’t even talk about and invoke more and more switch cases that may craft more messages. So, there must be one that says “hijack screen controls” or “spoof chat messages,” right? Unfortunately, it’s not that simple, as things get incredibly more complex beyond these 35 cases that are invoked. Some examples of switch case functionalities that can be triggered by these function IDs are: The network message is sent to this handler, where an identifier from the message tells it which case to invoke (for this scenario I call them function IDs). The TCP channel is then used throughout the meeting for updates on attendee status and meeting state. If so, then the Zoom server can lay low, and leave the Audio/Video to be streamed directly from client to client. Another important part in this initialization is a peer-to-peer (P2P) check which checks if the meeting can be streamed P2P rather than proxied through Zoom servers. When a Zoom client starts/joins a meeting, it will reach out to a Zoom server over TCP to officially notify that a “meeting is starting/being joined.” This allows the Zoom server to then notify appropriate attendees (“hey meeting member has joined / started meeting”), setup UDP streaming for the new client, etc. Now that I have explained a bit of what Zoom’s internal messaging is about, let’s move onto how networking is involved in all of this. This is where hardware breakpoints (and some IDA debug scripting) helped greatly, as it allowed me to break when specific messages were being read off the queue, so I could easily trace execution flow from message creation to the actual pump processing the message. The Zoom message class is very simple, having this general structure:Ĭlass msg_db_t : public ssb_allocator ĭuring a meeting, when a Zoom client needs meeting status updated or is receiving packets that are part of an audio/visual stream, a msg_db_t object is constructed and and posted to the appropriate msg_queue, in which the message pump for that queue will process and dispatch the object to the appropriate message handler in Zoom’s application which will then carry out the desired action/update.ĭebugging and tracking messages through this was quite a challenge, as stepping into a message posting system and tracking where the pump reads it is like finding a needle in haystack… where the haystack is being shot out of a fire hose. In this case, the messaging system is proprietary and uses Zoom message class ( msg_db_t) for message objects. This messaging system is the typical inter-thread messaging system that you may find in large applications.
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |