将反汇编的Python字节码转换回源代码

时间:2016-08-02 08:15:40

标签: python reverse-engineering bytecode

这不是传统的字节码,而是反汇编的字节码,没有编译器来编译这段代码。

我有一个编码器来进行逆向工程。然而,该编码器被拆卸并以人类可读的形式出现。到目前为止,我已将大部分代码重写为源代码,但遇到了倒数第二行的问题,我不知道如何更改为源代码。经过无数个小时在互联网上寻求我没有找到的帮助,如果他们有阅读已经被拆解的python-bytecode的经验,我会向任何人寻求帮助。 到目前为止我所拥有的:

import sys
YSaM = open
YSam = max
YSaN = len
YSaP = xrange
YSap = sys.argv
YSal = YSaM(sys.argv[1],'r').realines()
YSaW = [l.strip().replace(' ','.') for l in (YSal)]
YSas = YSam([YSaN(l) for l in (YSaW)])  #Missing CALL_FUNCTION_VAR with 0 attributes
YSaO = YSaN(YSaW)
YSak = [l + ('.' * (YSas - YSaN(l))) for l in (YSaW)]
YSaJ = [(s[(YSaN(s)/2):] + s[:(YSaN(s)/2)]) for s in (YSak)]
def YSag(s,f,i):
    YSaw = ''
    if YSaN(s) > YSaO:
        YSaw = YSag(s[:-YSaO],f,i)
    f(s[-YSaO:]) + YSaw
YSao = ''
for x in YSaP(0,YSas):
    YSaL = [l[x] for l in (YSaJ)]
    YSaF = ''.join(YSaL)
    if x%2 == 0:
        YSaF = (YSaF[(x%YSaN(YSaF)):] + YSaF[:(x%YSaN(YSaF))])
    else:
        YSaF = (YSaF[-(x%YSaN(YSaF)):] + YSaF[:-(x%YSaN(YSaF))])
    YSao = YSaF + YSao
YSay = [YSag(YSao,(lambda x: s[x]),x) for x in YSaP(0,YSaO)]
for YSar in (YSay): print YSar

这是在反汇编的python-bytecode中给我的原始信息:

 14           0 LOAD_CONST               1 ('')
              3 STORE_FAST               3 (YSaw)

 15           6 LOAD_GLOBAL              0 (YSaN)
              9 LOAD_FAST                0 (s)
             12 CALL_FUNCTION            1
             15 LOAD_GLOBAL              1 (YSaO)
             18 COMPARE_OP               4 (>)
             21 POP_JUMP_IF_FALSE       50

 16          24 LOAD_GLOBAL              2 (YSag)
             27 LOAD_FAST                0 (s)
             30 LOAD_GLOBAL              1 (YSaO)
             33 UNARY_NEGATIVE      
             34 SLICE+2             
             35 LOAD_FAST                1 (f)
             38 LOAD_FAST                2 (i)
             41 CALL_FUNCTION            3
             44 STORE_FAST               3 (YSaw)
             47 JUMP_FORWARD             0 (to 50)

 17     >>   50 LOAD_FAST                1 (f)
             53 LOAD_FAST                0 (s)
             56 LOAD_GLOBAL              1 (YSaO)
             59 UNARY_NEGATIVE      
             60 SLICE+1             
             61 CALL_FUNCTION            1
             64 LOAD_FAST                3 (YSaw)
             67 BINARY_ADD          
             68 RETURN_VALUE        
 27           0 LOAD_FAST                0 (s)
              3 LOAD_GLOBAL              0 (x)
              6 BINARY_SUBSCR       
              7 RETURN_VALUE        
  1           0 LOAD_CONST               0 (-1)
              3 LOAD_CONST               1 (None)
              6 IMPORT_NAME              0 (sys)
              9 STORE_NAME               0 (sys)

  2          12 LOAD_NAME                1 (open)
             15 STORE_NAME               2 (YSaM)

  3          18 LOAD_NAME                3 (max)
             21 STORE_NAME               4 (YSam)

  4          24 LOAD_NAME                5 (len)
             27 STORE_NAME               6 (YSaN)

  5          30 LOAD_NAME                7 (xrange)
             33 STORE_NAME               8 (YSaP)

  6          36 LOAD_NAME                0 (sys)
             39 LOAD_ATTR                9 (argv)
             42 STORE_NAME              10 (YSap)

  7          45 LOAD_NAME                2 (YSaM)
             48 LOAD_NAME               10 (YSap)
             51 LOAD_CONST               2 (1)
             54 BINARY_SUBSCR       
             55 LOAD_CONST               3 ('r')
             58 CALL_FUNCTION            2
             61 LOAD_ATTR               11 (readlines)
             64 CALL_FUNCTION            0
             67 STORE_NAME              12 (YSal)

  8          70 BUILD_LIST               0
             73 LOAD_NAME               12 (YSal)
             76 GET_ITER            
        >>   77 FOR_ITER                30 (to 110)
             80 STORE_NAME              13 (l)
             83 LOAD_NAME               13 (l)
             86 LOAD_ATTR               14 (strip)
             89 CALL_FUNCTION            0
             92 LOAD_ATTR               15 (replace)
             95 LOAD_CONST               4 (' ')
             98 LOAD_CONST               5 ('.')
            101 CALL_FUNCTION            2
            104 LIST_APPEND              2
            107 JUMP_ABSOLUTE           77
        >>  110 STORE_NAME              16 (YSaW)

  9         113 LOAD_NAME                4 (YSam)
            116 BUILD_LIST               0
            119 LOAD_NAME               16 (YSaW)
            122 GET_ITER            
        >>  123 FOR_ITER                18 (to 144)
            126 STORE_NAME              13 (l)
            129 LOAD_NAME                6 (YSaN)
            132 LOAD_NAME               13 (l)
            135 CALL_FUNCTION            1
            138 LIST_APPEND              2
            141 JUMP_ABSOLUTE          123
        >>  144 CALL_FUNCTION_VAR        0
            147 STORE_NAME              17 (YSas)

 10         150 LOAD_NAME                6 (YSaN)
            153 LOAD_NAME               16 (YSaW)
            156 CALL_FUNCTION            1
            159 STORE_NAME              18 (YSaO)

 11         162 BUILD_LIST               0
            165 LOAD_NAME               16 (YSaW)
            168 GET_ITER            
        >>  169 FOR_ITER                30 (to 202)
            172 STORE_NAME              13 (l)
            175 LOAD_NAME               13 (l)
            178 LOAD_CONST               5 ('.')
            181 LOAD_NAME               17 (YSas)
            184 LOAD_NAME                6 (YSaN)
            187 LOAD_NAME               13 (l)
            190 CALL_FUNCTION            1
            193 BINARY_SUBTRACT     
            194 BINARY_MULTIPLY     
            195 BINARY_ADD          
            196 LIST_APPEND              2
            199 JUMP_ABSOLUTE          169
        >>  202 STORE_NAME              19 (YSak)

 12         205 BUILD_LIST               0
            208 LOAD_NAME               19 (YSak)
            211 GET_ITER            
        >>  212 FOR_ITER                44 (to 259)
            215 STORE_NAME              20 (s)
            218 LOAD_NAME               20 (s)
            221 LOAD_NAME                6 (YSaN)
            224 LOAD_NAME               20 (s)
            227 CALL_FUNCTION            1
            230 LOAD_CONST               6 (2)
            233 BINARY_DIVIDE       
            234 SLICE+1             
            235 LOAD_NAME               20 (s)
            238 LOAD_NAME                6 (YSaN)
            241 LOAD_NAME               20 (s)
            244 CALL_FUNCTION            1
            247 LOAD_CONST               6 (2)
            250 BINARY_DIVIDE       
            251 SLICE+2             
            252 BINARY_ADD          
            253 LIST_APPEND              2
            256 JUMP_ABSOLUTE          212
        >>  259 STORE_NAME              21 (YSaJ)

 13         262 LOAD_CONST               7 (<code object YSag at 0x7f7ca5faa930, file "./slither_encode_obfu_min.py", line 13>)
            265 MAKE_FUNCTION            0
            268 STORE_NAME              22 (YSag)

 18         271 LOAD_CONST               8 ('')
            274 STORE_NAME              23 (YSao)

 19         277 SETUP_LOOP             174 (to 454)
            280 LOAD_NAME                8 (YSaP)
            283 LOAD_CONST               9 (0)
            286 LOAD_NAME               17 (YSas)
            289 CALL_FUNCTION            2
            292 GET_ITER            
        >>  293 FOR_ITER               157 (to 453)
            296 STORE_NAME              24 (x)

 20         299 BUILD_LIST               0
            302 LOAD_NAME               21 (YSaJ)
            305 GET_ITER            
        >>  306 FOR_ITER                16 (to 325)
            309 STORE_NAME              13 (l)
            312 LOAD_NAME               13 (l)
            315 LOAD_NAME               24 (x)
            318 BINARY_SUBSCR       
            319 LIST_APPEND              2
            322 JUMP_ABSOLUTE          306
        >>  325 STORE_NAME              25 (YSaL)

 21         328 LOAD_CONST               8 ('')
            331 LOAD_ATTR               26 (join)
            334 LOAD_NAME               25 (YSaL)
            337 CALL_FUNCTION            1
            340 STORE_NAME              27 (YSaF)

 22         343 LOAD_NAME               24 (x)
            346 LOAD_CONST               6 (2)
            349 BINARY_MODULO       
            350 LOAD_CONST               9 (0)
            353 COMPARE_OP               2 (==)
            356 POP_JUMP_IF_FALSE      400

 23         359 LOAD_NAME               27 (YSaF)
            362 LOAD_NAME               24 (x)
            365 LOAD_NAME                6 (YSaN)
            368 LOAD_NAME               27 (YSaF)
            371 CALL_FUNCTION            1
            374 BINARY_MODULO       
            375 SLICE+1             
            376 LOAD_NAME               27 (YSaF)
            379 LOAD_NAME               24 (x)
            382 LOAD_NAME                6 (YSaN)
            385 LOAD_NAME               27 (YSaF)
            388 CALL_FUNCTION            1
            391 BINARY_MODULO       
            392 SLICE+2             
            393 BINARY_ADD          
            394 STORE_NAME              27 (YSaF)
            397 JUMP_FORWARD            40 (to 440)

 25     >>  400 LOAD_NAME               27 (YSaF)
            403 LOAD_NAME               24 (x)
            406 LOAD_NAME                6 (YSaN)
            409 LOAD_NAME               27 (YSaF)
            412 CALL_FUNCTION            1
            415 BINARY_MODULO       
            416 UNARY_NEGATIVE      
            417 SLICE+1             
            418 LOAD_NAME               27 (YSaF)
            421 LOAD_NAME               24 (x)
            424 LOAD_NAME                6 (YSaN)
            427 LOAD_NAME               27 (YSaF)
            430 CALL_FUNCTION            1
            433 BINARY_MODULO       
            434 UNARY_NEGATIVE      
            435 SLICE+2             
            436 BINARY_ADD          
            437 STORE_NAME              27 (YSaF)

 26     >>  440 LOAD_NAME               27 (YSaF)
            443 LOAD_NAME               23 (YSao)
            446 BINARY_ADD          
            447 STORE_NAME              23 (YSao)
            450 JUMP_ABSOLUTE          293
        >>  453 POP_BLOCK           

 27     >>  454 BUILD_LIST               0
            457 LOAD_NAME                8 (YSaP)
            460 LOAD_CONST               9 (0)
            463 LOAD_NAME               18 (YSaO)
            466 CALL_FUNCTION            2
            469 GET_ITER            
        >>  470 FOR_ITER                27 (to 500)
            473 STORE_NAME              24 (x)
            476 LOAD_NAME               22 (YSag)
            479 LOAD_NAME               23 (YSao)
            482 LOAD_CONST              10 (<code object <lambda> at 0x7f7ca5faf2b0, file "./slither_encode_obfu_min.py", line 27>)
            485 MAKE_FUNCTION            0
            488 LOAD_NAME               24 (x)
            491 CALL_FUNCTION            3
            494 LIST_APPEND              2
            497 JUMP_ABSOLUTE          470
        >>  500 STORE_NAME              28 (YSay)

 28         503 SETUP_LOOP              19 (to 525)
            506 LOAD_NAME               28 (YSay)
            509 GET_ITER            
        >>  510 FOR_ITER                11 (to 524)
            513 STORE_NAME              29 (YSar)
            516 LOAD_NAME               29 (YSar)
            519 PRINT_ITEM          
            520 PRINT_NEWLINE       
            521 JUMP_ABSOLUTE          510
        >>  524 POP_BLOCK           
        >>  525 LOAD_CONST               1 (None)
            528 RETURN_VALUE        

任何帮助都将非常感谢!!!

1 个答案:

答案 0 :(得分:2)

你真的想要自动化,而不是手工完成;有一些工具,如decompyleuncompyle,可以从字节码生成Python源代码。

来自代码对象的字节码有些混乱,我们错过了代码对象中的co_argcountco_varnames信息。但是,我非常确定列表理解应该是:

YSay = [YSag(YSao, lambda s: s[x], x) for x in YSaP(0, YSaO)]

字节码

            476 LOAD_NAME               22 (YSag)
            479 LOAD_NAME               23 (YSao)
            482 LOAD_CONST              10 (<code object <lambda> at 0x7f7ca5faf2b0, file "./slither_encode_obfu_min.py", line 27>)
            485 MAKE_FUNCTION            0
            488 LOAD_NAME               24 (x)
            491 CALL_FUNCTION            3

从上到下转换为包含x,lambda,YSaoYSag的堆栈,CALL_FUNCTION以相反的顺序将前3个传递到最后一个,所以YSag(YSao, <lambda>, x)被称为。{/ p>

lambda从第27行加载,其字节码为:

 27           0 LOAD_FAST                0 (s)
              3 LOAD_GLOBAL              0 (x)
              6 BINARY_SUBSCR       
              7 RETURN_VALUE        

这意味着s是lambda的参数(它本地加载了LOAD_FAST),而x是全局的,所以这转换为lambda s: s[x]

请注意,CALL_FUNCTION_VAR使用*args来电功能,因此您需要将第9行更正为:

YSas = YSam(*[YSaN(l) for l in YSaW])

结果证明是拼写max(len(l) for l in YSaW)的冗长方式,但是列表推导扩展为单独的参数而不是作为单个参数传入的生成器表达式。

我发现将dis.dis() functioncompile()一起使用可以看看我对字节码的解释是否正确;提供表达式或语句,输出应大致匹配您的字节码(行号和字节码编号偏移量):

from dis import dis
dis(compile(string, '', 'exec'))

例如,对于最后一行,我用以下结果验证了结果:

>>> dis(compile('YSas = YSam(*[YSaN(l) for l in YSaW])', '', 'exec'))
  1           0 LOAD_NAME                0 (YSam)
              3 BUILD_LIST               0
              6 LOAD_NAME                1 (YSaW)
              9 GET_ITER
        >>   10 FOR_ITER                18 (to 31)
             13 STORE_NAME               2 (l)
             16 LOAD_NAME                3 (YSaN)
             19 LOAD_NAME                2 (l)
             22 CALL_FUNCTION            1
             25 LIST_APPEND              2
             28 JUMP_ABSOLUTE           10
        >>   31 CALL_FUNCTION_VAR        0
             34 STORE_NAME               4 (YSas)
             37 LOAD_CONST               0 (None)
             40 RETURN_VALUE

对于函数对象,您希望从给定的co_consts条目(compile(...).co_code.co_consts[an_index])中提取代码对象,或者首先创建函数,然后将函数对象传递给dis.dis()

>>> dis(lambda s: s[x])
  1           0 LOAD_FAST                0 (s)
              3 LOAD_GLOBAL              0 (x)
              6 BINARY_SUBSCR
              7 RETURN_VALUE

最后,你有一个编码很差的软件,它会从文件中混淆字符。我已经清理了混淆并使用了一些惯用的Python来实现我认为产生相同输出的东西:

import sys

def rotn(s, n): return s[n:] + s[:n]

with open(sys.argv[1]) as inf:
    lines = [l.strip().replace(' ', '.') for l in inf]

maxlength = max(len(l) for l in lines)
padded = (l.ljust(maxlength, '.') for l in lines)
swapped = [rotn(s, len(s) // 2) for s in padded]

cols = []
for x, col in enumerate(zip(*swapped)):
    offset = (x % len(col)) * (-1 if x % 2 else 1)
    cols.append(rotn(col, offset))

for row in zip(*cols):
    print ''.join(row)

因此将.的所有剥离线填充到相同的长度,交换开始和结束的行,然后在结果中向上或向下旋转生成的文本块中的每个数字(每列交换方向),然后显示结果文本。

我怀疑在这里也不一定需要使用'.'代替空格;放弃.replace()调用并让str.ljust()使用默认空格填充为您提供基本相同的结果,但空格保持不变。