29 February, 2020

#29: "Preventing" video downloads?

Reverse-engineering the "Solution to prevent video downloads" from protectvideodownload dot com

#29: "Preventing" video downloads?
Available in:
 English
 Vietnamese
Reading time: 3 min.
Table of content

    This article is written quite briefly, for fun reference. I don't have "click-to-run" code, because I'm lazy, and also to avoid affecting their product.

    Yesterday, having just learned about the "Solution to prevent video downloads" from protectvideodownload dot com, I was quite interested in learning about this technology. Many people asked about it, so I decided to do a "quick" investigation to see how it actually works, and whether it truly "prevents" video downloads completely as advertised.

    Without further ado, let's dive into the technical aspects.

    Investigation

    At first glance in the Network tab, you can filter out some queries to files with .m3u8, .ts extensions, which belong to the HLS video streaming format that has become popular recently.

    Great, so finding the m3u8 file means we can download it using ffmpeg, right?

    Nope, it's not that easy

    Now, paying close attention to the Network tab, you'll clearly see it follows a repeating pattern:

    • hls.key
    • touch.php
    • (.ts file)

    So clearly something suspicious is happening. Let's see which function called these queries (check the Initiator)

    For hls.key and .ts files, there's nothing interesting, as they're called from the videojs library, which is a library to support reading hls files in browsers.

    However, notice touch.php, you'll see it's called from custom.js, and it returns a random string that looks like base64.

    There must be something interesting in custom.js, let's take a look

    Well, it's been obfuscated (NOT ENCRYPTED, mind you). For this type of array of strings, it's quite basic, you can just google "deobfuscate js" to find solutions.

    Here I use https://lelinhtinh.github.io/de4js/

    Continue scrolling down to find touch.php, it's called from here:

    Here we see "beforeRequest", so it turns out it will modify the query, adding "&token=" to the query sent by videojs

    But where does "&token=" come from? It turns out, it's taken from touch.php itself, and processed by a function that looks quite complex. But never mind, we'll treat it as a black box.

    Operating principle

    So it's clear now, the way it works is as follows:

    1. videojs gets the m3u8 playlist file, containing addresses of all video segments
    2. videojs will create HTTP queries to get the data of these segments
    3. HOWEVER, due to the code in custom.js, every query from videojs will have a token appended
    4. This token is obtained from "video/touch.php", and it's a one-time use token (so each time a new segment is loaded, a new token must be obtained)

    And so, it creates quite a few difficulties. The biggest difficulty is that programs like ffmpeg are only programmed to directly fetch video parts (.ts files), and we can't program it to append tokens => Can't download using existing software

    Solution?

    Understanding the operating principle, having the deobfuscated code, we can devise a plan as follows:

    1. Get the m3u8 file
    2. Download hls.key so ffmpeg can later decrypt the downloaded file
    3. Simulate queries to touch.php to get tokens
    4. Temporarily download .ts parts to the machine, put them in one place
    5. Create a new m3u8 file, with the same parameters as the old m3u8 file, only different in that the addresses will be changed to the files downloaded to the machine (including .ts files and hls.key)
    6. Convert this new m3u8 file to mp4, using ffmpeg

    Due to time constraints, I'll leave the code for the part used to get tokens (calling touch.php), and then inserting "&token=" into the link of the parts.

    With this method, if done manually, I've gradually downloaded the first parts and pieced them together.

    Want to receive latest articles from my blog?
    Follow on