目录
普通:
1. 简介
2. 加密原理
二.实战案例
1. 逆向目标
2. 逆向分析
1. 逆向目标
2. 逆向分析
实战:
无限debugger原理
1. Function("debugger").call()
2. XXX.constructor("debugger").call("action")
3. (function(){return !![];})["constructor"]("debugger")["call"]("action")
总结
如何过
通杀代码:
一.常见COOKIE反爬
普通:
1. 简介
-
Cookie 反爬虫指的是服务器端通过校验请求头中的 Cookie 值来区分正常用户和爬虫程序的手段,这种
手段被广泛应用在 Web 应用中。
2. 加密原理
-
cookie加密分为大致两种方式
-
浏览器向服务器发送请求,服务器在响应头带上响应cookie,下次请求的时候需要再带上cookie去进行请求
-
浏览器向服务器发送请求,服务器返回的是一段js代码,浏览器需要解析js代码,在通过js代码在生成cookie信息
-
二.实战案例
1. 服务器响应cookie信息
-
学习响应cookie和session的处理
-
学习基于首页返回的cookie值
1. 逆向目标
-
地址:互动交流 - 麻章区政府网站
-
接口:http://www.zjmazhang.gov.cn/hdjlpt/letter/pubList
-
对抗: cookie 反爬虫处理
2. 逆向分析
-
可以先测试当前网站的接口,可以发现,当前的接口需要一个cookie值,一个token值
确定为cookie反爬,第一步先清除cookie
-
重新请求
-
发现published中的
-
_csrf为
publist中的X_Csrf-Token
先请求published这个接口
-
发现publist中的cookie也是这个里面带出来的
-
那我们首先请求published,再请求publist即可
-
import requests import re def get_cookie(): url = 'http://www.zjmazhang.gov.cn/hdjlpt/published?via=pc' headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36' } res = requests.get(url, headers=headers) csrf = re.findall("var _CSRF = '(.*?)';", res.text)[0] # print(res.cookies) cookie = res.cookies.get('szxx_session') return csrf, cookie csrf, cookie = get_cookie() url = 'http://www.zjmazhang.gov.cn/hdjlpt/letter/pubList' headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36', 'X-Csrf-Token': csrf } cookies = {'szxx_session': cookie} data = { "offset": "0", "limit": "20", "site_id": "759010", "time_from": "1669564800", "time_to": "1701014399" } res = requests.post(url, headers=headers, cookies=cookies, data=data) print(res.text)
2. 阿里系cookie逆向
-
阿里系cookie 请求两次 第一次会得到一个响应的cookie 会返回一个js代码 通过js代码会生成一个新的cookie 第二次请求需要拿到两次生成的cookie才能访问 自动的断点
-
学习JS设置的cookie处理
-
学习轻度JS混淆处理
1. 逆向目标
-
首页:aHR0cHM6Ly90YW5nLmNkdC1lYy5jb20vbm90aWNlL21vcmVDb250cm9sbGVyL3RvTW9yZT9nbG9ibGVUeXBlPTA=
-
目标:cookie: acw_sc__v2
2. 逆向分析
-
逆向cookie时需要先清空cookie,让网页重新生成
-
阿里系的cookie在重新刷新之后,会进入到debugger模式
-
过无限debugger
Function.prototype.__constructor_back = Function.prototype.constructor; Function.prototype.constructor = function() { if(arguments && typeof arguments[0]==='string'){ if("debugger" === arguments[0]){ return } } return Function.prototype.__constructor_back.apply(this,arguments); }
-
可以直接通过调试断点的方式,找到加密的位置
实战:
-
-
发现他是getlist这个请求,加密参数是要带上cookie的acw_sc_v2
-
我们先把这个cookie去掉,重发请求
-
如我们所料,发了两个包,第一个是js代码,第二个是正常的包
-
下面我们下script断点:
断到这个地方了,继续执行接下来断到
-
继续执行会到无限debugger里面去
-
进去,看是如何调用的
-
发现debugger是这样的
-
无限debugger原理
-
下面是基本原理:
-
这些代码示例利用了JavaScript中的
Function
构造函数和对象的constructor
属性来动态执行字符串形式的代码。这些方法通常用于执行任意代码,但也可以用于注入和执行恶意代码。下面我将解释每个示例的原理,并提供一些例子。1.
Function("debugger").call()
这个示例使用
Function
构造函数来创建一个新的函数,该函数包含一个debugger
语句。然后使用call
方法执行这个新函数。// 创建并执行一个包含debugger的函数 Function("debugger").call();
这行代码会立即执行
debugger
,导致浏览器在调试模式下暂停执行。2.
XXX.constructor("debugger").call("action")
这个示例首先获取某个对象
XXX
的constructor
属性,这是一个指向创建该对象的构造函数的引用。然后,它使用这个构造函数来创建一个新的函数,该函数包含一个debugger
语句,并尝试用call
方法执行这个新函数。// 假设有一个对象obj const obj = {}; // 使用obj的constructor(即Object)来创建并执行一个包含debugger的函数 obj.constructor("debugger").call();
这行代码同样会执行
debugger
,导致浏览器在调试模式下暂停执行。3.
(function(){return !![];})["constructor"]("debugger")["call"]("action")
这个示例稍微复杂一些。它首先创建一个立即执行函数表达式(IIFE),该函数返回一个布尔值。然后,它获取这个函数的
constructor
属性,这是一个指向Function
构造函数的引用。接着,它使用这个构造函数来创建一个新的函数,该函数包含一个debugger
语句。最后,它使用call
方法执行这个新函数。// 创建一个IIFE,返回一个布尔值 const boolFunc = (function() { return !![]; })(); // 使用boolFunc的constructor(即Function)来创建并执行一个包含debugger的函数 boolFunc.constructor("debugger").call();
这行代码也会执行
debugger
,导致浏览器在调试模式下暂停执行。总结
这些示例展示了如何使用
Function
构造函数和对象的constructor
属性来动态执行代码。这些技术可以用于测试、调试或执行动态代码,但也可能被用于恶意目的,如代码注入和执行恶意代码。因此,在使用这些技术时需要谨慎,并确保代码的安全性。
这段代码是一个混淆过的JavaScript代码片段,它使用了多种技巧来隐藏其真实意图。让我们逐步分析这段代码:
(function() {}
:这是一个空的立即执行函数表达式(IIFE)。
['\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72']
:这是一个数组,其中包含一个字符串,该字符串是"constructor"
的十六进制编码。
(undefined + '')[0x2]
:这是一个技巧,用于获取字符串"undefined"
的第三个字符,即d
。
(!![] + '')[0x3]
:这是一个技巧,用于获取字符串"true"
的第四个字符,即e
。
([][_0x55f3('0x1f', '\x4c\x24\x28\x44')]() + '')[0x2]
:这部分代码看起来是调用了一个名为_0x55f3
的函数(可能是一个混淆后的函数名),并传递了两个参数。这个函数可能返回一个方法名,然后调用该方法,并将其结果与空字符串拼接,最后取第二个字符。由于_0x55f3
函数的具体实现未知,我们无法确定这部分代码的确切行为。
(![] + [0x0] + String)[0x14]
:这是一个技巧,用于获取字符串"false"
的第十五個字符,即s
。
(!![] + '')[0x3]
:这是一个技巧,用于获取字符串"true"
的第四个字符,即e
。
(!![] + '')[0x1]
:这是一个技巧,用于获取字符串"true"
的第二个字符,即r
。将这些部分组合起来,这段代码实际上是在构造一个字符串,该字符串通过连接上述字符来形成
"constructor"
。然后,它使用这个字符串作为键来访问当前上下文中的一个对象的constructor
属性。
如何过
我们可以这么过:
Function.prototype.__constructor_back = Function.prototype.constructor;
Function.prototype.constructor = function() {
if(arguments && typeof arguments[0]==='string'){
if("debugger" === arguments[0]){
return
}
}
return Function.prototype.__constructor_back.apply(this,arguments);
}
过了这个进入我们之前打的断点
看上一层堆栈,发现是由settimeout执行函数,加密位置在arg2,arg2加密也在上面
开始扣代码
var _0x23a392 = arg1[_0x55f3('0x19', '\x50\x67\x35\x34')]();
arg2 = _0x23a392[_0x55f3('0x1b', '\x7a\x35\x4f\x26')](_0x5e8b26);
扣的过程中随时替换
arg1是变化的
扣完的成品:
通杀代码:
https://articles.zsxq.com/id_bblrs5mvwdit.html,见知识星球
包装成一个方法后,在python先把加密参数删除掉,请求第一次,用re提取arg1形成加密参数,请求第二次
完结。