Possible to execute Python bytecode from a script?

筅森魡賤 提交于 2019-12-07 04:29:38

问题


Say I have a running CPython session,

Is there a way to run the data (bytes) from a pyc file directly? (without having the data on-disk necessarily, and without having to write a temporary pyc file)

Example script to show a simple use-case:

if foo:
    data = read_data_from_somewhere()
else:
    data = open("bar.pyc", 'rb').read()

assert(type(data) is bytes)

code = bytes_to_code(data)

# call a method from the loaded code
code.call_function()

Exact use isn't important, but generating code dynamically and copying over a network to execute is one use-case (for the purpose of thinking about this question).


Here are some example use-cases, which made me curious to know how this can be done:

  • Checking Python scripts for malicious code.
    If a single command can access a larger body of code hidden in binary data, what would that command look like?
  • Dynamically generate code and cache it for re-use (not necessarily on disk, could use a data-base for example).
  • Ability to send pre-compiled byte-code to a process, control an application which embeds Python for eg.

回答1:


Is there a way to run the data from a pyc file directly?

The compiled code object can be saved using marshal

import marshal
bytes = marshal.dumps(eggs)

the bytes can be converted back to a code object

eggs = marshal.loads(bytes)
exec(eggs)

A pyc file is a marshaled code object with a header

For Python3, the header is 12 bytes which need to be skipped, the remaining data can be read via marshal.loads.


See Ned Batchelder's blog post:

At the simple level, a .pyc file is a binary file containing only three things:

  • A four-byte magic number,
  • A four-byte modification timestamp, and
  • A marshalled code object.

Note, the link references Python2, but its almost the same in Python3, the pyc header size is just 12 instead of 8 bytes.




回答2:


Assuming the platform of the compiled .pyc is correct, you can just import it. So with a file bar.pyc in the python path, the following works even if bar.py does not exist:

import bar
bar.call_function()


来源:https://stackoverflow.com/questions/29897480/possible-to-execute-python-bytecode-from-a-script

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!