AST交互-if语句转switch语句
閱讀時間:全文 621 字,預估用時 4 分鐘
創作日期:2022-08-14
上篇文章:AST交互-三元表达式转switch语句
下篇文章:\@babel|traverse使用教程
BEGIN
这两年前端代码加密进化很大,为了在逆向过程中不那么累,我们需要使用babel修改网站源码,改成我们调试不那么累的代码,如将if语句代码改成switch语句代码。
我们找到网站实际代码如下:
while (1) {
_$a9 = _$kI[_$iW++];
if (_$a9 < 12) {
if (_$a9 < 4) {
if (_$a9 === 0) {
_$gP = window,
_$$i = String,
_$$_ = Array,
_$_q = document,
_$b8 = Math.random,
_$g$ = Math.round,
_$_W = Date;
} else if (_$a9 === 1) {
_$_s.lcd = _$ht;
} else if (_$a9 === 2) {
_$aW = !_$_W;
} else {
_$_s = _$gP['$_ts'];
}
} else if (_$a9 < 8) {
if (_$a9 === 4) {
_$_s = _$gP['$_ts'] = {};
} else if (_$a9 === 5) {
_$f2(69);
} else if (_$a9 === 6) {
_$iW += 2;
} else {
_$_0 = [4, 16, 64, 256, 1024, 4096, 16384, 65536];
}
} else {
if (_$a9 === 8) {
!_$aW ? _$iW += 0 : 0;
} else if (_$a9 === 9) {
return;
} else if (_$a9 === 10) {
!_$aW ? _$iW += 2 : 0;
} else {
_$aW = _$_s;
}
}
} else
;
}
处理后的代码如下:
while (1) {
_$a9 = _$kI[_$iW++];
switch (_$a9) {
case 0:
_$gP = window, _$$i = String, _$$_ = Array, _$_q = document, _$b8 = Math.random, _$g$ = Math.round, _$_W = Date;
break;
case 1:
_$_s.lcd = _$ht;
break;
case 2:
_$aW = !_$_W;
break;
case 3:
_$_s = _$gP['$_ts'];
break;
case 4:
_$_s = _$gP['$_ts'] = {};
break;
case 5:
_$f2(69);
break;
case 6:
_$iW += 2;
break;
case 7:
_$_0 = [4, 16, 64, 256, 1024, 4096, 16384, 65536];
break;
case 8:
!_$aW ? _$iW += 0 : 0;
break;
case 9:
return;
case 10:
!_$aW ? _$iW += 2 : 0;
break;
case 11:
_$aW = _$_s;
break;
}
}
这里贴上处理代码(这段代码由博主个人原创,转载请注明出处)
const fs = require('fs');
const parser = require("@babel/parser");
const generate = require("@babel/generator").default
const traverse = require("@babel/traverse").default
const t = require('@babel/types');
const code = getCode()
const ast = parser.parse(code, { allowReturnOutsideFunction: true })
function valueHandle(operator, value) {
switch(operator) {
case '<':
return value
case '==':
case '===':
return value + 1
}
}
function getIfTestValue(test) {
if (!test) return false
const { operator, left, right } = test
if (!['<', '==', '==='].includes(operator)) return false
if (!t.isIdentifier(left)) return false
if (!t.isNumericLiteral(right)) return false
return { name: left.name, value: valueHandle(operator, right.value) }
}
function getNode(node) {
if (t.isIfStatement(node)) return [node]
if (t.isBlockStatement(node)) return node.body
console.error(`未知类型请检查: ${node.type}`)
return [node]
}
function getIfNode(node, ans=[], opt = {}) {
const testValue = getIfTestValue(node?.test)
if (testValue === false) return
if (!opt.name) { Object.assign(opt, testValue) }
if (testValue.name !== opt.name) return
['alternate', 'consequent'].forEach((key, idx) => {
const nextNode = getNode(node[key])
ans[testValue.value - idx] = nextNode
nextNode?.forEach(item => getIfNode(item, ans, opt))
})
return [opt.name, ans.filter(Boolean)]
}
const visitor = {
IfStatement(path) {
const [key, cases] = getIfNode(path.node) || []
if (!key || cases.length <= 6) return
const newNode = t.switchStatement(
t.identifier(key),
cases.map((mycase, idx) => {
const otherCode = mycase.some(item => t.isReturnStatement(item)) ? [] : [t.breakStatement()]
return t.switchCase(t.numericLiteral(idx), [ ...mycase, ...otherCode ])
})
)
path.replaceInline(newNode)
path.skip()
}
}
traverse(ast, visitor)
const result = generate(ast, { minified: false, concise: false, compact: false })
console.log(result.code)
FINISH
上篇文章:AST交互-三元表达式转switch语句
下篇文章:\@babel|traverse使用教程