【JS逆向】xx社区 帖子 请求参数加密(nonce)

 

注意:文章内容仅用于学习和技术交流,如有侵权请联系我删除。
学者应洁身自好,切勿做出违法的事情,旨在提供逆向思路。

➣➣欢迎关注本人微信公众号Anonymous NoteBook➣➣

分享好玩有趣的网络资源&软件工具~

分享各种技术性PDF资源/付费查询PDF资源~

分享各种编程语言、开发技术、分布式事务、大数据与云计算技术~

分享有关网络爬虫(Web爬虫逆向 | 安卓逆向)案例、数据挖掘、技术心得等~

aHR0cHM6Ly9iYnMudml2by5jb20uY24vbmV3YmJzLw==

问题分析:

打开网页,鼠标往下滑,不停的加载数据,典型的ajax动态加载。

打开F12查看接口:

随着不停的加载数据,lastid 和 nonce 都在随着变化, nonce看着有点想md5加密,下面开始进入分析阶段。

逆向分析:

全局搜索”nonce“,出现两条数据:

 

先点击第一条看下:

看到了md5,并且把最终结果动态赋值给e,猜测这里就是加密nonce解密入口,打个断点,加载数据验证下,看看是否能断下来:

 果然,断点起作用了,分析下里面的参数数据:

t :时间戳;

1e7 * Math.random():生成随机数据;

parseInt 函数:对字符串进行解析,最后返回整数。

知识点:

 这些参数都将作为匿名函数的参数进行处理,也就是进行md5处理:

 跟进去:

 此处就是参数加密的逻辑所在,拷贝下来,粘贴到本地js文件中,进行测试:

 完美运行。

接下来分析 lastid 参数:

全局搜索下:

就一条数据,此处为初始化变量的地方。

在文件里再次进行搜索,结果出现4处地方:

 打上断点进行调试,刷新页面,数据停到此处:

这里想必就是赋值的地方。

根据调试的结果,发现lastid的值是this属性中的字段,this是某对象的一个实例,而结果却早已生成,此时我们复制下 lastid的值,去搜索下:

 找到一条,点进去看下:

 恍然大悟。。。 tid是上一页数据中最后一条用户数据的tid,这就好办了。

构造请求代码时,生成一个空间容量为1的队列,每次把最后一个用户的tid放进队列里,下次请求时,从列队里取出来构造参数去请求,周而复始,不断地重复这样的操作,就会有源源不断的数据生成。

至此,分析完毕。

function md5(e, t) {
    function n(e, t) {
        return e << t | e >>> 32 - t
    }
    function i(e, t) {
        var n, i, a, r, o;
        return a = 2147483648 & e,
            r = 2147483648 & t,
            n = 1073741824 & e,
            i = 1073741824 & t,
            o = (1073741823 & e) + (1073741823 & t),
            n & i ? 2147483648 ^ o ^ a ^ r : n | i ? 1073741824 & o ? 3221225472 ^ o ^ a ^ r : 1073741824 ^ o ^ a ^ r : o ^ a ^ r
    }
    function a(e, t, a, r, o, s, l) {
        return e = i(e, i(i(function(e, t, n) {
            return e & t | ~e & n
        }(t, a, r), o), l)),
            i(n(e, s), t)
    }
    function r(e, t, a, r, o, s, l) {
        return e = i(e, i(i(function(e, t, n) {
            return e & n | t & ~n
        }(t, a, r), o), l)),
            i(n(e, s), t)
    }
    function o(e, t, a, r, o, s, l) {
        return e = i(e, i(i(function(e, t, n) {
            return e ^ t ^ n
        }(t, a, r), o), l)),
            i(n(e, s), t)
    }
    function s(e, t, a, r, o, s, l) {
        return e = i(e, i(i(function(e, t, n) {
            return t ^ (e | ~n)
        }(t, a, r), o), l)),
            i(n(e, s), t)
    }
    function l(e) {
        var t, n = "", i = "";
        for (t = 0; t <= 3; t++)
            n += (i = "0" + (e >>> 8 * t & 255).toString(16)).substr(i.length - 2, 2);
        return n
    }
    var c, u, p, m, d, h, f, v, y, g = e, b = Array();
    for (b = function(e) {
        for (var t, n = e.length, i = n + 8, a = 16 * ((i - i % 64) / 64 + 1), r = Array(a - 1), o = 0, s = 0; s < n; )
            o = s % 4 * 8,
                r[t = (s - s % 4) / 4] = r[t] | e.charCodeAt(s) << o,
                s++;
        return t = (s - s % 4) / 4,
            o = s % 4 * 8,
            r[t] = r[t] | 128 << o,
            r[a - 2] = n << 3,
            r[a - 1] = n >>> 29,
            r
    }(g),
             h = 1732584193,
             f = 4023233417,
             v = 2562383102,
             y = 271733878,
             c = 0; c < b.length; c += 16)
        u = h,
            p = f,
            m = v,
            d = y,
            f = s(f = s(f = s(f = s(f = o(f = o(f = o(f = o(f = r(f = r(f = r(f = r(f = a(f = a(f = a(f = a(f, v = a(v, y = a(y, h = a(h, f, v, y, b[c + 0], 7, 3614090360), f, v, b[c + 1], 12, 3905402710), h, f, b[c + 2], 17, 606105819), y, h, b[c + 3], 22, 3250441966), v = a(v, y = a(y, h = a(h, f, v, y, b[c + 4], 7, 4118548399), f, v, b[c + 5], 12, 1200080426), h, f, b[c + 6], 17, 2821735955), y, h, b[c + 7], 22, 4249261313), v = a(v, y = a(y, h = a(h, f, v, y, b[c + 8], 7, 1770035416), f, v, b[c + 9], 12, 2336552879), h, f, b[c + 10], 17, 4294925233), y, h, b[c + 11], 22, 2304563134), v = a(v, y = a(y, h = a(h, f, v, y, b[c + 12], 7, 1804603682), f, v, b[c + 13], 12, 4254626195), h, f, b[c + 14], 17, 2792965006), y, h, b[c + 15], 22, 1236535329), v = r(v, y = r(y, h = r(h, f, v, y, b[c + 1], 5, 4129170786), f, v, b[c + 6], 9, 3225465664), h, f, b[c + 11], 14, 643717713), y, h, b[c + 0], 20, 3921069994), v = r(v, y = r(y, h = r(h, f, v, y, b[c + 5], 5, 3593408605), f, v, b[c + 10], 9, 38016083), h, f, b[c + 15], 14, 3634488961), y, h, b[c + 4], 20, 3889429448), v = r(v, y = r(y, h = r(h, f, v, y, b[c + 9], 5, 568446438), f, v, b[c + 14], 9, 3275163606), h, f, b[c + 3], 14, 4107603335), y, h, b[c + 8], 20, 1163531501), v = r(v, y = r(y, h = r(h, f, v, y, b[c + 13], 5, 2850285829), f, v, b[c + 2], 9, 4243563512), h, f, b[c + 7], 14, 1735328473), y, h, b[c + 12], 20, 2368359562), v = o(v, y = o(y, h = o(h, f, v, y, b[c + 5], 4, 4294588738), f, v, b[c + 8], 11, 2272392833), h, f, b[c + 11], 16, 1839030562), y, h, b[c + 14], 23, 4259657740), v = o(v, y = o(y, h = o(h, f, v, y, b[c + 1], 4, 2763975236), f, v, b[c + 4], 11, 1272893353), h, f, b[c + 7], 16, 4139469664), y, h, b[c + 10], 23, 3200236656), v = o(v, y = o(y, h = o(h, f, v, y, b[c + 13], 4, 681279174), f, v, b[c + 0], 11, 3936430074), h, f, b[c + 3], 16, 3572445317), y, h, b[c + 6], 23, 76029189), v = o(v, y = o(y, h = o(h, f, v, y, b[c + 9], 4, 3654602809), f, v, b[c + 12], 11, 3873151461), h, f, b[c + 15], 16, 530742520), y, h, b[c + 2], 23, 3299628645), v = s(v, y = s(y, h = s(h, f, v, y, b[c + 0], 6, 4096336452), f, v, b[c + 7], 10, 1126891415), h, f, b[c + 14], 15, 2878612391), y, h, b[c + 5], 21, 4237533241), v = s(v, y = s(y, h = s(h, f, v, y, b[c + 12], 6, 1700485571), f, v, b[c + 3], 10, 2399980690), h, f, b[c + 10], 15, 4293915773), y, h, b[c + 1], 21, 2240044497), v = s(v, y = s(y, h = s(h, f, v, y, b[c + 8], 6, 1873313359), f, v, b[c + 15], 10, 4264355552), h, f, b[c + 6], 15, 2734768916), y, h, b[c + 13], 21, 1309151649), v = s(v, y = s(y, h = s(h, f, v, y, b[c + 4], 6, 4149444226), f, v, b[c + 11], 10, 3174756917), h, f, b[c + 2], 15, 718787259), y, h, b[c + 9], 21, 3951481745),
            h = i(h, u),
            f = i(f, p),
            v = i(v, m),
            y = i(y, d);
    return 32 == t ? l(h) + l(f) + l(v) + l(y) : l(f) + l(v)
}

function get_nonce() {
    var time_ = new Date().getTime().toString(),
        params = time_ + '' + parseInt(1e7 * Math.random(), 10) + 1;
    var nonce = md5(params, 32)
    return nonce
}

console.log('nonce: ',get_nonce())

import requests
import execjs
import json
import time
from queue import Queue
q = Queue(maxsize=1)

with open('D:\xxxx.js', 'r', encoding='utf-8') as f:
    data = f.read()

ctx = execjs.compile(data)
result = ctx.call('get_nonce')
print(result)

headers = {
    'Content-Type': 'application/json;charset=UTF-8',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36',
    'Origin': 'https://xxxx.com.cn',
    'Referer': 'https://xxxx.com.cn/newbbs/',
}

q.put('32172070')

for i in range(1,10):
    while q.empty():
        time.sleep(1.5)
        print('等待...')
        continue
    data = {"lastId":q.get(),"pageNum":i,"pageSize":10,"imgSpecs":["t577x324","t577x4096"],"timestamp":int(time.time()*1000),"nonce":result}
    time.sleep(1.5)
    response = requests.post('https://xxxx.cn/api/community/index', headers=headers, data=json.dumps(data))
    data_list = response.json()['data']['list']
    tid = ''
    for data in data_list:
        tid = data.get('tid')
        summary = data.get('summary')
        author = data.get('author').get('bbsName')
        print('tid:',tid,'\n', 'author: ',author,'\n', 'summary: ', summary)
    q.put(tid)
    print("隊列放入tid:", tid)

 【Ps:代码为测试随意构建,无严谨性可言,轻喷!】

完事~~~ 收工~~~

<think>好的,我现在需要解决用户的问题:如何在Python爬虫中对请求参数进行加密。用户提到了之前的回答和相关引用,我需要结合这些信息来给出详细的步骤和方法。 首先,回顾用户之前的对话,用户已经了解了如何添加GET和POST请求参数,现在关注的是参数加密。根据提供的引用内容,加密通常涉及到逆向分析JavaScript代码,然后用Python模拟加密逻辑。引用1提到使用hashlib来模拟MD5加密,引用2和3讨论了逆向JS和用Python重写加密函数,引用4提到了时间戳、参数排序和Base64加密的例子。 用户的需求可能包括常见的加密方法,如哈希、Base64、AES等,以及如何处理动态参数如时间戳和随机数。此外,用户可能还想了解如何逆向JS找到加密逻辑,这是实际爬虫中常遇到的难点。 接下来,我需要组织回答的结构。首先概述加密的必要性,然后分步骤介绍常见加密方法,包括哈希、Base64、对称加密(如AES)、非对称加密(如RSA)。然后详细说明如何逆向分析JavaScript,包括使用浏览器开发者工具定位加密函数,调试并理解逻辑,最后用Python实现。可能需要结合引用中的例子,如MD5模拟、Base64处理,以及动态参数生成。 还要注意用户可能遇到的困难,比如复杂的JS混淆,这时可能需要工具如PyExecJS来执行JS代码,或者使用自动化工具如Selenium。同时,提醒用户注意法律和道德规范,避免侵犯隐私或触犯法律。 最后,生成相关问题,帮助用户进一步学习,比如处理JS混淆、解决动态密钥、提升逆向效率等。 需要确保回答清晰,步骤明确,代码示例正确,并正确引用之前的资料,比如引用1的MD5示例,引用4的Base64和时间戳处理。同时,保持语言口语化,避免使用专业术语过多,但必要时解释清楚。</think>在Python爬虫中处理请求参数加密,需要通过逆向分析目标网站的加密逻辑,并采用Python代码模拟实现。以下是具体实现方法和步骤: --- ### 一、常见加密类型及Python实现 #### 1. 哈希算法(如MD5/SHA) 用于参数签名验证,通过不可逆加密生成唯一标识 ```python import hashlib def md5_encrypt(text): md5 = hashlib.md5() md5.update(text.encode('utf-8')) return md5.hexdigest() # 示例:加密时间戳 timestamp = str(int(time.time()*1000)) sign = md5_encrypt(f"key={timestamp}&salt=abc123") ``` [^1] #### 2. Base64编码 常用于简单数据混淆处理 ```python import base64 # 参数编码 param = "page=2&size=20".encode('utf-8') encoded = base64.b64encode(param).decode() # 解码验证 decoded = base64.b64decode(encoded).decode() ``` [^4] #### 3. 对称加密(AES/DES) 需要获取密钥进行加解密 ```python from Crypto.Cipher import AES import binascii def aes_encrypt(data, key, iv): cipher = AES.new(key.encode(), AES.MODE_CBC, iv.encode()) padded = data + (16 - len(data) % 16) * chr(16 - len(data) % 16) encrypted = cipher.encrypt(padded.encode()) return binascii.b2a_hex(encrypted).decode() # 示例使用 encrypted = aes_encrypt('page=1', '1234567890123456', '1234567890123456') ``` #### 4. 非对称加密(RSA) 处理需要公钥加密的场景 ```python from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 def rsa_encrypt(data, public_key): rsa_key = RSA.importKey(public_key) cipher = PKCS1_v1_5.new(rsa_key) return base64.b64encode(cipher.encrypt(data.encode())).decode() ``` --- ### 二、逆向分析JS加密流程 #### 步骤1:定位加密入口 1. 使用Chrome开发者工具(F12) 2. 在Network面板捕获加密请求 3. 通过XHR断点或搜索加密参数定位JS文件 #### 步骤2:调试加密逻辑 ```javascript // 典型加密函数结构 function encryptParams(params) { let timestamp = Date.now(); let sorted = Object.keys(params).sort().map(k => `${k}=${params[k]}`).join('&'); return md5(sorted + salt_key); } ``` #### 步骤3:Python复现逻辑 ```python import time def generate_params(page): params = { "page": page, "ts": int(time.time()*1000), "nonce": random.randint(1000,9999) } sorted_str = '&'.join([f"{k}={v}" for k,v in sorted(params.items())]) params['sign'] = hashlib.sha256(f"{sorted_str}appSecret").hexdigest() return params ``` [^4] --- ### 三、实战案例解析 以某电商网站搜索接口为例: 1. 原始请求参数: ```python {"keyword": "手机", "page": 1} ``` 2. 加密参数: ```python { "payload": "eyJraWQiOiIxMjM0NSIsImVuY3J5cHRlZERhdGEiOiJNek...", "x-sign": "a1b2c3d4e5f6" } ``` 3. Python复现流程: ```python def encrypt_payload(params): # 步骤1:添加时间戳 params['timestamp'] = int(time.time()*1000) # 步骤2:参数排序并序列化 sorted_params = json.dumps(params, sort_keys=True) # 步骤3:AES加密 encrypted = aes_encrypt(sorted_params, AES_KEY, AES_IV) # 步骤4:生成签名 sign = md5_encrypt(encrypted + SIGN_SALT) return {"payload": encrypted, "x-sign": sign} ``` --- ### 四、特殊场景处理 1. **动态密钥**:通过首次请求获取加密密钥 2. **环境检测**:使用`execjs`库直接执行JS代码 ```python import execjs with open('encrypt.js') as f: js_code = f.read() ctx = execjs.compile(js_code) encrypted = ctx.call('encrypt', 'raw_data') ``` 3. **反调试绕过**:使用无头浏览器获取加密结果 ```python from selenium.webdriver import ChromeOptions options = ChromeOptions() options.add_argument('--headless') driver = webdriver.Chrome(options=options) driver.get(url) encrypted = driver.execute_script('return window.encrypt(param);') ``` --- ### 五、注意事项 1. 优先使用网站的公开API接口 2. 遵守robots.txt协议 3. 控制请求频率避免被封禁 4. 加密逻辑变更时需要及时更新代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值