头图

statement

All the content in this article is for learning and communication only. The captured content, sensitive URLs, and data interfaces have been desensitized. Commercial and illegal uses are strictly prohibited. Otherwise, all consequences arising therefrom have nothing to do with the author. If there is any infringement , please contact me to delete immediately!

reverse goal

  • Goal: Login interface of a government service network
  • Home: aHR0cHM6Ly9sb2dpbi5obnp3ZncuZ292LmNuL3RhY3MtdWMvbG9naW4vaW5kZXg=
  • Interface: aHR0cHM6Ly9sb2dpbi5obnp3ZncuZ292LmNuL3RhY3MtdWMvbmF0dXJhbE1hbi9sb2dpbk5v
  • Inverse parameters:

    Form Data:loginNo、loginPwd、code、requestUUID

    Request Headers:token

Packet capture analysis

This reverse goal comes from a fan's request for help:

01.png

Just enter the account password and click login. The Request Headers of the packet capture interface has an encrypted parameter token. The loginNo, loginPwd, code, and requestUUID in the Form Data are all encrypted. The loginNo and loginPwd should be the username and password. You need to go through the sliding verification code before, so you can guess that the other two parameters are related to the verification code, but only from the packet capture point of view, the other two parameters are similar to the uuid format, not very similar to the parameters of the verification code.

02.png

03.png

In addition, it can be noticed that there are two requests for csrfSave and one verCode before logging in. If the normal request is successful, a JSON will be returned with a data parameter, which should be used later.

04.png

Parametric inverse

Form Data

First look at Form Data, search for any parameter, such as loginNo, it is easy to find the encrypted place in login.js, the user name and password are encrypted by the encrypt function, and the value of backUrl is stored from the browser using the localStorage attribute. It is taken from the data of the key-value pair, and it is not affected if it is empty.

05.png

Following up on encrypt, you can see that JSEncrypt is used, the standard RSA encryption:

06.png

Look at the loginCode again, search for this value directly, and you can see that it is returned by the verCode request:

07.png

08.png

Then look at the requestUUID, its value is a UUID, search directly in the current file (login.js), you can see the definition, there is a uploadUUID() method, which is to set the value of UUID, which is to an uploadIdentifier The interface sends a post request:

09.png

10.png

Note here that if you directly search for UUID globally, you can also search for a method in common.js. After testing, directly using this method to generate a uuid can also be requested to pass. This website may not be rigorous and will not strictly detect this value.

11.png

Request Headers

Form Data is solved, let's take a look at the token parameter in Request Headers. Since it exists in the request header, we can find the place where it is generated by Hook:

(function () {
    var org = window.XMLHttpRequest.prototype.setRequestHeader;
    window.XMLHttpRequest.prototype.setRequestHeader = function (key, value) {
        if (key == 'token') {
            debugger;
        }
        return org.apply(this, arguments);
    };
})();

Here we can also directly search for keywords such as token and setRequestHeader, which are easy to find in common.js. When we click login, there will be a request for csrfSave, and the returned data value will be the login request header after being encrypted by the encrypt method. 's token.

This token parameter is used in many requests. The generation method is the same, which is obtained by RSA encryption of the data returned by the csrfSave request:

12.png

Another point to note is that for all the above related network requests, the cookie needs a SESSION value, which can be obtained on the first visit page:

13.png

Login process

Here is the process of logging in:

  1. Visit the homepage to get the SESSION value in the cookie;
  2. Access csrfSave, get a data value, get token after RSA encryption, access uploadIdentifier with token, and get uuid;
  3. Access csrfSave, get a data value, get a token through RSA encryption, access verCode with the token, and get the code;
  4. Access csrfSave, get a data value, get token after RSA encryption, carry token, uuid, code and encrypted account password, access loginNo to log in.

In the second step here, you can also directly generate a uuid with Python or JS. The website verification is not strict, and it can also pass. In addition, it can be seen that the slider is fake, and the code can ignore the slider to log in.

14.png

full code

GitHub pays attention to Brother K's crawler and continues to share crawler-related code! Welcome star! https://github.com/kgepachong/

following only demonstrates some key codes, which cannot be run directly! full code warehouse address: https://github.com/kgepachong/crawler/

JavaScript encryption code

/* ==================================
# @Time    : 2022-01-11
# @Author  : 微信公众号:K哥爬虫
# @FileName: encrypt.js
# @Software: PyCharm
# ================================== */

JSEncrypt = require("jsencrypt")

function encrypt(pwd){
    var key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsgDq4OqxuEisnk2F0EJFmw4xKa5IrcqEYHvqxPs2CHEg2kolhfWA2SjNuGAHxyDDE5MLtOvzuXjBx/5YJtc9zj2xR/0moesS+Vi/xtG1tkVaTCba+TV+Y5C61iyr3FGqr+KOD4/XECu0Xky1W9ZmmaFADmZi7+6gO9wjgVpU9aLcBcw/loHOeJrCqjp7pA98hRJRY+MML8MK15mnC4ebooOva+mJlstW6t/1lghR8WNV8cocxgcHHuXBxgns2MlACQbSdJ8c6Z3RQeRZBzyjfey6JCCfbEKouVrWIUuPphBL3OANfgp0B+QG31bapvePTfXU48TYK0M5kE+8LgbbWQIDAQAB";
    var encrypt = new JSEncrypt();
    encrypt.setPublicKey(key);
    var encrypted = encrypt.encrypt(pwd);
    return encrypted;
}

// 测试样例
// console.log(encrypt("15555555555"))

Python login code

# ==================================
# @Time    : 2022-01-11
# @Author  : 微信公众号:K哥爬虫
# @FileName: hnzww_login.py
# @Software: PyCharm
# ==================================


import execjs
import requests


cookies = {}
UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"

with open("encrypt.js", encoding="utf-8") as f:
    js = execjs.compile(f.read())


def csrf_save():
    url = "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler"
    headers = {"User-Agent": UA}
    response = requests.post(url=url, headers=headers, cookies=cookies).json()
    data = response["data"]
    return data


def get_session():
    url = "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler"
    headers = {"User-Agent": UA}
    response = requests.get(url=url, headers=headers)
    cookies.update(response.cookies.get_dict())


def get_uuid():
    url = "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler"
    headers = {
        "User-Agent": UA,
        "token": js.call("encrypt", csrf_save())
    }
    response = requests.post(url=url, headers=headers, cookies=cookies).json()
    uuid = response["data"]
    return uuid


def ver_code():
    url = "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler"
    headers = {
        "User-Agent": UA,
        "token": js.call("encrypt", csrf_save())
    }
    response = requests.post(url=url, headers=headers, cookies=cookies).json()
    data = response["data"]
    return data


def login(phone, pwd, code, uuid):
    url = "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler"
    headers = {
        "User-Agent": UA,
        "token": js.call("encrypt", csrf_save())
    }
    data = {
        "backUrl": "",
        "loginNo": js.call("encrypt", phone),
        "loginPwd": js.call("encrypt", pwd),
        "code": code,
        "requestUUID": uuid,
        "guoBanAuthCode": ""
    }
    response = requests.post(url=url, headers=headers, cookies=cookies, data=data)
    print(response.json())


def main():
    phone = input("请输入账号:")
    pwd = input("请输入密码:")
    get_session()
    uuid = get_uuid()
    code = ver_code()
    login(phone, pwd, code, uuid)


if __name__ == '__main__':
    main()


K哥爬虫
166 声望148 粉丝

Python网络爬虫、JS 逆向等相关技术研究与分享。