Tuesday, August 26, 2008

Capturing content streamed by Flash Media Server: How and How to avoid it

Flash media server is a media server which streams flash video. Basic difference between streaming and progressive (youtube) is that incase of streaming, the video is never stored on client's disk. As soon as it is displayed, video data is discarded. This makes it difficult for a user to store the video on it's disk to view it offline. Then how are tools like 'Replay Media Catcher' etc able to do this so easily?

To start with, RTMP (Real Time Media Protocol) has been completely reverse engineered. Being a text based protocol, doing this wasn't very difficult for experienced hackers. A lot of open source implementations of RTMP are available, which allow a user to write C++ or Java applications to connect to FMS and subscribe to streams. Once you know the name of the FMS server and the stream name, you can use these applications to subscribe to that stream and dump audio/video data into a FLV.

Is it really that simple? The answer is yes, only if the server side application developer forgot to add any kind of authentication mechanism. This is 2nd reason why these so called 'media catchers' are able to work without a glich. Wihtout any kind of authentication, 'Replay Media Catcher' is easily able to open a new NetConnection with FMS, which is gracefully accepted by the server since the application programmer forgot to authenticate the client. That would be a silly thing to do especially if one is planning to commercialy host video content.

Now to the ultimate question. How does 'Replay' figure out the name of the application to connect to and the stream name to subscribe when a .swf file(in a separate process) is trying to subscribe to a stream. My initial guess is that it is trying to hack into flash player's memory to get this information. It would be very difficult to extract this information by looking at the packets being sent over the network and virtualy impossible if RTMPE is used by the .swf. There is no way it can decrypt data being exchanged between client and the server incase of RTMPE.

So what should one do to protect their content? Simple, authenticate the clients which try to connect to your application. Don't just blindly accept connections. The auth mechanism need not be complex. Very simple mechanisms like exchanging random numbers during the connection process can do the trick. Also use RTMPE to avoid any kind of packet sniffing. RTMPE is a lot faster than SSL and doesnt require certificates.
The following link provides a nice introduction of various sceurity features offered by FMS:
http://blogs.adobe.com/security/2007/07/how_to_protect_flash_video_wit.html

Finally i'd like to say is that content is precious. Don't let these tools hack into your hard work.

Thursday, May 1, 2008

Fixing youtube flv's to make them streamable through FMS (flash media server)

FLV's available on youtube are not streamable through Flash Media Server. They will play fine using vlc player or other tools, but as soon as FMS tries to stream these,  the requesting client will be disconnected.
This happens because the metadata tag is not correctly formed. In the following post i'll show how to correct such files.

Step 1. Add 6 to the metadata tag's size field.
  • Size of the metadata tag is written 3 bytes, starting from the 15th byte. This is an integer stored in big endian format. Replace this size by size + 6. (in big endian).
Step 1: Location of the size field
        
Step 1: Size field after adding 6 to it


Step 2: Add 6 bytes at the end of the metadata tag.
  • To reach boundary of the end of metadata and the starting of the first tag, search for the following hex string '0x00 0x00 0x00 0x00 0x08'. The first 4 bytes are the end of the metadata tag (called the 'previous tag size') and '0x08' is the starting of the next tag.

Step 2: Search the end of the metadata tag.
  • Insert 6 bytes (0x00 0x00 0x09 0x00 0x00 0x09) before this. These are the 'object end markers'.

Step 2: Add the 'object end markers'


Step 3: Correct the 'previous tag size', for the metadata tag. This should contain a value = new metadata size + 11. This should be an integer and should be written in big endian.

Step 3: Correct the 'previous tag size'.

That's it!