2025-02-11
编程
00
请注意,本文编写于 75 天前,最后修改于 69 天前,其中某些信息可能已经过时。

目录

1.debugger
1.1 debugger原理
1.11第一种情况,直接制造debugger
1.12、使用 eval() 函数
1.13、定时器触发
1.14、其他方式
1.14.1
1.14.2
1.14.3
1.14.4
1.14.5
2.过debugger
2.1 Add conditional breakpoint条件断点(有的地方不行)
2.2 Never pause here不停在此处(有的地方不行)
2.3 钩子函数
2.31设置 script 断点
2.32 Hook Function 构造器函数
2.33 Hook eval 函数
2.34 Hook setInterval 函数
2.4 代码替换
2.4.1 直接保存修改
2.4.2 在线替换文件
2.5.fiddler代理
2 搜索关键词
3. 打断点
3.1 时间轴
3.2 DOM断点(dom主要负责渲染)
3.3 DOM事件断点(dom主要负责渲染)</br>
3.4 XHR断点
3.5 代码行断点
3.6 代码的断点
3.7 全局事件断点(类似click、canvas等事件)
3.8 全局异常捕获断点
4.Hook
4.1 hook aXMLHttpRequest 函数
4.2 hook alert 函数
4.3 hook setInterval 绕过无限 debugger
4.4 对象属性 hook
4.5 原型链 hook
4.6 代理 hook

爬虫进阶(js逆向)-调试篇

1.debugger

1.1 debugger原理

1.11第一种情况,直接制造debugger

在代码中直接使用debugger

1.12、使用 eval() 函数

eval("debugger;") eval('(function() {var a = new Date(); debugger; return new Date() - a > 100;}())')

1.13、定时器触发

setInterval(function (){debugger;},1000); 实例 //在js调用后可以直接debugger (function() {}["constructor"]("debugger")()) 调用后 (function anonymous( ) { debugger }) 完整代码 (function anonymous( ) { setInterval(function() { check(); }, 2000); var check = function() { function doCheck(a) { if (("" + a / a)["length"] !== 1 || a % 20 === 0) { (function() {} ["constructor"]("debugger")()) } else { (function() {} ["constructor"]("debugger")()) } doCheck(++a) } try { doCheck(0) } catch (err) {} }; check(); })

解决方法:下面2.32的Hook Function 构造器函数

1.14、其他方式

1.14.1

Function("debugger").call()/apply() 或赋值 bind()

1.14.2

xxx.constructor("debugger").call("action")

1.14.3

Fuction.constructor("debugger").call("action")

1.14.4

(function(){return !![];}["constructor"]("debugger")["call"]("action"))

1.14.5

eval('(function() {}["constructor"]("debugger")["call"]("action"));')

2.过debugger

2.1 Add conditional breakpoint条件断点(有的地方不行)

https://segmentfault.com/a/1190000012359015

(function anonymous( ) { debugger //左侧右击,选择添加条件断点false })

然后点击调试的绿色箭头放过代码继续运行

image.png

2.2 Never pause here不停在此处(有的地方不行)

https://segmentfault.com/a/1190000012359015

(function anonymous( ) { debugger //左侧右击,选择不停在此处 })

然后点击调试的绿色箭头放过代码继续运行

image.png

2.3 钩子函数

适合在setInterval中使用

2.31设置 script 断点

在Sources面板设置 script 断点,这一步的目的,是为了让浏览器在刚运行时就被断下来,以方便进行 Hook image.png 重新刷新页面,就会断下来,然后就可以进行hook了

2.32 Hook Function 构造器函数

https://zhuanlan.zhihu.com/p/584684377

Function.prototype.__constructor_back = Function.prototype.constructor; Function.prototype.constructor = function() { if(arguments && typeof arguments[0]==='string'){ //alert("new function: "+ arguments[0]); if("debugger" === arguments[0]){ //arguments[0]="console.log(\"anti debugger\");"; //arguments[0]=";"; return } } return Function.prototype.__constructor_back.apply(this,arguments); }

2.33 Hook eval 函数

https://zhuanlan.zhihu.com/p/584684377

eval_ = eval; //下面这样写,是为了过瑞数的 eval.toString 检测 eval = function(a){if(a=='debugger'){return ''}else{return eval_(a)}} // 或者如下: var my_eval = eval; eval = function (arg) { if (arg.indexOf('debugger') != -1) { return function () { }; } return my_eval(arg); } var _old = Function.prototype.toString.call Function.prototype.toString.call = function (arg) { if (arg === eval) { return "function eval() { [native code] }" } return _old(arg); }

2.34 Hook setInterval 函数

https://zhuanlan.zhihu.com/p/584684377

(1)业务代码和 setInterval 无关时 setInterval = function(){} (2)业务代码和 setInterval 有关时 setInterval_back = setInterval setInterval = function(a,b){ if(a.toString().indexOf('debugger') != -1){ return null; } return setInterval_back(a, b); }

2.4 代码替换

2.4.1 直接保存修改

在F12模式下,有时可以直接修改js源码,Ctrl + S 保存就可以了。但是有时这种方法会不起作用,这里介绍本地替换js的方式。

2.4.2 在线替换文件

1、定位js在边栏的位置
2、在本地新建一个js文件,用来存放替换js文件
3、浏览器在sourece/源代码选择工作区替换文件在本地的存放位置,点击允许访问
4、保存并覆盖
5、格式化代码
6、修改代码并保存
7、打个断点,重新刷新页面

2.5.fiddler代理

fiddler替换图片链接

2 搜索关键词

密码 password、pwd、sign key 0123456789abcdef 加密有关 key、data、rsa、key 加密 encrypt 解密 decrypt 字符串转换json JSON.parse() json转换字符串 JSON.stringify() md5等加密算法的关键词 md5、1732514893 sha等加密算法的关键词 sha

搜索技巧,

a = 1

注意:注意格式化代码的空格

.password、["password"]

**案例 **

字符串转换json
const json = '{"result":true, "count":42}'; const obj = JSON.parse(json);
json转换字符串
console.log(JSON.stringify({ x: 5, y: 6 })); // Expected output: '{"x":5,"y":6}'

3. 打断点

3.1 时间轴

加载html、js - 运行js - 用户触发了某个事件 - 调用了某段js - 加密函数 - 给服务器发信息(xhr-send) - 接受到服务器 - 解密函数 - 刷新渲染函数
注意:断住后按ctrl就可以显示数据,全选数据查找_proto_

3.2 DOM断点(dom主要负责渲染)

在页面选择右击检查,在element选择按钮等等的dom元素,在element的dom元素右击break on (中断与)选择subtree modifications(子树断点)
注意:dom断点只有页面渲染,属性发生改变才能被断住
位置:执行比较靠前(无法看到栈调用,无法利用栈快速点位,有时定位比较准)

3.3 DOM事件断点(dom主要负责渲染)

在页面选择右击检查,在element选择按钮等等的dom元素,
在element右侧的Eventlisteners选择并取消Ancestors All的勾(默认是勾上的,表示该页面所有的dom事件,取消后就为element页面选择的元素的dom事件)

3.4 XHR断点

复制某一发送网络连接的后缀,在source面板右击XHR Breakpoints(XHR 提取断点),添加xhr断点
注意:非xhr就短不住
位置:执行比较靠后(可以看到栈调用,可以利用栈快速点位,距离加密函数较近)

3.5 代码行断点

在source面板右击格式化后的代码前面的数字,然后编辑这个断点(false)

3.6 代码的断点

直接在代码输入debugger

3.7 全局事件断点(类似click、canvas等事件)

在source面板点击Event Listener Breakpoints(全局监听器),勾选添加断点

3.8 全局异常捕获断点

处理try......catch......

4.Hook

4.1 hook aXMLHttpRequest 函数

XMLHttpRequest.prototype.send_ = XMLHttpRequest.prototype.send// 备份需要 hook 的方法 MLHttpRequest.prototype.send = function () { debugger; console.log("断住了!") }

4.2 hook alert 函数

alert_ = alert; // 备份需要 hook 的方法 alert = function () { // 方法执行前执行的内容 console.log('alert初始化'); // 执行原函数 alert_.apply(this, arguments); // 方法执行后执行的内容 console.log('alert执行结束'); }; // 防止 hook 检测 alert.toString = function () {return "function alert() { [native code] }"}

4.3 hook setInterval 绕过无限 debugger

// 在 setInterval 调用行打断点 / 勾选 script 断点 // 在 console 注入如下代码 setInterval_ = setInterval; // hook setInterval定时器 setInterval = function (func, timer) { // 若定时器函数中不包含debugger关键字,则正常执行定时器,否则不执行 if (func.toString().indexOf('debugger') === -1) { setInterval_(func, timer) } else { console.log('检测到无限debugger, 已绕过!') } }; setInterval.toString = function () { return "function setInterval() { [native code] }" }

4.4 对象属性 hook

// 示例一:hook window.a变量 a_ = a; Object.defineProperty(window, 'a', { get:function(){ return a_; }, set: function(val){ console.log('正在把a修改为', val); a_ = val; } }) // 示例二:cookies Object.defineProperty(document, 'cookie', { set: function(val){ debugger; } })

4.5 原型链 hook

// hook String 中 split 方法,当调用 split 时自动进入 debugger // 备份原函数,并添加至原型链 String.prototype.split_ = String.prototype.split; // hook split 方法 String.prototype.split = function(val){ str = this.toString(); debugger; return str.split_(val); }; // 过检测 String.prototype.split.toString = function (){ return "function split() { [native code] }"; } // hook 正则 test 方法,使其总是返回 true RegExp.prototype.test_ = RegExp.prototype.test; RegExp.prototype.test = function (val) { return true; }; RegExp.prototype.test.toString = function () { return "function test() { [native code] }" }

4.6 代理 hook

proxy

如果有任何错误或需要改进,欢迎留言指正。