const {default: generator} = require("@babel/generator");
const type = require("@babel/types");
const {parse} = require("@babel/parser");
const traverse = require('@babel/traverse').default
function flower_instruction_code (ast_code) {
this.ast_code = ast_code
this.all_constant_obj = {}
// 1.输出需要初始化的代码
this.get_init_js_code = function (init_code_row) {
let init_ast_code = parse('')
for (let i = 0; i < init_code_row.length; i++) {
init_ast_code.program.body.push(this.ast_code.program.body[init_code_row[i]])
}
return generator(init_ast_code, {'compact': true}).code
}
// 替換賦值混淆名
this.replace_confuse_name = function () {
let that = this
traverse(this.ast_code, {
VariableDeclarator(path) {
if (type.isIdentifier(path.node.id)) {
let can_rename = that.can_rename(path.node.init)
if (can_rename) {
let binding = path.scope.getOwnBinding(path.node.id.name)
if (!binding) {
return null
}
binding.scope.rename(path.node.id.name, path.node.init.name)
path.remove()
}
}
}
})
}
// 针对形式:Object['prototype']['hasOwnProperty']["call"](_0x185f56, _0x73e89b)
this.obj_prototype_hasOwnProperty_call = function () {
traverse(this.ast_code, {
'CallExpression'(path) {
let first_member = path.node.callee
if (!type.isMemberExpression(first_member) && first_member.property.value !== 'call') {
path.stop()
}
let second_member = first_member.object
if (!type.isMemberExpression(second_member) && second_member.property.value !== 'hasOwnProperty') {
path.stop()
}
let third_member = first_member.object
if (!type.isMemberExpression(third_member) && third_member.property.value !== 'prototype') {
path.stop()
}
path.replaceWith(type.valueToNode(false))
}
})
}
// 针对for循环:for (_0x73e89b in _0x185f56) false && (_0x679414[_0x73e89b] = _0x185f56[_0x73e89b]);
this.for_false_and = function () {
traverse(this.ast_code, {
'ForInStatement|ForStatement'(path) {
let left_name = path.node.body.expression.left.name
if (!eval(left_name)) {
path.remove()
}
}
})
}
/* 二进制和十六进制干扰,'\x48\x32\x41\x47'*/
this.binary_hexadecimal = function () {
traverse(this.ast_code, {
'StringLiteral|NumericLiteral'(path) {
delete path.node.extra // 主要是由于row这个节点造成的
}
})
}
/* 运算符混淆,示例:'a'+'b'或者1+3 */
this.binary_confuse = function () {
traverse(this.ast_code, {
'BinaryExpression'(path) {
let has_identifier_in_binary = check_identifier_in_binary(path.node)
if (!has_identifier_in_binary) {
let binary_result = eval(generator(path.node).code)
path.replaceWith(type.valueToNode(binary_result))
}
},
})
// 检查运算符内是否有参数
function check_identifier_in_binary (node) {
if (type.isBinaryExpression(node)) {
let left = check_identifier_in_binary(node.left)
let right = check_identifier_in_binary(node.right)
return left || right
} else if (type.isStringLiteral(node) || type.isNumericLiteral(node) || type.isUnaryExpression(node)) {
return false
}
return true
}
}
/* 针对function形参定义后函数体内赋值混淆,function(a, b, c, d){d=1,console.log(d)} */
this.params_define_confuse = function () {
traverse(this.ast_code, {
AssignmentExpression(path) {
let name = path.node.left.name
let binding = path.scope.getOwnBinding(name)
if (binding && binding.constantViolations.length === 1 && type.isLiteral(path.node.right)) {
for (let i = 0; i < binding.referencePaths.length; i++) {
binding.referencePaths[i].replaceWith(path.node.right)
}
path.remove()
}
}
})
}
/* 利用解密函数进行加密字符串解密 */
this.decrypt_string_confuse = function (decrypt_function_list) {
traverse(this.ast_code, {
CallExpression(path) {
if (decrypt_function_list.indexOf(path.node.callee.name) !== -1) {
let result = eval(generator(path.node).code)
path.replaceWith(type.valueToNode(result))
}
}
})
}
/* 成员属性混淆,a['b']='fuck' */
this.member_attr_confuse = function () {
let all_member_obj = {}
// 放入成员对象合集中并去掉复制
traverse(this.ast_code, {
AssignmentExpression(path) {
// 針對a = b這樣直接賦值
if (type.isIdentifier(path.node.left) && type.isIdentifier(path.node.right) && all_member_obj[path.node.right.name]) {
all_member_obj[path.node.left.name] = all_member_obj[path.node.right.name]
return
}
let member_value = set_and_get_member_attr(path.node)
if (member_value) {
path.remove()
}
}
})
// 判斷是否對象屬性混淆並保存對象屬性到全局
function set_and_get_member_attr(node){
if (!type.isMemberExpression(node.left)) {
return
}
if (!all_member_obj[node.left.object.name]) {
all_member_obj[node.left.object.name] = {}
}
if (type.isLiteral(node.right)) {
all_member_obj[node.left.object.name][node.left.property.value] = node.right
return true
}
if (type.isMemberExpression(node.right)) {
let obj_name = node.right.object.name
let property_value = node.right.property.value
if (all_member_obj[obj_name] && all_member_obj[obj_name][property_value]) {
all_member_obj[node.left.object.name][node.left.property.value] = all_member_obj[obj_name][property_value]
return true
}
}
}
// 进行替换
traverse(this.ast_code, {
MemberExpression(path) {
let obj_name = path.node.object.name
let property_value = path.node.property.value
if (all_member_obj[obj_name] && property_value && all_member_obj[obj_name].hasOwnProperty(property_value)) {
try {
path.replaceWith(all_member_obj[obj_name][property_value])
} catch (e) {
console.log(generator(path.node).code)
path.stop()
}
}
}
})
}
/* 成员属性方法混淆,_0x434ddb["GXMkb"] = function(_0x2741e5, _0x22b6d0) {return _0x2741e5 + _0x22b6d0;} */
this.remove_member_attr_function_confuse = function (is_test=false) {
let member_attr_obj_function = {}
let js_code = generator(this.ast_code).code
this.ast_code = parse(js_code)
/* 收集全部成员属性方法 */
traverse(this.ast_code, {
AssignmentExpression(path) {
let left = path.node.left
let right = path.node.right
// 針對a = b這樣直接賦值
if (type.isIdentifier(left) && type.isIdentifier(right) && member_attr_obj_function[right.name]) {
member_attr_obj_function[left.name] = member_attr_obj_function[right.name]
return
}
if (!type.isMemberExpression(left)) {
return
}
if (!member_attr_obj_function[left.object.name]) {
member_attr_obj_function[left.object.name] = {}
}
// 针对:_0x13a684["rYJFX"] = _0x13a684["rsYJFX"]
if (type.isMemberExpression(right) &&
member_attr_obj_function[right.object.name] &&
member_attr_obj_function[right.object.name][right.property.value])
{
member_attr_obj_function[left.object.name][left.property.value] = member_attr_obj_function[right.object.name][right.property.value]
return ;
}
// 针对:_0x13a684["rYJFX"]=function(){return xxxx}
if (type.isFunctionExpression(right) && type.isReturnStatement(right.body.body[0]))
{
let return_statement = right.body.body[0]
// 二项式直接使用,针对:_0x434ddb["vCXqC"]=function(_0x202936,_0x21f1f2){return _0x202936<<_0x21f1f2;}
if (type.isBinaryExpression(return_statement.argument)) {
member_attr_obj_function[left.object.name][left.property.value] = right
if (!is_test){path.remove()}
return;
}
// 函数调用
if (type.isCallExpression(return_statement.argument)) {
let callee = return_statement.argument.callee
// 直接参数嵌套调用,_0x434ddb["RjlFz"] = function(_0x2840c0){return _0x2840c0();}
if (type.isIdentifier(callee)) {
member_attr_obj_function[left.object.name][left.property.value] = right
if (!is_test){path.remove()}
return;
}
// 成员属性函数嵌套调用,_0x13a684["rYJFX"]=function(_0x2f8c0d,_0xb26c0){return _0x5500bb["aGBTS"](_0x2f8c0d, _0xb26c0);}
if (type.isMemberExpression(return_statement.argument.callee) &&
member_attr_obj_function[callee.object.name] &&
member_attr_obj_function[callee.object.name][callee.property.value])
{
let function_node = member_attr_obj_function[callee.object.name][callee.property.value]
let new_return_node = construct_new_return_node(return_statement.argument.arguments, function_node)
right.body.body[0] = new_return_node
member_attr_obj_function[left.object.name][left.property.value] = right
if (!is_test){path.remove()}
return;
}
}
}
}
})
/* 将原函数重构成依据底层函数改造的新函数 */
function construct_new_return_node(arguments, function_node) {
let formal_parameter_dict = {} // 原调用的实参与方法形参名的对应表
let params = function_node.params // 方法参数
let return_statement = function_node.body.body[0]
for (let i = 0; i < params.length; i++) {
if (params[i]) {
formal_parameter_dict[params[i].name] = arguments[i] ? arguments[i] : type.valueToNode(null)
}
}
let new_argument = return_statement['argument']
// 底层是二项式混淆
if (type.isBinaryExpression(new_argument)) {
new_argument = get_binary_new_node(new_argument, formal_parameter_dict)
}
// 底层是函数调用混淆
if (type.isCallExpression(return_statement['argument'])) {
let new_callee = formal_parameter_dict[return_statement['argument'].callee.name]
let return_arguments = return_statement['argument'].arguments
let new_arguments = []
for (let i = 0; i < return_arguments.length; i++) {
new_arguments[i] = formal_parameter_dict[return_arguments[i].name]
}
try {
new_argument = type.callExpression(new_callee, new_arguments)
} catch (e) {
console.log(arguments)
}
}
// 产生新的函数
return type.returnStatement(new_argument)
}
/* 获取二项式新节点 */
function get_binary_new_node(node, formal_parameter_dict) {
let left = node.left
let rignt = node.right
if (formal_parameter_dict[left.name]) {
left = formal_parameter_dict[left.name]
}
if (type.isBinaryExpression(rignt)) {
rignt = get_binary_new_node(right, formal_parameter_dict)
} else if (type.isIdentifier(rignt) && formal_parameter_dict[rignt.name]) {
rignt = formal_parameter_dict[rignt.name]
}
return type.binaryExpression(node.operator, left, rignt)
}
/* 成员属性方法替换 */
traverse(this.ast_code, {
'CallExpression': {
exit(path){
if (!type.isMemberExpression(path.node.callee)) {
return;
}
let object = path.node.callee.object
let property = path.node.callee.property
if (member_attr_obj_function[object.name] &&
member_attr_obj_function[object.name].hasOwnProperty(property.value))
{
let function_node = member_attr_obj_function[object.name][property.value]
if (!type.isReturnStatement(function_node.body.body[0])) {
return;
}
let formal_parameter_dict = {}
for (let i = 0; i < function_node.params.length; i++) {
if (path.node.arguments[i]) {
formal_parameter_dict[function_node.params[i].name] = path.node.arguments[i]
} else {
formal_parameter_dict[function_node.params[i].name] = type.valueToNode(undefined)
}
}
let argument = function_node.body.body[0].argument
// 嵌套函数调用混淆,function(_0x4fd34e, _0x54cdbe){return _0x4fd34e(_0x54cdbe);}
if (type.isCallExpression(argument)) {
let new_callee = formal_parameter_dict[argument.callee.name]
let return_arguments = argument.arguments
let new_arguments = []
for (let i = 0; i < return_arguments.length; i++) {
new_arguments[i] = formal_parameter_dict[return_arguments[i].name]
}
path.replaceWith(type.callExpression(new_callee, new_arguments))
path.skip()
}
// 二项式嵌套混淆,function(_0x4fd34e, _0x54cdbe){return _0x485945 * _0x4a409e;}
if (type.isBinaryExpression(argument)) {
let new_node = get_binary_new_node(argument, formal_parameter_dict)
path.replaceWith(new_node)
path.skip()
}
}
}
},
// CallExpression(path) {
// if (!type.isMemberExpression(path.node.callee)) {
// return;
// }
// let object = path.node.callee.object
// let property = path.node.callee.property
// if (object.name === '_0x426597' && property.value === 'eejBg') {
// console.log(231)
// }
// if (member_attr_obj_function[object.name] &&
// member_attr_obj_function[object.name].hasOwnProperty(property.value))
// {
// let function_node = member_attr_obj_function[object.name][property.value]
// if (!type.isReturnStatement(function_node.body.body[0])) {
// return;
// }
// let formal_parameter_dict = {}
// for (let i = 0; i < function_node.params.length; i++) {
// if (path.node.arguments[i]) {
// formal_parameter_dict[function_node.params[i].name] = path.node.arguments[i]
// } else {
// formal_parameter_dict[function_node.params[i].name] = type.valueToNode(undefined)
// }
// }
// let argument = function_node.body.body[0].argument
// // 嵌套函数调用混淆,function(_0x4fd34e, _0x54cdbe){return _0x4fd34e(_0x54cdbe);}
// if (type.isCallExpression(argument)) {
// let new_callee = formal_parameter_dict[argument.callee.name]
// let return_arguments = argument.arguments
// let new_arguments = []
// for (let i = 0; i < return_arguments.length; i++) {
// new_arguments[i] = formal_parameter_dict[return_arguments[i].name]
// }
// path.replaceWith(type.callExpression(new_callee, new_arguments))
// path.skip()
// }
// // 二项式嵌套混淆,function(_0x4fd34e, _0x54cdbe){return _0x485945 * _0x4a409e;}
// if (type.isBinaryExpression(argument)) {
// let new_node = get_binary_new_node(argument, formal_parameter_dict)
// path.replaceWith(new_node)
// path.skip()
// }
// }
// }
})
}
// 移除IF语句混淆
this.remove_if_confuse = function () {
traverse(this.ast_code, {
IfStatement(path) {
// 排除无法正常判断的条件
let if_test_js_code = generator(path.node.test).code
// 存在變量則會報錯
try {
let judge_result = eval(if_test_js_code)
if (judge_result) {
let consequent = path.node.consequent
// 正常的if语句
if (type.isBlockStatement(consequent)) {
consequent.body.length > 0 ? path.replaceInline(consequent.body) : null
}
// 省略了{}的if语句
if (type.isExpressionStatement(consequent)) {
consequent.expression ? path.replaceInline(consequent.expression) : null
}
if (type.isEmptyStatement(consequent)) {
path.remove()
}
} else {
let alternate = path.node.alternate
// 正常的if语句
if (type.isBlockStatement(alternate)) {
alternate.body.length > 0 ? path.replaceInline(alternate.body) : path.remove()
}
// 省略了{}的if语句
if (type.isExpressionStatement(alternate)) {
alternate.expression ? path.replaceInline(alternate.expression) : path.remove()
}
if (type.isEmptyStatement(alternate)) {
path.remove()
}
}
} catch (e) {
console.log('轉換失敗,JS判斷測試代碼是:' + if_test_js_code)
}
}
})
}
// 函数参数内进行变量定义混淆,针对类型:function(a, b) {a=12, b=13, c=a+b}转换成function() {var a=12, var b=13, c=a+b}配合参数先定义后赋值混淆使用
this.function_params_define_confuse = function () {
// 收集函数对应的真正使用的参数长度
let real_function_params_length = {}
// 进行收集
traverse(this.ast_code, {
CallExpression(path) {
let callee = path.node.callee
let arguments = path.node.arguments
// 自执行函数:
if (type.isFunctionExpression(callee)) {
// 针对非匿名自执行函数:(function test(){})()
if (type.isIdentifier(callee.id)) {
real_function_params_length[callee.id.name] = arguments.length
} else if (!callee.id){
// 针对匿名函数自执行形式:(function (){})()
solve_function_params_confuse(callee, arguments)
}
}
// 函数调用,针对形式:$dbsm_0x37d29a(_0x2608da, OooIi1);
if (type.isIdentifier(callee)) {
// 如果没有记录该函数或者记录的传参长度小于本地传参,则直接记录下来
if (!real_function_params_length[callee.name] || real_function_params_length[callee.name] < arguments.length){
real_function_params_length[callee.name] = arguments.length
}
}
}
})
// 进行替换
traverse(this.ast_code, {
// 针对类型:function test(){}
FunctionExpression(path) {
if (type.isIdentifier(path.node.id) && real_function_params_length.hasOwnProperty(path.node.id.name)) {
solve_function_params_confuse(path.node, real_function_params_length[path.node.id.name])
}
},
// 针对赋值类型:var test = function (_0x2608da, OooIi1, qQOQo0, OOQQ1I, qoo1ql) {}
VariableDeclarator(path) {
if (!type.isFunctionExpression(path.node.init) || !type.isIdentifier(path.node.id)) {
return;
}
solve_function_params_confuse(path.node.init, real_function_params_length[path.node.id.name])
}
})
// 将函数参数里进行定义的变量,改成函数内进行定义
function solve_function_params_confuse(functionExpression_node, arguments_length) {
let params = functionExpression_node.params
let body = functionExpression_node.body.body
let new_params = []
for (let i = 0; i < params.length; i++) {
if (i < arguments_length) {
new_params.push(params[i])
} else {
// 向body里插入定义
body.unshift(type.variableDeclaration('var', [type.variableDeclarator(params[i], null)]))
}
}
functionExpression_node.params = new_params
}
}
// 针对参数先定义后赋值混淆,var a;a = 2
this.assignment_after_define_confuse = function () {
let assignment_after_define_obj = {}
// 收集全部定义参数
traverse(this.ast_code, {
VariableDeclarator(path) {
if (!type.isIdentifier(path.node.id) || path.node.init) {
return;
}
let binding = path.scope.getOwnBinding(path.node.id.name)
let constantViolations = binding.constantViolations
// 只进行一次赋值将引用全部修改
if (constantViolations.length === 1 && constantViolations[0].isAssignmentExpression()) {
let right = constantViolations[0].node.right
if (type.isLiteral(right)) {
assignment_after_define_obj[path.node.id.name] = right
constantViolations[0].remove()
} else if (type.isIdentifier(right) && assignment_after_define_obj.hasOwnProperty(right.name)) {
assignment_after_define_obj[path.node.id.name] = assignment_after_define_obj[right.name]
constantViolations[0].remove()
} else {
return;
}
}
},
// 替换值
Identifier(path) {
// 排除掉定义,赋值和没保存在对象中的变量
if (path.parentPath.isVariableDeclarator() ||
path.parentPath.isAssignmentExpression() ||
!assignment_after_define_obj.hasOwnProperty(path.node.name)) {
return;
}
path.replaceWith(assignment_after_define_obj[path.node.name])
}
})
}
// 去除不被引用的定义变量
this.remove_unuseful_variable = function () {
let js_code = generator(this.ast_code).code
this.ast_code = parse(js_code)
traverse(this.ast_code, {
VariableDeclarator(path) {
let binding = path.scope.getBinding(path.node.id.name)
if (binding && !binding.referenced) {
path.remove()
}
}
})
}
// 去除(0, b[$_BHHGs(175)])()这样的混淆
this.remove_zero_call_function = function () {
traverse(this.ast_code, {
CallExpression(path) {
let callee = path.node.callee
if (!type.isSequenceExpression(callee)) {
return
}
let expressions = callee.expressions
if (expressions.length === 2 && type.isLiteral(expressions[0]) && expressions[0].value === 0) {
path.replaceWith(type.callExpression(expressions[1], path.node.arguments))
}
}
})
}
// 特殊函数赋值替换,初始化行数+{被赋值后的变量名:原方法名}
this.special_function_assign_replace = function (init_line_row, assign_name_source_name) {
let init_ast_code = parse('')
for (let i = 0; i < init_line_row; i++) {
init_ast_code.program.body.push(this.ast_code.program.body[i])
}
let init_code = generator(init_ast_code, {'compact': true}).code
init_code = "const {JSDOM} = require('jsdom');" +
"const dom = new JSDOM('<!DOCTYPE html><p>Hello world</p>');" +
"var {window} = dom;" +
"var {document} = window;" +
"var {navigator} = window;" +
init_code
eval(init_code)
traverse(this.ast_code, {
CallExpression(path) {
let callee = path.node.callee
if (assign_name_source_name[callee.name]) {
// 赋值到变量
eval('var ' + callee.name + '=' + assign_name_source_name[callee.name])
// 生成值
var result = eval(generator(path.node).code)
path.replaceWith(type.valueToNode(result))
}
}
})
}
}
基础使用:
const fs = require('fs');
input_file_path = "./encoding.js"
output_file_path = "./decoding.js"
let sourceCode = fs.readFileSync(input_file_path, {encoding: "utf-8"});
let ast = parse(sourceCode);
parse_tool = new flower_instruction_code(ast)
// 这里初始化解析函数
init_code = parse_tool.get_init_js_code([0, 1, 2])
eval(init_code)
parse_tool.binary_hexadecimal()
parse_tool.replace_confuse_name()
parse_tool.decrypt_string_confuse(['解密函数名'])
let {code} = generator(ast, opts = {jsescOption:{"minimal":true}});
fs.writeFile(output_file_path, code, (err) => {});
console.log('完成')