js加密,js混淆机制

  • 分析:
  • 1.当我们修改页面的查询条件后,点击查询按钮,在抓包工具会捕获两个一样的数据包,我们只要破解其中一个就可以逐个击破
  • 请求地址:https://www.aqistudy.cn/apinew/aqistudyapi.php
  • 请求方式:POST
  • 请求参数:d:加密数据
  • 返回相应数据:加密
  • 2.点击查询按钮,页面没有刷新,说明是ajax请求:
  • 请求地址:https://www.aqistudy.cn/apinew/aqistudyapi.php
  • 请求方式:POST
  • 请求参数:d:加密数据
  • 返回相应数据:加密
  • 前台页面中显示的是原文数据
  • 原因:响应回来的数据进行了解密
  • 在该网站的相关数据包中是存在解密方案,我们只需要将其解密方法获取,对密文进行解密,即可
  • 3.请求方式和请求可以从抓包工具捕获
  • 携带请求参数:可以从ajax的代码中获取
  • 请求回来的数据对应的回调函数
  • 函数的参数就是请求到的响应数据(加密的密文数据),该函数会对拿到的密文数据进行解密,将解密后的原文动态显示前台页面中
  • 重点:只要能够找到点击查询按钮对于的ajax请求代码后,就可以知道动态变化且加密的请求参数如果生成,就可以获取相应的密文数据,然后通过回调函数的操作获取解密方案,使用该方案的响应进行解密即可
  • 操作:找ajax代码
  • 获取搜索按钮对应的点事件:
  • getData();绑定的点击事件
  • 有价值的信息:
  • type == "HOUR"查询时间是以小时为单位
  • 发现函数内部调用了另外两个函数getAQIData(); getWeatherData();
  • ajax代码的实现一定实在上述的两个函数内部
  • 这这两个函数内部没有发现ajax 代码的实现
  • 调用了一个叫做getServerData()函数,
  • getServerData的参数:
  • method :GETDETAIL 字符串
  • param:字典,有四组键值对
    param.type = type;
    param.startTime = startTime;
    param.endTime = endTime;
  • 回掉函数:
  • 0.5
  • 进入 getServerData的函数内部找ajax代码:
  • 这个函数没有存在当前文件中需要在抓包工具里面进行全局搜索
  • 通过全局搜索找到了getServerData在jquery文件中,是密文
  • js混淆:
  • 在网站的后后台,关键的重要的js函数的实现为了保密,一般会对这些js函数代码进行混淆(加密),所以我们需要进行解密(反混淆)
  • 反混淆网址:http://www.bm8.com.cn/jsConfusion/
  • 分析getServerData函数中的ajax代码:
  • 动态变化加密的请求参数:
  • var param = getParam(method, object);
  • method = GETDETAIL
  • object = param 字典
  • decodeData(data);将data这个响应数据进行解密
  • 需要调用这两个函数就可以进行发生请求了
  • 总结:
  • 调用getParam后就可以获取加密变化的请求参数
  • 调用decodeData就可以将响应数据进行解密
  • 问题:python调用js
  • js逆向:
  • 可以将js代码改写成 python代码
  • 使用相关模块进行js逆向 pip3 install PyExecJS
  • PyExecJS的使用:
  • 1.需要接待执行,的js函数的全部定义存到text.js中
  • 2.模拟执行js源文件中的js函数
  • 加载js源文件js代码
  • 将js源文件中的代码进行编译
import requests
import execjs
# 实例化一个对象
node = execjs.get()

# Params 
method = "GETDETAIL"
city = '北京'
type = "HOUR"
start_time = "2018-01-25 00:00:00"
end_time = "2018-01-25 23:00:00"

# Copile javascript
file = "./text.js" # 待加载编译的js源文件
ctx = node.compile(open(file,encoding='utf-8').read())

# 调用getPostParamCode
js = 'getPostParamCode("{0}","{1}","{2}","{3}","{4}")'.format(method,city,type,start_time,end_time)

# eval表示模拟进行编译好的js函数
params = ctx.eval(js)
# print(params) # 返回是加密变化的请求参数

# 发起post请求
url = "https://www.aqistudy.cn/apinew/aqistudyapi.php"

response_text = requests.post(url=url,data={'d':params}).text
# print(response_text) # 返回加密的数据

# 模拟执行decodeData进行解密
jes = 'decodeData("{0}")'.format(response_text)
decrypted_data = ctx.eval(jes)
print(decrypted_data)
print("我结束了")

多任务线程池

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
import time
from multiprocessing.dummy import Pool
import requests
#同步代码
# urls = [
#     'http://127.0.0.1:5000/bobo',
#     'http://127.0.0.1:5000/jay',
#     'http://127.0.0.1:5000/tom'
# ]
# def get_request(url):
#     page_text = requests.get(url).text
#     print(len(page_text))
#
# if __name__ == "__main__":
#     start = time.time()
#     for url in urls:
#         get_request(url)
#     print('总耗时:',time.time()-start)


#基于线程池的异步效果
urls = [
    'http://127.0.0.1:5000/bobo',
    'http://127.0.0.1:5000/jay',
    'http://127.0.0.1:5000/tom'
]
def get_request(url):
    page_text = requests.get(url).text
    return len(page_text)

if __name__ == "__main__":
    start = time.time()

    pool = Pool(3) #启动了三个线程
    #参数1:回调函数
    #参数2:可迭代的对象,alist
    #作用:可以将alist中的每一个元素依次传递给回调函数作为参数,然后回调函数会异步
        #对列表中的元素进行相关操作运算
    #map的返回值就是回调函数返回的所有结果
    page_text_len_list = pool.map(get_request,urls)
    print(page_text_len_list)


    print('总耗时:',time.time()-start)