一次简单的先知社区js逆向记录
字数 926 2025-08-25 22:58:40
先知社区JS逆向分析教学文档
一、概述
本文档详细分析先知社区(XZ)的JS反爬机制,并提供完整的逆向解决方案。该反爬系统主要包含数组还原、数组解密和Cookie生成三个核心部分。
二、反爬机制分析
1. 数组还原机制
1.1 初始数组结构
var _0x4818 = ["csKHwqMI", "ZsKJwr8VeAsy", "UcKiN8O/wplwMA==", ...];
1.2 数组还原过程
通过自执行函数对数组进行348次头出尾进操作:
(function (_0x4c97f0, _0x1742fd) {
var _0x4db1c = function (_0x48181e) {
while (--_0x48181e) {
_0x4c97f0["push"](_0x4c97f0["shift"]()); // 头出尾进
}
};
_0x52d57c(_0x4db1c, _0x1742fd);
})(_0x4818, 347);
1.3 还原后数组
var _0x4818 = ['wqImMT0tw6RNw5k=', 'DMKcU0JmUwUv', 'VjHDlMOHVcONX3fDicKJHQ==', ...];
2. 数组解密机制
2.1 RC4解密函数
var _0x55f3 = function (_0x4c97f0, _0x1742fd) {
var _0x4c97f0 = parseInt(_0x4c97f0, 16);
var _0x48181e = _0x4818[_0x4c97f0];
_0x48181e = _0x55f3["rc4"](_0x48181e, _0x1742fd); // RC4解密
_0x55f3["data"][_0x4c97f0] = _0x48181e;
return _0x48181e;
};
2.2 解密后数据
_0x55f3["data"] = {
"1": "_phantom",
"3": "3000176000856006061501533003690027800375",
"5": "prototype",
"6": "hexXor",
// ...其他解密数据
}
3. Cookie生成机制
3.1 核心函数
String.prototype.hexXor = function (_0x4e08d8) {
// 十六进制异或运算
var _0x5a5d3b = "";
for (var _0xe89588 = 0; _0xe89588 < this.length; _0xe89588 += 2) {
var _0x401af1 = parseInt(this.substr(_0xe89588, 2), 16);
var _0x105f59 = parseInt(_0x4e08d8.substr(_0xe89588, 2), 16);
var _0x189e2c = (_0x401af1 ^ _0x105f59).toString(16);
_0x5a5d3b += _0x189e2c.length == 1 ? "0" + _0x189e2c : _0x189e2c;
}
return _0x5a5d3b;
};
String.prototype.unsbox = function () {
// 数组重排函数
var _0x4b082b = [15,35,29,24,33,16,1,38,10,9,19,31,40,27,22,23,25,13,6,11,39,18,20,8,14,21,32,26,2,30,7,4,17,5,3,28,34,37,12,36];
var _0x4da0dc = [];
for (var _0x20a7bf = 0; _0x20a7bf < this.length; _0x20a7bf++) {
var _0x385ee3 = this[_0x20a7bf];
for (var _0x217721 = 0; _0x217721 < _0x4b082b.length; _0x217721++) {
if (_0x4b082b[_0x217721] == _0x20a7bf + 1) {
_0x4da0dc[_0x217721] = _0x385ee3;
}
}
}
return _0x4da0dc.join("");
};
3.2 Cookie生成流程
- 获取初始参数
arg1 = '2F526E76D908955D2065FE39FACBFD626530F9B0' - 执行
arg1.unsbox()进行数组重排 - 对重排结果与密钥
3000176000856006061501533003690027800375进行hexXor运算 - 生成最终Cookie值并设置:
arg2 = arg1.unsbox().hexXor("3000176000856006061501533003690027800375");
document.cookie = "acw_sc__v2=" + arg2;
三、完整逆向实现
1. Python实现代码
import base64
from Crypto.Cipher import ARC4
class XZAntiCrawler:
def __init__(self):
self._0x4818 = ['wqImMT0tw6RNw5k=', 'DMKcU0JmUwUv', 'VjHDlMOHVcONX3fDicKJHQ==', ...] # 完整还原后数组
self._0x55f3_data = {}
def rc4_decrypt(self, data, key):
cipher = ARC4.new(key.encode())
return cipher.decrypt(base64.b64decode(data)).decode()
def unsbox(self, s):
order = [15,35,29,24,33,16,1,38,10,9,19,31,40,27,22,23,25,13,6,11,39,18,20,8,14,21,32,26,2,30,7,4,17,5,3,28,34,37,12,36]
result = [''] * len(order)
for i in range(len(s)):
for j in range(len(order)):
if order[j] == i + 1:
result[j] = s[i]
return ''.join(result)
def hex_xor(self, s, key):
result = ""
for i in range(0, len(s), 2):
if i + 2 > len(key):
break
s_hex = int(s[i:i+2], 16)
key_hex = int(key[i:i+2], 16)
xor_result = s_hex ^ key_hex
result += f"{xor_result:02x}"
return result
def generate_cookie(self, arg1):
unsboxed = self.unsbox(arg1)
key = "3000176000856006061501533003690027800375"
arg2 = self.hex_xor(unsboxed, key)
return f"acw_sc__v2={arg2}"
# 使用示例
xz = XZAntiCrawler()
arg1 = "2F526E76D908955D2065FE39FACBFD626530F9B0"
cookie = xz.generate_cookie(arg1)
print("生成的Cookie:", cookie)
2. 关键点说明
- 数组还原:必须准确执行348次头出尾进操作
- RC4解密:需要使用正确的密钥解密数组元素
- unsbox函数:严格按照给定的顺序数组[15,35,29,...]进行重排
- hexXor运算:十六进制字符串按两位一组进行异或运算
四、实际应用数据
通过逆向分析,收集了2022年10月13日-2023年2月23日的162条技术文章数据:
1. 作者分析
- LeeH师傅平均10天发表一篇文章
- Top10作者发文量占比显著
2. 地区分布
- 四川、广东、北京是发文量最大的三个地区
- 各地区安全研究重点有所不同
3. 内容分析
- Java安全和漏洞分析是主要研究方向
- 各地区技术关注点:
- 四川:Web安全、渗透测试
- 广东:漏洞分析、安全研究
- 北京:Java安全、系统安全
五、总结
先知社区的反爬系统通过多层混淆和加密保护数据:
- 使用数组还原和RC4加密混淆关键函数
- 通过Cookie验证机制阻止非浏览器访问
- 动态生成的arg1参数增加逆向难度
完整逆向需要:
- 准确还原数组顺序
- 实现RC4解密算法
- 复现unsbox和hexXor函数逻辑