# -*- coding: utf-8 -*- """解析 webpack 稀疏数组,确定登录模块 P.b 引用哪个 RSA 公钥模块""" import re import sys import requests import urllib3 urllib3.disable_warnings() s = requests.Session() s.verify = False t = s.get('https://newpc.996db.com/static/js/mainv2.6.01789526607.chunk.js', timeout=30).text def match_bracket(text, start): depth = 0 for k in range(start, len(text)): c = text[k] if c in '([{': depth += 1 elif c in ')]}': depth -= 1 if depth == 0: return k return -1 def split_top_array(arr_text): """[a,b,,c] → 顶层逗号切分(跳过空槽)""" items, depth, cur = [], 0, '' in_str = None for c in arr_text[1:-1]: if in_str: cur += c if c == in_str: in_str = None continue if c in '"\'': in_str = c cur += c continue if c in '([{': depth += 1 elif c in ')]}': depth -= 1 if c == ',' and depth == 0: items.append(cur) cur = '' continue cur += c items.append(cur) return items i = t.find('this.webpackJsonp996box||[]).push(') p1 = t.index('[', i) # [[33],[mods]] q1 = t.index(']', p1) # [33] 闭合(第一个子数组很短) r = t.index('[', q1) # mods 数组起点 r_end = match_bracket(t, r) mods = split_top_array(t[r:r_end + 1]) print(f'total slots: {len(mods)}, non-empty: {sum(1 for x in mods if x.strip())}') login_id = crypto_old_id = crypto_new_id = None for idx, item in enumerate(mods): if not item.strip(): continue if 'AjCQvqNP' in item: crypto_old_id = idx print(f'crypto OLD-key module id={idx} size={len(item)} exports={re.findall(r"n\.d\(t,.(\w+).", item)}') if 'KuB+7dLm' in item: crypto_new_id = idx print(f'crypto NEW-key module id={idx} size={len(item)} exports={re.findall(r"n\.d\(t,.(\w+).", item)}') if 'function _e()' in item: login_id = idx imps = re.findall(r'(\w+)=n\((\d+)\)', item) print(f'LOGIN module id={idx} size={len(item)}') print(f' imports: {imps}') # 在登录模块里找 P 的绑定 login_mod = mods[login_id] if login_id is not None else '' for m in re.finditer(r'(\w+)=n\.n?\((\d+)\)', login_mod): name, num = m.group(1), m.group(2) if name == 'P': print(f'\n*** P = n({num})') target = int(num) if target == crypto_old_id: print('*** P 指向 OLD 公钥模块 (b=old key)') elif target == crypto_new_id: print('*** P 指向 NEW 公钥模块 (a=new key)') else: print(f'*** P 指向模块 {target}(非公钥模块!)其内容片段:') if target < len(mods): print(mods[target][:600])