天天看點

【JS 逆向百例】37網遊登入接口參數逆向

【JS 逆向百例】37網遊登入接口參數逆向

聲明

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

逆向目标

  • 目标:37網遊登入
  • 接口:​​​​
  • 逆向參數:

    Query String Parameters:

    password: SlVEOThrcjgzNDNjaUYxOTQzNDM0eVM=

逆向過程

抓包分析

随便輸入一個賬号密碼,點選登陸,抓包定位到登入接口為 ​​https://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 !

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 = 'https://my.37.com/api/login.php'


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()