Skip to content

pyc 格式分析

pyc 格式

  • 前 8 bytes 是 magic number,不同的 python 的版本會有不同的 magic number,參考 cpython/Lib/importlib/_bootstrap_external.py
  • 接下來 8 bytes 是 pyc 被產生出來的時間戳記
  • 剩下的都是序列化的 PyCodeObject ( marshal.dumps 的結果 )
python2

python2 的 magic number 和時間戳記都是 4 bytes

python → pyc

import

import 其他的 python 程式的時候,會把被引入的程式編譯成 .pyc 放到 __pycache__ 資料夾
這樣可以減少引入的時間

py_compile

import py_compile
py_compile.compile('test.py')

就會生成 .pyc 檔在 __pycache__ 資料夾

compileall

python -m compileall .

可以一次 compile 資料夾內所有檔案

pyc → python ( bytecode → python )

使用 uncompyle6

uncompyle6 test.pyc
# uncompyle6 version 3.3.2
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.7.0 (default, Oct  9 2018, 16:58:41)
# [GCC 5.4.0 20160609]
# Embedded file name: /home/oalieno/lib.py
# Size of source mod 2**32: 23 bytes


def f(x):
    return x
# okay decompiling lib.cpython-37.pyc

python → PyCodeObject

code = compile('x = 1', 'filename', 'exec')

compile 是內建的函式

marshal

import marshal

obj = marshal.loads(open('test.pyc', 'rb').read()[16:])
data = marshal.dumps([1, 2, 3])

bytecode disassemble

import dis
dis.dis(bytecode)