Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Свой обфускатор as3 кода (http://www.flasher.ru/forum/showthread.php?t=181653)

vizgl 28.06.2012 20:25

Свой обфускатор as3 кода
 
Написал свой обфускатор as3 кода.
Используются 2 библиотеки: работа с тегами swf файла as3swf, работа с байтокодом as3abc. Последнюю библиотеку дополнил возможностью сохранять измененный байткод, т.к. она позволяла только получить данные о классах, методах и т.д.
Обфускатор умеет обфусцировать: неймспейсы, классы, переменные, методы, геттеры/сеттеры, и константы.

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

Теперь вылез вот такой случай, например есть такой код:
Код:
Код AS3:

var obj: Object;
function Foo(): void
{
  obj.Foo();
}

Когда мы обфусцируем метод Foo, вместе с ним обфусцируется и свойство Foo у obj, но это не правильно, т.к. это свойство динамическое, то в рантайме вылезет ошибка. Так вот выходом было добавление в анализатор, обработки таких случаев.
Если опкод один из этих GetProperty, SetProperty, CallProperty, CallPropVoid то добавляем в игнорлист его значение. В примере это свойство Foo обьекта obj.
Так все работает, но только если обфусцировать приложения скомпилированное в Flex Sdk, если приложение скомпилированное во Flash, то получается что все, выше перечисленные опкоды, применяются когда класс обращается к своему члену, а не как обращение к динамическому методу обьекта. И получается ни один метод не переименовывается, т.к. находится в игнор листе.

Посоветуйте как это лучше сделать.

Aquahawk 28.06.2012 21:06

офигеть, дайте две! as3abc я так и не полез дописывать сборщик на место. Вы опубликовали или собираетесь ли опубликовать сырцы этого дополнения?
Действительно есть над чем подумать.
А что вы делаете с jmp в коде? все пересчитываете на новые адреса?

vizgl 28.06.2012 21:39

Сам обфускатор открывать не буду, а дописанную либу могу опубликовать. В репозитории последний коммит 2 года назад, не думаю что автор еще собирается поддерживать проект.
На счет jmp, я не заморачивался, автор библиотеки не дописал этот функционал, я тоже не писал. Сам то не использую метки в коде.
К тому же код я не меняю, а только таблицу констант, в таком случае не приходится пересчитывать смещения для меток свича, джампов и т.д.

vizgl 28.06.2012 21:49

Вложений: 1
Вот дополненная библиотека. Еще многое нужно тестировать, т.к. думаю багов полно будет, если изменять само байткод.
Есть еще такая библиотека AS3 Commons Bytecode но она у меня что-то плохо собирала файл обратно.

maxkar 28.06.2012 22:18

Цитата:

Посоветуйте как это лучше сделать.
Вариантов два. Менять все динамические GetProperty, на нужные вам классические getlex и т.п.. Или править имена в GetProperty, etc....

В первом случае придется разбирать либо один вариант GetProperty (если там multiname) или пару getpropertystrict + getproperty (если во втором multinameL). Также придется смотреть на тип obj в динамическом вызове и проверять, есть ли у этого тип соответствующие методы или нет (на этапе анализа, исходя из типов аргументов функции, например). Ну и при выполнении всех условий заменять опкод (или два) на один "строгий" вызов.

Во втором случае все примерно так же. В этом случае одна из констант переименовывается вместе с именем метода/свойства.

Но в исходном подходе "маскирования" свойств есть большая проблема. Как вы обрабатываете multinameL? Пример:
Код AS3:

trace(obj[a==3 ? 'a' : 'b']);

multinameL скорее всего будут, например, при работе со внешним миром (что-то по сети прочитали, распарсили, сложили в map). По идее в качестве значения может быть все, что угодно, и это автоматически запретит переименования везде. Так что нужно определять набор классов, к каким допустимо переименование, а к каким - нет. И при этом учитывать, что запрет переименования в родителе не всегда должен приводить к невозможности переименования в детях (иначе обычный динамический доступ к Object опять убъет все переименования). Это тоже делается, для каждой переменной нужно строить список классов, значения которых могут храниться в этой переменной (не то, что заявлено типами, а то, что туда может придти через program flow).

vizgl 28.06.2012 23:11

Цитата:

Сообщение от maxkar (Сообщение 1086490)
Как вы обрабатываете multinameL? Пример:
Код AS3:

trace(obj[a==3 ? 'a' : 'b']);


Так 'a' и 'b' отметятся как строки и не будут переименованы.

А действительно некоторые опкоды выполняют разные задачи при компиляции flex sdk и в flash ide? Или это я где-то натупил?

maxkar 28.06.2012 23:23

А кто их как строки то отметит? Если бы там было
Код:

trace(a==3 ? obj['a'] : obj['b']);
тогда да.
А мой код эквивалентен
Код:

const tmp : String = a== 3 ? 'a' : 'b';
trace(obj[tmp]);

Вы же, наверное, не все "строки" из пула строк помечаете как невалидные. Но даже это не поможет против multinameL, имена могут быть не в пуле:
Код:

for (var i : int = 0; i < 10; i++)
  trace(obj['field' + i]);

В этом случае у вас в процессе вычисления на стек будет класться значение 'field' + i. Не выполняя выполнения кода (или какого-то сложного анализа) вы просто не узнаете все возможные строки.

Код:

действительно некоторые опкоды выполняют разные задачи при компиляции flex sdk и в flash ide?
Это вряд ли, для этого придется усложнять плеер. А вот то, что одна и та же AS3-конструкция компилируется по-разному flex и flash вполне возможно.

vizgl 28.06.2012 23:35

Цитата:

Сообщение от maxkar (Сообщение 1086497)
А кто их как строки то отметит? Если бы там было
Код:

trace(a==3 ? obj['a'] : obj['b']);
тогда да.

Упс, забыл добавить, что анализируются все опкоды, которые работают со строками:
IntStringIntIntOperation
StringOperation

Ну и multiname операции
GetProperty
SetProperty
CallProperty
CallPropVoid

Так, то все ваши примеры будут работать нормально. Обфускатор уже тестировался на 2 зарелизиных игрушках, просто собирались они под flex sdk. Вот решил обфусцировать свою первую игру на flash и вылезли такие косяки с динамическими свойствами.

wvxvw 28.06.2012 23:50

Я бы шел по такому пути: искал бы только пользовательские классы, не динамические, и переименовывал их свойства тогда когда из кода понятно, что обращаются именно к экземпляру этого класса. То, что обращаются именно к экземпляру нужного класса всегда можно понять в самом месте вызова, так что даже далеко ходить не нужно. Остальное не трогал бы. Самое худшее, что в таком случае может произойти - пользовательский ввод интерпретируется как имя свойства - но от этого вы никак не застрахуетесь, так что прийдется смирится, т.как если какой-нибудь паблик-морозов в коде есть, то таким образом можно даже к приватным свойствам обратиться.

vizgl 28.06.2012 23:58

Цитата:

Сообщение от wvxvw (Сообщение 1086505)
Я бы шел по такому пути: искал бы только пользовательские классы, не динамические

Любой "пользовательский" класс может иметь динамические свойства.

Update: с ключевым словом dynamic


Часовой пояс GMT +4, время: 17:22.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.