Python逆向(三)—— Python编译运行及反汇编
一、前言
前期我們已經對python的運行原理以及運行過程中產生的文件結構有了了解。本節,我們將結合具體的例子來實踐python運行,編譯,反編譯的過程,并對前些章節中可能遺漏的具體細節進行補充。
二、Python編譯
python在正常運行時,有時編譯生成pyc文件,有時候沒有pyc文件的生成。那么我們能不能手動將python程序編譯成pyc文件呢?答案是可以的,不但可以編譯,還可以直接運行pyc文件以實現程序運行的效率。
2.1、pyc文件的生成
命令行模式:
python -m py_compile file.py # 生成單個pyc文件
python -m py_compile /dir/{file1,file2}.py # 生成多個pyc文件
python -m compileall /dir/ # 生成目錄下所有py文件對應的pyc文件
交互shell模式:
>>> import py_compile # 相當于命令行中的“-m py_compile”
>>> py_compile.compile('py file path')
>>> import compileall
>>> compileall.compile_dir("py files dir")
2.2、pyo文件生成
pyo文件是源代碼文件經過優化編譯后生成的文件,是pyc文件的優化版本。編譯時需要使用-O和-OO選項來生成pyo文件。在Python3.5之后,不再使用.pyo文件名,而是生成文件名類似“test.opt-n.pyc的文件。
python -O -m py_compile file.py
python -O -m py_compile /dir/{file1,file2}.py
python -O -m compileall /dir/
2.3、直接運行編譯好的pyc或者pyo文件
三、字節碼文件反編譯
經過編譯的python文件可以提高程序的運行速度,一定程度上也對源代碼起到了保護作用。然而如果我們只有編譯過的python字節碼文件,就給我們審查源碼造成了一定的困難,這就引出了python字節碼反編譯的需求。
上一節我們介紹過pyc文件的結構,其實就是pyc文件頭部加上PyCodeObject對象。文件頭部的信息在python2中只占用固定8字節,用來攜帶一些版本類的信息,不是我們做反編譯的重點,因此通過提取8字節之后的部門做反編譯處理就可以了。
PyCodeObjectData就是我們需要提取的數據,根據python的編譯原理我們知道PyCodeObjectData是python源文件作為一個實例化的類,通過python內置庫函數marshal.dumps生成的二進制數據段,因此通過marshal.loads(PyCodeObjectData) ,我們可以得到PyCodeObjectData反序列化的對象。
可以看到PyObj對象包含了很多內置方法和屬性,這些屬性在第二節中我們已經有過介紹,各個字段的含義都已經知道了。通過對這些方法的引用可以直接看到相關字段反序列后的具體值。
使用python內置模塊dis可以對PyCodeObject進行反編譯,從而獲取到python二進制字節碼代碼段的“匯編形式”。這樣可以便于對字節碼進行閱讀。dis模塊也可以單獨對PyCodeObject中的co_data模塊進行反編譯,但是這樣得到的是單純的代碼段字節碼,缺少很多代碼段中涉及的變量名字。如上圖所示。
四、結語
本節我們對python源碼編譯生成字節碼文件和從字節碼文件反編譯生成字節碼代碼段(python的匯編形式)進行介紹。下一章節我們將對dis模塊的源碼進行解讀,以便于后續章節關于python代碼混淆技術的涉及。
總結
以上是生活随笔為你收集整理的Python逆向(三)—— Python编译运行及反汇编的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 18000字的SQL优化大全,收藏直接起
- 下一篇: 精选6种制作酷炫动图的方法,收藏!