吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 50436|回复: 139
收起左侧

[原创] Chrome CDM框架重大缺陷,DRM视频轻易复制

    [复制链接]
codelive 发表于 2017-5-18 12:03
本帖最后由 codelive 于 2017-5-18 21:12 编辑

       我的工作领域和视频相关,保护视频内容非常重要,主流的浏览器和移动设备都支持DRM。近日我偶然发现Google Chrome浏览器的CDM(Content Decryption Module-内容解密模块)框架存在重大的设计缺陷,通过一些手段就可以轻松绕过DRM保护机制,非常容易的获取解密后的数据,从而把视频重新封装为未压缩的MP4等格式文件,还可以做到在观看的过程中直接进行无加密的视频直播。

发现问题后,我花了一点时间,写了一个测试程序,验证了我的想法。由于DRM的保护机制非常的重要,如果可以轻松被攻破,将对整个视频领域是一个威胁,所以我当时就向Google Chromium提交了bug,说明了CDM的框架的重大缺陷,并描述了实现细节。
这是的issue url(一般人没有权限查看,仅内部可见):
https://bugs.chromium.org/p/chromium/issues/detail?id=721639

Google有漏洞奖励规则,这是规则描述地址:
https://www.google.com/about/app ... -rewards/index.html
其实我当时的想法是,如果能获取来自Google的奖励,不论奖金多少,都将是一个至高无上的荣誉。

我提交后,Chromium团队很快的做出了回复,他们确认这是一个重大的安全问题,而且影响所有运行Chrome浏览器的操作系统,包括: Linux, Windows, Chrome, Mac等等. 但另一个员工说这是一个已知的问题,并提供了一个issue号: 658022,但我无限查看漏洞内容是否与我提交的一致。之后我向google 团队的几个成员发了邮件,说既然是已知的问题,那也就是不符合奖励规则,因此我也就可以公布细节,让视频内容公司重视这个问题,以便尽早的商讨更加安全的解决方案。

说了这么多,只想说明一下事件的背景,下面我就说明实现细节,很多东西可能有些专业,主要讲述一个过程。

1.安装Google Chrome 32bit版本(32版本容易使用工具进行调试)
2.Chrome内置的CDM是Widevine(几年前收购来的),目录在Google\Chrome\Application\58.0.3029.110\WidevineCdm,在子目录_platform_specific\win_x86有下2个dll:
    widevinecdm.dll - widevine核心模块,导出的函数有:InitializeCdmModule_4,DeinitializeCdmModule,CreateCdmInstance,GetCdmVersion,GetHandleVerifier
    widevinecdmadapter.dll - PPAPI插件标准适配库,导出函数有:PPP_GetInterface,PPP_InitializeModule,PPP_ShutdownModule
3.正常情况下播放DRM视频的流程:
    Chrome -> Widevine CDM Adapter(widevinecdmadapter.dll) -> Widevine CDM Module (widevinecdm.dll)
    widevinecdmadapter.dll调用widevinecdm.dll的导出函数CreateCdmInstance来创建CDM实例.
4.CDM框架是Google Chrome的标准,所以API参数和接口都有C++ include文件,比如API CreateCdmInstance:
    CDM_API void* CreateCdmInstance(int cdm_interface_version, const char* key_system, uint32_t key_system_size, GetCdmHostFunc get_cdm_host_func, void* user_data);

    CDM实例要继承于class ContentDecryptionModule_8,查看class ContentDecryptionModule_8,发现了一个非常重要的函数:Decrypt,主要是将加密的数据传入,解密后的数据传出,我的天呐,只要截获了这个函数不就搞定了吗!!!

[C++] 纯文本查看 复制代码
   class CDM_CLASS_API ContentDecryptionModule_8 {      // Decrypts the |encrypted_buffer|.
      //
      // Returns kSuccess if decryption succeeded, in which case the callee
      // should have filled the |decrypted_buffer| and passed the ownership of
      // |data| in |decrypted_buffer| to the caller.
      // Returns kNoKey if the CDM did not have the necessary decryption key
      // to decrypt.
      // Returns kDecryptError if any other error happened.
      // If the return value is not kSuccess, |decrypted_buffer| should be ignored
      // by the caller.
      virtual Status Decrypt(const InputBuffer& encrypted_buffer,
                             DecryptedBlock* decrypted_buffer) = 0;
    };

5.了解了API参数和class定义后,就设想如果在widevinecdmadapter.dll 和 widevinecdm.dll之间在互相调用时截获到解密后的数据就可以绕过DRM保护机制.
6.开始写一个DLL, 名为CdmProxy.dll, 我自己的CreateCdmInstance函数,这部分不解释了:
[C++] 纯文本查看 复制代码
    extern "C" __declspec(dllexport) void * CDMAPI_DEFINE my_CreateCdmInstance(int cdm_interface_version, const char* key_system,
        uint32_t key_system_size, GetCdmHostFunc get_cdm_host_func, void* user_data)
    {
        gHostUserData = user_data;
        wsprintf(wchLog, L"CdmProxy - call CreateCdmInstance(%d, %S, %d, 0x%08X, 0x%08X)",
            cdm_interface_version, key_system, key_system_size, get_cdm_host_func, user_data);
        OutputDebugStringW(wchLog);
        void *p = pCreateCdmInstance(cdm_interface_version, key_system, key_system_size, get_cdm_host_func, user_data);

        cdm::ContentDecryptionModule_8 *pCdmModule = (cdm::ContentDecryptionModule_8 *)(p);
        MyContentDecryptionModuleProxy *pMyCdmModule = new MyContentDecryptionModuleProxy(pCdmModule);

        return pMyCdmModule;
    }

    我的代{过}{滤}理class MyContentDecryptionModuleProxy,代码不解释:
    // class MyContentDecryptionModuleProxy
[C++] 纯文本查看 复制代码
    class MyContentDecryptionModuleProxy : public cdm::ContentDecryptionModule_8
    {
    public:
        MyContentDecryptionModuleProxy(cdm::ContentDecryptionModule_8 *pCdm)
        {
            mCdm = pCdm;
        }
    private:
        cdm::ContentDecryptionModule_8 *mCdm;

    public:
        // 最重要的解密函数,保存原数据和解密后的数据
        virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer, cdm::DecryptedBlock* decrypted_buffer)
        {
            cdm::Status status = cdm::kSuccess;
            codelive();
            DebugDecryptBreak(encrypted_buffer.iv, encrypted_buffer.key_id, encrypted_buffer.data);
            status = mCdm->Decrypt(encrypted_buffer, decrypted_buffer);
            
            string strIV = data2HexString((const char *)encrypted_buffer.iv, encrypted_buffer.iv_size);
            string strEncData = data2HexString((const char *)encrypted_buffer.data, min(encrypted_buffer.data_size, 32));
            string strDecData = data2HexString((const char *)decrypted_buffer->DecryptedBuffer()->Data(), 
                min(decrypted_buffer->DecryptedBuffer()->Size(), 32));
            wsprintf(wchLog, L"CdmProxy - call Decrypt(IV:%S, encData(%d):%S, decData(%d):%S)", 
                strIV.c_str(), encrypted_buffer.data_size, strEncData.c_str(), 
                decrypted_buffer->DecryptedBuffer()->Size(), strDecData.c_str());
            OutputDebugStringW(wchLog);

            if(mEncFile == NULL)
            {
                mEncFile = fopen("d:\\cdm_enc.bin", "wb");
            }
            if(mEncFile != NULL)
            {
                fwrite(encrypted_buffer.data, 1, encrypted_buffer.data_size, mEncFile);
            }
            if(mDecFile == NULL)
            {
                mDecFile = fopen("d:\\cdm_dec.bin", "wb");
            }
            if(mDecFile != NULL)
            {
                fwrite(decrypted_buffer->DecryptedBuffer()->Data(), 1, decrypted_buffer->DecryptedBuffer()->Size(), mDecFile);
            }
            return status;
        }
    };

7.核心代码写完了,就要解决DLL加载的问题,尝试了几种简单的方式,分别把widevinecdm.dll和widevinecdmadapter.dll改名为widevinecdm_org.dll和widevinecdmadapter_org.dll,然后自己写一个DLL,导出和widevinecdm.dll或者widevinecdmadapter.dll相同的API,然后再调用原来DLL的方式,但这种方式发现不可行,原因在于Chrome的安全沙盒,所有的插件都是加载的沙盒进程空间,敏感的API都无法使用,比如:ReadProcessMemory,CeateFile,OutputDebugString等等. 逃脱沙盒(Sandbox Escape)是Google奖金数额非常高的,最高可达$15,000.
8.既然进程都是Chrome创建的,所以就直接对chrome.exe下手,直接patch chrome.exe,让其加载我的CdmProxy.dll,结果成功了,毕竟chrome启动时还未启用沙盒机制,所以没花费太多技术就解决了DLL加载问题.

9.改变API截获方式,对widevinecdmadapter.dll进行动态的补丁,将调用API CreateCdmInstance的地址改为我自己的API my_CreateCdmInstance,然后在DLL加载时进行以下处理:
[C++] 纯文本查看 复制代码
    BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
    {
        switch(ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
            {
                hWideVineCdm = LoadLibraryW(L"{PATH}\\widevinecdm.dll");

                pInitializeCdmModule_4 = (InitializeCdmModule_4Func)GetProcAddress(hWideVineCdm, "InitializeCdmModule_4");
                pDeinitializeCdmModule = (DeinitializeCdmModuleFunc)GetProcAddress(hWideVineCdm, "DeinitializeCdmModule");
                pCreateCdmInstance = (CreateCdmInstanceFunc)GetProcAddress(hWideVineCdm, "CreateCdmInstance");
                pGetCdmVersion = (GetCdmVersionFunc)GetProcAddress(hWideVineCdm, "GetCdmVersion");

                hWideVineCdmAdapter = LoadLibraryW(L"{PATH}\\widevinecdmadapter.dll");
                if(hWideVineCdmAdapter != NULL)
                {
                    DWORD dwSrcAddr = (DWORD)hWideVineCdmAdapter + 0x0000446D;
                    const BYTE chVerify[] = { 0xFF, 0x15 };
                    BOOL isOK = patch_DsCallFunction(dwSrcAddr, (DWORD)my_CreateCdmInstance, chVerify, sizeof(chVerify));
                    wsprintf(wchLog, L"CdmProxy - patch CreateCdmInstance, Address:0x%08X-0x%08X, %s.",
                        dwSrcAddr, (uint32_t)my_CreateCdmInstance,
                        isOK ? L"OK" : L"FAILED");
                    OutputDebugStringW(wchLog);
                }
            }
            break ;
        }
    }

10.然后进行测试,播放一个有DRM保护的DASH视频:
    https://shaka-player-demo.appspo ... gleKey/Manifest.mpd
    发现文件没保存下来,LOG也没输出,想必是安全沙盒起作用了。
11.又要逃脱沙盒,经过研究,发现根本不需要,只要在chrome启动参数增加 --no-sandbox 即可。我的天呐,为啥要提供这样一个后门啊!!!

12.再次播放加密的视频,文件顺利保存下来,LOG也输出成功,经验证,解密后的数据与之前未加密的数据是一致的。

13.Google Chrome的CDM就这样被破解了,非常的简单的就绕过了Widevine DRM的算法,这应该是Chrome CDM的框架设计的严重问题,估计要改变也不是非常容易的。

这是LOG数据:

( "CdmProxy - call CreateCdmInstance(8, com.widevine.alpha, 18, 0x70F86310, 0x00D75A88)" )           0.0001399
( "CdmProxy - call CreateCdmInstance(8, com.widevine.alpha, 18, 0x70F86310, 0x00D757C8)" )           0.0000937
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818F00000000000000000, encData(348):FFF158402B9FFC2FF05300F2BF83E9A0, decData(0):)" )           0.0001350
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818F00000000000000000, encData(348):FFF158402B9FFC2FF05300F2BF83E9A0, decData(348):FFF158402B9FFC00D03403E95B8639BD)" )         0.0001335
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818F00000000000000000, encData(348):FFF158402B9FFC2FF05300F2BF83E9A0, decData(348):FFF158402B9FFC00D03403E95B8639BD)" )         0.0001032
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818F10000000000000000, encData(348):FFF158402B9FFC487380B8930FFFAB41, decData(348):FFF158402B9FFC00F43420C24620902C)" )         0.0001392
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818F20000000000000000, encData(349):FFF158402BBFFC1175E15FE4B6154B30, decData(349):FFF158402BBFFC00FA342D90762A3188)" )         0.0001032
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818F30000000000000000, encData(348):FFF158402B9FFCC45D5715E87235E5CF, decData(348):FFF158402B9FFC00F8342CEC825A2D85)" )         0.0000994
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818F40000000000000000, encData(348):FFF158402B9FFC6749FBAF64926471DE, decData(348):FFF158402B9FFC00F83421884529290A)" )         0.0000880
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818F50000000000000000, encData(349):FFF158402BBFFCF8132EFC31C186DDE1, decData(349):FFF158402BBFFC00F2342D9049124988)" )         0.0001088
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818F60000000000000000, encData(348):FFF158402B9FFC82EDA0BD4AB7158938, decData(348):FFF158402B9FFC00EE342D7475223D85)" )         0.0001035
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818F70000000000000000, encData(348):FFF158402B9FFC4B2C585CC10F74036E, decData(348):FFF158402B9FFC00F4342D74662A2088)" )         0.0001555
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818F80000000000000000, encData(349):FFF158402BBFFCCF33665AC4E219EC92, decData(349):FFF158402BBFFC00FA342E30547B0604)" )         0.0001494
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818F90000000000000000, encData(348):FFF158402B9FFC2C9A7362594261CE23, decData(348):FFF158402B9FFC00F4342E305429150A)" )         0.0004035
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818FA0000000000000000, encData(348):FFF158402B9FFC1905A086AE3CEF0AEC, decData(348):FFF158402B9FFC00EE342E3456391906)" )         0.0005913
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818FB0000000000000000, encData(349):FFF158402BBFFC8D0EB865013262FB6E, decData(349):FFF158402BBFFC00F6342E34563A2186)" )         0.0001479
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818FC0000000000000000, encData(348):FFF158402B9FFC484211C612F22283FB, decData(348):FFF158402B9FFC0102342E74482A2E02)" )         0.0002507
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818FD0000000000000000, encData(348):FFF158402B9FFC283122B1DDE740DAC2, decData(348):FFF158402B9FFC0104342EB464190D08)" )         0.0003011
( "CdmProxy - call Decrypt(IV:6CD1F4FBCE5818FE0000000000000000, encData(349):FFF158402BBFFCAC8759D48FF1A258A3, decData(349):FFF158402BBFFC010E342ED04A1A2982)" )         0.0003095


DRM这么多年了,很多保护机制和算法都做的非常严密,但还是被Zhu一样的队友给出卖了。

公开这个研究,是为了让广大的视频公司不要以为DRM非常的安全,有时候真的是不堪一击,某个环节出现漏洞,同样面临极大的安全问题。

如果此篇文章不适合公布,请通知我,谢谢。

点评

厉害了我的哥  发表于 2017-6-18 12:42
以前我要有好的想法都投稿给电脑爱好者赚稿费了。楼主更牛~~不得不佩服  发表于 2017-5-18 18:58

免费评分

参与人数 76吾爱币 +82 热心值 +75 收起 理由
suxiaoxiann + 1 + 1 谢谢@Thanks!
用户APTX4869 + 1 + 1 用心讨论,共获提升!
greydesolate + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
小菜戏大神 + 1 + 1 厉害了我的楼主
【健谈】 + 1 + 1 谢谢@Thanks!
奴爱破戒 + 1 + 1 我很赞同!
xouou + 3 + 1 666
GlowCarlos + 1 + 1 用心讨论,共获提升!
zy1234 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
王大大 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
wintter + 1 + 1 不明觉厉
roamshi + 1 + 1 谢谢@Thanks!
劣酒先生 + 1 + 1 已答复!
福特野马 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
wangjunwu1995 + 1 + 1 热心回复!
仁二 + 1 + 1 看完第4点的最后一句 我就觉得vevry good!
哇哦哇哦哇咔咔 + 1 我很赞同!
logh + 1 + 1 热心回复!
测试中…… + 1 + 1 用心讨论,共获提升!
lxrhome + 1 + 1 谢谢@Thanks!
腹黑狐狸 + 1 + 1 用心讨论,共获提升!
biubiufish + 1 + 1 我很赞同!
海海海℃ + 1 + 1 用心讨论,共获提升!
fu90 + 1 + 1 热心回复!
jasonsi + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
DarinLo + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
大器晚成0125 + 1 + 1 用心讨论,共获提升!
wl123 + 1 + 1 我很赞同!
jackjack999 + 1 + 1 用心讨论,共获提升!
Y城的L君 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
疯狂の马甲 + 1 + 1 我很赞同!
QingTianGG + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
mjchjs6 + 1 + 1 我很赞同!
aa5833891 + 1 + 1 谢谢@Thanks!
MatrixOne + 1 + 1 热心回复!
SunAndMoon + 1 + 1 谢谢@Thanks!
xyuetao + 1 + 1 谢谢@Thanks!
ricky2015 + 1 + 1 热心回复!
dushiyufu + 1 + 1 鼓励转贴优秀软件安全工具和文档!
w694950582 + 1 + 1 用心讨论,共获提升!
Mrxn + 1 + 1 用心讨论,共获提升!
sylph + 1 + 1 谢谢@Thanks!
hsia_y + 1 + 1 谢谢@Thanks!
MXWXZ + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
白吱声 + 1 + 1 请收下我的膝盖
仙峰涯 + 1 + 1 其实已经有很多解析可以解析drm保护。
anwzx + 2 + 1 热心回复!
shanhuyi + 1 + 1 我很赞同!
0001 + 2 + 1 我很赞同!
Karma。 + 1 + 1 谢谢@Thanks!
食土码农 + 1 用心讨论,共获提升!
TheMistyStar + 1 + 1 用心讨论,共获提升!
myqqq + 2 + 1 厉害了
zjjxyz + 1 + 1 膜拜一下大神。
当合 + 1 + 1 热心回复!
virgo + 1 + 1 热心回复!
修罗本灭世 + 1 + 1 我很赞同!
swx5201314 + 1 + 1 用心讨论,共获提升!
秋水 + 1 + 1 干货
lightback + 1 + 1 用心讨论,共获提升!
白笙 + 1 + 1 谢谢@Thanks!
sau + 1 + 1 热心回复!
niconico128 + 1 + 1 一个字 牛
说再见 + 1 + 1 用心讨论,共获提升!
xwei9277 + 1 + 1 谢谢@Thanks!不是一般的N!!!
Koardor + 1 + 1 用心讨论,共获提升!
biaggi + 1 + 1 禁止发布黑客相关内容!
失业 + 1 + 1 小白赶紧百度一下什么叫DRM
a5606495 + 1 + 1 谢谢@Thanks!
junshang + 1 + 1 热心回复!
5乐知 + 1 + 1 热心回复!
yzzxtaofeng + 1 + 1 我很赞同!
repobor + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
懇樂樂 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Xu1120 + 1 + 1 厉害了楼主
小裕 + 2 + 1 我很赞同!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

lrv 发表于 2017-5-18 13:23
谷歌应该不会耍赖吧!又不是中国华为!
头像被屏蔽
summer591 发表于 2019-4-27 17:03
小裕 发表于 2017-5-18 12:13
浮萍不是花 发表于 2017-5-18 12:22
厉害了我的神,你可以去淘宝卖视频了
落枫BJ 发表于 2017-5-18 12:28
讲解得很详细~但是,建议设置权限~不然,吾爱也有很多水货的。
懇樂樂 发表于 2017-5-18 12:36
前排膜拜大神
colinjian22 发表于 2017-5-18 12:49
看不懂。。。。
junshang 发表于 2017-5-18 13:04
虽然看不懂。但是必须支持下大佬。。
潇湘珠媚 发表于 2017-5-18 13:05
膜拜大神
5乐知 发表于 2017-5-18 13:05
哇,可不敢卖视频啊,买视频可不敢告诉我们你的门店啊
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 13:26

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表