Contourner la protection « debugger » des sites de streaming

Certains sites de streaming trouvent malin d'interdire l'accès au débogueur de Firefox. Qui entreprend de l'activer se trouve confronté à un point d'arrêt sur exécution de l'instruction debugger, point d'arrêt qu'il est visiblement impossible de désactiver. Par exemple :
La protection "Mise en pause par l'instruction debugger" ("Paused on debugger statement" d'un site de streaming
Dans ces conditions, impossible d'accéder au moniteur Réseau du débogueur pour visualiser la requête à une playlist dont il serait possible d'utiliser l'URL pour télécharger la vidéo via un outil quelconque, notamment ffmpeg.
Heureusement, il existe une solution très simple pour y parvenir : prendre quelques minutes pour écrire une extension.

La protection "Mise en pause par l'instruction debugger"

Sur un site ainsi protégé, activer le débogueur provoque l'arrêt de l'exécution sur une instruction debugger. La page est recouverte d'une interface "Mise en pause par l'instruction debugger" - "Paused on debugger statement" chez Shakespeare -, dotée d'un bouton pour passer à l'étape suivante, et d'un autre pour reprendre le fil de l'exécution. Toutefois, presser le second fait reboucler sur la même situation.
Quelques tentatives permettent vite de constater qu'il serait difficile de supprimer l'obstacle en se contentant de modifier le code en cours d'exécution via la console, notamment en réécrivant ce qui semble être une fonction appelée à intervalle régulier, comme celle-ci :
function _0x39426c(e) {
	function t(e) {
		if ("string" == typeof e) return function(e) {}.constructor("while (true) {}").apply("counter");
		1 !== ("" + e / e).length || e % 20 == 0 ? function() {
			return !0
		}.constructor("debugger").call("action") : function() {
			return !1
		}.constructor("debugger").apply("stateObject"), t(++e)
	}
	try {
		if (e) return t;
		t(0)
	} catch (e) {}
}
setInterval(function() {
	_0x39426c()
}, 4e3), console.log("%cSTOP! %s", css, "Great power comes great responsibility!");
En fait, il est bien possible d'essayer de supprimer les timers à l'aveugle et de redéfinir les fonctions accessibles - noter qu'il y a beaucoup d'IIFE de fonctions donc bien anonymes -, mais la protection contient d'autres mécanismes dont le code est assez ésotérique. Par ailleurs, le code est lisible sur ce site, mais il pourrait parfaitement être brouillé - obfuscation, comme disent les angliches.
Dans ces conditions, plutôt que de tenter de supprimer l'obstacle, mieux vaut chercher à le contourner.
Il s'agit de se placer en observateur plutôt qu'en acteur de la situation, en codant une extension qui va faire le travail du moniteur Réseau, soit tracer les requêtes. Ainsi, il sera possible d'accéder à l'URL de la playlist sans avoir à accéder au débogueur, donc sans déclencher la protection.

Une extension qui se substitue au moniteur Réseau

Créer une extension pour Firefox est d'une simplicité enfantine. Mozilla a produit un excellent didacticiel pour commencer ici. En complément, l'examen du code d'une extension comme Network Monitor - qui permet de tracer les requêtes, comme l'on souhaite le faire ici, mais qui n'inspire pas trop confiance, n'étant pas certifiée par Mozilla - permet vite de comprendre qu'il va falloir utiliser un objet particulier, browser.webRequest. Sur le gestionnaire d'événements onBeforeRequest que cet objet permet de greffer, il se trouve que l'aide produite par Mozilla ici renvoie sur un exemple clé en main . Que demande le peuple ?
Pour commencer, il faut créer un répertoire sniffer qui contiendra le code et les données de l'extension :
/sniffer
	background.js
	/icons
		sniffer-48.png
	manifest.json
	sniffer.js
 vrai dire, ni sniffer-48.png ni sniffer.js ne sont indispensable, mais nous allons doter l'extension d'une icône pour l'esthétique, et d'un programme principal pour s'assurer qu'elle fonctionne.
Le programme principal qui réside dans sniffer.js se contente d'entourer le contenu de la page d'une bordure de 5 pixels de large en rouge vif. Cela permettra de voir que l'extension est à l'oeuvre dans la page :
document.body.style.border = "5px solid red";
La tâche récurrente à accomplir, tracer les requêtes, doit nécessairement être logée dans un autre fichier, background.js. Il s'agit rès simplement de rajouter un gestionnaire de l'événement onBeforeRequest à l'objet browser.webRequest. Le gestionnaire se contente d'afficher l'URL de la requête dans la console de l'extension :
function logURL(requestDetails) {
	console.log(`Loading: ${requestDetails.url}`);
}
browser.webRequest.onBeforeRequest.addListener(
	logURL,
	{urls: ["<all_urls>"]}
);
Enfin, le détail de l'extension doit être documenté dans un fichier au nom réservé, manifest.json :
{
	"manifest_version": 2,
	"name": "Sniffer",
	"version": "1.0",

	"description": "Sniff requests.",

	"icons": {
		"48": "icons/sniffer-48.png"
	},

	"content_scripts": [
		{
			"matches": ["<all_urls>"],
			"js": ["sniffer.js"]
		}
	],

	"permissions": [
		"<all_urls>",
		"webRequest"
	],

	"background": {
		"scripts": ["background.js"]
	}
}
Ce travail de titan étant accompli, il ne reste plus qu'à installer l'extension.
Mozilla a prévu un mécanisme qui permet de tester une extension en local, ce qui permet de s'épargner tout un travail de distribution. Il faut accéder à une page de configuration de Firefox en saisissant about:debugging dans la barre d'adresse, puis cliquer sur Ce Firefox. De là, cliquer sur le bouton Charger un module complémentaire temporaire..., sélectionner n'importe quel fichier à la racine du répertoire de l'extension, et cliquer sur Ouvrir :
L'extension temporaire une fois installée
L'extension étant chargée, cliquer sur Examiner pour afficher la console de l'extension. En effet, c'est dans cette dernière et non dans la console de la page - à laquelle il serait de toute manière impossible d'accéder, car il faudrait pour cela activer le débogueur, ce qui déclencherait la protection - que les URL des requêtes seront affichés :
Interface d'installation d'une extension temporaire
Il suffit alors de se rendre sur le site et de commencer à lire la vidéo. Les URL des requêtes s'affichent dans la console de l'extension :
L'historique des requêtes HTTP affiché par l'extension temporaire
Pour récupérer l'URL d'un .m3u8, il n'y a plus qu'à filtrer les requêtes en saisissant cette extension, puis à cliquer du bouton droit sur la requête et sélectionner Copier l'adresse du lien.
Récupération de l'URL d'un .m3u8 sur le site de streaming
Disposant de l'URL de la playlist, il est possible de l'utiliser avec VLC, comme expliqué ici, ou ffmpeg, comme expliqué , pour télécharger les vidéos qu'elle référence. La solution la plus rapide semble être d'utiliser ffmpeg :
ffmpeg -i "http://example.com/video_url.m3u8" -c copy -bsf:a aac_adtstoasc "output.mp4"
Cliquez ici pour récupérer le code et les données de l'extension, et vous amuser avec.
Contourner la protection « debugger » des sites de streaming