js逆向實戰之某網遊登入引數password加密

死不悔改奇男子發表於2024-10-27

宣告:本篇文章僅用於知識分享,不得用於其他用途
網址:https://www.37.com/

加密邏輯

  1. 訪問網址,輸入使用者名稱和密碼,看觸發哪些資料包。
    image

注意:這裡的流量包要選擇all,如果選擇fetch/XHR則看不到任何資料包。

  1. 明顯看到password被加密了,先去搜尋url中的關鍵字api/login.php
    image
    可以看到觸發的資料包中有action=login,但是搜尋出來的沒有一個符合,所以這裡搜尋url關鍵字不太合適。
  2. 再看資料包中所傳的引數有非常多,我們可以選擇一個引數名比較不常見的,這樣搜尋出來的結果會少一點,容易篩選。經過測試,選擇remember_me作為關鍵字搜尋,只有一處。
    image
  3. remember_me處打斷點,發現打不上,卻在下面的一行程式碼打上了斷點,說明可能邏輯在下面。
    image

image
5. 重新輸入使用者名稱和密碼觸發斷點,變數b中有使用者名稱和密碼。
image
6. 單步除錯,看執行到哪一步,密碼發生了變化。執行到如下這行程式碼的時候,還是原來的密碼。
image
再往下執行一步,等h.password = td(f)這行程式碼執行完,password被加密了,說明加密邏輯就在這行程式碼中。
image
7. 定位td函式,打斷點,重新輸入使用者名稱和密碼,讓程式執行到td函式中。
image
8. 傳給td函式的引數還是明文的密碼,經過td函式的處理就變成了加密字串。知道了加密的函式,就可以開始摳程式碼了。

function td(a) {
    var maxPos = ch.length - 2
      , w = [];
    for (i = 0; i < 15; i++) {
        w.push(ch.charAt(Math.floor(Math.random() * maxPos)));
        if (i === 7) {
            w.push(a.substr(0, 3))
        }
        if (i === 12) {
            w.push(a.substr(3))
        }
    }
    return __rsa(w.join(""))
}

var a = "123456";
console.log(td(a));

執行報錯,缺少ch
image
去原頁面找。
image
複製出來,再執行,報錯__rsa未定義。
image
再去原頁面找。
image
都在同一個檔案中,既然這樣,就把整個頁面的程式碼都複製出來。

var ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
function __rsa(str) {
    var out, i, len;
    var c1, c2, c3;
    len = str.length;
    i = 0;
    out = "";
    while (i < len) {
        c1 = str.charCodeAt(i++) & 0xff;
        if (i == len) {
            out += ch.charAt(c1 >> 2);
            out += ch.charAt((c1 & 0x3) << 4);
            out += "==";
            break
        }
        c2 = str.charCodeAt(i++);
        if (i == len) {
            out += ch.charAt(c1 >> 2);
            out += ch.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
            out += ch.charAt((c2 & 0xF) << 2);
            out += "=";
            break
        }
        c3 = str.charCodeAt(i++);
        out += ch.charAt(c1 >> 2);
        out += ch.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
        out += ch.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
        out += ch.charAt(c3 & 0x3F)
    }
    return out
}
function td(a) {
    var maxPos = ch.length - 2
      , w = [];
    for (i = 0; i < 15; i++) {
        w.push(ch.charAt(Math.floor(Math.random() * maxPos)));
        if (i === 7) {
            w.push(a.substr(0, 3))
        }
        if (i === 12) {
            w.push(a.substr(3))
        }
    }
    return __rsa(w.join(""))
}


var a = "123456";
console.log(td(a));

執行,成功得到加密的字串,且每一次的結果都不一樣。
image
9. 編寫python程式碼進行登入。

import requests
import execjs

login_account = input("請輸入使用者名稱:")
pwd = input("請輸入密碼:")

file = open("encrypt.js", mode="r")
exec_js = file.read()
exec_code = execjs.compile(exec_js)
password = exec_code.call("td", pwd)

url = "https://my.37.com/api/login.php?callback=jQuery183008257522373901449_1730007524424&action=login&login_account" \
      "={}&password={}&ajax=0&remember_me=1&save_state=1&ltype=1&tj_from=100&s=1&img_ver=1" \
      ".0&tj_way=1&_=1730007546145".format(login_account, password)
headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                         "Chrome/128.0.0.0 Safari/537.36"}
resp = requests.get(url, headers=headers)
print(resp.text.encode("utf-8").decode("unicode_escape"))

執行結果如下。
image
涉及到了驗證碼的滑塊驗證,還沒學過,等學會了再回來補,暫時只能做到這裡了。

相關文章