pyc逆向之opcode簡單置換

2021-09-24 14:52:08 字數 3797 閱讀 2827

最近做了一道pyc的逆向題,主要難點在於python環境的opcode被置換,就簡單記錄一下相關知識。

opcode其實是指python原始碼的操作碼,python源***.py編譯後可以得到二進位制檔案*.pyc,*.pyc檔案中就含有opcode序列。對於不同版本的python,其opcode是不完全相同的,這也就是為什麼某一版本的python虛擬機器不能執行另乙個版本的原始碼。

檢視當前版本opcode的方式有很多種,最簡單的是直接匯入opcode庫檢視:

import opcode

for key in opcode.opmap.keys():

print (key, opcode.opmap[key])

或者在/python/include/opcode.**件中檢視。

乙個簡單原始碼的opcode檢視如下:

import dis

def foo():

x = 20

y = 10

z = x - y

return z

dis.dis(foo)

輸出如下:

3           0 load_const               1 (20)

2 store_fast 0 (x)

4 4 load_const 2 (10)

6 store_fast 1 (y)

5 8 load_fast 0 (x)

10 load_fast 1 (y)

12 binary_subtract

14 store_fast 2 (z)

6 16 load_fast 2 (z)

18 return_value

或者可以在命令列執行 python -m py_compile filename.pyc,然後利用pycdas等軟體去反編譯至opcode。

一些逆向題會構建乙個修改的python環境,從而使對應的*.pyc檔案只能被本地識別並執行,而不能在別的計算機執行。

那如何構建這樣的環境呢,一般是通過原始碼安裝python的方式實現,在安裝前更改opcode的相關檔案。對於2.7.13版本以下,似乎只需要更改/include/opcode.h,/lib/opcode.py兩個檔案,而2.7.14及以上版本則還需要修改/python/opcode_targets.**件。本文的例子是針對2.7.16的。

構建三個補丁檔案(這裡以加減法交換為例)如下,分別命名為re1.patch,re2.patch,re3.patch。

--- include/opcode.h

+++ include/opcode.h

@@ -30,2 +30,2 @@

-#define binary_add 23

-#define binary_subtract 24

+#define binary_add 24

+#define binary_subtract 23

--- lib/opcode.py

+++ lib/opcode.py

@@ -65,2 +65,2 @@

-def_op('binary_add', 23)

-def_op('binary_subtract', 24)

+def_op('binary_add', 24)

+def_op('binary_subtract', 23)

--- python/opcode_targets.h

+++ python/opcode_targets.h

@@ -25,2 +25,2 @@

- &&target_binary_add,

- &&target_binary_subtract,

+ &&target_binary_subtract,

+ &&target_binary_add,

執行以下命令:

~$ xz -d python-2.7.16.tar.xz

~$ tar -xvf python-2.7.16.tar

~$ cd python-2.7.16

~/python-2.7.16$ cp ~/re1.patch re1.patch

~/python-2.7.16$ cp ~/re2.patch re2.patch

~/python-2.7.16$ cp ~/re3.patch re3.patch

~/python-2.7.16$ patch -p0 < re1.patch

~/python-2.7.16$ patch -p0 < re2.patch

~/python-2.7.16$ patch -p0 < re3.patch

~/python-2.7.16$ ./configure --prefix=/usr/local/python

~/python-2.7.16$ sudo make & make install

此時python環境編譯成功,可以用下面的小例子測試一下:

x = 10

y = input("number:")

print x-y

然後將原始碼編譯為pyc檔案:python -m py_compile main.py,分別在不同平台上執行main.pyc如下:

在windows下使用uncompyle6嘗試對main.pyc反編譯:

d:\>uncompyle6 main.pyc

# uncompyle6 version 3.2.6

# python bytecode 2.7 (62211)

# decompiled from: python 2.7.16 (v2.7.16:413a49145e, mar 4 2019, 01:37:19) [msc v.1500 64 bit (amd64)]

# embedded file name: main.py

# compiled at: 2019-06-20 14:51:58

x = 10

y = input('number:')

print x + y

# okay decompiling main.pyc

我們發現,加減法已經被置換了。

簡單置換也可以置換多個opcode,需要注意的是上面三個檔案中opcode的順序必須是一致的,否則make將會失敗。

使用編譯好的pycdc就可以反編譯到正確的原始碼了。

其實我們一般做題很難事先知道正確的opcode順序是什麼,主要還是得通過一次反編譯之後的原始碼,對照其中異常的語句猜測正確的opcode值。

逆向 簡單的pyc

這個是i c的比賽逆向題目 比賽還沒結束qaq 題目內容很簡單 提示說要逆向乙個pyc 直接拉進去 執行 得到如下內容 import base64 def encode message s for i in message x ord i 32 x x 16 s chr x return base6...

180627 逆向 pyc還原指令碼

針對suctf的python 好一題,通過解析內容還原pyc的指令碼 對於不同的解析內容需要另加修改,但原理一致 將元素按照 格式識別符號 len 內容的形式遞迴填入即可 值得說明的一點是指令碼無法還原出原來一模一樣的pyc,但可以還原出相同的py檔案 這是因為python在編譯pyc的時候,會將一...

關於pyc檔案的逆向

關於pyc檔案的逆向 最近感覺遇到的pyc檔案逆向的越來越多了,所以就來總結下。參考了大佬的blog 0x1 pyc的檔案結構 在命令列輸入 python m filename.py的時候,便會得到乙個對應的filename.pyc。拖進hxd中看二進位制。其中,開頭的4個位元組是magic num...