Действительно ли исполняемые файлы, созданные с помощью Cython, свободны от исходного кода?
Я прочитал " Создание исполняемого файла в Cython" и ответ BuvinJ на вопрос " Как эффективно запутать код Python?" и хотел бы проверить, действительно ли исходный код, скомпилированный с помощью Cython, "больше не существует" после компиляции. Действительно, популярно мнение, что использование Cython - это способ защиты исходного кода Python, см., Например, статью Защита источников Python с помощью Cython.
Возьмем этот простой пример test.pyx
:
import json, time # this will allow to see what happens when we import a library
print(json.dumps({'key': 'hello world'}))
time.sleep(3)
print(1/0) # division error!
Тогда воспользуемся Cython:
cython test.pyx --embed
Это дает test.c
. Скомпилируем:
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
cl test.c /I C:\Python37\include /link C:\Python37\libs\python37.lib
Оно работает! Он производит 140 КБtest.exe
исполняемый, здорово!
Но в этом ответе Как эффективно запутать код Python? неявно сказано, что эта "компиляция" скроет исходный код. Это не кажется правдой, если ты бежишьtest.exe
, ты увидишь:
Traceback (most recent call last):
File "test.pyx", line 4, in init test
print(1/0) # division error! <-- the source code and even the comments are still there!
ZeroDivisionError: integer division or modulo by zero
что показывает, что исходный код в удобочитаемой форме все еще существует.
Вопрос: Есть ли способ скомпилировать код с помощью Cython, чтобы утверждение "исходный код больше не раскрывается" было верным?
Примечание: я ищу решение, в котором нет ни исходного кода, ни байт-кода (.pyc) (если байт-код / .pyc встроен, восстановить исходный код с помощью uncompyle6 тривиально)
PS: Я вспомнил, что сделал то же наблюдение несколько лет назад, но я больше не мог его найти, после более глубокого исследования вот оно: можно ли декомпилировать файл.dll/.pyd для извлечения исходного кода Python?
1 ответ
Код находится в исходном pyx-файле рядом с вашим exe. Удалите / не распространяйте этот pyx-файл вместе с exe.
Когда вы посмотрите на сгенерированный C-код, вы увидите, почему сообщение об ошибке показывает ваш исполняемый файл:
При появлении ошибки Cython выдаст код, подобный следующему:
__PYX_ERR(0, 11, __pyx_L3_error)
где __PYX_ERR
макрос определяется как:
#define __PYX_ERR(f_index, lineno, Ln_error) \
{ \
__pyx_filename = __pyx_f[f_index]; __pyx_lineno = lineno; __pyx_clineno = __LINE__; goto Ln_error; \
}
и переменная __pyx_f
определяется как
static const char *__pyx_f[] = {
"test.pyx",
"stringsource",
};
В основном __pyx_f[0]
сообщает, где можно найти исходный код. Теперь, когда возникает исключение, (встроенный) интерпретатор Python ищет ваш исходный файл pyx и находит соответствующий код (его можно найти в __Pyx_AddTraceback
который вызывается при возникновении ошибки).
Как только этого pyx-файла нет, исходный исходный код больше не будет известен интерпретатору Python / никому другому. Однако трассировка ошибок по-прежнему будет показывать имена функций и номера строк, но не фрагменты кода.
Полученный исполняемый файл (или расширение, если он создается) не содержит байт-кода (как в файлах pyc) и не может быть декомпилирован с помощью таких инструментов, как uncompyle
: байт-код создается, когда файл py переводится в коды операций Python, которые затем оцениваются в огромном цикле вceval.c
. Тем не менее, для встроенных модулей / модулей cython байт-код не требуется, потому что результирующий код напрямую использует C-API Python, что исключает необходимость иметь / оценивать коды операций - эти модули пропускают интерпретацию, что является причиной их большей скорости. Таким образом, в исполняемом файле не будет байт-кода.
Одно важное замечание: следует убедиться, что компоновщик не включает отладочную информацию (и, следовательно, C-код, в котором содержимое pyx-файла можно найти в виде комментариев). MSVC с/Z7
options является таким примером.
Однако полученный исполняемый файл может быть разобран на ассемблер, а затем сгенерированный C-код может быть подвергнут обратному проектированию - так что, хотя цитонизация подходит для затруднения понимания кода, это не тот инструмент, который позволяет скрывать ключи или алгоритмы безопасности.