Ответ 1
В проекте, над которым я работал, я сделал что-то очень похожее. У вас есть два варианта:
-
Оставьте файлы в их структуре каталогов.
Это, безусловно, более простой вариант, но обеспечивает гораздо более низкий уровень обфускации, поскольку у кого-то достаточно интересного в вашем коде в основном есть копия логической организации файлов.
Злоумышленник может просто красиво распечатать все файлы и переименовать имена запутанных переменных в каждом файле, пока они не поймут, что происходит.
Чтобы сделать это, используйте
fs.readdir
иfs.stat
для рекурсивного перехода по папкам, чтения в каждом .js файле и вывода измененного кода. -
Скомпилировать все в один JS файл.
Это намного сложнее для вас реализовать, но делает жизнь более сложной для злоумышленника, поскольку они больше не имеют преимущества вашей организации проекта.
Ваша основная проблема заключается в согласовании вызовов
require
с файлами, которые больше не существуют (поскольку все сейчас находится в одном файле).Я сделал это, используя Uglify для выполнения статического анализа моего исходного кода, проанализировав AST для вызовов
require
. Затем я загрузил исходный код требуемого файла и повторил.Как только весь код был загружен, я заменил вызовы
require
на вызовы на пользовательскую функцию, завернул каждый исходный код файла в функцию, которая эмулирует как работает система модуля node, а затем искалечил все и скомпилировал его в один файл.Моя пользовательская функция требует большую часть того, что требуется node, за исключением того, что вместо поиска на диске для модуля он ищет функции-обертки.
К сожалению, я не могу поделиться каким-либо кодом для # 2, поскольку он был частью проприетарного проекта, но суть такова:
- Разберите исходный текст в AST, используя
UglifyJS.parse
. -
Используйте
TreeWalker
, чтобы посетить каждый node AST и проверить,node instanceof UglifyJS.AST_Call && node.start.value == 'require'