Hello,
i'm trying to download a videos from guruflix.biz that uses anti scrape by cloudflare. The page loads a file called drm.js and a wasm component. The manifest of .m3u8 is able to download only if you include the correct headers and cookies by cloudflare. The chunk in the playlist can be downloaded without this but are encripted. The .m3u8 says AES-128 but i think that the videos doesnt exist in .ts format
for every chunck from the playlist the cdn response with something that seems base64 encoded, maybe a token for single fragment or info/key for the wasm.
in drm.js i've found a function that calculate a key from my email and one of x-ray headers token but the key is too long for aes128
i've have tried to inject the attached js code but after tests... i can only get the audio in the right sequence and the correct mpg header not the video
i've run out of ideas and i need your help -_-"
+ Reply to Thread
Results 1 to 5 of 5
-
-
-
I tried one course myself and it's using widevine for me
Bypass HMACs, One-time-tokens and Lic.Wrapping: https://github.com/DevLARLEY/WidevineProxy2 -
Hello, I had a Python script to download a video from an Italian website using Cloudflare. I did it like this:
Code:import re import base64 import requests from Crypto.Cipher import AES from pathlib import Path import subprocess import time import sys # ================================== # SANITIZE INPUTS (fix unicode issues) # ================================== def sanitize(s: str) -> str: return s.replace("…", "").encode("utf-8", "ignore").decode("utf-8") # ================================== # CONFIG # ================================== M3U8_URL = input("Playlist URL or local m3u8 file: ").strip() TIMEOUT = 20 MAX_RETRIES = 15 DELAY_BETWEEN_SEGMENTS = 2.5 SESSION_COOKIE = sanitize(input("PASTE_COOKIE : ").strip()) Fingerprint = sanitize(input("PASTE_X-Fingerprint : ").strip()) Token = sanitize(input("PASTE_X-Turnstile-Token : ").strip()) OUT_DIR = Path("segments") OUT_DIR.mkdir(exist_ok=True) # ================================== # SESSION # ================================== session = requests.Session() session.headers.update({ "Cookie": SESSION_COOKIE, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Referer": "https://guruflix.io/", "Origin": "https://guruflix.io", "X-Fingerprint": Fingerprint, "X-Turnstile-Token": Token, }) # ================================== # UTILS # ================================== def unpad_pkcs7(data: bytes) -> bytes: pad = data[-1] if 1 <= pad <= 16: return data[:-pad] return data # ================================== # LOAD PLAYLIST # ================================== print("[+] Loading playlist") if M3U8_URL.startswith("http"): r = session.get(M3U8_URL, timeout=TIMEOUT) r.raise_for_status() lines = r.text.splitlines() else: lines = Path(M3U8_URL).read_text(encoding="utf-8").splitlines() # ================================== # PARSE PLAYLIST # ================================== segments = [] next_key = None next_iv = None index = 0 for line in lines: line = line.strip() if "EXT-X-KEY" in line: key_match = re.search(r'URI="key:([^"]+)"', line) iv_match = re.search(r'IV=0x([0-9a-fA-F]+)', line) if not key_match or not iv_match: raise ValueError("Invalid EXT-X-KEY") next_key = base64.b64decode(key_match.group(1)) next_iv = bytes.fromhex(iv_match.group(1).zfill(32)) continue if line.startswith("http"): if next_key is None or next_iv is None: raise ValueError(f"No key for segment {index}") segments.append({ "index": index, "url": line, "key": next_key, "iv": next_iv, }) next_key = None next_iv = None index += 1 print(f"[+] {len(segments)} segments found") # ================================== # DOWNLOAD + DECRYPT # ================================== print("[+] Downloading segments (stable mode)") for seg in segments: idx = seg["index"] out_file = OUT_DIR / f"{idx:05d}.ts" if out_file.exists() and out_file.stat().st_size > 188: print(f"[→] Segment {idx} already exists, skipping") continue for attempt in range(1, MAX_RETRIES + 1): try: r = session.get(seg["url"], timeout=TIMEOUT) if r.status_code != 200: raise RuntimeError(f"HTTP {r.status_code}") cipher = AES.new(seg["key"], AES.MODE_CBC, seg["iv"]) decrypted = unpad_pkcs7(cipher.decrypt(r.content)) out_file.write_bytes(decrypted) print(f"[✓] Segment {idx} OK") break except Exception as e: print(f"[!] Segment {idx} failed ({attempt}/{MAX_RETRIES}) → {e}") time.sleep(4) else: print(f"❌ Segment {idx} abandoned") sys.exit(1) time.sleep(DELAY_BETWEEN_SEGMENTS) print("✅ All segments downloaded") # ================================== # MERGE # ================================== print("[+] Merging TS → MP4") list_file = OUT_DIR / "list.txt" with list_file.open("w", encoding="utf-8") as f: for seg in segments: f.write(f"file '{(OUT_DIR / f'{seg['index']:05d}.ts').as_posix()}'\n") subprocess.run(["ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", str(list_file), "-c", "copy", "output.mp4"], check=True) print("🎬 output.mp4 created successfully")
Similar Threads
-
delete Windows environment variables
By blanc in forum Newbie / General discussionsReplies: 1Last Post: 31st Jan 2025, 12:58 -
Social environment or Internet?
By MicroMagic in forum Off topicReplies: 3Last Post: 2nd Jan 2024, 22:35 -
How to setup an MSYS2 building environment
By El Heggunte in forum User guidesReplies: 3Last Post: 10th Jul 2022, 00:35



Quote