作者声明:文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除!
本次逆向直接使用补环境方法。
目标请求数据在homefeed里面 ;直接复制cURL(cmd),从工具库直接转换成Python代码。
但发现直接这样运行代码后拿数据是拿不到的,只返回了一个状态码 <Response [406]>
接着分析后发现响应头里面其中一个 “content-type” 用的是json格式。请求头里面的**“content-type”**也是同理。所以需要JSON序列化。
json转换代码
import json
data = json.dumps(json_data, separators=(",", ":"))
response = requests.post('https://edith.xiaohongshu.com/api/sns/web/v1/homefeed', cookies=cookies, headers=headers,
data=data)
print(response.text)
技术细节
⚠️json.dumps(json_data, separators=(“,”, “:”)) 这里需要注意的是即使使用JSON转换还是会报错。因为源代码载荷的JSON格式 **“content-type”**是可以读取到的,但是如果我们用是Python的json序列化的dumps格式是会报错,有些网站可能做了识别机制。
所以才需要使用separators这个方法。
import json
data = {"a": 1, "b": 2}
print(json.dumps(data)) //{"a": 1, "b": 2}
print(json.dumps(data,separators=(",",":")))//{"a":1,"b":2}
可以观察出直接用dumps转换的Python格式 逗号跟冒号后面是带有空格的,但是源代码的载荷JSON是不带空格的。所以需要把不必要的符号之类改成相对于的就好。
这样就可以成功获取到数据了。但这不能长期有效,需要处理一下其他请求头的逆向。
这里可以发现 headers里面的 “x-s”值如果去掉就无法再获取到数据。
即使“x-s”带着但也是只能获取当前值的数据量,如果想批量获取其他数据就不行了。
利用关键词全局搜索,得到6个搜索项。
逐个分析找出x-s的生成方法。 这种比较少的可以直接都给他们打上断点,
打好断点后,转到其他页后就会断在这里, 可以看到 e.headers[“X-s”]=l[“X-s”] 是l生成的。 l就在上面,可以在l那一行重新打上断点。
l = (a && void 0 !== window._webmsxyw ? window._webmsxyw : encrypt_sign)(c, i) || {};
运行这个三目运算发现生成的是X-s,和一个X-t;
运行a 的结果是true,void 0 !== window._webmsxyw 结果也是真,那么就在 window._webmsxyw : encrypt_sign 这两个值取window._webmsxyw这个值, “void 0 !== window._webmsxyw”结果是false那就取 encrypt_sign。
运行一下 window._webmsxyw(c, i) ,查看一下c 的运行结果,‘/api/sns/web/v1/homefeed’ 如果路径不是我们目标值那就是错的。说明断点还没走进来。 到此 加密入口已找到。
找到加密入口后直接进入方法调用位置,
这里发现代码都用上了混淆,看不懂代码了,即使不混淆的情况下也是无法看懂了。
直接全局整合发现是自执行函数。 有一个函数为Sanji();
直接Ctrl+a, copy到自己文件夹。
运行发现报错,提示缺少window环境;
需要补充一下window对象, window = global; global 是node内置的全局变量,提供了很多window对象的方法。
细节 delete global;
需要添加一下 delete global ,原因是有些网站会分析global这个单词有没有生效 global is not defined, 他们会加一个if判断,因为我们用的环境是node提供的global,如果判断正常他们会返回一些假的数据源,如果判断报错那就返回真的数据。
这里提示报错,TypeError: Cannot read properties of undefined (reading ‘createElement’) 需要把createElement对象值补上;
createElement是在document下的一个对象值。
直接在env.js里补上即可, document={};
补上document对象后还是出现报错,这里分析后发觉这是一种无效报错信息。根本看不懂哪里的问题,这时就得上代理,让代理帮我找出问题所在。
function SetProxy(proxyObjs) {
for (let i = 0; i < proxyObjs.length; i++) {
const handler = `{
get: function(target, property, receiver) {
if (property!="Math" && property!="isNaN"){
if (target[property] && typeof target[property] !="string" && Object.keys(target[property]).length>3){
}else{
console.log("方法:", "get ", "对象:", "${proxyObjs[i]}", " 属性:", property, " 属性类型:", typeof property, ", 属性值:", target[property]);}}
return target[property];
},
set: function(target, property, value, receiver) {
console.log("方法:", "set ", "对象:", "${proxyObjs[i]}", " 属性:", property, " 属性类型:", typeof property, ", 属性值:", value, ", 属性值类型:", typeof target[property]);
return Reflect.set(...arguments);
}
}`;
eval(`try {
${proxyObjs[i]};
${proxyObjs[i]} = new Proxy(${proxyObjs[i]}, ${handler});
} catch (e) {
${proxyObjs[i]} = {};
${proxyObjs[i]} = new Proxy(${proxyObjs[i]}, ${handler});
}`);
}
}
SetProxy(["window"])
使用代理找出问题所在,就是这些属性值是undefined; 把这些属性值都补上;
直接在控制台打印一下,如果他本身就是空的 那就补一个空的。
navigator这种的就拿常用的几个值就行了
但是最终把这些属性值补上了还是会报错。这是因为有可能不只是window对象没补齐,需要把所有补过的属性值都监控一遍,在刚刚代理代码中加上那几个环境对象值"document", “location”, “navigator”,“localStorage” 。