js加密和混淆篇(進階進階!!!)


14.js加密和js混淆

知識點

1.js加密
 對於提交表單的數據進行加密   
2.js混淆
JS混淆:對js函數的實現代碼進行加密
3.js逆向
    //手動逆向
    字節解密出來js代碼進行代碼執行
    //模塊逆向
    使用模塊PyExecJS 
    使用js執行我們的代碼

3.案列分析流程

3.1.某ip的爬取

1.判斷一個網站有沒有動態加載數據 
	查看response的數據是不是可以局部搜索到搜索到就部署動態加載數據 反之則是
	1.2.捕獲動態加載數據
    	基於抓包工具進行全局搜索,最終可以定位到動態加載數據對應的數據包。
        沒有搜索到對應的結果 就意味着 爬取的數據從服務端請求
2.判斷頁面每10s刷新一次,刷新數據沒有變說明是ajax請求的
3.2詳細流程
  • 爬取的數據是動態加載
  • 並且我們進行了抓包工具的全局搜索,沒有查找到結果
    • 意味着:爬取的數據從服務端請求到的是加密的密文數據
  • 頁面每10s刷新一次,刷新后發現數據更新,但是瀏覽器地址欄的url沒有變,說明加載出的數據是由ajax請求到的。
    • 動態加載出來的數據是由ajax請求到的,並且請求到的數據為加密數據
  • 定位到ajax數據包,從中可以看到url和動態變化的請求參數和加密的相應數據
  • 將ajax請求到的密文數據捕獲
    • 動態的獲取動態變化的請求參數
    • 基於抓包工具進行了動態變化請求參數token的全局搜索,定位到了token產生的源頭,就是如下js代碼:
      • var token = md5(String(page) + String(num) + String(timestamp));
  • 對密文數據進行解密
    • 通過分析找到了解密的js函數:decode_str(encode_str),encode_str就是密文數據
  • 查找encode_str的實現:
    • js逆向:將js代碼轉換成python代碼。開發環境只能執行python代碼
3.3具體解題思路
1.
查詢到是動態加載並且傳入的token是密文的,所以優先查看token
token是一串加密的數據優先查詢 因為是動態數據需要進行全局搜索
	token: 6eaacd1a30be918477d14fa3c47b6810
	var token = md5(String(page) + String(num) + String(timestamp));
    #獲取token值
2.自己手寫一個md5加密 然后做出token值  等待發送 發送完之后 得到密文數據
	proxy?page=' + page + '&num=' + num + '&token=' + token + '&t=' + 		timestamp對應的動態變換的值
   	#result 是返回的值
    #result.list 就是返回的密文
    #返回的值
    {list: "OUofBg89Mwc2BS4HKzY7DCIVDRA/BDAUI","status":true}
    
    
    var encode_str = result.list;
    var items = str_to_json(decode_str(encode_str));#對密文進行解密
    #對應decode的代碼
    function decode_str(scHZjLUh1) {
        #Base64.decode(scHZjLUh1)
        scHZjLUh1 = Base64["\x64\x65\x63\x6f\x64\x65"](scHZjLUh1);
        key = '\x6e\x79\x6c\x6f\x6e\x65\x72';#key = 'b'nyloner'
        len = key["\x6c\x65\x6e\x67\x74\x68"];
        code = '';
        for (i = 0; i < scHZjLUh1["\x6c\x65\x6e\x67\x74\x68"]; i++) {
            var coeFYlqUm2 = i % len;
            code += window["\x53\x74\x72\x69\x6e\x67"]["\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65"](scHZjLUh1["\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74"](i) ^ key["\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74"](coeFYlqUm2))
        }
        return Base64["\x64\x65\x63\x6f\x64\x65"](code)
    }
3.發現是編碼過的數據
	使用utf-8對16進制字節進行轉換編碼格式
	#"\x64\x65\x63\x6f\x64\x65".encode('utf-8')#重新編碼 這是16進制加密
4.#js逆向之后的結果
def decode_str(scHZjLUh1):
    #解密成字符串
    scHZjLUh1 = base64.decodestring(scHZjLUh1.encode())
    key = 'nyloner'
    lenth = len(key)
    code = ''
    sch_lenth = len(scHZjLUh1)
    for i in range(sch_lenth):
        coeFYlqUm2 = i % lenth
        #chr(0-255)返回對應編碼的字符
        #ord(a-z)返回編碼數值
        code += chr(scHZjLUh1[i] ^ ord(key[coeFYlqUm2]))
    code = base64.decodestring(code.encode())
    code = code.decode('utf-8')
    return code
5.然后就獲取了對應值進行相同格式的加密
        var token = md5(String(page) + String(num) + String(timestamp));

        token = getToken()
        url = 'https://nyloner.cn/proxy'
        param = {
            'num':'15',
            'page':'1',
            't':str(int(time.time())),
            'token':token

        }
        headers = {
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36',
            'Cookie':'sessionid=20ryihg87smnkko2kx6634jbcf4umhfp'
        }
        code = requests.get(url,headers=headers,params=param).json().get('list')
        str_code = decode_str(code)#對獲取的數據進行解碼
        str_code#打印獲取的數據
圖解
1.查找token值

全局搜索

某氣象站的爬取

流程

白話分析

1.首先判斷頁面是否是動態加載的
	發現局部搜索不到說明是動態加載的數據
2. 使用全局搜索也搜索不到說明進行了加密
	1.通過點擊a標簽的事件(推薦使用火狐)
    	
    2. 	尋找到點擊事件 執行對應的getdata函數
    	'''
     	$("#btnSearch").click(function(){
     	  	  getData();
     	    });
     	    '''
3.執行getData DATA內部有一個按小時的封裝
	type為hour
	1.內部封裝了兩個函數
		getAQIData();
		getWeatherData();
        
	2.
        function getAQIData()
           {
             var method = 'GETDETAIL';
             var param = {};
             字典內封裝了city,type,startTime,endTime
             	param.city = city;
             	param.type = type;
             	param.startTime = startTime;
             	param.endTime = endTime;
             	getServerData(method, param, function(obj)
     	
          function getWeatherData()
       {
		
         var method = 'GETCITYWEATHER';
         var param = {};
         param.city = city;
         param.type = type;
         param.startTime = startTime;
         param.endTime = endTime;
         getServerData(method, param, function(obj)
4.兩個函數的共同點內部都維護一個相同的字典
         1.局部查詢Serverdata查詢不到
         2.全局查詢Serverdata 查詢到了一加密js代碼
5.暴力破解js代碼
   分析getServerData函數的實現:
		終於找到了ajax請求對應的代碼
	參數d的構成:getParam(method, object)返回
		method:method
		object:param字典,四個鍵值分別是城市名稱。type,起始時間,結束時間
		請求到的密文數據的解密方式:
		decodeData(data):data參數就是響應的密文數據,返回值就是解密后的原文	數據
6. JS逆向:
	使用 PyExecJS 庫來實現模擬JavaScript代碼執行。
	環境的安裝:
	pip install PyExecJS
	必須還要安裝nodeJs的開發環境
     安裝nodejs

具體代碼實現

import execjs
import requests
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}
node = execjs.get()
file = 'test.js'
ctx = node.compile(open(file,encoding='utf-8').read())

#如何五個變量會作為getPostParamCode的參數
method = 'GETDETAIL'#GETCITYWEATHER
city = '北京'
type = 'HOUR'
start_time = '2018-01-25 00:00:00'
end_time = '2018-01-25 23:00:00'
#模擬執行getPostParamCode函數
js = 'getPostParamCode("{0}", "{1}", "{2}", "{3}", "{4}")'.format(method, city, type, start_time, end_time)
params = ctx.eval(js)
# print(params)#請求參數
url = 'https://www.aqistudy.cn/apinew/aqistudyapi.php'
data = {
    'd':params
}
#獲取了加密的響應數據
response_code = requests.post(url=url,headers=headers,data=data).text
# response_code

#模擬執行decodeData函數對密文數據進行解密
js = 'decodeData("{0}")'.format(response_code)
page_text = ctx.eval(js)
print(page_text)
為什么火狐比谷歌更容易查看點擊事件

上圖

谷歌!

火狐

如果所示

1.火狐可以更加清晰的看出點擊事件的觸發 谷歌只能查看對應的返回值
2.谷歌的代碼沒有js代碼自動換行 火狐內部做了處理可以查看函數的整體架構
但是火狐的一些搜索有點冗余


免責聲明!

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



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