def compile_py3k(source, filename, mode, *args, **kwds):
"""
py3k example:
import py3to2; from py3to2 import print_py3k
src = "a, b, *c = 1, 2, 3, 4, 5; print('a =', a); print('b =', b); print('c =', c)"
code_object = py3to2.compile_py3k(src, '', 'exec')
exec(code_object, globals())
"""
s = "x = compile(%s, %s, %s, *%s, **%s); x = codetree(x).py3to2()"%tuple(repr(x) for x in (source, filename, mode, args, kwds))
server.input(s)
x = server.get('x')
x = eval(x)
x = x.compile()
if 1: dis.dis(x)
return x
python类dis()的实例源码
def get_env(ctx):
return dict(
print=print_,
timeit=timeit,
dis=dis,
discord=discord,
bot=ctx.bot,
client=ctx.bot,
ctx=ctx,
con=ctx.con,
msg=ctx.message,
message=ctx.message,
guild=ctx.guild,
server=ctx.guild,
channel=ctx.channel,
me=ctx.me
)
def get_opcode(self):
# Based on the settings decide to show the line-by-line trace
# Get the current line being executed
ip = self.__ip
op = self.__code[self.__ip]
ip += 1
opmethod = "execute_%s" % dis.opname[op]
oparg = None
if op >= dis.HAVE_ARGUMENT:
low = self.__code[ip]
high = self.__code[ip + 1]
oparg = (high << 8) | low
return opmethod, oparg
def do_disassembly_test(self, func, expected):
s = io.StringIO()
save_stdout = sys.stdout
sys.stdout = s
dis.dis(func)
sys.stdout = save_stdout
got = s.getvalue()
# Trim trailing blanks (if any).
lines = got.split('\n')
lines = [line.rstrip() for line in lines]
expected = expected.split("\n")
import difflib
if expected != lines:
self.fail(
"events did not match expectation:\n" +
"\n".join(difflib.ndiff(expected,
lines)))
def do_disassembly_test(self, func, expected):
s = StringIO.StringIO()
save_stdout = sys.stdout
sys.stdout = s
dis.dis(func)
sys.stdout = save_stdout
got = s.getvalue()
# Trim trailing blanks (if any).
lines = got.split('\n')
lines = [line.rstrip() for line in lines]
expected = expected.split("\n")
import difflib
if expected != lines:
self.fail(
"events did not match expectation:\n" +
"\n".join(difflib.ndiff(expected,
lines)))
def do_disassembly_test(self, func, expected):
s = StringIO.StringIO()
save_stdout = sys.stdout
sys.stdout = s
dis.dis(func)
sys.stdout = save_stdout
got = s.getvalue()
# Trim trailing blanks (if any).
lines = got.split('\n')
lines = [line.rstrip() for line in lines]
expected = expected.split("\n")
import difflib
if expected != lines:
self.fail(
"events did not match expectation:\n" +
"\n".join(difflib.ndiff(expected,
lines)))
def do_disassembly_test(self, func, expected):
s = StringIO.StringIO()
save_stdout = sys.stdout
sys.stdout = s
dis.dis(func)
sys.stdout = save_stdout
got = s.getvalue()
# Trim trailing blanks (if any).
lines = got.split('\n')
lines = [line.rstrip() for line in lines]
expected = expected.split("\n")
import difflib
if expected != lines:
self.fail(
"events did not match expectation:\n" +
"\n".join(difflib.ndiff(expected,
lines)))
def do_disassembly_test(self, func, expected):
s = StringIO.StringIO()
save_stdout = sys.stdout
sys.stdout = s
dis.dis(func)
sys.stdout = save_stdout
got = s.getvalue()
# Trim trailing blanks (if any).
lines = got.split('\n')
lines = [line.rstrip() for line in lines]
expected = expected.split("\n")
import difflib
if expected != lines:
self.fail(
"events did not match expectation:\n" +
"\n".join(difflib.ndiff(expected,
lines)))
def func_bytes(fl):
import console, dis
"""
This function reads a script and
prints it's memory address.
"""
f = open(fl).readlines()
for line in f:
try:
co = compile(line,"<none>","exec")
t = str(str(co).split("at ")[1]).split(",")[0]
print t, co.consts
except:
pass
console.set_font("Menlo",10)
f = open(fl).readlines()
for line in f:
try:
dis.dis(line)
except:
pass
console.set_font()
def dis_code(code):
"""Disassemble `code` and all the code it refers to."""
for const in code.co_consts:
if isinstance(const, types.CodeType):
dis_code(const)
print("")
print(code)
dis.dis(code)
def test():
global xxx
if 1: # reflect self
c0 = compile(TESTCODE, '', 'exec')
t0 = codetree(c0); s = repr(t0); t0 = eval(s); c = t0.compile()
t0 = codetree(c); s = repr(t0)
print 'exec'; exec(c0, globals()); exec(c, globals()); print dis.dis(c)
# compile, expand, recompile, exec
if PYVERSION == 'py2x': print s
if 0: print s
else:
t = t0.py3to2() if hasattr(t0, 'py3to2') else t0; xxx = t; s = repr(t)
def test():
self = _server
global xxx
if 1: # server init
self.restart()
self.input("1, 2;3")
if 0: # py3k codetree
server.input("codetree.test()")
if 1: # 3to2
s = server.get('xxx')
t = eval(s)
c = t.compile()
print dis.dis(c)
exec(c, globals())
def test():
global xxx
if 1: # reflect self
c0 = compile(TESTCODE, '', 'exec')
t0 = codetree(c0); s = repr(t0); t0 = eval(s); c = t0.compile()
t0 = codetree(c); s = repr(t0)
print 'exec'; exec(c0, globals()); exec(c, globals()); print dis.dis(c)
# compile, expand, recompile, exec
if PYVERSION == 'py2x': print s
if 0: print s
else:
t = t0.py3to2() if hasattr(t0, 'py3to2') else t0; xxx = t; s = repr(t)
def test():
self = _server
global xxx
if 1: # server init
self.restart()
self.input("1, 2;3")
if 0: # py3k codetree
server.input("codetree.test()")
if 1: # 3to2
s = server.get('xxx')
t = eval(s)
c = t.compile()
print dis.dis(c)
exec(c, globals())
def execute_MAKE_FUNCTION(self, argc):
"""
Pushes a new function object on the stack. From bottom to top, the consumed stack must consist of argc & 0xFF default argument
objects in positional order (argc >> 8) & 0xFF pairs of name and default argument, with the name just below the object on the
stack, for keyword-only parameters (argc >> 16) & 0x7FFF parameter annotation objects a tuple listing the parameter names for the
annotations (only if there are ony annotation objects) the code associated with the function (at TOS1) the qualified name of the
function (at TOS)
"""
num_default_args = argc & 0xFF
num_kw_args = (argc >> 8) & 0xFF
name = self.__stack.pop()
name = name.replace(self.__class_name + ".", "")
special_func = False
if is_special_func(name):
special_func = True
code = self.__stack.pop()
defaults = self.popn(num_default_args)
fn = Function(name, defaults)
fn.code = code
if special_func == True:
self.__klass.add_special_func(fn)
else:
self.__klass.add_normal_func(fn)
self.__vm_state = VMState.BUILD_FUNC
if self.__config.show_disassembly:
draw_header("FUNCTION CODE: %s" % name)
dis.dis(code)
def get_opcode(self):
# Based on the settings decide to show the line-by-line trace
# Get the current line being executed
current_lineno = self.__exec_frame.line_no_obj.line_number(self.__exec_frame.ip)
ip = self.__exec_frame.ip
# Update the line number only if the currently executing line has changed.
if self.__exec_frame.line_no_obj.currently_executing_line is None or \
self.__exec_frame.line_no_obj.currently_executing_line != current_lineno:
self.__exec_frame.line_no_obj.currently_executing_line = current_lineno
self.__exec_frame.line_no_obj.currently_executing_line = current_lineno
if self.__config.show_line_execution:
current_line = self.__exec_frame.line_no_obj.get_source_line(current_lineno)
print("Execution Line: %s" % current_line)
op = self.__exec_frame.program[self.__exec_frame.ip]
ip += 1
opmethod = "execute_%s" % dis.opname[op]
oparg = None
if op >= dis.HAVE_ARGUMENT:
low = self.__exec_frame.program[ip]
high = self.__exec_frame.program[ip + 1]
oparg = (high << 8) | low
return opmethod, oparg, current_lineno
def execute_MAKE_FUNCTION(self, argc):
"""
Pushes a new function object on the stack. From bottom to top, the consumed stack must consist of argc & 0xFF default argument
objects in positional order (argc >> 8) & 0xFF pairs of name and default argument, with the name just below the object on the
stack, for keyword-only parameters (argc >> 16) & 0x7FFF parameter annotation objects a tuple listing the parameter names for the
annotations (only if there are ony annotation objects) the code associated with the function (at TOS1) the qualified name of the
function (at TOS)
"""
num_default_args = argc & 0xFF
num_kw_args = (argc >> 8) & 0xFF
name = self.__exec_frame.pop()
code = self.__exec_frame.pop()
defaults = self.__exec_frame.popn(num_default_args)
if self.__BUILD_CLASS_STATE == True:
build_class = BuildClass(name, code, self.__config, self.__module)
self.__exec_frame.append(build_class)
self.__BUILD_CLASS_STATE = False
else:
fn = Function(name, defaults)
fn.code = code
self.__exec_frame.add_global(name, fn)
self.__exec_frame.vm_state = VMState.BUILD_FUNC
if self.__config.show_disassembly:
draw_header("FUNCTION CODE: %s" % name)
dis.dis(code)
def main():
filename = sys.argv[1]
fptr = open(filename, "r")
source = fptr.read()
fptr.seek(0)
source_lines = format_source_lines(fptr.readlines())
fptr.close()
draw_header("Source")
display_source(source_lines)
code = compile(source, filename, "exec")
vm = BytecodeVM(code, source_lines, filename)
WITH_DEBUGGER = False
if not WITH_DEBUGGER:
draw_header("Disassembly")
dis.dis(code)
# Configure the VM and set the settings based on command line. For now use defaults
config = configure_vm()
config.show_disassembly = True
vm.config = config
vm.execute()
else:
debugger = Debugger(code, source_lines, filename)
debugger.execute(False)
def disassemble(func):
f = StringIO()
tmp = sys.stdout
sys.stdout = f
dis.dis(func)
sys.stdout = tmp
result = f.getvalue()
f.close()
return result
def test_opmap(self):
self.assertEqual(dis.opmap["STOP_CODE"], 0)
self.assertIn(dis.opmap["LOAD_CONST"], dis.hasconst)
self.assertIn(dis.opmap["STORE_NAME"], dis.hasname)
def test_opname(self):
self.assertEqual(dis.opname[dis.opmap["LOAD_FAST"]], "LOAD_FAST")
def test_boundaries(self):
self.assertEqual(dis.opmap["EXTENDED_ARG"], dis.EXTENDED_ARG)
self.assertEqual(dis.opmap["STORE_NAME"], dis.HAVE_ARGUMENT)
def test_show_code(self):
self.maxDiff = 1000
for x, expected in self.test_pairs:
with captured_stdout() as output:
dis.show_code(x)
self.assertRegex(output.getvalue(), expected+"\n")
def post(self):
parser = reqparse.RequestParser()
parser.add_argument('payload', type=str, help='Payload as code, to be analyzed by Unravelr.')
args = parser.parse_args()
try:
Binary = compile(args['payload'], "<string>", "exec")
result = StringIO()
with captureStdOut(result):
dis.dis(Binary)
# import ipdb; ipdb.set_trace()
return jsonify(dict(result=result.getvalue()))
except:
abort(404)
def dis_code(code):
"""Disassemble `code` and all the code it refers to."""
for const in code.co_consts:
if isinstance(const, types.CodeType):
dis_code(const)
print("")
print(code)
dis.dis(code)
def compare(a, b):
if not (a.co_name == "?" or a.co_name.startswith('<lambda')):
assert a.co_name == b.co_name, (a, b)
if a.co_stacksize != b.co_stacksize:
print("stack mismatch %s: %d vs. %d" % (a.co_name,
a.co_stacksize,
b.co_stacksize))
if a.co_stacksize > b.co_stacksize:
print("good code")
dis.dis(a)
print("bad code")
dis.dis(b)
assert 0
def walk(co, match=None):
if match is None or co.co_name == match:
dump(co)
print()
dis.dis(co)
for obj in co.co_consts:
if type(obj) == types.CodeType:
walk(obj, match)
def disassemble(func):
f = StringIO()
tmp = sys.stdout
sys.stdout = f
dis.dis(func)
sys.stdout = tmp
result = f.getvalue()
f.close()
return result
def test_opname(self):
self.assertEqual(dis.opname[dis.opmap["LOAD_FAST"]], "LOAD_FAST")
def test_boundaries(self):
self.assertEqual(dis.opmap["EXTENDED_ARG"], dis.EXTENDED_ARG)
self.assertEqual(dis.opmap["STORE_NAME"], dis.HAVE_ARGUMENT)