首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

優酷視頻絕對地址獲取深度解析:從 AS3 反編譯到 PHP 實現

     編輯:PHP 相關知識

早期優酷播放器採用 ActionScript 3 加密邏輯,透過 ASV 反編譯可還原核心演算法。本文記錄從逆向分析到 PHP 移植的完整過程。

核心流程回顧

  1. 請求 getPlayList/VideoIDS/{id} 獲取 JSON
  2. 提取 seed、key1、key2、加密 fileid
  3. 種子演算法重建亂序字串表
  4. 解密 fileid 與 key
  5. 組合最終播放地址

PHP 解密類實現 (移植自 AS3)

<?php
class YoukuDecoder {
    private $randomSeed = 0;
    private $cgStr = '';

    public function __construct($seed) {
        $this->randomSeed = (int)$seed;
    }

    // 線性同餘產生器
    private function ran() {
        $this->randomSeed = (($this->randomSeed * 211) + 30031) % 65536;
        return $this->randomSeed / 65536; // 返回 [0,1) 比例
    }

    // 重建亂序字串表 (CG混)
    private function cgHun() {
        $this->cgStr = '';
        $sttext = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/:._-1234567890';
        $len = strlen($sttext);
        for ($i = 0; $i < $len; $i++) {
            $cuch = (int)($this->ran() * strlen($sttext));
            $this->cgStr .= $sttext[$cuch];
            $sttext = str_replace($sttext[$cuch], '', $sttext);
        }
    }

    // 解密 fileid
    public function decode($string) {
        $this->cgHun();
        $output = '';
        $expl = explode('*', $string);
        for ($i = 0; $i < count($expl) - 1; $i++) {
            $output .= $this->cgStr[(int)$expl[$i]];
        }
        return $output;
    }

    // 解密 key
    public function decodeKey($key1, $key2) {
        $key = hexdec($key1);
        $key = $key ^ -1520786011; // 0xA55AA5A5 的有號整數表示
        return $key2 . dechex($key);
    }
}

// 使用流程
$baseUrl = 'https://v.youku.com/player/getPlayList/VideoIDS/';
$videoId = $_GET['vid'] ?? 'XMjY0ODE1MDA0';

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => $baseUrl . $videoId,
    CURLOPT_HEADER => 1,
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_REFERER => 'https://v.youku.com/v_show/id_' . $videoId,
    CURLOPT_USERAGENT => $_SERVER['HTTP_USER_AGENT'],
    CURLOPT_NOBODY => 0,
]);
$content = curl_exec($ch);
curl_close($ch);

// 正則提取關鍵字段 (早期 JSON 格式)
preg_match('~"seed"\s*:\s*(\d+)\s*,~iUs', $content, $seed);
preg_match('~{\s*"(flv|mp4)"\s*:\s*"(.*)"\s*}~iUs', $content, $encoded);
preg_match('~"key1"\s*:\s*"(.*)"\s*,~iUs', $content, $key1);
preg_match('~"key2"\s*:\s*"(.*)"\s*,~iUs', $content, $key2);

$decoder = new YoukuDecoder($seed[1]);
$fileid = $decoder->decode($encoded[2]);
$key = $decoder->decodeKey($key1[1], $key2[1]);

// 組合地址
$s7 = substr($fileid, 10);
$s5 = substr($fileid, 0, 8);
$s6 = substr($fileid, 6, 2);
$s4 = '00'; // 分段號 (HEX)
$sid = time() . mt_rand(10, 99) . '1000' . mt_rand(30, 80) . '00';

$dAddr = 'https://f.youku.com/player/getFlvPath/sid/' . $sid . '_' . $s4 
    . '/st/' . $encoded[1] 
    . '/fileid/' . $fileid 
    . '?K=' . $key;

echo $dAddr;

關鍵演算法細節

種子亂序表重建 (cgHun)

對應 AS3 的 cg_hun 函數:

  • 字元池:64 字元 (a-z, A-Z, /, :, ., _, -, 0-9)
  • 每輪用 ran() 產生 [0,1) 隨機數,乘以池長度取索引
  • 取出字元加入結果,並從池中移除 (不重複)
  • 64 輪後得到唯一亂序表

Key 解密邏輯

// AS3 原始邏輯
var key:Number = hexdec(key1);
key = key ^ 0xA55AA5A5; // XOR 魔數
return key2 + dechex(key);

PHP 中 0xA55AA5A5 超過 32 位有號整數範圍,使用負數 -1520786011 等價處理。

⚠️ 現狀與限制

  • 早期版本專用:現代優酷已多次更新加密演算法
  • 當前採用 streamfileids 多畫質結構,每段獨立 K 值
  • 播放器已遷移至 HTML5/DRM,Flash 時代方案失效
  • 僅供逆向工程學習參考,請勿用於商業用途

現代版本處理流程 (參考)

// 1. 獲取播放清單
// 2. 解析 streamfileids: {"flv":"enc1","mp4":"enc2","hd2":"enc3"}
// 3. 各畫質獨立解密 fileid
// 4. 從 segs 獲取分段:[{no,size,seconds,k},...]
// 5. 每段組合 URL:.../fileid/{fileid}?K={段k值}
// 6. 串流播放需按順序請求各分段
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved