Pay attention to wechat public number: K brother reptile, QQ exchange group: 808574309, continue to share crawler advanced, JS/ Android reverse technology and other goods!

The statement

All content in this article is only for learning and communication, packet capture content, sensitive website, data interface have been desensitized processing, strictly prohibited for commercial use and illegal use, otherwise all the consequences are unrelated to the author, if there is infringement, please contact me immediately delete!

Reverse the target

  • Target: an E netcom login interface
  • Homepage: aHR0cHM6Ly93ZWIuZXd0MzYwLmNvbS9yZWdpc3Rlci8jL2xvZ2lu
  • Interface: aHR0cHM6Ly9nYXRld2F5LmV3dDM2MC5jb20vYXBpL2F1dGhjZW50ZXIvdjIvb2F1dGgvbG9naW4vYWNjb3VudA = =
  • Reverse parameter:
    • The Request Headers.sign: 3976F10977FC65F9CB967AEF79E508BD
    • The Request content:password: "A7428361DEF118911783F446A129FFCE"

The reverse process

Caught analysis

Go to the login page of a certain E-com, enter a random account password to log in, Caught positioning to the login interface for aHR0cHM6Ly9nYXRld2F5LmV3dDM2MC5jb20vYXBpL2F1dGhjZW50ZXIvdjIvb2F1dGgvbG9naW4vYWNjb3VudA = =, request head, there is a sign, Payload, the password is encrypted.

Parameters of the reverse

sign

The value of sign in the request header is not the same as that in the request header. The value of sign is not the same as that in the request header.

JS and request.ts files respectively. The breakpoint is buried and the value is broken successfully. The principle is also very simple, the timestamp is added with a string of fixed characters. After MD5 encryption, switch to uppercase.

Using Python:

import time
import hashlib


timestamp = str(int(time.time() * 1000))
sign = hashlib.md5((timestamp + 'bdc739ff2dcf').encode(encoding='utf-8')).hexdigest().upper()
print(sign)
Copy the code

password

Password is the value of the plaintext password after it is encrypted. If you try to search directly, you will find many values, and it is very difficult to find the exact value:

This request is an XHR request, this time we use XHR breakpoint method to locate the specific encryption location, through this case, we will learn how to follow up the call stack, how to locate the specific encryption location through the context.

Switch to the Network TAB, find the login request, move the mouse to JS under the Initiator TAB, and you can see its call stack. If the site encryption is simple and there is not too much confusion, In this case, you can directly click on the call stack to find the encryption. However, most sites confuse function names and variable names, as in this case, Call stack display is a number of single or multiple irregular letter functions, can not be directly located, at this time we need to start from the last function slowly forward.

Click to enter the last function, the Y function, which is located at the top of the call stack, indicating that after this function, the browser will send the login request, and the password encryption process has been processed. If the breakpoint is buried in this function, you can see the Call Stack on the right side. From bottom to top, it represents the execution process of successively called functions after clicking login:

In order to find the specific encryption location, we need to search for the function one by one, for example, to locate the next to last call stack, that is, o function, you can see that the passed params parameter contains the encrypted password information, which indicates that the encryption operation must be before this function:

Utils. Ts calls passwordEncrypt, which is used to encrypt the password: utils. Ts calls passwordEncrypt, which is used to encrypt the password.

This is where the breakpoint is placed to debug, and passwordEncrypt is passed in plain text. PasswordEncrypt is actually the O function called encode.ts:

Follow up O function, referenced crypto-JS encryption module, AES encryption is obvious, local rewrite on the line.

The case of encryption is simpler, but encryption function better, it takes patience to follow up the call stack, through direct search, the result is too much, is not very easy to locate encryption function, after the case follow up to a function, can very clearly see the encryption, so some sites may confuse more severe, is look not to come out with encryption function, In this case, we need to pay attention to the change of parameters. If we see the encrypted parameters in this call stack and the plaintext parameters in the previous call stack, then the encrypted operation must be buried between the two call stacks, and careful analysis can be done.

The complete code

GitHub pay attention to K brother crawler, continue to share crawler related code! Welcome to star! github.com/kgepachong/

** The following is only part of the key code, can not run directly! ** Full repository address: github.com/kgepachong/…

JavaScript encryption code

CryptoJS = require("crypto-js")

const key = CryptoJS.enc.Utf8.parse("20171109124536982017110912453698");
const iv = CryptoJS.enc.Utf8.parse('2017110912453698'); // A hexadecimal number used as the key offset

function getEncryptedPassword(word) {
    let srcs = CryptoJS.enc.Utf8.parse(word);
    let encrypted = CryptoJS.AES.encrypt(srcs, key, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
    return encrypted.ciphertext.toString().toUpperCase();
}

// Test example
// console.log(getEncryptedPassword("123457"))
Copy the code

Python login code

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

import time
import hashlib

import execjs
import requests


login_url = 'attention GitHub:https://github.com/kgepachong/crawler desensitization treatment, complete code'
session = requests.session()


def get_sign() :
    timestamp = str(int(time.time()*1000))
    sign = hashlib.md5((timestamp + 'bdc739ff2dcf').encode(encoding='utf-8')).hexdigest().upper()
    return sign


def get_encrypted_parameter(password) :
    with open('ewt360_encrypt.js'.'r', encoding='utf-8') as f:
        ewt360_js = f.read()
    encrypted_password = execjs.compile(ewt360_js).call('getEncryptedPassword', password)
    return encrypted_password


def login(sign, username, encrypted_password) :
    headers = {
        'sign': sign,
        'timestamp': str(int(time.time()*1000)),
        'sec-ch-ua': '" Not; A Brand"; v="99", "Google Chrome"; v="91", "Chromium"; v="91"'.'User-Agent': 'the Mozilla / 5.0 (Windows NT 10.0; Win64; X64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
    }
    data = {
        'autoLogin': True.'password': encrypted_password,
        'platform': 1.'userName': username
    }
    response = session.post(url=login_url, headers=headers, json=data)
    print(response.json())


def main() :
    username = input('Please enter login account:')
    password = input('Please enter login password:')
    sign = get_sign()
    encrypted_password = get_encrypted_parameter(password)
    login(sign, username, encrypted_password)


if __name__ == '__main__':
    main()
Copy the code