关注它,不迷路。
本文章中所有内容仅供学习交流,不可用于任何商业用途和非法用途,否则后果自负,如有侵权,请联系作者立即删除!
https://match.yuanrenxue.com/match/2
上面的网站打开后,按下F12,停留在debugger位置,往上一层堆栈,可以看到混淆的js,格式化,然后复制下来,从头看到尾,大致的阅读下js,寻找可还原的点,发现了这里:
这是一大片的十六进制字符串,可以先将其还原:
const simplifyLiteral = {
NumericLiteral({node}) {
if (node.extra && /^0[obx]/i.test(node.extra.raw)) {
node.extra = undefined;
}
},
StringLiteral({node})
{
if (node.extra && /\\[ux]/gi.test(node.extra.raw)) {
node.extra = undefined;
}
},
}
还原后的效果如下:
还原后,就是想办法把这些字符串进行回填,举个简单的例子:
OooIi1 = "0x1fd"
......
$dbsm_0x42c3(OooIi1, QQQO0q)
===>
$dbsm_0x42c3("0x1fd", QQQO0q)
这样就能删除一大堆代码,在这里,可以利用scope进行替换:
const replaceLiteral = {
AssignmentExpression(path)
{
let {scope,parentPath,node} = path;
let {left,right,operator} = node;
if (!types.isIdentifier(left) || operator != "=" ||
!types.isLiteral(right))
{
return;
}
let binding = scope.getBinding(left.name);
if (!binding) return; //SCOPE可能为空,目前看的话,只有函数定义的形参和变量定义才有scope
let {constantViolations,referencePaths} = binding;
if (binding.constantViolations.length == 1 &&
path == binding.constantViolations[0])
{
for (let referPath of referencePaths)
{
referPath.replaceWith(right);
}
path.remove();
binding.path.remove(); //binding.path 都是形参,所以可以直接删除。
}
},
"BinaryExpression"(path)
{
if(path.isUnaryExpression({operator:"-"}) ||
path.isUnaryExpression({operator:"void"}))
{
return;
}
const {confident,value} = path.evaluate();
if (!confident || value == "Infinity") return;
path.replaceWith(types.valueToNode(value));
},
}
还原后,效果如下:
这是一系列的逗号表达式,再将其还原:
const resolveSequence =
{
SequenceExpression(path)
{
let {scope,parentPath,node} = path;
let expressions = node.expressions;
if (parentPath.isReturnStatement({"argument":node}))
{
let lastExpression = expressions.pop();
for (let expression of expressions)
{
parentPath.insertBefore(types.ExpressionStatement(expression=expression));
}
path.replaceInline(lastExpression);
}
else if (parentPath.isExpressionStatement({"expression":node}))
{
let body = [];
expressions.forEach(express=>{
body.push(types.ExpressionStatement(express));
});
path.replaceInline(body);
}
else
{
return;
}
scope.crawl();
}
}
还原后效果如下:
熟悉ob混淆的朋友可以看到,已经非常像了,但是,还不能用我开源的那个一键还原,需要做如下变形:
_0x434ddb = {};
===>
var _0x434ddb = {};
因此,写下插件,进行变形,使之成为ob混淆,便于我们使用一键还原工具,代码如下:
function deleteParams(path,name)
{
let funcPath = path.getFunctionParent();
let params = funcPath.node.params;
for (let i=0; i
上面的代码处理后,变成了这样:
这样,就给变量加上了var,接下来,就可以使用ob混淆一键还原工具了,
https://github.com/Tsaiboss/decodeObfuscator
运行后结果变这样:
setInterval(function () {
$dbsm_0x1a0b2e();
}, 4000);
傻眼了,啥也没了,还怎么分析?这个时候,打开一键还原项目里的main.js,看到这里:
它说可能会误删代码,因此,我们将这行代码屏蔽试试:
代码还剩343行,具体的cookie赋值位置也可以看到:
本文完整分析就到这里,AST还原其实很简单,无非就是分析前后节点的变化。完整AST代码及数据请求代码我放在星球里了,需要的请自取:
https://t.zsxq.com/jAIIYNF
今天的内容就介绍到这里,如果你有更好玩的工具,欢迎分享给我们,感谢。
加我好友,拉你进群,注意,严禁讨论破解相关的话题。