Network
观察当前数据流的请求情况
Source
debugger console
Resume
恢复
Step over
直接执行当前函数
Step into
进入当前函数
Step out
跳出当前函数
Step
直接进入下一个局部函数内部, 比较少用
Deactive breakpoint
禁止debugger模式下的所有断点
Pause on exceptions
在所有抛出异常点的位置暂停, 比较少用
Watch
监控变量值的变化
Breakpoints
Scope
作用域
Global
全局变量
Local
局部变量
Closure
闭包(自由变量)
Call Stack
调用栈, 用来了解当前结果产生所经历的函数调用过程.
我们在Call Stack上跳转函数的时候, 可以看到堆栈环境, 但是当前堆栈环境不一定准确.
XHR/fetch Breakpoints
监听请求中的关键字, 在请求发送前暂停
DOM Breakpoints
监听DOM的变化
Global Listeners
全局监听器
Event Listeners Breakpoints
事件监听器
eval
eval可以将字符串转换为可执行语句
eval('n("0x155", "uYFB")')
通过正则还远混淆的代码
const n = require('./anti_confuse.js').n
restoreJs = function(jsContent){
// 使用正则表达式匹配所有混淆函数
let matchArray = jsContent.match(/n\("[^\"]+", "[^\"]+"\)/g)
for(let i=0; i导出模块exports
module.exports = {
n: d
}
导入模块require
const anti_confuse = require('./anti_confuse.js');
const n = anti_confuse.n
导入文件处理模块
const file = require("fs");
文件读取
readFileSync返回的是二进制数组, 需要调用toString来转变为字符串
let jsContent = file.readFileSync("./react_pdd_20210513.js").toString();
文件写入
let newJsContent = restoreJs(jsContent)
file.writeFile(
"react_pdd_20210513.restore.js", // 文件名
newJsContent, // 写入内容
{encoding: "utf-8", flag: "w"}, // 参数
function (e){
if (e){
console.log("文件写入失败")
}else{
console.log("文件写入成功")
}
}
)
三元运算符
true?console.log("true"): console.log("false")
我们定位到了加密函数, 调用后产生了加密结果anti_content, 接下来就是要找齐加密所需要的参数和加密的具体函数
将多个参数加密成多个小数组, 最终合并为大数组
a = (t = [])[K].apply(t, [s[o](), Wt[o](), pt[o](), mt[o](), vt[o](), bt[o](), gt[o](), kt[o](), _t[o](), yt[o](), wt[o]()].concat(function(t) {
if (Array.isArray(t)) {
for (var n = 0, e = Array(t.length); n < t.length; n++)
e[n] = t[n];
return e
}
return Array.from(t)
}(Ct[o]()), [St[o](), Ot[o](), Rt[o](), Pt[o](), jt[o](), Dt[o]()]));
生成了大数组a的长度为16的二进制信息u
for (var u = a[E][g](2)[p](""), f = 0; r["ZIIDs"](u[E], 16); f += 1)
u[r["XjWuA"]]("0");
u = u[x]("");
通过u生成了W参数列表中的l
l[H](et[k](u[O](0, 8), 2), et[k](u[O](8, 16), 2))
合并了a和l
a = [][K]([3], [1, 0, 0], l, a);
压缩了大数组a
h = i['deflate'](a)
将hUint8Array中的元素值转变为String, 产生了W
W = [][b]["call"](h, (function(t) {
return String[S](t)
}
));
W通过encode函数加密W和tt后的结果和定值0ap相加生成了anti_content
r["yrFVy"](r["ZRscj"], c[r["wSNTe"]](r["yrFVy"](W[x](""), tt[x]("")), c["budget"]))
tt是验证函数dt和At是否被修改的字段.