JS逆向-反反爬案例

本文涉及的产品
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时数仓Hologres,5000CU*H 100GB 3个月
实时计算 Flink 版,5000CU*H 3个月
简介: 破解爬虫JS加密反爬, 逆向JS解析

1. 逆向js-破解翻译网页的爬取

    1. 分析目标:某词霸的PC端
    1. 爬取目的:制作属于自己的翻译小词典

2. 抓包分析

选中网页右击点‘检查’或者F12, 选择network, 输入“中国”, 回车
image.png

查看请求的参数:
image.png

查看实际返回的翻译结果:
image.png

3.解决方案

    1. 第一种方案:使用模拟浏览器类似selenium的工具, 绕过js加解密直接获取
    1. 第二种方案:逆向js

3.1 逆向请求参数sign加密

从network抓包请求来看, 这是一个ajax请求(XMLHttpRequest),返回的是json数据。 我们需要通过打断点来定位sign的加密过程。

选中Source, 最右侧面板的 XHR/fetch Breakpoints, 添加"index.php"
image.png

添加之后, 重新输入需要翻译的词语, 回车,断点就开始生效了:
image.png

重新输入单词,即会断住,可以看到,此时 sign 参数已经生成了:

// 发送的请求全网址
"/index.php?c=trans&m=fy&client=6&auth_user=key_web_new_fanyi&sign=".concat(encodeURIComponent(r))

找到R值是最为关键

// 其中 r 值 是需要特殊关注的
var r = u()("6key_web_new_fanyi".concat(s.LI).concat(t.q.replace(/(^\s*)|(\s*$)/g, ""))).toString().substring(0, 16);
return r = (0, _.$Q)(r),


// 1. "6key_web_new_fanyi" 固定字符串(是否是固定需要多次测试)
// 2. s.LI 固定字符串:“6dVjYLFyzfkFkk”
// 3. t.q  是需要翻译的数据:“中国”
// 4. concat()函数是字符串拼接方法, 
//    replace() 是字符串替换方法, 
//    toString() 是转换成字符串的类型
//    substring(0,16) 截取前 16个字符
//

image.png

一直往下点击追踪,会发现 u() 方法内部使用的是:MD5加密
image.png

var r = u()("6key_web_new_fanyi".concat(s.LI).concat(t.q.replace(/(^\s*)|(\s*$)/g, ""))).toString().substring(0, 16);

// 所以从上面的 追踪结果来分析的结论是:
MD5("6key_web_new_fanyi" + “6dVjYLFyzfkFkk” + “中国”)[:16]

将拼接的字符创 使用MD5加密, 加密之后是32位, 截取前 16

image.png

断点继续

return r = (0, _.$Q)(r),

image.png
进入内部方法

image.png

从以上代码中可以 看出是AES加密,加密mode为ECB,padding为 PKCS7
使用过AES加密的人知道AES需要一个key来进行加密,所以我们需要找到key的值

n.AES.encrypt(e, r, {
   
   
                mode: n.mode.ECB,
                padding: n.pad.Pkcs7}
// e 是需要加密的 内容
// r 就是加密的key
r = n.enc.Utf8.parse(s(t))
// r 是经过 s(t) 函数来获取的, n.enc.utf8.parse只是在转译
// key: 'L4fBtD5fLC9FQw22'

image.png

分析到这一步, sign值的加密过程就分析完毕了, 我们可以根据实现原理通过Python来实现并验证

// aes_secret.py

import base64
import hashlib
import urllib.parse
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad


# AES 加密方法
def aes_encrypt(aes_key: str, text: str) -> str:
    key = aes_key.encode('utf-8')
    srcs = text.encode('utf-8')
    cipher = AES.new(key, AES.MODE_ECB)
    # 在加密之前进行填充
    padded_data = pad(srcs, AES.block_size)
    encrypted = cipher.encrypt(padded_data)
    # 返回 base64 编码后的密文
    return base64.b64encode(encrypted).decode('utf-8')

# 生成Sign的方法
def get_sign() -> str:
    search_word = '中国'
    aes_key = 'L4fBtD5fLC9FQw22'
    concat_search_params = '6key_web_new_fanyi' + '6dVjYLFyzfkFkk' + search_word
    md5_encrypt_result = hashlib.md5(concat_search_params.encode()).hexdigest()[:16]
    sign = aes_encrypt(aes_key, md5_encrypt_result)
    return urllib.parse.quote(sign)


print(get_sign())  
# aG5ry6oF+IvstLPiNdhDiNRriqVIAJSQ+xmfU0q7dIE=
# 经过对比 这个加密值 和 爱词霸的sign 一模一样

3.2 逆向 content 的加密内容

image.png
在这里解密的方法是:B6
image.png

进入B6 之后可以看到解密也使用的市AES:
image.png

解密方式:AES
key: aahc3TfyfCEmER33 
mode:ECB
padd:pkcs7

分析完解密js之后, python复现解密过程

# aes_secret.py

import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad



def aes_decrypt(ciphertext):
    key = 'aahc3TfyfCEmER33'.encode('utf-8')
    # 将密文进行 base64 解码
    ciphertext = base64.b64decode(ciphertext)
    # 创建 AES 解密器对象
    cipher = AES.new(key, AES.MODE_ECB)
    # 对密文进行解密
    decrypted_data = cipher.decrypt(ciphertext)
    # 对解密后的数据进行去填充操作
    decrypted_data = unpad(decrypted_data, AES.block_size)
    # 返回解密后的明文
    return decrypted_data.decode('utf-8')


content = "nCRjxZwyh/7P3ee74BIU0r+VpYqC1/VewPqzx0un7jyu16Zu+DoJ69fUH5j/kw8Qy0B+M69qfiZXuNmK/ojCoUt/Ccnr8yD8+ptxnH1DkEEsTfbrhTNWIXzg5vsxTi8raJf9MJpvANQw7285y3YD7L9fWOC9Nn0hsLdDAWJOgm4p45ozDcMrAvaLI5kVnkC5DXmu4lgquGouf1F+k4YFpiEUJ5XHAbshY51gmoeoEXYuobI4eswavxrdxqh0HYSXNLxoz198exBfVyR3fSa2eUGRQWYe1P8xK/dskvuEYXw0RbGM0yYu02AzQ2wHI+0PzR1yzSbJQp1MiZ5Y8eisCt9UjVIme7ZpNyfr3u8U3sg="
print(aes_decrypt(content))


# china

4. 完整代码过程

注意: aes_secret.py 需要自己创建

import requests
import json
from aes_secrect import aes_decrypt,get_sign

class King(object):

    def __init__(self, word):
        self.word = word
        # 生成加密的sign
        sign = get_sign(self.word)
        print('sign:', sign)
        self.url = f"https://ifanyi.iciba.com/index.php?c=trans&m=fy&client=6&auth_user=key_web_new_fanyi&sign={sign}"

        self.headers = {
   
   
            "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
        }
        self.post_data = {
   
   
            "from": "auto",
            "to": "auto",
            "q": self.word
        }

    def get_data(self):

        response = requests.post(self.url, headers=self.headers, data=self.post_data)
        # 解密 返回的加密内容
        data = aes_decrypt(response.json()['content'])
        return data

    def parse_data(self, data):
        # 打印解密之后的数据
        print(data)
        # 将json数据转换成python字典
        dict_data = json.loads(data)

        # 从字典中抽取翻译结果
        try:
            print(dict_data['out'])

        except:
            print("翻译失败")

    def run(self):
        # 发送请求
        data = self.get_data()
        # 解析
        self.parse_data(data)

if __name__ == '__main__':
    king = King('人生苦短,我用python')
    king.run()
相关文章
|
3月前
|
数据采集 Web App开发 JavaScript
利用Selenium和XPath抓取JavaScript动态加载内容的实践案例
利用Selenium和XPath抓取JavaScript动态加载内容的实践案例
|
1月前
|
前端开发 JavaScript
JavaScript动态渲染页面爬取——CSS位置偏移反爬案例分析与爬取实战
JavaScript动态渲染页面爬取——CSS位置偏移反爬案例分析与爬取实战
|
3月前
|
JavaScript 前端开发 UED
Javaweb之javascript的小案例的详细解析
通过上述步骤,我们得到了一个动态更新的实时时钟,这个简单的JavaScript案例展示了定时器的使用方法,并讲解了如何处理日期和时间。这个案例说明了JavaScript在网页中添加动态内容与交互的能力。对于涉足JavaWeb开发的学习者来说,理解和运用这些基础知识非常重要。
42 11
|
3月前
|
JavaScript API 图形学
一个案例带你从零入门Three.js,深度好文!
【8月更文挑战第1天】本教程无需任何Threejs知识!本教程以入门为主,带你快速了解Three.js开发
86 2
一个案例带你从零入门Three.js,深度好文!
|
3月前
|
前端开发 JavaScript 开发者
fuse.js前端搜索简单使用的三个案例
通过这三个例子可以看出,Fuse.js 是一个功能丰富、易于实现的前端搜索库。它使开发者能够便捷地实现从基础到高级的搜索功能,无论是简单的列表搜索还是实时的搜索建议,都能够高效、精确地提供给用户所需的信息。
193 0
|
3月前
|
JavaScript 前端开发 开发者
Vue.js 2 项目实战(四):成绩案例
Vue.js 2 项目实战(四):成绩案例
|
3月前
|
JavaScript 前端开发 开发者
Vue.js 2 项目实战(三):综合案例-小黑记事本
Vue.js 2 项目实战(三):综合案例-小黑记事本
|
3月前
|
JavaScript 前端开发 开发者
Vue.js 2 项目实战(二):图书管理案例
Vue.js 2 项目实战(二):图书管理案例
|
3月前
|
JavaScript 前端开发 开发者
Vue.js 2 项目实战(一):图片切换案例
Vue.js 2 项目实战(一):图片切换案例
|
3月前
|
数据采集 存储 JavaScript
JS逆向案例:巨潮资讯数据采集
JS逆向案例:巨潮资讯数据采集
49 0
下一篇
无影云桌面