python爬蟲簡單實現逆向JS解密

FFlike發表於2019-08-29

目標解決零度代理JS解密

網址: https://nyloner.cn/proxy在這裡插入圖片描述


觀察下面的引數有什麼不同之處。上圖的token和下圖的token不一樣,上圖的t和下圖的t也不一樣,有過程式設計經驗的小夥伴會明白引數是動態生成的,簡單來說被加密了。

再來看看裡面的內容
在這裡插入圖片描述

這裡我們來分析一下加密的引數,上圖t這個引數是一串數字,我們來猜一下啊,這串數字是什麼呢?。一個簡單的時間戳。token肯定是被加密方式加密的具體哪種加密方式,等下看JS程式碼。
JS程式碼怎麼找,自己去研究一下吧,很簡單的,這裡就不介紹了,直接上程式碼。
下面是其中部分的JS程式碼,只找有用的部分就可以了
發現用的是md5加密,很簡單。下面用Python實現一下,幾行程式碼的事。

function get_proxy_ip(page, num, click_btn) {
    var timestamp = Date.parse(new Date());
    timestamp = timestamp / 1000;
    var token = md5(String(page) + String(num) + String(timestamp));
    $.get('../proxy?page=' + page + '&num=' + num + '&token=' + token + '&t=' + timestamp, function (result) {
        if (result.status === 'true') {
            var setHtml = "";
            $("#ip-list").html(setHtml);
            var encode_str = result.list;
            var items = str_to_json(decode_str(encode_str));
            for (var index = 0; index < items.length; ++index) {
                item = items[index];
                setHtml += "<tr>\n<td>" + (index + 1) + "</td>\n";
                setHtml += "<td>" + item.ip.toString() + "</td>\n";
                setHtml += "<td>" + item.port.toString() + "</td>\n";
                setHtml += "<td>" + item.time.toString() + "</td>\n</tr>\n";
            }
            $("#ip-list").html(setHtml);
            if (click_btn === 'next') {
                document.getElementById("last-page").disabled = false;
                if (items.length < 15) {
                    document.getElementById("next-page").disabled = true;
                }
            } else {
                document.getElementById("next-page").disabled = false;
                if (page === 1) {
                    document.getElementById("last-page").disabled = true;
                }
            }

        }
    });
}

python程式碼
模仿JS程式碼,模仿JS程式碼,模仿JS程式碼

def get_token(self,page,num):

    #獲取時間戳
    timestamp = int(time.time())

    token = str(page) + str(num) + str(timestamp)
    
    #模仿token加密
    token = hashlib.md5(token.encode()).hexdigest()
    
	#我這裡是把引數返回到url地址上,每個人寫程式碼方式不同,這裡可以忽略,明白上面就可以了
    basurl = self.url.format(page, num, token, timestamp)

    return basurl

引數加密解決了,最後解決內容加密
上JS程式碼

function decode_str(scHZjLUh1) {
    scHZjLUh1 = Base64["\x64\x65\x63\x6f\x64\x65"](scHZjLUh1);
    key = '\x6e\x79\x6c\x6f\x6e\x65\x72';
    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)
}

不要慌,簡單的base64和16進位制
上python

16進位制可以藉助工具啊
http://www.bejson.com/convert/ox2str/

def decode_str(self,scHZjLUh1):
    """
    解密base64
    \x64\x65\x63\x6f\x64\x65 : decode
    \x6e\x79\x6c\x6f\x6e\x65\x72 : nyloner
    \x6c\x65\x6e\x67\x74\x68 : length
    \x53\x74\x72\x69\x6e\x67 : String
    \x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65 : fromCharCode
    \x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74 : charCodeAt

    :param scHZjLUh1:
    :return:
    """
    scHZjLUh1 = base64.decodestring(scHZjLUh1.encode())
    key = 'nyloner'
    lenth = len(key)
    code = ''
    sch_lenth = len(scHZjLUh1)

    for i in range(sch_lenth):
        coeFYlqUm2 = i % lenth
        code += chr(scHZjLUh1[i] ^ ord(key[coeFYlqUm2]))

    code = base64.decodestring(code.encode())

    code = code.decode('utf-8')


    return code

最後就是呼叫一下解析文字就OK了,解密方式就是模仿JS程式碼,對比一下JS和Python程式碼。
想看原始碼可以在留言區評論,我會把我微信給你。
小白一個,希望與大家交流心得,一起進步。

相關文章