Jump to content
Korean Random
ggivi89

Как защитить *.pyc?

Recommended Posts

Начинаю тока вникать в питон! 
Задался вопросом как защитить файл скрипта! Перерыл весь интернет. единственное, что нашел это obfuscate-0.2.2.tar. Установить получилось, но как пользоваться я не понял так. И вообще то ли это вообще? Воопщем смысл один! Надо, чтоб не декомпилировался .*pyc

ДА и еще по теме: посоветуйте книги по python 2.7 для ракочайника

 

Edited by ggivi89

Share this post


Link to post

Short link
Share on other sites
как защитить файл скрипта!

Посмотрите в теме PjOrion'а, он вроде умеет обфусцировать скрипты.

Так же посмотрите Pyminifier - утилита с хорошей документацией, умеет сжимать и обфусцировать.

 

книги по python 2.7

Много их. Вот, например, на habrahabr.

 

чтоб не декомпилировался .*pyc

Декомпилировать можно всё что угодно. Всё зависит от усилий.

 

P.S. Защита интерпретируемых языков может сильно сказаться на производительности.

Edited by Azbuka_slovensko
  • Upvote 2

Share this post


Link to post

Short link
Share on other sites

Посмотрите в теме PjOrion'а, он вроде умеет обфусцировать скрипты.

Так же посмотрите Pyminifier - утилита с хорошей документацией, умеет сжимать и обфусцировать.

 

Много их. Вот, например, на habrahabr.

 

Декомпилировать можно всё что угодно. Всё зависит от усилий.

 

P.S. Защита интерпретируемых языков может сильно сказаться на производительности.

Спасибо огромное. Я просто декомпилил какой то мод там было так:  # Embedded file name: rfcheats Error: tuple index out of range. B PJ Orion закрыты эти функции... Да и я читаю книгу и примеры испытываю на обычном IDLE (Python GUI).

Обращался к Юше. сказал так: давай мод, я обфусцирую... Но я не согласился ); 

Edited by ggivi89

Share this post


Link to post

Short link
Share on other sites

 

 

Я просто декомпилил какой то мод

Декомпилировать получится мало - большая часть модификаций обфусцирована.

Лучше воспользуйтесь поиском на GitHub'е - там довольно много модификаций, и есть удобные фильтры поиска.

  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

Да тут не зачем. Тут почему! Я так для себя изучаю. 

Share this post


Link to post

Short link
Share on other sites

 

 

Что я не так делаю?

Его нужно запускать из командной строки (Win + R -> Ввести cmd -> Ок)

В открывшемся окне терминала нужно ввести:

python pyminifier <аргументы>

Путь к папке с python и pyminifier должен быть в PATH, иначе нужно указывать полные пути.

Можно, конечно, использовать pyminifier и из python, но для этого нужно ознакомиться с документацией

Share this post


Link to post

Short link
Share on other sites

Его нужно запускать из командной строки (Win + R -> Ввести cmd -> Ок)

В открывшемся окне терминала нужно ввести:

python pyminifier <аргументы>

Путь к папке с python и pyminifier должен быть в PATH, иначе нужно указывать полные пути.

Можно, конечно, использовать pyminifier и из python, но для этого нужно ознакомиться с документацией

примерно так: python pyminifier --obfuscate "C:\4321.py" ???

Share this post


Link to post

Short link
Share on other sites

Именно.

ХМ наверно я что то не то делаю... Код декомпилируется как и прежде

Share this post


Link to post

Short link
Share on other sites
ХМ наверно я что то не то делаю... Код декомпилируется как и прежде

Обфускатор запутывает код, заменяя имена переменных, функций, классов и т.д.

Вот пример из документации:

'Входной файл'

#!/usr/bin/env python
"""
tumult.py - Because everyone needs a little chaos every now and again.
"""

try:
    import demiurgic
except ImportError:
    print("Warning: You're not demiurgic. Actually, I think that's normal.")
try:
    import mystificate
except ImportError:
    print("Warning: Dark voodoo may be unreliable.")

# Globals
ATLAS = False # Nothing holds up the world by default

class Foo(object):
    """
    The Foo class is an abstract flabbergaster that when instantiated
    represents a discrete dextrogyratory inversion of a cattywompus
    octothorp.
    """
    def __init__(self, *args, **kwargs):
        """
        The initialization vector whereby the ineffiably obstreperous
        becomes paramount.
        """
        # TODO.  BTW: What happens if we remove that docstring? :)

    def demiurgic_mystificator(self, dactyl):
        """
        A vainglorious implementation of bedizenment.
        """
        inception = demiurgic.palpitation(dactyl) # Note the imported call
        demarcation = mystificate.dark_voodoo(inception)
        return demarcation

    def test(self, whatever):
        """
        This test method tests the test by testing your patience.
        """
        print(whatever)

if __name__ == "__main__":
    print("Forming...")
    f = Foo("epicaricacy", "perseverate")
    f.test("Codswallop")

'Выходной файл'

$ pyminifier --obfuscate /tmp/tumult.py
#!/usr/bin/env python
T=ImportError
q=print
m=False
O=object
try:
 import demiurgic
except T:
 q("Warning: You're not demiurgic. Actually, I think that's normal.")
try:
 import mystificate
except T:
 q("Warning: Dark voodoo may be unreliable.")
Q=m
class U(O):
 def __init__(self,*args,**kwargs):
  pass
 def B(self,dactyl):
  G=demiurgic.palpitation(dactyl)
  w=mystificate.dark_voodoo(G)
  return w
 def k(self,whatever):
  q(whatever)
if __name__=="__main__":
 q("Forming...")
 f=U("epicaricacy","perseverate")
 f.test("Codswallop")
# Created by pyminifier.py (https://github.com/liftoff/pyminifier

Совершенно очевидно, что выходной файл совершенно невозможно прочитать. Именно для этого и нужен обфускатор.

Для того, чтобы исключить декомпиляцию байт-кода используются коммерческие защитники, совмещающие обфускатор и компилятор защищённого байткода.

Edited by Azbuka_slovensko
  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

 

 

Код декомпилируется как и прежде

 

Недекомпелируемым код сделать невозможно) Возможно только усложнить его декомпиляцию и понимание)

  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

 

 

Недекомпелируемым код сделать невозможно

Есть способы защиты, которые сводятся к тому, что для того, чтобы декомпилировать надо потратить.. год (на самый простой скрипт).

В целом - "недекомпилируемым кодом" можно назвать такой код, затраты на декомпиляцию которого больше чем затраты на создание с нуля оригинального кода (как человеко-часы, так и финансовые).

Для примера http://dropmefiles.com/dYmbg

Исходник:

print 'Hello World!'
LOAD_CONST 'Hello World!'
PRINT_ITEM
PRINT_NEWLINE
LOAD_CONST None
RETURN_VALUE

попытайся декомпилировать..;)

Можно назвать этот скрипт недекомпилируемым?

 

А некоторые защиты основываются на дозагрузке некоторой части скрипта (примерно как это реализовано в варпаке)..

  • Upvote 2

Share this post


Link to post

Short link
Share on other sites

А некоторые защиты основываются на дозагрузке некоторой части скрипта (примерно как это реализовано в варпаке)..

 

+ инжектирование скрипта не питон-методами (ассм,  си, делфи, ... инжектор). Что в реальности и составляет защиту как таковую.

 


@ggivi89, obfuscate-0.2.2.tar - это набор функций для шифрования текста на питоне, к защите или обфускации отношения почти не имеет. Pyminifier - обфусцирует пользовательские имена путем их замены на абракадабру. Это ни как не усложняет декомпиляцию, но вот разобраться в коде будет сложновато. В PjOrion я сейчас работаю над обфускацией и протекцией в ближайшее время буду вводить функциональность по частям. Если хочешь чтобы не декомпилировалось, то надо научиться скрамблировать pyc-скрипт. Это остановит тех, кто знает питон только на уровне правки чужих готовых модов, остальным это не помеха.

 

"Вот небольшой отрывок с моего поста о скрамблировании"

.....Я так понял ты пытался сделать скрамблер от дизассемблера, типа АСМ-петли с мусором внутри. Простой скрамблер сделать не сложно, но надо быть аккуратным с петлями и мусором в них, там главное что бы мусор не смещал точку входу в рабочую инструкцию. Инструкции бывают разной длины, есть те у кого два байта под параметры идет, а есть и больше. Если мусор интерпретируется как многобайтовая инструкция то она может сожрать точку входу.

 

Разберу пример:

 

1. Берем исходный код py-модуля:

 

import sys

s = sys.copyright

print s

 

Он же в dis.dis():

 

  1           0 LOAD_CONST               0 (-1)          0x64

              3 LOAD_CONST               1 (None)        0x64

              6 IMPORT_NAME              0 (sys)         0x6c

              9 STORE_NAME               0 (sys)         0x5a

  2          12 LOAD_NAME                0 (sys)         0x65

             15 LOAD_ATTR                1 (copyright)   0x6a

             18 STORE_NAME               2 (s)           0x5a

  3          21 LOAD_NAME                2 (s)           0x65

             24 PRINT_ITEM                               0x47

             25 PRINT_NEWLINE                            0x48

             26 LOAD_CONST               1 (None)        0x64

             29 RETURN_VALUE                             0x53

 

Он же в HxD программе:

 

64 00 00

64 01 00

6C 00 00

5A 00 00

65 00 00

6A 01 00

5A 02 00

65 02 00

47

48

64 01 00

53 28 02

 

2. Впихиваем в исходный код заготовки для АСМ-петель, например вот такие:

 

if False:

    a = 1

    b = 2

    c = 3

 

код такой заготовки имеет вид:

 

72 1B 00 64 00 00 5A 01 00 64 01 00 5A 02 00 64 02 00 5A 03 00 6E 00 00

 

Пихаем:

 

import sys

if False:

    a = 1

    b = 2

    c = 3

s = sys.copyright

if False:

    a = 1

    b = 2

    c = 3

print s

 

3. Теперь компилим и заполняем петлю мусором. Фокус тут в том, что не надо делать больших петель с огромными кусками мусора - это наоборот облегчает чистку кода, их видно очень хорошо, для блокировки ассмблера достаточно одного ложного кода в петле, но вот этих петель надо наставить побольше и разных - вот тогда чтоб их все убрать в большом исходнике нужно будет повозиться.

 

Имеем dis.dis код:

 

  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 (False)

             15 POP_JUMP_IF_FALSE       39             0x72

  3          18 LOAD_CONST               2 (1)

             21 STORE_NAME               2 (a)

  4          24 LOAD_CONST               3 (2)         ....

             27 STORE_NAME               3 (b)

  5          30 LOAD_CONST               4 (3)

             33 STORE_NAME               4 ©

             36 JUMP_FORWARD             0 (to 39)     0x6e

  6     >>   39 LOAD_NAME                0 (sys)

             42 LOAD_ATTR                5 (copyright)

             45 STORE_NAME               6 (s)

  7          48 LOAD_NAME                1 (False)

             51 POP_JUMP_IF_FALSE       75             0x72

  8          54 LOAD_CONST               2 (1)

             57 STORE_NAME               2 (a)

  9          60 LOAD_CONST               3 (2)

             63 STORE_NAME               3 (b)         ....

10           66 LOAD_CONST               4 (3)

             69 STORE_NAME               4 ©

             72 JUMP_FORWARD             0 (to 75)     0x6e

11     >>    75 LOAD_NAME                6 (s)

             78 PRINT_ITEM         

             79 PRINT_NEWLINE      

             80 LOAD_CONST               1 (None)

 

             83 RETURN_VALUE 

 

а в HxD редакторе вот такой код:

 

64 00 00 64 01 00 6C 00 00 5A 00 00 65 01 00 72 27 00 64 02 00 5A 02 00 64 03 00 5A 03 00 64 04 00 5A 04 00 6E 00 00 65 00 00 6A 05 00 5A 06 00 65 01 00 72 4B 00 64 02 00 5A 02 00 64 03 00 5A 03 00 64 04 00 5A 04 00 6E 00 00 65 06 00 47 48 64 01 00 53 28 05

 

Замусорим некоторые инструкции и их значения, например случайно увеличим/уменьшим на 1, но при этом последнюю инструкцию трогать не будем:

 

64 00 00 64 01 00 6C 00 00 5A 00 00 65 01 00 72 27 00 47 02 01 50 03 01 65 02 FF 5B 02 01 65 03 FF 50 05 00 6E 00 00 65 00 00 6A 05 00 5A 06 00 65 01 00 71 4B 00 64 03 00 5B 01 FF 63 02 01 5B 04 01 64 04 00 5A 04 00 6E 00 00 65 06 00 47 48 64 01 00 53 28 05

 

4. Чтобы петли было тяжелее отследить можно произвольно поменять некоторые джампы с 72 на 71:

JUMP_ABSOLUTE     - 0x71

POP_JUMP_IF_FALSE - 0x72

 

5. Смотрим результат, вот чего выдает dis.dis():

 

  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 (False)

             15 POP_JUMP_IF_FALSE       39

  3          18 PRINT_ITEM         

             19 ROT_TWO            

             20 POP_TOP            

             21 BREAK_LOOP         

             22 ROT_THREE          

             23 POP_TOP            

  4          24 LOAD_NAME            65282

Traceback (most recent call last):

  File "<pyshell#9>", line 1, in <module>

    dis.dis(code)

  File "C:\Python27\lib\dis.py", line 43, in dis

    disassemble(x)

  File "C:\Python27\lib\dis.py", line 97, in disassemble

    print '(' + co.co_names[oparg] + ')',

IndexError: tuple index out of range

 

А вот как выглядит код модуля dis.dis(XXX.co_code):

 

          0 LOAD_CONST          0 (0)

          3 LOAD_CONST          1 (1)

          6 IMPORT_NAME         0 (0)

          9 STORE_NAME          0 (0)

         12 LOAD_NAME           1 (1)

         15 POP_JUMP_IF_FALSE    39

         18 PRINT_ITEM    

         19 ROT_TWO       

         20 POP_TOP       

         21 BREAK_LOOP    

         22 ROT_THREE     

         23 POP_TOP       

         24 LOAD_NAME       65282 (65282)

         27 DELETE_NAME       258 (258)

         30 LOAD_NAME       65283 (65283)

         33 BREAK_LOOP    

         34 ROT_FOUR      

         35 STOP_CODE     

         36 JUMP_FORWARD        0 (to 39)

    >>   39 LOAD_NAME           0 (0)

         42 LOAD_ATTR           5 (5)

         45 STORE_NAME          6 (6)

         48 LOAD_NAME           1 (1)

         51 JUMP_ABSOLUTE       75

         54 LOAD_CONST          3 (3)

         57 DELETE_NAME     65281 (65281)

         60 DUP_TOPX          258

         63 DELETE_NAME       260 (260)

         66 LOAD_CONST          4 (4)

         69 STORE_NAME          4 (4)

         72 JUMP_FORWARD        0 (to 75)

    >>   75 LOAD_NAME           6 (6)

         78 PRINT_ITEM    

         79 PRINT_NEWLINE 

         80 LOAD_CONST          1 (1)

         83 RETURN_VALUE

 

---------------------------------------------------------------------------------------------------

 

Код на выходе будет работоспособен на 100%, а вот дизассемблер на нем загнется.........


 

 

 

Для примера http://dropmefiles.com/dYmbg

 

Это откуда? 

Edited by StranikS_Scan
  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

https://github.com/0vercl0k/stuffz/blob/master/Python's%20internals/wildfire.py

но там ctypes используется (я потому и хотел в Орионе потестить немного). короче в танках этот способ защиты не применим :(

 

Глянул мельком - замена опкодов с расшифровкой на лету?

Share this post


Link to post

Short link
Share on other sites

 

 

Глянул мельком - замена опкодов с расшифровкой на лету?

да, примерно так.

Share this post


Link to post

Short link
Share on other sites

да, примерно так.

 

Ответ спустя полгода. Прям будто с Альфа-Центаврой переписываюсь  :heh:

Share this post


Link to post

Short link
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...