import sys import esprima import operator as OP import esprima.nodes as N def eval_binex(op, lhs, rhs): return {"*": OP.mul, "+": OP.add,"-": OP.sub}[op](lhs, rhs) def eval_unex(op,val): return {"-":OP.neg,"!":OP.not_}[op](val) class Emulator(object): def __init__(self, code): self.ret_cache = {} self.funcs = {} self.edges = set() self.ast = esprima.parseModule(code, delegate=self) def __call__(self, node, meta): self.pos = meta attr_name = "visit_" + node.type func = getattr(self, attr_name,None) if callable(func): return func(node) else: # print("UNIMPL:",node.type) pass return node def visit_VariableDeclaration(self,node): return node def visit_FunctionDeclaration(self,node): if node.body.type=="BlockStatement": body=node.body.body if len(body)==1 and body[0].type=="ReturnStatement" and body[0].argument.type=="CallExpression": arg=body[0].argument print("EDGE:",node.id.name,"->",arg.callee.name) self.edges.add((node.id.name,arg.callee.name)) self.funcs.setdefault(node.id.name,[]).append(node) return node def visit_CallExpression(self,node): const_args=all([a.type=="Literal" for a in node.arguments]) if node.callee.type=="Identifier" and const_args: print("CALL",node.callee.name,[a.value for a in node.arguments]) return node def visit_Literal(self,node): return node def visit_UnaryExpression(self,node): if node.argument.type=="Literal": val=eval_unex(node.operator,node.argument.value) node = N.Literal(val, hex(val)) return node def visit_BinaryExpression(self, node): if node.left.type == "Literal" and node.right.type == "Literal": if isinstance(node.left.value,(int,float)) and isinstance(node.right.value,(int,float)): val = eval_binex(node.operator, node.left.value, node.right.value) node = N.Literal(val, hex(val)) return node def visit_Identifier(self, node): # print("Ident", node.name) return node # def deobf(node,meta): # if node.type=="Identifier": # if node.name.find("_0x")!=-1: # node.name=idents.setdefault(node.name,f"var_{len(idents)}") # return node # if node.type=="BinaryExpression" and node.left.type=="Literal" and node.right.type=="Literal": # return simplify_binex(node) code = open(sys.argv[1]).read() emu = Emulator(code) print("EDGES:",len(emu.edges)) print("FUNCS:",len(emu.funcs)) # print(emu.ast)