Pay attention to WeChat public account: K brother crawler, QQ exchange group: 808574309, continue to share advanced crawler, JS/Android reverse engineering and other technical dry goods!
statement
All the content in this article is for learning and communication only. The captured content, sensitive URLs, and data interfaces have been desensitized, and it is strictly forbidden to use them for commercial or illegal purposes. Otherwise, all the consequences arising therefrom will have nothing to do with the author. Infringement, please contact me to delete it immediately!
Reverse target
- Target: an e Netcom login interface
- Homepage: aHR0cHM6Ly93ZWIuZXd0MzYwLmNvbS9yZWdpc3Rlci8jL2xvZ2lu
- Interface: aHR0cHM6Ly9nYXRld2F5LmV3dDM2MC5jb20vYXBpL2F1dGhjZW50ZXIvdjIvb2F1dGgvbG9naW4vYWNjb3VudA==
Reverse parameters:
- Request Headers:
sign: 3976F10977FC65F9CB967AEF79E508BD
- Request Payload:
password: "A7428361DEF118911783F446A129FFCE"
- Request Headers:
Reverse process
Packet capture analysis
Came to the login page of a certain e Netcom, just enter an account and password to log in, capture the packet and locate the login interface as aHR0cHM6Ly9nYXRld2F5LmV3dDM2MC5jb20vYXBpL2F1dGhjZW50ZXIvdjIvb2F1dGgvbG9=naW3Vudload in the password, and the password is processed in the header of the request.
Parameter reverse
sign
First look at the sign of the request header, try to search directly, and find that it is not the data returned by some requests. If you observe other requests, you can find that there is the same sign, and the value of each request is different:
It can be preliminarily judged that this value should be generated by JS, the global search keyword 0615125b1d2cb9, you can see the suspected sign assignment in the request.js and request.ts files respectively, sign:
Next, the principle is also very simple, add a string of fixed characters to the timestamp, and then convert to uppercase after MD5 encryption.
Use Python to achieve:
import time
import hashlib
timestamp = str(int(time.time() * 1000))
sign = hashlib.md5((timestamp + 'bdc739ff2dcf').encode(encoding='utf-8')).hexdigest().upper()
print(sign)
password
password is the value obtained after the plaintext password is encrypted. If you try to search directly, you will find a lot of values. It is very difficult to find an accurate value:
You can see that this request is an XHR request. This time we use the XHR breakpoint method to locate the specific encryption location. Through this case, we will learn how to follow up the call stack and how to locate the specific location through the context. Encryption location.
Switch to the Network tab, find the login request, move the mouse to the JS under the Initiator tab, you can see its call stack, if the site encryption method is relatively simple, there is not much confusion, you can see login in the call stack Key words such as, send, post, encrypt, etc., in this case, you can click directly in, it is easier to find the encrypted place, but most sites have confused function names and variable names, just like this case , The functions displayed in the call stack are some single or multiple irregular letter functions, which cannot be directly located. At this time, we need to look forward from the last function slowly.
Click to enter the last function, the Y function, which is at the top of the call stack, which means that after this function, the browser will send a login request, and the password encryption process has been processed. Put a breakpoint in this function, and you can see the call stack on the Call Stack on the right. From bottom to top, it means the execution process of the functions that are called successively after you click to log in:
To find the specific encryption location, we have to look forward one by one and analyze each function one by one. For example, move forward to the penultimate call stack, namely the o function. You can see that the passed params parameter contains the Encrypted password information, which means that the encryption operation must be before this function:
According to this idea, follow up the call stack step by step, and you can see that an anonymous function is executed in utils.ts, which calls a passwordEncrypt function. You can see from the function name that it is basically a function of password encryption. :
Bury a breakpoint here to debug, the plaintext password is passed in, and passwordEncrypt is actually the O function in encode.ts that is called:
Follow up with the O function and quote the crypto-js encryption module. Obviously, AES encryption, just rewrite it locally.
The encryption of this case is relatively simple, but the encryption function is better hidden, and you need to follow up the call stack patiently. If you search directly, there are too many results, and it is not easy to locate the encryption function. In this case, follow up to one After the function, you can clearly see the encrypted place, then some sites may be more confusing, and it is impossible to see that there is an encrypted function. In this case, we need to pay attention to the change of parameters. If in this call stack What you see is the encrypted parameters, and what you see in the previous call stack is the plaintext parameters, then the encrypted operation must be between the two call stacks, and you can bury a breakpoint and analyze it carefully.
Complete code
GitHub pays attention to K brother crawler, and continues to share crawler-related code! Welcome star! https://github.com/kgepachong/
only part of the key code is demonstrated and cannot be run directly! complete code warehouse address: https://github.com/kgepachong/crawler/
JavaScript encryption code
CryptoJS = require("crypto-js")
const key = CryptoJS.enc.Utf8.parse("20171109124536982017110912453698");
const iv = CryptoJS.enc.Utf8.parse('2017110912453698'); //十六位十六进制数作为密钥偏移量
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();
}
// 测试样例
// console.log(getEncryptedPassword("123457"))
Python login code
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import time
import hashlib
import execjs
import requests
login_url = '脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler'
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': '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('请输入登录账号: ')
password = input('请输入登录密码: ')
sign = get_sign()
encrypted_password = get_encrypted_parameter(password)
login(sign, username, encrypted_password)
if __name__ == '__main__':
main()
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。