DRM, short for Digital Rights Management, is a technology for access control to prevent copyrighted multimedia content from being accessed illegally. Videos protected by DRM cannot be watched normally even after they are downloaded. There are currently three major implementation solutions globally, namely Google's Widevine, Apple's FairPlay, and Microsoft's PlayReady. Among them, Widevine is the simplest, free, and has the highest market share, and is the most widely used. The Widevine client is mainly integrated into mobile phones, TVs, various browsers, players, and other devices, used for decrypting protected videos. This article focuses on the working principle of Widevine and the methods to bypass the protection.
I. Principle
The streaming media service provider first places the encrypted video content on its own content server and places the key in the Widevine authentication server provided by Google. When the user plays the video, they first complete authentication with the Widevine server, obtain the key, and then download the video from the content server and decrypt and play it with the key.
Widevine has three security levels - L1, L2, and L3. L1 is the highest security level, with the entire decryption process completed in hardware, which requires device support. L3 is the lowest security level, with the entire decryption process completed in the CDM (Content Decryption Module) software. L2 is between the two, with the core decryption process completed in hardware, and the video processing stage completed in software. This article only discusses the decryption method of L3 video.
To play L3 encrypted video, the CDM module is required, and mainstream video playback devices are all built-in with CDM. When the player calls DRM for decryption, the following process occurs:
When the user starts to play the video, the client downloads the mpd file from the video server. After parsing the mpd, the player determines whether the video uses Widevine encrypted video based on the relevant fields.
The player sends the initialization information of the encrypted audio and video stream to the built-in CDM module for decryption.
Upon receiving the initialization information from the player, the CDM creates a 'license request' and sends it back to the player.
After receiving the license request, the player sends the request to the Widevine license server. The license request is fully encrypted, and the method of packet capture and modification cannot be used for attacks.
After receiving the player's request, the license server decrypts it, extracts the initialization information, and finds the playback key in its database through the initialization information. Then the key is encrypted and returned to the player.
The player receives the key returned by the license server and passes it to the CDM. All traffic is encrypted, and neither the player nor the intermediary can read the relevant information.
The CDM calls the relevant decryption tool to decrypt the encrypted video segment by segment and transmit it to the player in real time for playback, without storing it locally.
The process diagram is as follows:
II. Methods of Decryption
According to the above principles, as long as we can obtain the CDM and capture the request URL of the license server, we can construct a decryption request message and obtain the decryption key. However, as a preset module of the player, CDM has no download channel, and the official will monitor the abuse situation in real time. Frequent decryption of CDM will result in the revocation of the license, so there are no ready-made decryption tools on the Internet, nor any CDM available for download. Therefore, we need to extract CDM ourselves.
2.1 Extract CDM
The simplest way is to buy an old Android phone that can be rooted, and the Android version needs to be below 11. After rooting, you can extract it with the tools of wvdumper:https://github.com/wvdumper/dumper
Operation method:
Install frida on Android, and run
Connect the computer to adb debugging
Run dump_keys.py on the computer
Play a DRM video on the mobile browser, for examplehttps://bitmovin.com/demos/drm
There are already two device files in the key_dumps folder on the computer.
Note: The DRM video needs to be played successfully before CDM can be extracted. If the playback fails, it is usually due to network issues and may require a proxy. If not captured, try changing several browsers.
2.2 Generate a device file based on two device files
from pywidevine.device import Device
from pathlib import Path
# e.g., for an Android L3:
device = Device(
type_=Device.Types.ANDROID,
security_level=3,
flags=None,
private_key=Path(r"private_key.pem").read_bytes(),
client_id=Path(r"client_id.bin").read_bytes()
)
# save it to a .wvd file for easier loading next time
device.dump(r"https://www.freebuf.com/articles/database/device.wvd")
2.3 Get key
Materials required:
mpd link. It can be obtained by packet capture or app reverse engineering.
PSSH. Most mpd files will contain PSSH strings, while a small number of mpd files only contain KID. KID needs to be converted to PSSH with other tools, or captured through hook methods, or the results calculated internally by the player.
Get the address of the license server. It can be obtained by packet capture or app reverse engineering.
Enter the parameters into the following script to obtain the key
from pywidevine.cdm import Cdm
from pywidevine.device import Device
from pywidevine.pssh import PSSH
import requests
# prepare pssh
pssh = PSSH("AAAAW3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADsIARIQ62dqu8s0Xpa7z2FmMPGj2hoNd2lkZXZpbmVfdGVzdCIQZmtqM2xqYVNkZmFsa3IzaioCSEQyAA==")
# load device
device = Device.load("https://www.freebuf.com/articles/database/device.wvd")
# load cdm
cdm = Cdm.from_device(device)
# open cdm session
session_id = cdm.open()
# get license challenge
challenge = cdm.get_license_challenge(session_id, pssh)
# send license challenge (assuming a generic license server SDK with no API front)
proxies = {
'http': 'http://127.0.0.1:1080',
'https': 'http://127.0.0.1:1080',
}
licence = requests.post("https://cwip-shaka-proxy.appspot.com/no_auth", data=challenge,proxies=proxies)
licence.raise_for_status()
# parse license challenge
cdm.parse_license(session_id, licence.content)
# print keys
for key in cdm.get_keys(session_id):
print(f"[{key.type}] {key.kid.hex}:{key.key.hex()}"
# close session, disposes of session data
cdm.close(session_id)
The number of keys obtained is not fixed, and all need to be saved.
2.4 Download and decrypt the video:
It is recommended to use N_m3u8DL-RE+shaka tools:
https://github.com/nilaoda/N_m3u8DL-RE
https://github.com/shaka-project/shaka-packager
Place N_m3u8DL-RE and packager-linux-x64 in the same directory, and run the following command to download and decrypt.
https://www.freebuf.com/articles/database/N_m3u8DL-RE-M_format=mp4 "https://cdn.bitmovin.com/content/assets/art-of-motion_drm/mpds/11331.mpd" --key ccbf5fb4c2965be7aa130ffb3ba9fd73:9cc0c92044cb1d69433f5f5839a159df --key 9bf0e9cf0d7b55aeb4b289a63bab8610:90f52fd8ca48717b21d0c2fed7a12ae1 --key eb676abbcb345e96bbcf616630f1a3da:100b6c20940f779a4589152b57d2dacb --key 0294b9599d755de2bbf0fdca3fa5eab7:3bda2f40344c7def614227b9c0f03e26 --key 639da80cf23b55f3b8cab3f64cfa5df6:229f5f29b643e203004b30c4eaf348f4 --use-shaka-packager --save-name day6.mp4 --live-real-time-merge -sv best -sa best
Summary
L3-level encryption protection is safer than unprotected video, significantly increasing the decryption threshold. However, the security is not sufficient, theoretically it can all be decrypted. For content providers of streaming media to further improve security, it is recommended to use L1-level encryption, encrypt and hide key information such as license server, check if the playback environment is rooted, and other methods to further increase the decryption threshold.

评论已关闭