~boringcactus/widevine-l3-decryptor

08f1abc04643cc6fd538732c580f79989242e805 — fzfile 4 years ago 73aec0b + ed8a977 main
Merge pull request #1 from tomer8007/main

merge
4 files changed, 55 insertions(+), 53 deletions(-)

M README.md
M content_key_decryption.js
M content_script.js
M manifest.json
M README.md => README.md +3 -1
@@ 3,7 3,7 @@

But Widevine's least secure security level, L3, as used in most browsers and PCs, is implemented 100% in software (i.e no hardware TEEs), thereby making it reversible and bypassable.

This Chrome extension demonstates how it's possible to bypass Widevine DRM by hijacking calls to the browser's [Encrypted Media Extensions (EME)](https://www.html5rocks.com/en/tutorials/eme/basics) and decrypting all Widevine content keys transferred - effectively turning it into a clearkey DRM.
This Chrome extension demonstrates how it's possible to bypass Widevine DRM by hijacking calls to the browser's [Encrypted Media Extensions (EME)](https://www.html5rocks.com/en/tutorials/eme/basics) and decrypting all Widevine content keys transferred - effectively turning it into a clearkey DRM.

## Usage
To see this concept in action, just load the extension in Developer Mode and browse to any website that plays Widevine-protected content, such as https://bitmovin.com/demos/drm _[Update: link got broken?]_.


@@ 35,5 35,7 @@ Some reversing job on that binary can then be done to extract the secret keys an
## Why
This PoC was done to further show that code obfuscation, anti-debugging tricks, whitebox cryptography algorithms and other methods of security-by-obscurity will eventually by defeated anyway, and are, in a way, pointless.

This is **NOT** intended for copyright infringement or encouraging piracy.

## Legal Disclaimer
This is for educational purposes only. Downloading copyrighted materials from streaming services may violate their Terms of Service. **Use at your own risk.**

M content_key_decryption.js => content_key_decryption.js +16 -16
@@ 166,21 166,21 @@ function wordToByteArray(wordArray)
// byte array to CryptoJS format
function arrayToWordArray(u8Array) 
{
	var words = [], i = 0, len = u8Array.length;

	while (i < len) {
		words.push(
			(u8Array[i++] << 24) |
			(u8Array[i++] << 16) |
			(u8Array[i++] << 8)  |
			(u8Array[i++])
		);
	}

	return {
		sigBytes: len,
		words: words
	};
    var words = [], i = 0, len = u8Array.length;

    while (i < len) {
        words.push(
            (u8Array[i++] << 24) |
            (u8Array[i++] << 16) |
            (u8Array[i++] << 8)  |
            (u8Array[i++])
        );
    }

    return {
        sigBytes: len,
        words: words
    };
}

const toHexString = bytes => bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '');


@@ 209,4 209,4 @@ function PEM2Binary(pem)
    return bytes.buffer;
}

}());
\ No newline at end of file
}());

M content_script.js => content_script.js +14 -14
@@ 2,9 2,9 @@ injectScripts();

async function injectScripts() 
{
	await injectScript('lib/pbf.3.0.5.min.js');
	await injectScript('lib/cryptojs-aes_0.2.0.min.js');
	await injectScript('protobuf-generated/license_protocol.proto.js');
    await injectScript('lib/pbf.3.0.5.min.js');
    await injectScript('lib/cryptojs-aes_0.2.0.min.js');
    await injectScript('protobuf-generated/license_protocol.proto.js');


    await injectScript('content_key_decryption.js');


@@ 13,14 13,14 @@ async function injectScripts()

function injectScript(scriptName) 
{
	return new Promise(function(resolve, reject) 
	{
		var s = document.createElement('script');
		s.src = chrome.extension.getURL(scriptName);
		s.onload = function() {
			this.parentNode.removeChild(this);
			resolve(true);
		};
		(document.head||document.documentElement).appendChild(s);
	});
}
\ No newline at end of file
    return new Promise(function(resolve, reject) 
    {
        var s = document.createElement('script');
        s.src = chrome.extension.getURL(scriptName);
        s.onload = function() {
            this.parentNode.removeChild(this);
            resolve(true);
        };
        (document.head||document.documentElement).appendChild(s);
    });
}

M manifest.json => manifest.json +22 -22
@@ 1,29 1,29 @@
{
  "manifest_version": 2,
  "name": "Widivine Decryptor",
  "name": "Widevine Decryptor",
  "short_name": "WidevineDecryptor",
   "description": "Decrypts and logs media keys from websites that use Widivine DRM",
  "description": "Decrypts and logs media keys from websites that use Widevine DRM",
  "version": "1.0.0",
  "permissions": 
  "permissions":
  [
	

  ],
   "icons": 
   {
      
   },
   "browser_action": {
    
   },
   
   "content_scripts": 
   [
  	{
  	  "matches": ["https://*/*"],
  	  "js": ["content_script.js"],
  "icons":
  {

  },
  "browser_action": {

  },
  "content_scripts":
  [
    {
      "matches": ["https://*/*"],
      "js": ["content_script.js"],
      "css": [],
  	  "run_at": "document_start"
  	}
   ],
	"web_accessible_resources": ["content_key_decryption.js", "eme_interception.js", "lib/*", "protobuf-generated/*"]
}
\ No newline at end of file
      "run_at": "document_start",
      "all_frames": true
    }
  ],
  "web_accessible_resources": ["content_key_decryption.js", "eme_interception.js", "lib/*", "protobuf-generated/*"]
}