mirror of
https://github.com/smallfawn/decode_action.git
synced 2025-12-24 02:35:12 +08:00
247 lines
6.2 KiB
JavaScript
247 lines
6.2 KiB
JavaScript
/**
|
||
* Reference:
|
||
* * [某宝登录bx-ua参数逆向思路(fireyejs 225算法)](https://zhuanlan.zhihu.com/p/626187669)
|
||
*/
|
||
import { parse } from '@babel/parser'
|
||
import _generate from '@babel/generator'
|
||
const generator = _generate.default
|
||
import _traverse from '@babel/traverse'
|
||
const traverse = _traverse.default
|
||
import * as t from '@babel/types'
|
||
|
||
function RemoveVoid(path) {
|
||
if (path.node.operator === 'void') {
|
||
path.replaceWith(path.node.argument)
|
||
}
|
||
}
|
||
|
||
function LintConditionalAssign(path) {
|
||
if (!t.isAssignmentExpression(path?.parent)) {
|
||
return
|
||
}
|
||
let { test, consequent, alternate } = path.node
|
||
let { operator, left } = path.parent
|
||
consequent = t.assignmentExpression(operator, left, consequent)
|
||
alternate = t.assignmentExpression(operator, left, alternate)
|
||
path.parentPath.replaceWith(
|
||
t.conditionalExpression(test, consequent, alternate)
|
||
)
|
||
}
|
||
|
||
function LintConditionalIf(ast) {
|
||
function conditional(path) {
|
||
let { test, consequent, alternate } = path.node
|
||
// console.log(generator(test, { minified: true }).code)
|
||
if (t.isSequenceExpression(path.parent)) {
|
||
if (!sequence(path.parentPath)) {
|
||
path.stop()
|
||
}
|
||
return
|
||
}
|
||
if (t.isLogicalExpression(path.parent)) {
|
||
if (!logical(path.parentPath)) {
|
||
path.stop()
|
||
}
|
||
return
|
||
}
|
||
if (!t.isExpressionStatement(path.parent)) {
|
||
console.error(`Unexpected parent type: ${path.parent.type}`)
|
||
path.stop()
|
||
return
|
||
}
|
||
consequent = t.expressionStatement(consequent)
|
||
alternate = t.expressionStatement(alternate)
|
||
let statement = t.ifStatement(test, consequent, alternate)
|
||
path.replaceWithMultiple(statement)
|
||
}
|
||
|
||
function sequence(path) {
|
||
if (t.isLogicalExpression(path.parent)) {
|
||
return logical(path.parentPath)
|
||
}
|
||
let body = []
|
||
for (const item of path.node.expressions) {
|
||
body.push(t.expressionStatement(item))
|
||
}
|
||
let node = t.blockStatement(body, [])
|
||
let replace_path = path
|
||
if (t.isExpressionStatement(path.parent)) {
|
||
replace_path = path.parentPath
|
||
} else if (!t.isBlockStatement(path.parent)) {
|
||
console.error(`Unexpected parent type: ${path.parent.type}`)
|
||
return false
|
||
}
|
||
replace_path.replaceWith(node)
|
||
return true
|
||
}
|
||
|
||
function logical(path) {
|
||
let { operator, left, right } = path.node
|
||
if (operator !== '&&') {
|
||
console.error(`Unexpected logical operator: ${operator}`)
|
||
return false
|
||
}
|
||
if (!t.isExpressionStatement(path.parent)) {
|
||
console.error(`Unexpected parent type: ${path.parent.type}`)
|
||
return false
|
||
}
|
||
let node = t.ifStatement(left, t.expressionStatement(right))
|
||
path.parentPath.replaceWith(node)
|
||
return true
|
||
}
|
||
|
||
traverse(ast, {
|
||
ConditionalExpression: { enter: conditional },
|
||
})
|
||
}
|
||
|
||
function LintLogicalIf(path) {
|
||
let { operator, left, right } = path.node
|
||
if (operator !== '&&') {
|
||
// console.warn(`Unexpected logical operator: ${operator}`)
|
||
return
|
||
}
|
||
if (!t.isExpressionStatement(path.parent)) {
|
||
console.warn(`Unexpected parent type: ${path.parent.type}`)
|
||
return
|
||
}
|
||
let node = t.ifStatement(left, t.expressionStatement(right))
|
||
path.parentPath.replaceWith(node)
|
||
return
|
||
}
|
||
|
||
function LintIfStatement(path) {
|
||
let { test, consequent, alternate } = path.node
|
||
let changed = false
|
||
if (!t.isBlockStatement(consequent)) {
|
||
consequent = t.blockStatement([consequent])
|
||
changed = true
|
||
}
|
||
if (alternate && !t.isBlockStatement(alternate)) {
|
||
alternate = t.blockStatement([alternate])
|
||
changed = true
|
||
}
|
||
if (!changed) {
|
||
return
|
||
}
|
||
path.replaceWith(t.ifStatement(test, consequent, alternate))
|
||
}
|
||
|
||
function LintIfTest(path) {
|
||
let { test, consequent, alternate } = path.node
|
||
if (!t.isSequenceExpression(test)) {
|
||
return
|
||
}
|
||
if (!t.isBlockStatement(path.parent)) {
|
||
return
|
||
}
|
||
let body = test.expressions
|
||
let last = body.pop()
|
||
let before = t.expressionStatement(t.sequenceExpression(body))
|
||
path.insertBefore(before)
|
||
path.replaceWith(t.ifStatement(last, consequent, alternate))
|
||
}
|
||
|
||
function LintSwitchCase(path) {
|
||
let { test, consequent } = path.node
|
||
if (consequent.length == 1 && t.isBlockStatement(consequent[0])) {
|
||
return
|
||
}
|
||
let block = t.blockStatement(consequent)
|
||
path.replaceWith(t.switchCase(test, [block]))
|
||
}
|
||
|
||
function LintReturn(path) {
|
||
let { argument } = path.node
|
||
if (!t.isSequenceExpression(argument)) {
|
||
return
|
||
}
|
||
if (!t.isBlockStatement(path.parent)) {
|
||
return
|
||
}
|
||
let body = argument.expressions
|
||
let last = body.pop()
|
||
let before = t.expressionStatement(t.sequenceExpression(body))
|
||
path.insertBefore(before)
|
||
path.replaceWith(t.returnStatement(last))
|
||
}
|
||
|
||
function LintSequence(path) {
|
||
let body = []
|
||
for (const item of path.node.expressions) {
|
||
body.push(t.expressionStatement(item))
|
||
}
|
||
let node = t.blockStatement(body, [])
|
||
let replace_path = path
|
||
if (t.isExpressionStatement(path.parent)) {
|
||
replace_path = path.parentPath
|
||
} else if (!t.isBlockStatement(path.parent)) {
|
||
console.warn(`Unexpected parent type: ${path.parent.type}`)
|
||
return
|
||
}
|
||
replace_path.replaceWith(node)
|
||
return
|
||
}
|
||
|
||
function LintBlock(path) {
|
||
let { body } = path.node
|
||
if (!body.length) {
|
||
return
|
||
}
|
||
let changed = false
|
||
let arr = []
|
||
for (const item of body) {
|
||
if (!t.isBlockStatement(item)) {
|
||
arr.push(item)
|
||
continue
|
||
}
|
||
changed = true
|
||
for (const sub of item.body) {
|
||
arr.push(sub)
|
||
}
|
||
}
|
||
if (!changed) {
|
||
return
|
||
}
|
||
path.replaceWith(t.blockStatement(arr))
|
||
}
|
||
|
||
export default function (code) {
|
||
let ast = parse(code)
|
||
// Lint
|
||
traverse(ast, {
|
||
UnaryExpression: RemoveVoid,
|
||
})
|
||
traverse(ast, {
|
||
ConditionalExpression: { exit: LintConditionalAssign },
|
||
})
|
||
LintConditionalIf(ast)
|
||
traverse(ast, {
|
||
LogicalExpression: { exit: LintLogicalIf },
|
||
})
|
||
traverse(ast, {
|
||
IfStatement: { exit: LintIfStatement },
|
||
})
|
||
traverse(ast, {
|
||
IfStatement: { enter: LintIfTest },
|
||
})
|
||
traverse(ast, {
|
||
SwitchCase: { enter: LintSwitchCase },
|
||
})
|
||
traverse(ast, {
|
||
ReturnStatement: { enter: LintReturn },
|
||
})
|
||
traverse(ast, {
|
||
SequenceExpression: { exit: LintSequence },
|
||
})
|
||
traverse(ast, {
|
||
BlockStatement: { exit: LintBlock },
|
||
})
|
||
|
||
code = generator(ast, {
|
||
comments: false,
|
||
jsescOption: { minimal: true },
|
||
}).code
|
||
return code
|
||
}
|