Jump to content
Korean Random
IzeBerg

Как и чем декомпилировать/компилировать питон?

Recommended Posts

Защита 5-го поколения была готова уже тогда когда выкладывалась 1.

Вспомню пароль к архиву- выложу головоломочку. ^_^

 

Не удивлюсь если у вас их там 50 :)))

Мне так думается то что я видел ранее это только верхушка айсберга :))))

Share this post


Link to post

Short link
Share on other sites

 

 

Не взламываются только те защиты, взлом которых не оправдывает ни средств ни денег ни времени, которые надо потратить на это :))))))

"Золотые слова, Юрий Венедиктович" (с) НашаRussia

Защита считается надежной, если информация, которую она защищает, стоит дешевле самого преодоления защиты.... примерно так нас учили на криптографии....

Share this post


Link to post

Short link
Share on other sites

Я рад что на посты аж сам папа mercger сия скрипта пришёл ))))

Эвана как мелочи людей собирают :awsm:

 

Но что то мне ноё Шестое чувство подсказывает что mercger и dell один человек .

И всё равно спасибо за такую сложную задачу .

Edited by o-0-0-0

Share this post


Link to post

Short link
Share on other sites

Я рад что на посты аж сам папа mercger сия скрипта пришёл ))))

Эвана как мелочи людей собирают :awsm:

 

Но что то мне ноё Шестое чувство подсказывает что mercger и dell один человек .

И всё равно спасибо за такую сложную задачу .

Уверяю, не один. Dellux эмо, а  mercger - троль-параноик )

Share this post


Link to post

Short link
Share on other sites

 

в папке bytes выполни

python comp_map.py

Тоже попытался скомпилировать pycdc (в VS 2012). Вышеизложенную ошибку исправил, но появилась другая:

bytecode.obj : error LNK2019: ссылка на неразрешенный внешний символ "int __cdecl python_34_map(int)" (?python_34_map@@YAHH@Z) в функции "int __cdecl Pyc::ByteToOpcode(int,int,int)" (?ByteToOpcode@Pyc@@YAHHHH@Z)
pycdc.exe : fatal error LNK1120: неразрешенных внешних элементов: 1

Подскажите, как исправить?

 

Added: О, кажется, построил. Нужно было в проект добавить python_34_map

 

Где-то уже была тема по декомпиляторам питона в разделе, но не могу найти) Вот декомпиляторы Python которые удалось вспомнить. 

 

https://github.com/Mysterie/uncompyle2

https://code.google.com/p/unpyc3/

https://github.com/gstarnberger/uncompyle

https://code.google.com/p/unpyc/

unpyc3 при попытке запуска выдает: post-21522-0-29088200-1396171683_thumb.jpg

 

А pycdc почему-то каждый раз пишет: stack history is not empty, хотя декомпилит более-менее нормально

 

Ну ёмаё, decompyle++ тоже не хочет ставиться. Поставил MinGW, MSVC 2008 и добавил соотвествующий distutils.cfg. Выдаёт при установке (python setup.py install): unrecognized command line option '-mno-cygwin'

Edited by Ololosha

Share this post


Link to post

Short link
Share on other sites

@Ololosha, надоело читать :)))), ловите, там и ункомпил2 и декомпил++ - Easy Python Decompiler

 

ЗЫ: И напоминаю, декорированные и скрамблированные скрипты они не декомпильнут.

Edited by StranikS_Scan

Share this post


Link to post

Short link
Share on other sites

@Ololosha, надоело читать :)))), ловите, там и ункомпил2 и декомпил++ - Easy Python Decompiler

 

ЗЫ: И напоминаю, декорированные и скрамблированные скрипты они не декомпильнут.

Да, это у меня есть. Просто, во-первых, хотелось бы оригинальным софтом пользоваться, а не сборками, во-вторых, разобраться бы почему unpyc3 и decompyle++ не хотят работать. У кого-то же работают?

Share this post


Link to post

Short link
Share on other sites

unpyc3 при попытке запуска выдает

Вроде, он для 3-го питона...

 

decompyle++ тоже не хочет ставиться. [ ... ] Выдаёт при установке (python setup.py install): unrecognized command line option '-mno-cygwin'

Посмотрите здесь, может поможет.
  • Upvote 1

Share this post


Link to post

Short link
Share on other sites

уф. после выходных только руки вот дошли... чтож посмотрим...
1. Взглянем внутрь.

'имена модуля'


co_names :
0: BigWorld 1: safeCall 2: stfu 3: sys 4: marshal 5: _getframe
6: f_code 7: join 8: list 9: reversed 10: zip
11: co_code 12: bin 13: ord 14: rjust 15: chr
16: int 17: loads 18: globals

co_varnames: ('sys', 'marshal', 'code', 'zipdata', 'xordata', 'co_code')

до боли знакомо все.... для пущей уверенности глянем внутрь

'собственно код'


0: [121] SETUP_EXCEPT (20)
3: [101] LOAD_NAME (0) (BigWorld)
6: [106] LOAD_ATTR (1) (safeCall)
9: [101] LOAD_NAME (2) (stfu)
12: [131] CALL_FUNCTION (0)
15: [131] CALL_FUNCTION (1)
18: [1] POP_TOP
19: [87] POP_BLOCK
20: [110] JUMP_FORWARD (46)
23: [1] POP_TOP
24: [1] POP_TOP
25: [1] POP_TOP
26: [100] LOAD_CONST (1) (-1)
29: [100] LOAD_CONST (0) (None)
32: [108] IMPORT_NAME (3) (sys)
35: [125] STORE_FAST (0) (sys)
38: [100] LOAD_CONST (1) (-1)
41: [100] LOAD_CONST (0) (None)
44: [108] IMPORT_NAME (4) (marshal)
47: [125] STORE_FAST (1) (marshal)
50: [124] LOAD_FAST (0) (sys)
53: [106] LOAD_ATTR (5) (_getframe)
56: [131] CALL_FUNCTION (0)
59: [106] LOAD_ATTR (6) (f_code)
62: [125] STORE_FAST (2) (code)
65: [110] JUMP_FORWARD (1)
68: [88] END_FINALLY
69: [100] LOAD_CONST (2) ()
72: [106] LOAD_ATTR (7) (join)
75: [103] BUILD_LIST (0)
78: [101] LOAD_NAME (8) (list)
81: [101] LOAD_NAME (9) (reversed)
84: [101] LOAD_NAME (10) (zip)
87: [101] LOAD_NAME (8) (list)
90: [101] LOAD_NAME (9) (reversed)
93: [101] LOAD_NAME (10) (zip)
96: [103] BUILD_LIST (0)
99: [124] LOAD_FAST (2) (code)
102: [106] LOAD_ATTR (11) (co_code)
105: [68] GET_ITER
106: [93] FOR_ITER (40)
109: [125] STORE_FAST (3) (zipdata)
112: [101] LOAD_NAME (12) (bin)
115: [101] LOAD_NAME (13) (ord)
118: [124] LOAD_FAST (3) (zipdata)
121: [131] CALL_FUNCTION (1)
124: [131] CALL_FUNCTION (1)
127: [100] LOAD_CONST (3) (2)
130: [31] SLICE+1
131: [106] LOAD_ATTR (14) (rjust)
134: [100] LOAD_CONST (4) (8)
137: [100] LOAD_CONST (5) (0)
140: [131] CALL_FUNCTION (2)
143: [94] LIST_APPEND (2)
146: [113] JUMP_ABSOLUTE (106)
149: [140] CALL_FUNCTION_VAR (0)
152: [131] CALL_FUNCTION (1)
155: [131] CALL_FUNCTION (1)
158: [140] CALL_FUNCTION_VAR (0)
161: [131] CALL_FUNCTION (1)
164: [131] CALL_FUNCTION (1)
167: [68] GET_ITER
168: [93] FOR_ITER (42)
171: [125] STORE_FAST (4) (xordata)
174: [101] LOAD_NAME (15) (chr)
177: [101] LOAD_NAME (16) (int)
180: [100] LOAD_CONST (2) ()
183: [106] LOAD_ATTR (7) (join)
186: [101] LOAD_NAME (8) (list)
189: [124] LOAD_FAST (4) (xordata)
192: [131] CALL_FUNCTION (1)
195: [131] CALL_FUNCTION (1)
198: [100] LOAD_CONST (3) (2)
201: [131] CALL_FUNCTION (2)
204: [131] CALL_FUNCTION (1)
207: [94] LIST_APPEND (2)
210: [113] JUMP_ABSOLUTE (168)
213: [131] CALL_FUNCTION (1)
216: [125] STORE_FAST (5) (co_code)
219: [124] LOAD_FAST (1) (marshal)
222: [106] LOAD_ATTR (17) (loads)
225: [124] LOAD_FAST (5) (co_code)
228: [131] CALL_FUNCTION (1)
231: [125] STORE_FAST (2) (code)
234: [124] LOAD_FAST (2) (code)
237: [101] LOAD_NAME (18) (globals)
240: [131] CALL_FUNCTION (0)
243: [4] DUP_TOP
244: [85] EXEC_STMT
245: [126] DELETE_FAST (2)
248: [126] DELETE_FAST (5)
251: [100] LOAD_CONST (0) (None)
254: [83] RETURN_VALUE

в загрузчике ничего не изменилось...

суть вот он...
''.join([ chr(int(''.join(list(xordata)), 2)) for xordata in list(reversed(zip(*list(reversed(zip(*[ bin(ord(zipdata))[2:].rjust(8, '0') for zipdata in code_obj.co_code ])))))) ])

2. убираем загрузчик.
Ну чтож, лезем дальше... распакуем модуль. Собственно распаковщик прост как пять копеек.
def encode_file(filename):

    enc_file = filename+'.pyc'
    dec_file = 'enc_'+filename+'.pyc'

    enc_reader = open (enc_file,'rb')
    dec_writer = open (dec_file,'wb')

    magic_and_mod = enc_reader.read(8)
    dec_writer.write(magic_and_mod)

    code_obj = marshal.load(enc_reader)

    codeline = ''.join([chr(int(''.join(list(x)),2)) for x in list(reversed(zip(*list(reversed(zip(*[bin(ord(x))[2:].rjust(8,'0') for x in code_obj.co_code]))))))])
   
    decoded_codeobj = marshal.loads(codeline)
    и.т.д.....
   
3. глядим внутрь распакованного модуля
имена переменных зашифрованы либо приведены к ничитаемому виду, питону все равно, а хуману читать не очень

'Имена переменных'


0: os
1: time
2: bb1c2e9ba0
3: 8fe1baabbe
4: c90f4dcd7d
5: Node
6: dc54dc9fb7
7: a04ee827ef
8: 64dae64cfc
9: 53e3840af0
10: hasattr
и локальных тоже
co_varnames ('a8dfd', '4bba2', '5c34a', '8635c', '1c838', '30626', '276d7', 'e8b00', '7f5c7', 'ec8f4', '386dd')

оставим их на потом...

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

'список переходов по которым прошлась функция'


0: [113] JUMP_ABSOLUTE (258)
258: [113] JUMP_ABSOLUTE (151)
151: [113] JUMP_ABSOLUTE (42)
42: [113] JUMP_ABSOLUTE (363)
363: [113] JUMP_ABSOLUTE (271)
271: [113] JUMP_ABSOLUTE (49)
49: [113] JUMP_ABSOLUTE (324)
324: [113] JUMP_ABSOLUTE (198)
198: [113] JUMP_ABSOLUTE (478)
478: [113] JUMP_ABSOLUTE (183)
183: [113] JUMP_ABSOLUTE (490)
490: [113] JUMP_ABSOLUTE (229)

а начало кода собственно тут....

'кусочек начала кода'


229: [100] LOAD_CONST (1) (-1)
232: [100] LOAD_CONST (0) (None)
235: [108] IMPORT_NAME (0) (os)
238: [113] JUMP_ABSOLUTE (265)
*****241: [151] ERROR (31087)

265: [90] STORE_NAME (0) (os)
268: [113] JUMP_ABSOLUTE (274)
*****271: [113] JUMP_ABSOLUTE (49)

274: [100] LOAD_CONST (1) (-1)
277: [100] LOAD_CONST (0) (None)
280: [108] IMPORT_NAME (1) (time)
283: [90] STORE_NAME (1) (time)
286: [100] LOAD_CONST (2) (Sides)
289: [102] BUILD_TUPLE (0)
292: [100] LOAD_CONST (3) (<code object bb1c2e9ba0 at 0000000002C18C30, file "brainfuck.py", line 5>)
295: [132] MAKE_FUNCTION (0)
298: [131] CALL_FUNCTION (0)
301: [89] BUILD_CLASS
302: [90] STORE_NAME (2) (bb1c2e9ba0)
305: [101] LOAD_NAME (2) (bb1c2e9ba0)
308: [106] LOAD_ATTR (3) (8fe1baabbe)
311: [100] LOAD_CONST (4) (128)
314: [131] CALL_FUNCTION (1)
317: [1] POP_TOP



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

'Чистка от левых джампов'


0: [100] LOAD_CONST (1) (-1)
3: [100] LOAD_CONST (0) (None)
6: [108] IMPORT_NAME (0) (os)
9: [90] STORE_NAME (0) (os)
12: [100] LOAD_CONST (1) (-1)
15: [100] LOAD_CONST (0) (None)
18: [108] IMPORT_NAME (1) (time)
21: [90] STORE_NAME (1) (time)
24: [100] LOAD_CONST (2) (Sides)
27: [102] BUILD_TUPLE (0)
30: [100] LOAD_CONST (3) (<code object bb1c2e9ba0 at 0000000002C18C30, file "brainfuck.py", line 5>)
33: [132] MAKE_FUNCTION (0)
36: [131] CALL_FUNCTION (0)
39: [89] BUILD_CLASS
40: [90] STORE_NAME (2) (bb1c2e9ba0)
43: [101] LOAD_NAME (2) (bb1c2e9ba0)
46: [106] LOAD_ATTR (3) (8fe1baabbe)
49: [100] LOAD_CONST (4) (128)
52: [131] CALL_FUNCTION (1)
55: [1] POP_TOP
56: [100] LOAD_CONST (5) (0)
59: [90] STORE_NAME (4) (c90f4dcd7d)
62: [100] LOAD_CONST (6) (Node)

аналогично проходим по всем кодеобжектам
При попытке декомпилировать брякаемся из за съехавших относительных переходов

добавим в код функцию для их корректировки....  но об этом в следующий раз если кому то интересно

  • Upvote 5

Share this post


Link to post

Short link
Share on other sites

А чего мой скриптик до сих пор не разобрали то ? :(

 

Дык ты обещал новое, а выложил защиту третьего поколения (по моей классификации, см. выше), я такое уже видел:

- переопределением функции loads в маршале извлекаем внутренний код модуля и обходим верхний слой маскировки (вообще убери маршал оттуда нафиг, а то от внешнего слоя маскировки толку как от защиты 0);

- затем пишем скрипт для занупливания мусора (в каждом "настоящем" :))) блоке кода есть опкод выхода RETURN, вот его находим и от него начинаем реверс кода, прыгаем при этом по джампам в обратную сторону, все строки по которым мы проходимся, отмечаем как валидные, когда проход по всему блока заканчивается, берем смотрим какие строки остались невалидными и вот их то и занупливаем)

- с "ненастоящими" блоками кода, а такие есть, у них точка входа джампит в даль за блоком, RETURN вообще нет, можно поступать по разному...

- ну и всё дальше берем pyRETEC и реверсируем то что получили.

 

Может именно в этом коде какие-то нюансы и появились, но я не стал время тратить на полную распаковку.... И да именно так эта защита и работает - алгоритм понять легко, а вот писать скрипты на распаковку лень. В результате цель разработчика защита достигнута.

 

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

 

ЗЫ: И да, таки обфускацию я увидел - замена имен переменных на прочти -и-вырви-глаз :)))) Ну оно и правильно, в реальности это единственная форма обфускация, которая реально создает проблемы. Попробуй перепиши код с 50 нечитабельными переменными на читабельные, только вручную и только с вниканием в код программы... :)) 

По поводу легко снимающегося декорирующего верхнего слоя. Вот один из моих вариантов декорации с эффектом ложного реверса без использования маршала. Байт-код не скрамблирован ;)

 

Hello.zip

 

Ковыряйте :)))

 

Edited by StranikS_Scan

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

Молодцы :)

Да, основная ставка идет на нечитабельность. Полиморфность реализовать можно, но в любом случае, все это лишь вопрос времени, и стоит ли оно профита.

Исходники лучше не выкладывать- пусть у других тоже будет шанс покумекать, а то будут тупо бегать по форумам и искать очередную версию готовой тулзы ^_^

 

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

 

Базовая обфускация с потерей информации - в 1000 раз эффективнее любого суперсложного, но 100%-реверсируемого алгоритма :))))

Share this post


Link to post

Short link
Share on other sites

может это поможет

 

ункомпил2 - это понятно , а что делает декомпил++ ? какое та не нужная вещь .

Share this post


Link to post

Short link
Share on other sites

Завидую Вам всем "белой завистью" ;) Приятно, когда осознаешь, что на этом форуме собираются истинные профессионалы в программировании!

Share this post


Link to post

Short link
Share on other sites

Завидую Вам всем "белой завистью" ;) Приятно, когда осознаешь, что на этом форуме собираются истинные профессионалы в программировании!

 

Вот кому надо завидовать или не надо, смотря как посмотреть:

 

bomzhe с forum.ru-board.com

Восстановлено через python + HxD + uncompyle2.

Я под столом лежал, правка мусора и петель через HxD - чел неделю ковырялся походу, либо просто прикалывается :))))

Share this post


Link to post

Short link
Share on other sites

 

 

Я под столом лежал, правка мусора и петель через HxD - чел неделю ковырялся походу, либо просто прикалывается :))))

Идейный человек с морем терпения - из-за таких войну выиграли!

Share this post


Link to post

Short link
Share on other sites

   Hello.zip   1,3 Кб   15 раз скачано   Ковыряйте :)))

def foo():

    def _print(text):
        print text

    var1 = 'Hello1'
    var2 = 'Hello2Hello1Hello1Hello1'
    var3 = var1 + var2
    print var1
    print var2
    _print(var3)


foo()

too easy :)

Share this post


Link to post

Short link
Share on other sites

too easy :)

 

Ну это лучше чем загрузчик с выходом на маршал в конце алгоритма. Переопределяем функцию маршала и перехватываем код. Вот это реально просто, проще этого только ZipBase64-обертка c выходом на exec :))))

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