概要
x点w_tsfp参数逆向(补环境COOKIE)
URL:aHR0cHM6Ly93d3cucWlkaWFuLmNvbS9hbGwv
整体架构流程
提示:通过proxy代理,手补环境
首先进行hook
(function () {
'use strict';
var cookieTemp = '';
Object.defineProperty(document, 'cookie', {
set: function (val) {
debugger;
console.log('Hook捕获到cookie设置->', val);
cookieTemp = val;
return val;
},
get: function () {
return cookieTemp;
},
});
})();
找到加密文件:probev3.js,使用代理进行补环境
提示:请不要格式化代码,有检测
function get_enviroment(proxy_array) {
for(var i=0; i<proxy_array.length; i++){
handler = '{\n' +
' get: function(target, property, receiver) {\n' +
' console.log("方法:", "get ", "对象:", ' +
'"' + proxy_array[i] + '" ,' +
'" 属性:", property, ' +
'" 属性类型:", ' + 'typeof property, ' +
'" 属性值:", ' + 'target[property], ' +
'" 属性值类型:", typeof target[property]);\n' +
' return target[property];\n' +
' },\n' +
' set: function(target, property, value, receiver) {\n' +
' console.log("方法:", "set ", "对象:", ' +
'"' + proxy_array[i] + '" ,' +
'" 属性:", property, ' +
'" 属性类型:", ' + 'typeof property, ' +
'" 属性值:", ' + 'target[property], ' +
'" 属性值类型:", typeof target[property]);\n' +
' return Reflect.set(...arguments);\n' +
' }\n' +
'}'
eval('try{\n' + proxy_array[i] + ';\n'
+ proxy_array[i] + '=new Proxy(' + proxy_array[i] + ', ' + handler + ')}catch (e) {\n' + proxy_array[i] + '={};\n'
+ proxy_array[i] + '=new Proxy(' + proxy_array[i] + ', ' + handler + ')}')
}
}
proxy_array = ['window', 'document', 'location', 'navigator', 'screen', 'history', 'storage','process'];
get_enviroment(proxy_array)
边运行js看缺少的环境进行补充
local = {}
localStorage ={
getItem:function(k){
return local[k]
},
setItem:function(k,v){
local[k] = v
},
clear:function(){
local = {}
},
removeItem:function(k){
delete local[k]
}
}
document = {
cookie:'',
createElement:function(arg){
console.log('createElement',arg)
if(arg === 'canvas'){
return {}
}
}
}
location = {
"ancestorOrigins": {},
"href": "脱密处理",
"origin": "脱密处理",
"protocol": "https:",
"host": "脱密处理",
"hostname": "脱密处理",
"port": "",
"pathname": "脱密处理",
"search": "",
"hash": ""
}
navigator = {
appCodeName:"Mozilla",
appName:"Netscape",
appVersion:"xxx",
language:"zh-CN",
cookieEnabled:true,
doNotTrack:null,
geolocation:{},
hardwareConcurrency:8,
languages:['zh-CN', 'en', 'en-GB', 'en-US'],
maxTouchPoints: 0,
mediaCapabilities:{},
mediaSession:{metadata:null,playbackState:'none'},
platform:"Win32",
product:"Gecko",
productSub:"20030107",
onLine:true,
scheduling:{},
permissions:{},
pdfViewerEnabled:true,
userActivation:{hasBeenActive:true,isActive:false},
userAgent:"xxx",
vendor:"Google Inc.",
vendorSub:"",
webdriver:false,
connection:{
downlink: 5.65,
effectiveType: "4g",
onchange: null,
rtt: 150,
saveData: false
},
ink:{},
webkitPersistentStorage:{},
webkitTemporaryStorage:function (){},
windowControlsOverlay:{ongeometrychange:null,visible:false},
}
addEventListener = function(){}
open = function(){}
XMLHttpRequest = function (){}
重点在于定时器:
setTimeout = function (){}
setInterval = function (){
arguments[0]();
}
提示:如果并进行重写,定时器会0.5秒触发一次生成新的值,还有一点就是生成的cookie跟url有关,需要每次更改location的参数
function Tsfp(url){
location['href'] = url;
location['pathname'] = url.replace('脱敏','')
return {
'w_tsfp':document.cookie.split(';')[0].replace('w_tsfp=','')
}
}
技术名词解释
提示:python运行和调用js
例如:
效果
代码实现
import requests
import execjs
from lxml import etree
jsCode = execjs.compile(open('./w_tsfp.js',encoding='utf-8').read())
def getTsfp(url):
cookies = jsCode.call('Tsfp',url)
return cookies
url = 'https://xxx/'
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0',
'referer':'xxx/',}
response = requests.get(url, headers=headers,cookies=getTsfp(url))
html = response.text
tree = etree.HTML(html)
lis = tree.xpath('.//div[@class="book-img-text"]/ul/li')
for item in lis:
titleName = item.xpath('./div[@class="book-mid-info"]/h2/a/text()')[0]
shuUrl = 'https:' + item.xpath('./div[@class="book-mid-info"]/h2/a/@href')[0]
# print(f'书名为:{titleName},链接为:{shuUrl}')
# 书内部章节页
new_response = requests.get(shuUrl, headers=headers,cookies=getTsfp(shuUrl))
new_tree = etree.HTML(new_response.text)
allCatalog = new_tree.xpath('.//div[@id="allCatalog"]/div')[1:]
for catalog in allCatalog:
# 第几部
buName = '·'.join(catalog.xpath('./label//h3[@class="volume-name"]/text()'))
# 所有章节
uls = catalog.xpath('./ul[@class="volume-chapters"]/li')
for li in uls:
# 章节的名称
zhangName = li.xpath('./a[@class="chapter-name"]/text()')[0]
# 章节的链接
zhangUrl = 'https:' + li.xpath('./a[@class="chapter-name"]/@href')[0]
print(f'书名为:{titleName},链接为:{shuUrl},部集:{buName},章节:{zhangName},章节链接:{zhangUrl}')
# 章节内部内容正文
new1_response = requests.get(url = zhangUrl, headers=headers, cookies=getTsfp(zhangUrl))
new1_tree = etree.HTML(new1_response.text)
# 正文内容
contents = '\n'.join(i.replace('\u3000','') for i in new1_tree.xpath(f'.//main[@id="c-{zhangUrl.split("/")[-2]}"]/p/text()'))
print(f'正文内容:')
print('-----------------------------------------------------------------------------------------------------')
print(f'{contents}')
print('-----------------------------------------------------------------------------------------------------')
break
break
break
技术细节
- 找到反爬位置
- w_tsfp-cookie获取
- js反调试和定时器
- hook-cookie
- 补环境-格式化检测
小结
提示:补环境为主
学习交流群:v:wzwzwz0613拉进群