29 February, 2020

#29: "Chống" download video?

Nghiên cứu “Giải pháp chống download video” của protectvideodownload chấm com

#29: "Chống" download video?
Available in:
 English
 Vietnamese
Reading time: 4 min.
Table of content

    Bài viết này mình viết khá sơ sài, để tham khảo cho vui. Mình không có code “bấm là chạy”, do mình lười thật, và cũng để tránh ảnh hưởng tới sản phẩm của họ

    Hôm qua, do mới được biết đến “Giải pháp chống download video” của web protectvideodownload chấm com, nên mình khá hứng thú muốn tìm hiểu về công nghệ này. Và cũng có nhiều người hỏi, nên mình quyết định sẽ tìm hiểu “sơ sơ” xem nó thực sự hoạt động thế nào, và có đúng được như lời giới thiệu là “chống” hoàn toàn việc tải video hay không.

    Vậy không dài dòng nữa, mình sẽ đi vào kỹ thuật luôn.

    Tìm hiểu

    Thoạt nhìn vào tab Network, bạn có thể filter ra một vài truy vấn tới file có dạng .m3u8, .ts,… vốn thuộc định dạng HLS video streaming được sử dụng phổ biến gần đây.

    Ngon, vậy tìm file m3u8 là tải được bằng ffmpeg luôn đúng không?

    Nope, không dễ chơi như vậy

    Giờ để ý kỹ bên tab Network, bạn sẽ thấy rõ ràng nó theo 1 thứ tự lặp lại:
    – hls.key
    – touch.php
    – (file .ts)

    Vậy rõ ràng là có gì đó mờ ám xảy ra rồi, hãy cùng xem hàm nào đã gọi các truy vấn này nào (xem Initiator)

    Với hls.key và file .ts thì ko có gì thú vị, do nó đc gọi từ thư viện videojs, vốn là thư viện để hỗ trợ đọc file hls trên trình duyệt

    Tuy nhiên để ý touch.php, bạn sẽ thấy nó đc gọi từ custom.js, và nó trả lại 1 đoạn string random, nhìn như base64 vậy

    Ắt hẳn có gì thú vị ở custom.js rồi, cùng xem nào

    Ờ thì nó được làm rối – Obfuscated (chứ KHÔNG PHẢI MÃ HÓA nhé các bạn). Đối với kiểu array of strings thế này, thì nó cũng khá căn bản, chỉ cần lên google tìm “deobfuscate js” cũng ra.

    Ở đây mình dùng https://lelinhtinh.github.io/de4js/

    Tiếp tục cuộn xuống để tìm touch.php, nó được gọi từ đây:

    Ở đây ta thấy có “beforeRequest”, vậy hóa ra nó sẽ chỉnh sửa lại truy vấn, lắp thêm “&token=” vào truy vấn gửi đi bởi videojs

    Nhưng mà “&token=” được lấy từ đâu? Hóa ra, nó được lấy từ touch.php luôn, và đc xử lý bằng 1 function nhín khá rối. Nhưng kệ nó, ta sẽ coi nó như 1 black box

    Nguyên lý hoạt động

    Vậy là rõ rồi, cách nó hoạt động như sau:

    1. videojs lấy file playlist m3u8, chứa địa chỉ tất cả các mảnh của video
    2. videojs sẽ tạo các truy vấn HTTP để lấy dữ liệu của các mảnh này
    3. TUY NHIÊN, do đoạn code trong custom.js, mọi truy vấn của videojs sẽ được lắp thêm 1 token
    4. token này được lấy từ “video/touch.php”, và nó là token sử dụng 1 lần (nên mỗi lần tải mảnh mới phải lấy token mới)

    Và như vậy, nó cũng tạo ra kha khá những khó khăn đây chứ. Khó khăn nhất ở chỗ, những phần mềm như ffmpeg chỉ đc lập trình để lấy trực tiếp các phần của video (file .ts), chứ mình không thể lập trình nó để lắp thêm token được => Không thể tải bằng các phần mềm hiện có

    Giải pháp?

    Hiểu nguyên lý hoạt động, có code deobfuscated rồi, ta có thể lập 1 kế hoạch như sau:

    1. Lấy file m3u8
    2. Tải hls.key để cho ffmpeg sau này có thể giải mã file đã tải về
    3. Giả truy vấn tới touch.php để lấy token
    4. Tải tạm các part .ts về máy, đặt vào 1 chỗ
    5. Lập file m3u8 mới, có cùng thông số mới file m3u8 cũ, chỉ khác là các địa chỉ sẽ được chuyển về các file đã tải về máy (gồm các file .ts và hls.key)
    6. Chuyển file m3u8 mới này sang mp4, dùng ffmpeg

    Do cũng không có nhiều thời gian, nên mình sẽ để lại code của phần dùng để lấy token (gọi tới touch.php), và sau đó lắp vào “&token=” ở link của các part

    Với cách này, nếu làm thủ công, mình đã tải đc dần dần các part đầu về và ghép lại với nhau

    Want to receive latest articles from my blog?