【JS 逆向百例】37網遊登入介面引數逆向

kboypkb發表於2021-09-09

圖片描述

宣告

本文章中所有內容僅供學習交流,嚴禁用於商業用途和非法用途,否則由此產生的一切後果均與作者無關,若有侵權,請聯絡我立即刪除!

逆向目標

  • 目標:37網遊登入
  • 主頁:
  • 介面:my.37.com/api/login.php
  • 逆向引數:
    Query String Parameters:password: SlVEOThrcjgzNDNjaUYxOTQzNDM0eVM=

逆向過程

抓包分析

隨便輸入一個賬號密碼,點選登陸,抓包定位到登入介面為 my.37.com/api/login.php ,GET 請求,分析一下 Query String Parameters 裡的主要引數:

callback 是一個回撥引數,這個引數的值不影響請求結果,它的格式為 jQuery + 20位數字 + _ + 13位時間戳,使用 Python 很容易構建;

login_account 是登入的賬戶名;

password 是加密後的密碼;

_ 是13位時間戳。

圖片描述

引數逆向

需要我們逆向的引數就只有一個 password, 我們嘗試直接全域性搜尋此關鍵字,會發現出來的結果非常多,不利於分析,這裡就有一個小技巧,加個等號,搜尋 password=,這樣就極大地縮短了查詢範圍,當然也可以搜尋 password:,也可以在關鍵字和符號之間加個空格,還可以搜尋 var password 等,這些都是可以嘗試的,要具體情況具體分析,一種沒有結果就換另一種。

在本案例中,我們搜尋 password=,在 sq.login2015.js 檔案裡可以看到語句 h.password = td(f),疑似密碼加密的地方,在此處埋下斷點進行除錯,可以看到返回的值確實是加密後的密碼:

圖片描述

繼續跟進 td 函式,可以看到是用到了一個自寫的 RSA 加密,很簡單明瞭,我們直接將其複製下來使用 Python 呼叫即可:

圖片描述

完整程式碼

GitHub 關注 [K 哥爬蟲],持續分享爬蟲相關程式碼!歡迎 star !

本案例完整程式碼:github.com/kuaidaili/crawler/tree/main/www_37_com

37_encrypt.js

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 getEncryptedPassword(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(""))
}

// 測試樣例
// console.log(getEncryptedPassword("34343434"))

37_login.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import time
import random

import execjs
import requests


login_url = ''


def get_encrypted_password(password):
    with open('37_encrypt.js', 'r', encoding='utf-8') as f:
        www_37_js = f.read()
    encrypted_pwd = execjs.compile(www_37_js).call('getEncryptedPassword', password)
    return encrypted_pwd


def login(username, encrypted_password):
    timestamp = str(int(time.time() * 1000))
    jsonp = ''
    for _ in range(20):
        jsonp += str(random.randint(0, 9))
    callback = 'jQuery' + jsonp + '_' + timestamp
    params = {
        'callback': callback,
        'action': 'login',
        'login_account': username,
        'password': encrypted_password,
        'ajax': 0,
        'remember_me': 1,
        'save_state': 1,
        'ltype': 1,
        'tj_from': 100,
        's': 1,
        'tj_way': 1,
        '_': timestamp
    }
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
        'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"'
    }
    response = requests.post(url=login_url, headers=headers, params=params)
    print(response.text)


def main():
    username = input('請輸入登入賬號: ')
    password = input('請輸入登入密碼: ')
    encrypted_password = get_encrypted_password(password)
    login(username, encrypted_password)


if __name__ == '__main__':
    main()

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1916/viewspace-2796699/,如需轉載,請註明出處,否則將追究法律責任。

相關文章