- Added Amazon support
- Added Crunchyroll support
- Cleaned loading functions for body
- Removed invalid DOM manipulations
- Moved pre.py functions to more specific services for more modularity
This commit is contained in:
CDM-Project 2024-09-23 15:34:31 -04:00
parent 21933c6675
commit 9841e460ae
9 changed files with 49 additions and 25 deletions

View File

@ -38,13 +38,39 @@ chrome.webRequest.onBeforeSendHeaders.addListener(
["requestHeaders", "blocking"]
);
//Get requestBody from POST requests
// Get requestBody from POST requests
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
if (details.method === "POST") {
let body = null;
// Check if requestBody.raw exists
if (details.requestBody.raw) {
// Convert raw bytes to a Base64 string
body = btoa(String.fromCharCode(...new Uint8Array(details.requestBody.raw[0]['bytes'])));
} else if (details.requestBody.formData) {
body = {};
for (let key in details.requestBody.formData) {
if (details.requestBody.formData.hasOwnProperty(key)) {
body[key] = details.requestBody.formData[key][0];
}
}
body = JSON.stringify(body)
} else if (details.requestBody.json) {
// Handle JSON if available
body = details.requestBody.json; // Keep it as an object
for (let key in body) {
if (body.hasOwnProperty(key) && Array.isArray(body[key])) {
body[key] = body[key][0];
}
}
body = JSON.stringify(body);
}
// Push the body and request ID to the bodys array
window.bodys.push({
body:details.requestBody.raw ? btoa(String.fromCharCode(...new Uint8Array(details.requestBody.raw[0]['bytes']))) : "",
id:details.requestId
body: body,
id: details.requestId
});
}
},

View File

@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Widevine L3 Decrypter",
"version": "2",
"version": "2.1",
"version_name": "a1297aa-cdm-project",
"icons": {
"128": "icon.png"

View File

@ -50,6 +50,8 @@
<label for="scheme">Challenge scheme</label>
<select id="scheme">
<option value="CommonWV">CommonWV</option>
<option value="Crunchyroll">Crunchyroll</option>
<option value="Amazon">Amazon</option>
</select>
<input type="button" id="guess" value="Decrypt">
<br>

View File

@ -25,7 +25,6 @@ function writeListElement(arrElements, list, outputVar, search) {
document.getElementById('selectPssh').style.display = 'none';
document.getElementById('selectRequest').style.display = 'none';
document.getElementById('wvHome').style.display = 'flex';
document.getElementById('toggleHistory').style.display = 'none';
});
list.appendChild(li);
}

View File

@ -2,7 +2,6 @@ from pywidevine.cdm import Cdm
from pywidevine.remotecdm import RemoteCdm
from pywidevine.device import Device, DeviceTypes
from pywidevine.pssh import PSSH
import json
import js
import base64
@ -64,15 +63,8 @@ async def corsFetch(url: str, method: str, headers: [dict, str], body: [dict, by
return res
# Define loadBody API for loading requestBody to scheme concisely
def loadBody(loadAs: str):
def loadBody():
global licBody
licBody = base64.b64decode(licBody.encode())
match loadAs:
case "blob": pass
case "str": licBody = licBody.decode()
case "json": licBody = json.loads(licBody.decode())
return licBody
# prepare pssh
@ -84,9 +76,4 @@ cdm = await loadCdm()
# open cdm session
session_id = cdm.open()
# get license challenge
challenge = cdm.get_license_challenge(session_id, pssh)
licHeaders=json.loads(licHeaders)
js.chrome.extension.getBackgroundPage().isBlock=False

View File

@ -1,8 +1,8 @@
import urllib.parse
service_cert = "CAUSwgUKvAIIAxIQCuQRtZRasVgFt7DIvVtVHBi17OSpBSKOAjCCAQoCggEBAKU2UrYVOSDlcXajWhpEgGhqGraJtFdUPgu6plJGy9ViaRn5mhyXON5PXmw1krQdi0SLxf00FfIgnYFLpDfvNeItGn9rcx0RNPwP39PW7aW0Fbqi6VCaKWlR24kRpd7NQ4woyMXr7xlBWPwPNxK4xmR/6UuvKyYWEkroyeIjWHAqgCjCmpfIpVcPsyrnMuPFGl82MMVnAhTweTKnEPOqJpxQ1bdQvVNCvkba5gjOTbEnJ7aXegwhmCdRQzXjTeEV2dO8oo5YfxW6pRBovzF6wYBMQYpSCJIA24ptAP/2TkneyJuqm4hJNFvtF8fsBgTQQ4TIhnX4bZ9imuhivYLa6HsCAwEAAToPYW1hem9uLmNvbS1wcm9kEoADETQD6R0H/h9fyg0Hw7mj0M7T4s0bcBf4fMhARpwk2X4HpvB49bJ5Yvc4t41mAnXGe/wiXbzsddKMiMffkSE1QWK1CFPBgziU23y1PjQToGiIv/sJIFRKRJ4qMBxIl95xlvSEzKdt68n7wqGa442+uAgk7CXU3uTfVofYY76CrPBnEKQfad/CVqTh48geNTb4qRH1TX30NzCsB9NWlcdvg10pCnWSm8cSHu1d9yH+2yQgsGe52QoHHCqHNzG/wAxMYWTevXQW7EPTBeFySPY0xUN+2F2FhCf5/A7uFUHywd0zNTswh0QJc93LBTh46clRLO+d4RKBiBSj3rah6Y5iXMw9N9o58tCRc9gFHrjfMNubopWHjDOO3ATUgqXrTp+fKVCmsGuGl1ComHxXV9i1AqHwzzY2JY2vFqo73jR3IElr6oChPIwcNokmNc0D4TXtjE0BoYkbWKJfHvJJihzMOvDicWUsemVHvua9/FBtpbHgpbgwijFPjtQF9Ldb8Swf"
cdm.set_service_certificate(session_id=session_id, certificate=service_cert)
challenge = cdm.get_license_challenge(session_id, pssh)
licHeaders = json.loads(licHeaders)
payload = f"widevine2Challenge={urllib.parse.quote(base64.b64encode(challenge).decode())}&includeHdcpTestKeyInLicense=true"
licHeaders['User-Agent'] = "Mozilla/5.0 (X11; Linux x86_64; rv:126.0) Gecko/20100101 Firefox/126.0"
res = await corsFetch(licUrl, "POST", licHeaders, payload, "json")
licence = res['widevine2License']['license']
licence = await corsFetch(licUrl, "POST", licHeaders, payload, "json")
licence = licence['widevine2License']['license']

View File

@ -1 +1,6 @@
licHeaders=json.loads(licHeaders)
# get license challenge
challenge = cdm.get_license_challenge(session_id, pssh)
licence = await corsFetch(licUrl, "POST", licHeaders, challenge, "blob")

View File

@ -0,0 +1,4 @@
licHeaders = json.loads(licHeaders)
challenge = cdm.get_license_challenge(session_id, pssh)
licence = await corsFetch(licUrl, "POST", licHeaders, challenge, "json")
licence = licence['license']

View File

@ -18,6 +18,7 @@ motv.eu/widevine_proxy$$moTV
mw.tvnsul.com.br/widevine_proxy$$moTV
vodafone.com/vtv/ccursession/v1/start$$Vodafone
api.oqee.net/api/v1/avod/license$$oqee
/v1/license/widevine$$Crunchyroll
contentlicenseservice/v1/licenses
media-license-server/validate-auth-token
wv-keyos.licensekeyserver