Khi bạn muốn lấy link gốc video từ youtube đối với 1 số video thường của các kênh được xác minh tích xám thì các link video gốc đó có thể có chữ ký bảo mật hay được định danh là cipher như ví dụ minh họa bên dưới
Array (
[s] => bObOq0QJ8wRgIhAOJPpnO9AcUCc9UEAwEKnUd=drP-m3xvnI3v1Dge4x_nAiEA8gpSsZEKeAcqbUnI03X0Q-JAN0zSPzpHeOkRwEHO03wR3wR
[sp] => sig
[url] => https://r6—sn-vgqs7nls.googlevideo.com/videoplayback?expire=1590508352&[1 chuỗi rất dài với nhiều tham số …]
)
[s] => chữ ký đã mã hóa, ta cần decode chữ ký này nếu muốn video chạy
cấu trúc chạy url trên sẽ là: [url].’&sig=’.decode([s])
để Decode [s] ta cần phải dùng curl để get content từ link youtube.com/watch?v=IDVIDEO và tìm lấy link js sau: https://www.youtube.com/s/player/[4583e272]/player_ias.vflset/en_US/base.js phần [4583e272] nó là 1 biến sẽ thay đổi theo thời gian vì vậy tùy video và thời gian sẽ có url js khác nhau, link js trên chưa các hàm để decode cipher signature.
- Ta cần tìm được func name decode là gì:
- chúng ta sẽ dựa vào cấu trúc này để dùng biểu thức regex tìm và lấy ra func name decode chính:
- Khi viewsource link js trên chúng ta cũng sẽ tìm thấy cấu trúc func name decode như mẫu bên dưới và ta phải tìm cách lấy được hàm này để decode
- Mẫu func decode như sau:
-
zw = function(a) { a = a.split(""); yw.ro(a, 2); yw.S6(a, 43); yw.ro(a, 3); yw.uW(a, 14); yw.uW(a, 68); yw.S6(a, 4); yw.uW(a, 49); yw.uW(a, 30); yw.uW(a, 69); return a.join("") };
ta có thể dùng biểu thức regex như sau để lấy:
-
if (preg_match('@\b([a-zA-Z0-9$]{2})\s*=\s*function\(\s*a\s*\)\s*{\s*a\s*=\s*a\.split\(\s*""\s*\)@is', $js_code, $matches)) { echo $matches[1].'-'; return preg_quote($matches[1]); }
\s* : biểu thị cho khoảng trắng nhiều hay ít
Hoặc cũng có thể dùng lệnh sau để lấy được funcname hàm trên:
$fcname=explode('(decodeURIComponent(c))',$js_code)[0]; $fcname=preg_replace('#(.*)=#is','',$fcname); if($fcname!=''){ return $fcname; }
Cách nào cũng được cốt là ta cần xác định được func name decode như mẫu trên kết quả là zw
Tiếp đến ta cần cấu trúc lại hàm decode như mẫu chú thích sau:
zw = function(a) { a = a.split(""); yw.ro(a, 2); /* [0] => splice [1] => 2 */ yw.S6(a, 43); /* [0] => reverse [1] => 43 */ yw.ro(a, 3); /* [0] => splice [1] => 3 */ yw.uW(a, 14); /* [0] => swap [1] => 14 */ yw.uW(a, 68); /* [0] => swap [1] => 68 */ yw.S6(a, 4); /* [0] => reverse [1] => 4 */ yw.uW(a, 49); /* [0] => swap [1] => 49 */ yw.uW(a, 30); /* [0] => swap [1] => 30 */ yw.uW(a, 69); /* [0] => swap [1] => 69 */ return a.join("") };
Cấu trúc lại với ro = splice, S6 = reverse, uW = swap
Làm sao khi cấu trúc lại ta có công thức giải mã:
foreach ($instructions as $opt) { $command = $opt[0]; $value = $opt[1]; if ($command == 'swap') { $temp = $signature[0]; $signature[0] = $signature[$value % strlen($signature)]; $signature[$value] = $temp; } elseif ($command == 'splice') { $signature = substr($signature, $value); } elseif ($command == 'reverse') { $signature = strrev($signature); } }
$instructions có giá trị mẫu là 1 mảng như sau: [0] => splice [1] => 2 … cho đến [0] => swap [1] => 69 tương ứng theo từng số ở hàm func name zw mẫu bên trên.
với $opt[0]: là command giá trị có thể là: swap, splice, reverse
với $opt[1]: là các giá trị : 2, 43,3 … 69 tương ứng trong hàm func name zw mà ta lấy được như mẫu trên
Từ đó áp dụng theo công thức trên để thay thế tương ứng trong chuỗi signature gốc, như vậy là ta đã giải mã thành công.