2016-08-02 26 views
0

Dies ist kein traditioneller Bytecode, sondern zerlegter Bytecode, es wird kein Compiler zum Kompilieren dieses Codes gebaut.Disassemblierten Python-Bytecode zurück in Quellcode konvertieren

Ich habe einen Encoder zum Reverse-Engineering gegeben. Dieser Codierer wurde jedoch zerlegt und in eine für Menschen lesbare Form gebracht. Ich habe den Großteil des Codes so weit zurück in den Quellcode geschrieben, habe aber Probleme mit der vorletzten Zeile, von der ich nicht weiß, wie ich sie in Quellcode umwandeln kann. Nach unzähligen Stunden Suche im Internet nach Hilfe, die ich nicht gefunden habe, bitte ich jemanden um Hilfe, wenn sie Erfahrung beim Lesen von Python-Bytecode, der zerlegt wurde, haben. Was ich bisher haben:

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 

Hier ist die ursprüngliche Info mir in zerlegten Python-Bytecode gegeben:

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   

Jede Hilfe wäre sehr dankbar !!!

+0

Ich betrog Sie zu einer Frage diskutieren, wie die Dekompilierung zu automatisieren. –

+0

Dein Bytecode sieht unvollständig aus, alles von 'def YSag (s, f, i):' und davor ist nicht da? –

+0

Ah, Sie haben die Bestellung durcheinander gebracht; was mit Code-Konstanten in Funktionen geladen wird, die alle ziemlich verwirrend ist, was Abschnitt wo gehört. –

Antwort

2

Sie möchten dies wirklich automatisieren, anstatt dies manuell zu tun; Es gibt einige Tools wie decompyle und uncompyle, die Python-Quellcode aus Bytecode erzeugen können.

Ihr Bytecode von den Codeobjekten ist etwas durcheinander, und uns fehlen die co_argcount und co_varnames Informationen von den Codeobjekten. Aber ich bin ziemlich sicher, dass die Liste Verständnis sein sollte:

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

Der Bytecode

  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 

mit x zu einem Stapel übersetzt, einem Lambda, YSao und YSag von oben nach unten, und CALL_FUNCTION Pässe die ersten 3 in umgekehrter Reihenfolge zum letzten, also YSag(YSao, <lambda>, x) heißt.

Das Lambda von der Leitung 27 geladen wird, und der Bytecode für das heißt:

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

was bedeutet, dass s das Argument zum Lambda (es ist eine lokale loaded mit LOAD_FAST) und x ist ein globales, so übersetzt dies lambda s: s[x].

Beachten Sie, dass CALL_FUNCTION_VAR*args Call-Funktionalität verwendet, so dass Sie die Leitung 9 korrigieren müssen:

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

die max(len(l) for l in YSaW) eine ausführliche Art und Weise der Rechtschreibung erweist, aber mit einer Liste Verständnis erweiterten Argumente statt zu trennen eines Generatorausdrucks, der als einzelnes Argument übergeben wurde.

Ich finde es hilfreich, dis.dis() function zusammen mit compile() zu verwenden, um zu sehen, ob meine Interpretation des Bytecodes korrekt ist; speisen in einem Ausdruck oder Anweisung und die Ausgabe sollte Ihre Bytecode grob entsprechen (mit den Zeilennummern und eine Bytecode-Nummerierung Offset):

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

Für diese letzte Zeile zum Beispiel überprüft ich das Ergebnis mit:

>>> 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 

Für Funktionsobjekte, mögen Sie zuerst, dann den Code Objekt aus einem bestimmten co_consts Eintrag (compile(...).co_code.co_consts[an_index]) oder erstellen Sie die Funktion zum extrahieren der Funktion Objekt dis.dis() passieren:

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

Am Ende haben Sie eine ziemlich schlecht codierte Software, die Zeichen aus einer Datei umwirft. Ich habe die Verschleierung gereinigt und verwendet, um einen bisschen mehr idiomatischen Python zu kommen, was Ich denke, die gleiche Ausgabe:

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) 

so polstert alle gestrippt Linien mit . auf gleiche Länge, Swap-Beginn und das Ende Linien um, dann rotieren Sie jede Spalte im resultierenden Textblock um die Spaltennummer nach oben oder unten (in jeder Spalte) und zeigen Sie den resultierenden Text an.

Ich vermute, die Verwendung von statt eines Platzes ist hier auch nicht wirklich notwendig; Lassen Sie den .replace() Aufruf und str.ljust() verlassen, um den Standardraumfüller zu verwenden, gibt Ihnen im Grunde die gleichen Ergebnisse, aber mit Leerzeichen intakt.

+0

Vielen Dank! Ich werde beginnen, dies sofort zu testen. –