在解压缩python pyc文件时混淆的字节码

时间:2018-03-22 18:15:46

标签: python python-3.6 decompiling pyc

我正在尝试用uncompyle6反编译一个pyc文件。该操作在偏移966处给出了Parse错误,如此处所述。

Parse error at or near `POP_TOP' instruction at offset 996

Uncompyle打印出反编译的结果,从中可以看出,在反编译我的代码的最后一行(即root.mainloop()后,抛出了解析错误,因为源代码是tkinter gui。

如果有人可以解释如何将字节码修复为绝对的初学者以及我应该从哪里开始,我会很感激。由于错误是在我的代码结束时抛出的,我觉得错误是可以纠正的。 这是错误本身:

2295    6290  LOAD_NAME                'root'
        6292  LOAD_ATTR                'mainloop'
        6296  CALL_FUNCTION_0       0  ''
        6298  POP_TOP

Parse error at or near `POP_TOP' instruction at offset 996

这是错误行周围的字节码

 966 LOAD_NAME               23 (ttk)
 968 LOAD_ATTR              110 (Button)
 970 LOAD_NAME              107 (iS1cols)
 972 LOAD_NAME              112 (tools_be_xl)
 974 LOAD_NAME               43 (tools_browse_xls)
 976 LOAD_CONST             126 (('textvariable', 'command'))
 978 CALL_FUNCTION_KW         3
 980 LOAD_ATTR              108 (grid)
 982 LOAD_CONST               0 (0)
 984 LOAD_CONST             121 (20)
 986 LOAD_CONST             117 (4)
 988 LOAD_CONST             127 (2)
 990 LOAD_NAME              109 (W)
 992 LOAD_CONST             128 (('row', 'padx', 'pady', 'column', 'sticky'))
 994 CALL_FUNCTION_KW         5
 996 POP_TOP

 998 LOAD_NAME               23 (ttk)
1000 LOAD_ATTR              113 (LabelFrame)
1002 LOAD_NAME               91 (tab3Int)
1004 LOAD_CONST             129 (' Bulk Edit ')
1006 LOAD_CONST             107 (('text',))
1008 CALL_FUNCTION_KW         2
1010 STORE_NAME             114 (imgStep1)

1 个答案:

答案 0 :(得分:1)

你的程序长达数千行。在你把它缩小到更小的东西之后,在https://github.com/rocky/python-uncompyle6/issues报告它。

但请注意,您可能需要付出相当大的努力才能将程序削减成易于理解的东西。如果你不想花费精力,而是希望别人为你做这项工作,那我就listed a service that may be willing to do this。如果有人希望我在该文档中列出其他服务,请与我联系。

根据我的经验,我会说一旦错误被删除,除了控制流错误(这里似乎没有相关性),通常都很小即使是这些巨大的文件也能正确反编译。

有两种方法可以缩短程序以考虑uncompyle6 bug修复....

最简单的方法是猜测导致问题的代码类型。因为你有一些问题所在的想法 - 你说它是在tkinter gui循环的最后一行 - 写一些类似于它的新代码,字节编译并查看是否反编译给出了同样的错误。

也许你有一些旧的源代码与相同类型的tkinter gui循环。尝试拆解它。然后将其缩小,使其长度不超过数十行。

第二种方法是使用xdis包中的pydisasm上的--asm选项。这将为您提供可以更容易修改的Python汇编代码,并且在pyc-xasm之后--xasm可以转回到您可能能够反编译的pyc文件。

但是,POP_TOP选项中存在一些错误,需要一段时间才能完全抖动,所以xasm。同样,uncompyle6目前正在修复Python 3.6错误,这与你的情况有关,所以use what's on github也是如此

现在有点关于什么是uncompyle6 bug。 Warning: block stack is not empty!会丢弃Python评估堆栈中的值。例如,当未使用调用的返回值时可能会发生这种情况 - 也许调用是它自己的语句。然而,这种未使用的值一直在发生,并且像大多数反编译器一样,uncompyle6对此感到满意。更有可能的是,有一种非常重要的调用(使用关键字参数,*或**调用),Python 3.6现在创建的字节码与3.5或任何其他先前版本中的字节码非常不同。

pycdc 可能会给出一个答案,它可能会发出CALL_FUNCTION的警告

特别是对于Python 3.6上的 pycdc ,准备进行修复的 lot ,特别是在函数定义和函数调用方面。你可能也必须对uncompyle6做同样的事情,但它可能在语义上更正确。所以修复更多的是关于格式化东西的方式。

uncompyle6在处理Python 3.6时还有很长的路要走,因为Python 3.6彻底改变了调用函数中堆栈条目的语义(这可能是这里的情况)和创建函数。尽管Python 3.6在3.5上做出了巨大的改变,但3.7还有另一个重大变化,所以在此之前还需要一段时间才能使用。 (请参阅下文关于评级以及与我可能在项目上花费多少工作的关系)。

对于CALL_FUNCTION_0 vs {{1}},这是uncompyle6工作方式的工件。它使用无上下文语法分析器来构建程序的解析树。因此,有时会将一些作为指令操作数的信息添加到操作码中,因为解析只是基于操作码。这是use what's on github所描述的,并且描述了uncompyle6如何工作的更大图景here

最后一点,我在github项目中使用评级(或星标)来确定当我有时间处理项目时哪些项目有效。 xasm,xdis的评级可以忽略不计,这部分解释了为什么你会发现它们中的bug。 (当然,另一个原因是缺少时间或某些项目的难度)。

即使uncompyle6与其他(很大程度上已放弃的)Python反编译器相比评级相当低,而这些反编译器已经有一段时间没有工作,并且做得不好。