在4399游戏页面按下F12无反应,原因可能是捕捉了该键位。不过可以在chrome的More Tools中正常打开控制台。
然而接下来Debugger会一直卡在一个匿名函数处;即使continue也会触发新的函数.
1
2
3
4
5
6
7
8
9
10
11
// VM198
(function anonymous(
) {
debugger
})
// VM224
(function anonymous(
) {
debugger
})
// ...
全局搜索关键词debugger, 找到了可疑代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// ......
// Antiindulgence.js?20268251
if(window.location.host=="www.4399.com" || window.location.host=="h.4399.com" || window.location.host=="zuopin.4399.com" || window.location.host=="h.api.4399.com" || window.location.host=="zxwyouxi.com"){
// ----- 屏蔽快捷键基本没有影响 -----
//屏蔽F12
$(document).keydown(function(event){
if(event.keyCode==123){
if(event.preventDefault){
event.preventDefault();
}else{
window.event.returnValue == false;
}
}
});
//屏蔽ctrl+shift+i
$(document).keydown(function(event){
if(event.ctrlKey && event.shiftKey && event.keyCode==73){
if(event.preventDefault){
event.preventDefault();
}else{
window.event.returnValue == false;
}
}
});
// ----- 防止我们设置never stop at ... ----
// 为右键添加自定义事件,可以禁用
$(document).ready(function(){
$(document).bind("contextmenu",function(e){
return false;
});
});
//疯狂调试模式
setInterval(function(){
check();
}, 2000);
var check = function(){
function doCheck(a){
// 无条件触发(function() {}['constructor']('debugger')())
if (('' + a / a)['length'] !== 1 || a % 20 === 0){
// (function() {}).constructor === Function
// 所以等价于 Function('debugger')(), 即执行动态创建出的函数,这个函数只包含一个'debugger'语句
(function() {}['constructor']('debugger')());
} else {
(function() {}['constructor']('debugger')());
}
doCheck(++a);
}
try {
doCheck(0);
}catch(err){} // 栈溢出会被忽略,持续递归
};
check();
function consoleOpenCallback() {
alert('关闭调试窗');
window.location.reload();
}
var Anti_numtots = 0;
(function () {
window._windon_handler = setInterval( function() {
// 通过时间检测调试器,如果时间距离远,说明存在debugger.
var before = new Date();
debugger;
var after = new Date();
if (after.getTime() - before.getTime() > 100) {
if (after.getTime() - before.getTime() > 2000) {
consoleOpenCallback();
clearInterval(_windon_handler);
}else{
Anti_numtots++;
if(Anti_numtots>=2){
consoleOpenCallback();
clearInterval(_windon_handler);
}
}
}else{
Anti_numtots = 0;
}
}, 1000)
})();
}
我们需要绕过后面的无限调试和反调试检查. 可疑发现它们都依赖于setInterval这个函数设置的定时任务.
在正常情况下,我们可以通过记录其返回值,然后clearInterval来让其失效:
1
2
interval_id = setInterval(...)
clearInterval(interval_id);
但是这里没有interval_id, 所以可以尝试在执行之前就将setInterval函数覆盖:
1
2
3
4
5
6
const oldSetInterval = window.setInterval;
window.setInterval = function(fn, delay, ...args) {
console.log("blocked setInterval:", fn, delay);
return -1;
};
方法1:断点 + 查看 + interval
可以解决. 但是network部分还是没有看到目标.swf文件.
方法2:
如果想要直接disable所有的setInterval函数,副作用是可能会误杀正常逻辑中的定时函数。但是可以先试试.
首先要注意时机,我们需要在执行到反调试函数之前就完成hook。如果我们在一个页面先在控制台输入自己的setInterval覆盖原始函数,刷新后/重新进入目标页面,并不会奏效。
方法3:proxy
另一条线:搜索.swf后, 拼出路径:https://s7.4399.com/4399swf/upload_swf/ftp/20100703wen/1.swf
接着在network中找,发现有一个包的请求url对上了. 关闭ruffle插件的自动执行swf文件功能后,下载.
但是执行的时候显示请在4399内执行. 应该是整个swf文件内部被魔改了.