Identification du point d’entrée
En observant les échanges réseau, on constate que la valeur m est calculée dynamiquement. L’inspecteur de source (Initiator) pointe vers window.request. En posant un point d’arrêt, on voit que :
t(le timestamp) est obtenu viaDate.parse(new Date).toString()mest produit parbtoa(p_s)après simplification
Analyse de la fonction btoa
La fonction btoa n’est pas la fonction native. Elle utilise une table de caractères personnalisée et une obfuscation poussée. Après extraction, sa signature peut être réduite à :
function btoa(e) {
var r = {
// de nombreuses propriétés issues de u()
};
var i = r;
var f = "U9876543210zyxwvutsrqpomnlkjihgfdecbaZXYWVUTSRQPONABHICESQWK2Fi+9876543210zyxwvutsrqpomnlkjihgfdecbaZXYWVUTSRQPONABHICESQWK2Fi";
if (/([^\u0000-\u00ff])/.test(e)) throw new Error(i.TGmSp);
var o, a, s, l = 0, c = [];
while (l < e.length) {
a = e.charCodeAt(l);
s = i.kukBH(l, 6);
switch (s) {
case 0: /* ... */ break;
case 1: /* gestion d’erreur selon n.g */ break;
case 2: /* combinaisons avec f.charAt */ break;
// ... cas 3,4,5
}
o = a;
l++;
}
// finalisation avec d() et md5 du tableau c
return i.aQCDK(d(15), md5(c.join(''))) + i(d, 10);
}
Plusieurs fonctions auxiliaires sont nécessaires : u, d, md5 et un objet n.
Restauration des dépendances manquantes
L’exécution hors contexte échoue car de nombreux symboles ne sont pas définis.
1. La fonction u et le tableau _0x34e7
u est une simple indirection qui renvoie _0x34e7[e - 188]. L’ordre des chaînes dans _0x34e7 doit être identique à celui de la page originale. Voici un extrait du tableau :
var _0x34e7 = [
"split", "ABHICESQWK", "FKByN", "U987654321", "lmHcG", "dICfr",
"Szksx", "Bgrij", "iwnNJ", "jihgfdecba", "GfTek", "gfdecbaZXY",
/* ... */
];
function u(e, t) { return _0x34e7[e - 188]; }
2. La table de caractères f
Elle est directemant récupérée depuis le code source :
var f = "U9876543210zyxwvutsrqpomnlkjihgfdecbaZXYWVUTSRQPONABHICESQWK2Fi+" +
"9876543210zyxwvutsrqpomnlkjihgfdecbaZXYWVUTSRQPONABHICESQWK2Fi";
3. La fonction d (générateur de chaîne aléatoire)
Elle s’appuie également sur u :
function d(e) {
var t = u, n = {};
n[t(227)] = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
// ... logique de génération aléatoire
return c;
}
4. Le hachage MD5
L’appel à window.md5(c.join('')) nécessite une implémentation indépendante. On remplace window.md5 par une fonction md5 récupérée du contexte de la page, elle‑même dépendante d’un autre tableau _0x4c28 et d’une fonction n.
var _0x4c28 = [
"Rtsed","SUrST","nsaps","vyNVU","2|29|23|64",
"0|43|57|4|", /* ... */
];
function n(e, t) { return _0x4c28[e - 0]; }
var md5 = function(e) {
var t = n, r = { /* nombreuses propriétés */ };
// ... implémentation complète de l’algorithme MD5
return resultat;
};
L’objet n (qui diffère de la fonction n ci‑dessus) correspond à des propriétés globales, notamment n.g.
Correction du flux d’exécution : le piège window
À l’intérieur du case 1 du switch de btoa, la ligne try { "WhHMm" === i[198] || n.g && c.push(...) } catch(e) { ... } pose problème. En environnement page, n.g est défini (true), donc la branche correcte est exécutée. Hors navigateur, n.g est undefined, la condition évalue à false et le code passe dans le catch, modifiant le résultat. La solution consiste à forcer n.g = true; avant l’appel.
Script d’extraction des données
Une fois la fonction btoa entièrement reconstituée, on l’exporte via execjs. Le code JavaScript final appelle simplement btoa_change(timestamp) puis combine la valeur de hachage avec le timestamp.
Le script Python effectuant les requêtes :
import requests
import execjs
import re
pattern = r'"value": (\d+)'
total = 0
with open("btoa_bundle.js", "r") as f:
js_source = f.read()
ctx = execjs.compile(js_source)
for page in range(1, 6):
ts, token = ctx.call("btoa")
url = f"https://match.yuanrenxue.cn/api/match/16?page={page}&m={token}&t={ts}"
headers = {"User-Agent": "Mozilla/5.0 ..."}
cookies = {"sessionid": "votre_session"}
resp = requests.get(url, headers=headers, cookies=cookies)
for match in re.findall(pattern, resp.text):
total += int(match)
print("Somme totale :", total)
La boucle itère sur les 5 pages, calcule un nouveau couple (t, m) pour chaque appel (le timestamp évolue), récupère les valeurs JSON et les additionne.
Résultat
L’approche permet de contourner le pot de miel basé sur l’objet window et la fonction btoa modifiée, et d’obtenir la somme attendue.