2013년 10월 27일 일요일

[Python] 파이썬 바이트 코드 디컴파일


컴파일된 pyc가 포함된 zip파일에서 python 코드 디컴파일


문제 출처 :

Hack.lu 2013 [ What's wrong with this?]

- zip file : library.zip
- pyc file : __main__hello__.pyc


  1. >>> import zipimport
  2. >>>
  3. >>> importer = zipimport.zipimporter('library.zip')
  4. >>> code = importer.get_code('__main__hello__')
  5. >>>
  6. >>> print dir(code)
  7. ['__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__','__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars','co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize','co_varnames']
  8. >>> print code.co_names # 사용된 오브젝트 이름
  9. ('sys', 'hashlib', 'sha256', 'dis', 'multiprocessing', 'UserList', 'encrypt_string', 'rot_chr', 'SECRET', 'argv')
  10. >>>
  11. >>> import dis
  12. >>> dis.dis(code)# 파이썬 바이너리 코드를 disassemble함
  13.   1           0 LOAD_CONST               0 (-1)
  14.               3 LOAD_CONST               1 (None)
  15.               6 IMPORT_NAME              0 (sys)
  16.               9 STORE_NAME               0 (sys)
  17.   2          12 LOAD_CONST               0 (-1)
  18.              15 LOAD_CONST               2 (('sha256',))
  19.              18 IMPORT_NAME              1 (hashlib)
  20.              21 IMPORT_FROM              2 (sha256)
  21.              24 STORE_NAME               2 (sha256)
  22.              27 ROT_TWO
  23.   3          28 LOAD_CONST               0 (-1)
  24.              31 LOAD_CONST               1 (None)
  25.              34 IMPORT_NAME              3 (dis)
  26.              37 STORE_NAME               3 (dis)
  27.              40 LOAD_CONST               0 (-1)
  28.              43 LOAD_CONST               1 (None)
  29.              46 IMPORT_NAME              4 (multiprocessing)
  30.              49 STORE_NAME               4 (multiprocessing)
  31.              52 LOAD_CONST               0 (-1)
  32.              55 LOAD_CONST               1 (None)
  33.              58 IMPORT_NAME              5 (UserList)
  34.              61 STORE_NAME               5 (UserList)
  35.   5          64 LOAD_CONST               3 (<code object encrypt_string at 0x7fa62ded7cb0, file "chall.py", line 5>) # 첫번째 함수
  36.              67 MAKE_FUNCTION            0
  37.              70 STORE_NAME               6 (encrypt_string)
  38.  16          73 LOAD_CONST               4 (<code object rot_chr at 0x7fa62dedcb30, file "chall.py", line 16>) # 두번째 함수
  39.              76 MAKE_FUNCTION            0
  40.              79 STORE_NAME               7 (rot_chr)
  41.  19          82 LOAD_CONST               5 ('w*0;CNU[\\gwPWk}3:PWk"#&:ABu/:Hi,M')
  42.              85 STORE_NAME               8 (SECRET)
  43.  20          88 LOAD_NAME                6 (encrypt_string)
  44.              91 LOAD_NAME                0 (sys)
  45.              94 LOAD_ATTR                9 (argv)
  46.              97 LOAD_CONST               6 (1)
  47.             100 BINARY_SUBSCR
  48.             101 CALL_FUNCTION            1
  49.             104 LOAD_NAME                8 (SECRET)
  50.             107 COMPARE_OP               2 (==)
  51.             110 POP_JUMP_IF_FALSE      121
  52.  21         113 LOAD_CONST               7 ('Yup')
  53.             116 PRINT_ITEM
  54.             117 PRINT_NEWLINE
  55.             118 JUMP_FORWARD             5 (to 126)
  56.  23     >>  121 LOAD_CONST               8 ('Nope')
  57.             124 PRINT_ITEM
  58.             125 PRINT_NEWLINE
  59.         >>  126 LOAD_CONST               1 (None)
  60.             129 RETURN_VALUE
  61. >>> print code.co_consts
  62. (-1, None, ('sha256',), <code object encrypt_string at 0x7fa62ded7cb0, file "chall.py", line 5>, <code object rot_chr at 0x7fa62dedcb30, file"chall.py", line 16>, 'w*0;CNU[\\gwPWk}3:PWk"#&:ABu/:Hi,M', 1, 'Yup', 'Nope')
  63. >>> print code.co_consts[3]
  64. <code object encrypt_string at 0x7fa62ded7cb0, file "chall.py", line 5>
  65. >>>
  66. >>> dir(code.co_consts[3])
  67. ['__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__','__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars','co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize','co_varnames']
  68. >>>
  69. >>> print code.co_consts[3].co_code
  70. g}xct|▒E]U\}}|dkrD|jt|d▒▒q|jt|t||d▒▒▒qXdj|▒T
  71. >>> dis.dis(code.co_consts[3].co_code)
  72.           0 BUILD_LIST          0
  73.           3 STORE_FAST          1 (1) # '1' = new_str = []
  74.           6 SETUP_LOOP         99 (to 108) # for
  75.           9 LOAD_GLOBAL         0 (0) # 'global_0' = parameter : s
  76.          12 LOAD_FAST           0 (0) # '0' = s
  77.          15 CALL_FUNCTION       1 # enumerate(s)
  78.          18 GET_ITER
  79.     >>   19 FOR_ITER           85 (to 107)
  80.          22 UNPACK_SEQUENCE     2 # (index, c)
  81.          25 STORE_FAST          2 (2) # '2' = index
  82.          28 STORE_FAST          3 (3) # '3' = c
  83.          31 LOAD_FAST           2 (2) # index
  84.          34 LOAD_CONST          1 (1) # 'const_1' = 0
  85.          37 COMPARE_OP          2 (==) # ( '2' == '1' ) <-> ( index == 1 )
  86.          40 POP_JUMP_IF_FALSE    68
  87.          43 LOAD_FAST           1 (1) # '1' (new_str)
  88.          46 LOAD_ATTR           1 (1) # '1'.'1' (new_str.append)
  89.          49 LOAD_GLOBAL         2 (2) # 'global_2' = 'rot_chr'
  90.          52 LOAD_FAST           3 (3) # 'c'
  91.          55 LOAD_CONST          2 (2) # 'const_2' = 10
  92.          58 CALL_FUNCTION       2 # rot_chr(c, 10)
  93.          61 CALL_FUNCTION       1 # new_str.append(rot_chr(c, 10))
  94.          64 POP_TOP
  95.          65 JUMP_ABSOLUTE      19
  96.     >>   68 LOAD_FAST           1 (1) # '1' (new_str)
  97.          71 LOAD_ATTR           1 (1) # '1'.'1' (new_str.append)
  98.          74 LOAD_GLOBAL         2 (2) # 'global_2' = 'rot_chr'
  99.          77 LOAD_FAST           3 (3) # 'c'
  100.          80 LOAD_GLOBAL         3 (3) # 'global_3' = 'ord'
  101.          83 LOAD_FAST           1 (1) # '1' (new_str)
  102.          86 LOAD_FAST           2 (2) # '2' = index
  103.          89 LOAD_CONST          3 (3) # 'const_2' = 1
  104.          92 BINARY_SUBTRACT  # '2' - 'const_2' <-> index - 1
  105.          93 BINARY_SUBSCR  # new_str[index - 1]
  106.          94 CALL_FUNCTION       1  ord(new_str[index - 1])
  107.          97 CALL_FUNCTION       2  rot_chr(c, ord(new_str[index - 1]))
  108.         100 CALL_FUNCTION       1  new_str.append(rot_chr(c, ord(new_str[index - 1])))
  109.         103 POP_TOP
  110.         104 JUMP_ABSOLUTE      19
  111.     >>  107 POP_BLOCK
  112.     >>  108 LOAD_CONST          4 (4)
  113.         111 LOAD_ATTR           4 (4)
  114.         114 LOAD_FAST           1 (1)
  115.         117 CALL_FUNCTION       1
  116.         120 RETURN_VALUE

<code object encrypt_string at 0x7fa62ded7cb0, file "chall.py", line 5> 디컴파일 결과

  1. def encrypt_string(s):
  2.     new_str = []
  3.     for (index, c) in enumerate(s):
  4.         if (index == 0):
  5.             new_str.append(rot_chr(c,10))
  6.         else:
  7.             new_str.append(rot_chr(c,ord(new_str[index - 1])))
  8.     return ''.join(new_str)

전체 소스 디컴파일 결과

  1. import sys
  2. import dis
  3. import multiprocessing
  4. import UserList
  5. def encrypt_string(s):
  6.     new_str = []
  7.     for (index, c) in enumerate(s):
  8.         if (index == 0):
  9.             new_str.append(rot_chr(c,10))
  10.         else:
  11.             new_str.append(rot_chr(c,ord(new_str[index - 1])))
  12.     return ''.join(new_str)
  13. def rot_chr(c, amount):
  14.     return chr((((ord(c) - 33) + amount) % 94) + 33)
  15. SECRET = 'w*0;CNU[\\gwPWk}3:PWk"#&:ABu/:Hi,M'
  16. if encrypt_string(sys.argv[1]) == SECRET:
  17.     print
  18.     print >>'Yup'
  19. else:
  20.     print
  21.     print >>'Nope'


** key : modified_in7erpreters_are_3vil!!! **


Reference :

http://docs.python.org/2/library/dis.html#python-bytecode-instructions
http://pymotw.com/2/dis/
http://stackoverflow.com/questions/16219245/how-do-you-remove-the-nth-index-of-a-nested-list
-  http://stackoverflow.com/questions/13905741/accessing-class-variables-from-a-list-comprehension-in-the-class-definition

댓글 없음:

댓글 쓰기