爬虫进阶(js逆向)-调试篇
在代码中直接使用debugger
eval("debugger;") eval('(function() {var a = new Date(); debugger; return new Date() - a > 100;}())')
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 构造器函数
Function("debugger").call()/apply() 或赋值 bind()
xxx.constructor("debugger").call("action")
Fuction.constructor("debugger").call("action")
(function(){return !![];}["constructor"]("debugger")["call"]("action"))
eval('(function() {}["constructor"]("debugger")["call"]("action"));')
https://segmentfault.com/a/1190000012359015
(function anonymous( ) { debugger //左侧右击,选择添加条件断点false })
然后点击调试的绿色箭头放过代码继续运行
https://segmentfault.com/a/1190000012359015
(function anonymous( ) { debugger //左侧右击,选择不停在此处 })
然后点击调试的绿色箭头放过代码继续运行
适合在setInterval中使用
在Sources面板设置 script 断点,这一步的目的,是为了让浏览器在刚运行时就被断下来,以方便进行 Hook
重新刷新页面,就会断下来,然后就可以进行hook了
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); }
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); }
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); }
在F12模式下,有时可以直接修改js源码,Ctrl + S 保存就可以了。但是有时这种方法会不起作用,这里介绍本地替换js的方式。
1、定位js在边栏的位置
2、在本地新建一个js文件,用来存放替换js文件
3、浏览器在sourece/源代码选择工作区替换文件在本地的存放位置,点击允许访问
4、保存并覆盖
5、格式化代码
6、修改代码并保存
7、打个断点,重新刷新页面
fiddler替换图片链接
密码 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"]
**案例 **
字符串转换jsonconst 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}'
加载html、js - 运行js - 用户触发了某个事件 - 调用了某段js - 加密函数 - 给服务器发信息(xhr-send) - 接受到服务器 - 解密函数 - 刷新渲染函数
注意:断住后按ctrl就可以显示数据,全选数据查找_proto_
在页面选择右击检查,在element选择按钮等等的dom元素,在element的dom元素右击break on (中断与)选择subtree modifications(子树断点)
注意:dom断点只有页面渲染,属性发生改变才能被断住
位置:执行比较靠前(无法看到栈调用,无法利用栈快速点位,有时定位比较准)
在页面选择右击检查,在element选择按钮等等的dom元素,
在element右侧的Eventlisteners选择并取消Ancestors All的勾(默认是勾上的,表示该页面所有的dom事件,取消后就为element页面选择的元素的dom事件)
复制某一发送网络连接的后缀,在source面板右击XHR Breakpoints(XHR 提取断点),添加xhr断点
注意:非xhr就短不住
位置:执行比较靠后(可以看到栈调用,可以利用栈快速点位,距离加密函数较近)
在source面板右击格式化后的代码前面的数字,然后编辑这个断点(false)
直接在代码输入debugger
在source面板点击Event Listener Breakpoints(全局监听器),勾选添加断点
处理try......catch......
XMLHttpRequest.prototype.send_ = XMLHttpRequest.prototype.send// 备份需要 hook 的方法 MLHttpRequest.prototype.send = function () { debugger; console.log("断住了!") }
alert_ = alert; // 备份需要 hook 的方法 alert = function () { // 方法执行前执行的内容 console.log('alert初始化'); // 执行原函数 alert_.apply(this, arguments); // 方法执行后执行的内容 console.log('alert执行结束'); }; // 防止 hook 检测 alert.toString = function () {return "function alert() { [native code] }"}
// 在 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] }" }
// 示例一: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; } })
// 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] }" }
proxy
注
如果有任何错误或需要改进,欢迎留言指正。