Trời tính không bằng máy tính

blog, tản mạn

#29: “Chống” download video?

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

MỚI! Đăng ký nhận bài viết mới nhất qua chatbot: