Основная идея у вас верна: вам нужно частично оценить запрограммировать и предварительно вычислить все постоянные вычисления. В вашем случае постоянные вычисления, представляющие основной интерес, представляют собой шаги конкатенации над значениями, которые не меняются.
Для этого вам понадобится система преобразования программ (PTS). Это инструмент, который будет читать/анализировать исходный код для указанного языка и строить абстрактное синтаксическое дерево, позволять вам задавать преобразования и анализировать AST и запускать их, а затем снова выдавать модифицированный AST как исходный код.
В вашем случае вы, очевидно, хотите, чтобы PTS знал JavaScript из коробки (редко) или готов принять описание JavaScript, а затем прочитать JavaScript (что более типично) в надежде, что вы сможете создать или получить JavaScript. описание легко. [Я создаю PTS с доступными описаниями JavaScript, см. мою биографию].
Имея это в руках, вам необходимо:
- закодируйте анализатор, который проверяет каждую переменную, найденную в выражении, чтобы определить, является ли это выражение константой (например, "wf6"). Чтобы продемонстрировать, что это константа, вам нужно будет найти определение переменной и убедиться, что все значения, используемые в определении переменной, сами по себе являются константами. Если существует более одного определения переменной, возможно, вам придется проверить, что все определения дают одно и то же значение. Вам необходимо проверить наличие побочных эффектов для переменной (например, нет вызовов функций "foo(...,wf6,...)", которые позволили бы изменить значение переменной). Вам нужно беспокоиться о том, существует ли команда eval для достижения такого побочного эффекта [это практически невозможно сделать, поэтому вам часто приходится просто игнорировать eval и предполагать, что они не делают таких вещей]. У многих PTS есть возможность создавать такие анализаторы; некоторые легче, чем другие.
- Для каждой переменной с постоянным значением замените значение этой переменной в коде
- Для каждого подвыражения с постоянным значением после таких замен «сложите» (вычислите) результат этого выражения и подставьте это значение для этого подвыражения и повторяйте до тех пор, пока дальнейшее свертывание невозможно. Очевидно, вы хотите сделать это, по крайней мере, для всех операторов "+". [OP только что изменил свой пример; он захочет сделать это и для "eval" операторов, когда все его операнды постоянны].
- Возможно, вам придется повторить этот процесс, так как свертывание выражения может сделать очевидным, что переменная теперь имеет постоянное значение.
Описанный выше процесс в литературе по компиляторам называется "константным распространением" и является особенностью многих компиляторов.
В вашем случае вы можете ограничить свертывание констант только конкатенацией строк. Однако, если у вас есть адекватный механизм для распространения значений констант, выполнение всех или большинства операций над константами не так сложно. Вам может понадобиться это, чтобы отменить другие обфускации, связанные с константами, так как это похоже на стиль обфускации, используемый в коде, над которым вы работаете.
Вам понадобится специальное правило, которое преобразует
var['string'](args)
в
var.string(args)
как завершающий шаг.
У вас есть еще одна сложность: вы знаете, что у вас есть весь JavaScript, относящийся к созданию переменных с постоянными значениями. На одной веб-странице может быть много включенных фрагментов JavaScript; вам понадобятся все они, чтобы продемонстрировать отсутствие побочных эффектов для переменной. Я предполагаю, что в вашем случае вы уверены, что у вас есть все это.
Что касается создания значений с известными константами, вас может волновать сложный случай: выражение, которое создает постоянные значения из непостоянных операндов. Представьте, что запутанное выражение было:
x=random(); // produce a value between 0 and 1
one=x+(1-x); // not constant by constant propagation, but constant by algebraic relations
teststring['st'[one]+'vu'[one+1]+'bz'[one]+...](4,11)
Вы можете видеть, что он всегда вычисляет «подстроку» как свойство. Вы можете добавить правило преобразования, которое понимает прием, используемый для вычисления единицы, например, правило для каждого алгебраического приема, используемого для вычисления известных констант. К сожалению для вас, существует бесконечное количество алгебраических теорем, которые можно использовать для создания констант; сколько действительно используется в вашем примере бит кода? [Добро пожаловать к проблеме реверс-инжиниринга с умным противником].
Нет, ничего из этого "легкого". Вероятно, именно поэтому был выбран используемый метод запутывания.
person
Ira Baxter
schedule
08.10.2016