83 lines
2.8 KiB
Python
83 lines
2.8 KiB
Python
|
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)
|