關於pyc檔案的逆向

2021-09-11 18:45:45 字數 2794 閱讀 1594

關於pyc檔案的逆向

最近感覺遇到的pyc檔案逆向的越來越多了,所以就來總結下。//參考了大佬的blog:

0x1 pyc的檔案結構

在命令列輸入 python -m filename.py的時候,便會得到乙個對應的filename.pyc。

拖進hxd中看二進位制。其中,開頭的4個位元組是magic number,相對比較固定,是標識的此pyc的版本資訊,不同的版本的magic在python/import.c中定義。

而之後4個位元組是小端序的時間戳。

之後的位元組是個0x63,也就是pycodeobject的識別符號,隨後是小端序的co_argument(引數個數),co_nlocals(變數個數),co_stacksize(棧空間)和co_flags(特殊標誌)特殊標誌的flags:

#define co_optimized 0x0001

#define co_newlocals 0x0002

#define co_varargs 0x0004

#define co_varkeywords 0x0008

#define co_nested 0x0010

#define co_generator 0x0020

#define co_nofree 0x0040

#define co_future_division 0x2000

#define co_future_absolute_import 0x4000

#define co_future_with_statement 0x8000

#define co_future_print_function 0x10000

#define co_future_unicode_literals 0x20000

之後是opcode,先是0x73,之後接4個位元組的小端序的數字,表示opcode所佔的總的位元組//在我的個人理解中,opcode跟我們用c之類的編寫的反編譯出來的彙編差不多。

之後,乙個位元組表示儲存的型別,之後四個位元組表示該型別佔的空間(小端序表示)(例如如果是小端序的0x40,那之後的0x40個位元組就是他儲存的內容)以此類推。繼續從大佬blog中拖資料型別標識:

#define type_null 『0』

#define type_none 『n』

#define type_false 『f』

#define type_true 『t』

#define type_stopiter 『s』

#define type_ellipsis 『.』

#define type_int 『i』

#define type_int64 『i』

#define type_float 『f』

#define type_binary_float 『g』

#define type_complex 『x』

#define type_binary_complex 『y』

#define type_long 『l』

#define type_string 『s』

#define type_interned 『t』

#define type_stringref 『r』

#define type_tuple 『(』

#define type_list 『[』

#define type_dict 『{』

#define type_code 『c』

#define type_unicode 『u』

#define type_unknown 『?』

#define type_set 『<』

#define type_frozenset 『>』

0x2 pyc檔案反編譯的常用工具

最常用的就是uncompyle6,用uncompyle6 -o filename.py filename.pyc這個命令就可以了,當然,在網上也有一些把uncompyle6這種工具開出gui介面的,這個自行搜尋。

0x3 出現反編譯失敗的情況

以hgame的pro的python教室(三&四)為例子

先檢視發現magic number之類的沒有錯,這裡介紹乙個叫marshal的py庫,使用如下:

import dis,marshal

f = open(「third.pyc」, 「rb」)

magic = f.read(4)

mtime = f.read(4)

dis.dis(marshal.load(f)),

在偏移13的位置出現了load_const 100,然後,py返回錯誤。

來看下這邊的opcode的表達:

0 jump_absolute 3

3 jump_absolute 9

6 load_const 15 ("you』re wrong! ")

9 jump_absolute 14

12 print_item

13 load_const 100

好的,有個load_const 100的操作,這個是溢位了範圍的,但是在這上面有個jump 14的操作,所以其實12,13根本就不會執行(其實這也是一種常見的防反編譯的方法,在程式中加入一段跳轉到不存在的地方的操作,但是這個操作正常執行根本不會執行,所以程式執行沒有一點毛病,但是反編譯工具卻無法進行下去了。也就是花指令了)那麼就可以直接把它刪了,外加改下其他的定義的長度,使得符合上述的規則就ok了。

此外,還有那些用py檔案編譯出的exe檔案,這些檔案一般是用py extractor這個工具來進行反編譯。

逆向 簡單的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逆向之opcode簡單置換

最近做了一道pyc的逆向題,主要難點在於python環境的opcode被置換,就簡單記錄一下相關知識。opcode其實是指python原始碼的操作碼,python源 py編譯後可以得到二進位制檔案 pyc,pyc檔案中就含有opcode序列。對於不同版本的python,其opcode是不完全相同的,...