Analyse de cryptage des paramètres d'analyse Qimai

1. Analyse des interfaces

site cible :

aHR0cHM6Ly93d3cucWltYWkuY24vcmFuay9tYXJrZXRSYW5r

Actualisez d'abord la page Web et demandez le paramètre d'analyse dans l'interface pour la cible de cette analyse

insérez la description de l'image ici

2. Débogage des points d'arrêt

Marquez le point d'arrêt XHR, après avoir actualisé la page, le point d'arrêt sera cassé au niveau de l'interface, puis analyse étape par étape pour trouver la position de chiffrement
insérez la description de l'image ici
Ici, nous pouvons voir que e est la valeur d'analyse générée après le chiffrement . Cependant, la logique de code de la zone cryptée dans l'image ci-dessus est encore quelque peu compliquée et ne peut pas être déduite directement pour être utilisée.

Nous devons analyser chaque fonction, et il y a des valeurs fixes ( cette valeur changera fréquemment ), puis nous commençons à compléter l'environnement et à restaurer le code de cryptage JS final

3. Chiffrement de réécriture d'environnement supplémentaire

function v(t) {
    
    
    t = encodeURIComponent(t).replace(/%([0-9A-F]{2})/g, function (n, t) {
    
    
        return o("0x" + t)
    });
    try {
    
    
        return btoa(t)
    } catch (n) {
    
    
        return Buffer.from(t).toString("base64")
    }
}

function o(n) {
    
    
    let f2 = '66';
    let s2 = '72';
    let d2 = '6f';
    let m2 = '6d';
    let l2 = '43';
    let v2 = '68';
    let p2 = '61';
    let h2 = '64';
    let y2 = '65';
    t = "",

        [f2, s2, d2, m2, l2, v2, p2, s2, l2, d2, h2, y2].forEach(function (n) {
    
    
            t += unescape("%u00" + n)
        });
    var t, e = t;
    return String.fromCharCode(n)
}

function h(n, t) {
    
    
    t = t || u();
    for (var e = (n = n.split("")).length, r = t.length, a = "charCodeAt", i = 0; i < e; i++)
        n[i] = o(n[i][a](0) ^ t[(i + 10) % r][a](0));
    return n.join("")
}

function encrypted(key) {
    
    
    var s = 1359
    var H = 0
    var e, r = +new Date() - (s || H) - 1661224081041, a = [];
    var v1 = "@#"
    // 固定值
    var d = "xyz517cda96abcd"

    // a = a[Ot]()[I1](_),
    a = a.sort().join("")
    a = (a += v1 + key) + (v1 + r) + (v1 + 3)
    e = (0,
        v)((0,
        h)(a, d))
    return e
}

Parlons maintenant du flux de code JS réécrit ci-dessus, regardez d'abord cette ligne de code var e, r = +new z[W] - (s || H) - 1661224081041, a = [];

z[W] On voit qu'il s'agit d'un Data() quand on place la souris, et ensuite ce qu'il faut faire c'est récupérer les valeurs des deux variables s et H , et ces deux valeurs peut être codé en dur
insérez la description de l'image ici

Grâce à la méthode ci-dessus, trouvez et remplissez les valeurs des deux paramètres d et v . Il convient de noter ici que la valeur de d peut changer à tout moment dans le futur, ce qui équivaut à un jeton

Ensuite, nous devons trouver les deux méthodes de fonction de i[jt] et i[qt] dans le code

Le point d'arrêt de la méthode i[jt] est le suivant :
insérez la description de l'image ici

Le point d'arrêt de la méthode i[qt] est le suivant :

insérez la description de l'image ici

Dans la méthode h , nous devons également composer la valeur et remplacer directement la méthode et la valeur :

Code d'origine : pour (var e = (n = n $1 )[R], r = t[R], a = q1, i = H ; i < e ; i++)

替换:for (var e = (n = n.split(“”)).length, r = t.length, a = “charCodeAt”, i = 0; i < e; i++)

Ensuite, traitons cette ligne de code dans la méthode v , qui doit également être réécrite et restaurée :

Code d'origine : t = z V1 [T](/%([0-9A-F]{2})/g, fonction(n, t)

替换:t = encodeURIComponent(t).replace(/%([0-9A-F]{2})/g, function (n, t)

En ce qui concerne la manière de compenser et de restaurer, vous pouvez analyser chaque paramètre et variable à compenser en fonction du point d'arrêt. Par exemple, z[V1] ci-dessus est une méthode encodeURIComponent , T est une méthode de remplacement et le contenu des données reste inchangé.

Ensuite, continuez à descendre, vous pouvez voir qu'un o est appelé dans la méthode v , il faut déduire la méthode de ce o

Une fois que le mode point d'arrêt a trouvé la méthode o , on peut constater qu'il existe plusieurs valeurs de paramètres f2, s2, d2... dans cette méthode , car les paramètres externes ne sont pas transmis lors de l'appel, et les valeurs affichées s'ajoutent directement :
insérez la description de l'image ici

let f2 = '66';
let s2 = '72';
let d2 = '6f';
let m2 = '6d';
let l2 = '43';
let v2 = '68';
let p2 = '61';
let h2 = '64';
let y2 = '65';

Il existe également une méthode z dans la méthode v qui est réécrite de la même manière :

Code d'origine : retour z[W1] K1 U1

Remplacer : renvoyer Buffer.from(t).toString("base64")

4. Vérifiez le résultat

Ensuite, nous écrivons simplement un code d'appel de requête python pour tester l'effet :

import time
import execjs
import requests

headers = {
    
     
    'authority': 'api.qimai.cn',
    'sec-ch-ua': '"Google Chrome";v="87", " Not;A Brand";v="99", "Chromium";v="87"',
    'accept': 'application/json, text/plain, */*',
    'sec-ch-ua-mobile': '?0',
    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
    'sec-fetch-site': 'same-site',
    'sec-fetch-mode': 'cors',
    'sec-fetch-dest': 'empty',
    'accept-language': 'zh-CN,zh;q=0.9',
}

url = "https://api.qimai.cn"
url_args = "/rank/marketRank"

with open("./qimai.js") as f:
    js_code = f.read()

analysis = execjs.compile(js_code).call("encrypted", url_args)
res = requests.get(f"{
      
      url}{
      
      url_args}?analysis={
      
      analysis}", headers=headers).json()
print(res)

Vérifiez comme suit :

insérez la description de l'image ici
  Eh bien, il est temps de dire au revoir à tout le monde ici. Ce n'est pas facile à créer, merci de me donner un like avant de partir. Votre soutien est le moteur de ma création, et j'espère vous apporter plus d'articles de qualité

Je suppose que tu aimes

Origine blog.csdn.net/qiulin_wu/article/details/132343879
conseillé
Classement