13-爬蟲之js加密,解密,混淆,逆向破解思路


url:https://www.aqistudy.cn/apinew/aqistudyapi.php

分析思路:

原圖
原圖
現圖
在這里插入圖片描述

1,我們點擊查詢按鈕后發現抓取到了2個一樣的數據包,包含請求url和post的請求方式

在這里插入圖片描述

2,發起多次請求發現 請求參數 d 是動態加密的數據值,我們只要能破解其中一個數據包的內容剩下的一個也可以同理破解

在這里插入圖片描述
在這里插入圖片描述

3,返回的響應數據就是我們想要捕獲的空氣指標數據值,我們發現響應數據也是一組被加密的密文數據,我們必須將密文數據解密成原文數據才可以被我們使用

在這里插入圖片描述

4,通過類型可以看見發起的是ajax請求

在這里插入圖片描述

分析的結論

請求url
Request URL: https://www.aqistudy.cn/apinew/aqistudyapi.php 
請求方式 
Request Method: POST 
動態變化的參數
d: tdgHOYxwKdDSgYXe+RLPzYCgLvrddahasI5XXklB4gVLYqab+XRPpMD/oSqnJ/aEmFwzVEUhLnPzRy03+X1BIzLvxQKwu4A3YsqR3OemYgNnHqPdBwvJlbxia99YeK+xVtm/KUfxgICnZHiin/ojfqe1ZJXPHKDaOqwKab2iJt6YQRF4WQWYusdfEXhDolRtLCUy8ht8s821u5VxPcU+NezPIcU8U830QPCeWGAkKrHcsmuUaEHoRLJjnqpMnaid8OfacV5HCUeVhK3Uhju9Sr+bGsXveRwJFs5t307AlxFmwOBzCa6T6fmAQK9+1KoOfUz8EtNUEQkMB1LQBarJd9qsFKpe6TnoLFJ9G6xud+YIs8GecqTX4Pf2urDJLQ3LLfmLqMo7H/7LwYcq2BxyJiGqG2Xpp5wdr9L+oCZisZ9yKEBuYIprEM6A9PMUKADaw5ZESt11e9YX/xbkKPbnaw== 
返回的加密的響應數據
f9VXvMyFOzW7AzFWZjMa3oW5basBySGVYXbOpPoS6/W7Dh2wAk4bbiAr7xpyn/meJ/Hem3nHWnk4WtHFwrhKIyDSu2SUsVB5a/jusoqnpmDCxqr9YxCavi6qiilWtiVa49+C70wNGkoQqdo5w3hB/g==

破解操作

請求得到的數據是一組加密數據,但是web前台展示的是一組明文數據,原因是前台將響應回來的密文數據進行了解密
注:在該網站的相關數據包中是存在這解密方法,我們只需要將其解密方法獲取,就可對密文數據進行解密

找尋ajax請求的代碼
獲取搜索按鈕對應的點擊事件綁定的函數即可(使用火狐瀏覽器找尋點擊事件的函數代碼)

在這里插入圖片描述

點擊搜索按鈕對應的點擊事件函數名叫做getData,進入該函數內部扎尋ajax請求代碼

在這里插入圖片描述

找到了getDate函數的實現
  • 沒有發現ajax代碼的實現

  • 發現函數內部調用了另外的兩個函數getAQIData();
    getWeatherData();

  • 那么ajax代碼的實現一定是在上訴兩個函數內部

  • 有價值的信息: type==“HOUR” 查詢時間是以小時為單位

  • 進入getAQIData();getWeatherData();函數內部找尋ajax代碼實現

    • 在這兩個函數內部沒有發現ajax代碼的實現
    • 發現他兩都調用了一個名叫getServerData()的函數,那么ajax代碼一定存在getServerData()函數中
      在這里插入圖片描述
      在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述

進入getServerData函數內部找尋ajax代碼
  • 通過搜索我們發現只有2個getServerData的調用並不是函數的定義,那么getServerData並不在 city_datail.html中
    在這里插入圖片描述

在這里插入圖片描述

  • 函數實現的找尋,需要在抓包工具中進行全局搜索
  • 找到的結果是密文
js 混淆
	- 在網站后台,關鍵的重要的js函數的實現為了保密,一般會對這些js函數代碼進行混淆(加密),所以我們需要對js混淆的代碼進行反混淆,將js加密的函數進行解密

在這里插入圖片描述

js反混淆

js混淆暴力破解https://www.bm8.com.cn/jsConfusion/
在這里插入圖片描述
在這里插入圖片描述

function getServerData(method, object, callback, period) {
        const key = hex_md5(method + JSON.stringify(object));
        const data = getDataFromLocalStorage(key, period);
        if (!data) {
            var param = getParam(method, object);
            $.ajax({
                url: '../apinew/aqistudyapi.php', #請求url
                data: {
                    d: param #加密且動態變化的請求參數
                },
                type: "post",#請求方式
                #data請求到的加密的響應數據
                success: function (data) {
                    data = decodeData(data);#將data這個加密的響應數據進行解密
                    obj = JSON.parse(data);
                    if (obj.success) {
                        if (period > 0) {
                            obj.result.time = new Date().getTime();
                            localStorageUtil.save(key, obj.result)
                        }
                        callback(obj.result)
                    } else {
                        console.log(obj.errcode, obj.errmsg)
                    }
                }
            })
        } else {
            callback(data)
        }
    }
分析getServerData函數實現的ajax代碼:

- 動態變化且加密的請求參數

js逆向

我們需要借助於 PyExecJS 庫來實現模擬JavaScript代碼執行獲取動態加密的請求參數,然后再將加密的響應數據帶入decodeData進行解密即可!

  • PyExecJS介紹:PyExecJS 是一個可以使用 Python 來模擬運行 JavaScript 的庫。我們需要pip install PyExecJS對其進行環境安裝。
  • 以及安裝nodejs的開發環境:https://jingyan.baidu.com/article/e4511cf38c05092b845eaf9b.html
    - 開始執行js:
    • 1.創建一個jsCode.js文件將反混淆網站中的代碼粘貼進去

在這里插入圖片描述

在這里插入圖片描述
- 2.在jsCode.js文件中添加一個自定義函數getPostParamCode,該函數是為了獲取且返回post請求的動態加密參數:

function getPostParamCode(method, city, type, startTime, endTime){
    var param = {};
    param.city = city;
    param.type = type;
    param.startTime = startTime;
    param.endTime = endTime;
    return getParam(method, param);
}

在這里插入圖片描述
- 在py源文件中可以基於PyExecJS模擬執行jsCode.js中定義好的自定義函數,獲取動態加密參數:

import execjs
import requests


url = "https://www.aqistudy.cn/apinew/aqistudyapi.php"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"
}

#實例化一個對象
node = execjs.get()
# Params
method = 'GETCITYWEATHER'
city = '北京'
type = 'HOUR'
start_time = '2020-08-27 00:00:00'
end_time = '2020-08-28 23:00:00'

# Compile javascript
file = 'jsCode.js' #代加載編譯的js源文件
ctx = node.compile(open(file, encoding='utf-8').read())#加載編譯的js源文件中的js代碼
# Get params
js = 'getPostParamCode("{0}", "{1}", "{2}", "{3}", "{4}")'.format(method, city, type, start_time, end_time)
params = ctx.eval(js)# eval表示執行指定js函數
print(params)#返回的是加密變化的請求參數

在這里插入圖片描述

  • 我們用 requests 庫來模擬 POST 請求
import execjs
import requests


url = "https://www.aqistudy.cn/apinew/aqistudyapi.php"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"
}

#實例化一個對象
node = execjs.get()
# Params
method = 'GETCITYWEATHER'
city = '北京'
type = 'HOUR'
start_time = '2020-08-27 00:00:00'
end_time = '2020-08-28 23:00:00'

# Compile javascript
file = 'jsCode.js' #代加載編譯的js源文件
ctx = node.compile(open(file, encoding='utf-8').read())#加載編譯的js源文件中的js代碼
# Get params
js = 'getPostParamCode("{0}", "{1}", "{2}", "{3}", "{4}")'.format(method, city, type, start_time, end_time)
params = ctx.eval(js)# eval表示執行指定js函數
print(params)

data = {
    "d":params
}
page_text = requests.post(url=url,headers=headers,data=data).text
print(page_text)# 返回的是加密的響應數據

在這里插入圖片描述

  • 接下來我們再調用一下 JavaScript 中的 decodeData() 方法即可實現解密
完整代碼
import execjs
import requests


url = "https://www.aqistudy.cn/apinew/aqistudyapi.php"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36"
}

#實例化一個對象
node = execjs.get()
# Params
method = 'GETCITYWEATHER'
city = '北京'
type = 'HOUR'
start_time = '2020-08-27 00:00:00'
end_time = '2020-08-28 23:00:00'

# Compile javascript
file = 'jsCode.js' #代加載編譯的js源文件
ctx = node.compile(open(file, encoding='utf-8').read())#加載編譯的js源文件中的js代碼
# Get params
js = 'getPostParamCode("{0}", "{1}", "{2}", "{3}", "{4}")'.format(method, city, type, start_time, end_time)
params = ctx.eval(js)# eval表示執行指定js函數
print(params)

data = {
    "d":params
}
page_text = requests.post(url=url,headers=headers,data=data).text
print(page_text)# 返回的是加密的響應數據

# 對加密的響應數據進行解密
js = 'decodeData("{0}")'.format(page_text)
decrypted_data = ctx.eval(js)
print(decrypted_data) #解密后的真實數據


完美結束


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM