Сериализация Proto-buf с обфускацией

Я ищу руководство относительно того, что происходит при использовании сети proto-buf с обфускацией (Dotfuscator). Одна половина проекта - это DLL, а другая - EXE в другом месте, и с помощью proto-buf NET они безупречно обмениваются данными. Пока я не запутаю DLL.

В этот момент P-BN терпит неудачу, не вызывая исключения, возвращая по-разному массив байтов нулевой длины или укороченный, в зависимости от того, с чем я возился. Класс довольно простой (VB):

<ProtoContract(Name:="DMailer")> _
Friend Class DMailer

    Private _Lic As Cert
    Private _Sys As Sys
    Private _LList As List(Of LItem)

    ..
    ..
End Class

Есть 3 свойства, все украшенные ProtoMember для получения / установки составляющих объектов класса. Для краткости вырезано.

Опять же, он отлично работает, пока я не запутываю DLL. Затем Dotfuscator переименовывает каждый из них в null, по-видимому, поскольку все они являются Другом, и это, кажется, подавляет прото-бафф. Если я освобождаю класс от переименования (только имя класса, а не реквизиты / члены), похоже, он снова работает. Имеет смысл, что P-BN сможет действовать только с объектами с собственным именем, хотя, когда его просят сериализовать объект с нулевым именем, кажется, что исключение может быть в порядке.

С другой стороны, большая часть прелести PB-N заключается в независимой сериализации имен .NET, работающих с атрибутами - по крайней мере, как я это понимаю. Но в этом случае он работает только с классами с именами. Я попытался использовать квалификатор или аргумент Name, как показано выше, но безрезультатно - он, по-видимому, не делает того, что я думал.

Итак, мне любопытно, если:

а) ... я в принципе правильно догадался о проблеме

б) ... Есть другой атрибут или флаг, который может облегчить сериализацию объекта с нулевым именем.

c) ... если есть какие-то другие идеи, которые могут помочь.

Если я освобожу все 3 или 4 класса от переименования Dotfuscator (LList еще не реализован, оставив DMailer, Cert и Sys), DLL, похоже, снова заработает - по крайней мере, результат будет правильного размера. Я могу смириться с этим, хотя скрытые имена были бы лучше: Dotfuscator (CE) либо исключает их, либо устанавливает для имен значение Null - похоже, я не могу найти способ заставить их переименовать.

Вместо того, чтобы освобождать от переименования 3 или 4 класса, я рассматриваю одну альтернативу - просто сохранить вывод Serializer для Cert и Sys в виде массивов байтов или строк Base64 в DMailer вместо классов. Затем попросите получателя десериализовать каждый объект индивидуально. Приятно иметь возможность распаковать только одну вещь и получить свои игрушки прямо здесь, как по волшебству.

(много) TIA


person Ňɏssa Pøngjǣrdenlarp    schedule 29.11.2011    source источник


Ответы (2)


Поскольку было несколько всплесков интереса, вот что, похоже, будет работать:

a) Никакая форма отражения не сможет получить список свойств для обфусцированного типа. Я пробовал пройтись по всем типам, чтобы найти те, на которых есть ProtoContract, я смог их найти, но все имена свойств изменены на a, m, b, j, g.

Я также попробовал Me.GetType.GetProperties с тем же результатом.

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

б) Что действительно работает, так это освобождение класса NAME от обфускации. Поскольку PB-N ищет атрибуты ProtoMember для получения данных, вы МОЖЕТЕ скрыть имена свойств / членов, но не имя КЛАССА / типа. Если имя похоже на FederalReserveLogIn, на вашем классе / типе есть "яблочко".

Сначала я добился успеха, сделав следующее:

1) Создайте простой класс для хранения токена свойства и значения. Сохраните все как строку, используя ConvertFromInvariantString. Взяв подсказку от PBN, я использовал для токена целое число:

<ProtoMember(propIndex.Foo)>
Property Foo As String

Перечисление помогает связать все воедино позже. Храните их в Dictionary(Of T, NameValuePair)

2) добавить аксессуары. они могут выполнять преобразование типов за вас:

  Public Sub Add(ByVal Key As T, ByVal value As Object)
        If _col.ContainsKey(Key) Then
            _col.Remove(Key)
        End If

        _col.Add(Key, New TValue(value))

    End Sub

    Public Function GetTItem(Of TT)(key As T) As TT
        If _col.ContainsKey(key) Then
            Return CType(_col(key).TValue, TT)
        Else
            Return Nothing
        End If
    End Function

T - это любой тип ключа, который вы хотите использовать. Целое число дает наименьший результат и по-прежнему позволяет коду подписки использовать Enum. Но это может быть String.

TT - это исходный тип:

myFoo = props.GetTItem(Of Long)(propsEnum.Foo)

3) Откройте внутренний список (словарь) для PBN и бинго, все готово.

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

HTH

person Plutonix    schedule 09.01.2012

Интересно. Признаюсь, я никогда не пробовал этот сценарий, но если вы можете провести меня через свой процесс (или лучше: может быть, предоставьте базовый пример воспроизведения с «запустить это, затем это, затем это: бум»), я с радостью исследую.

Примечание: Name в ProtoContract в основном предназначен для GetProto() использования; он не нужен для основного сериализатора и может быть опущен, чтобы уменьшить вашу уязвимость. Кроме того, protobuf-net не интересует поля , если эти поля не украшены атрибутами, так что это не должно быть проблемой.

Тем не мение! здесь, вероятно, есть обходной путь, который должен работать сейчас; вы можете предварительно сгенерировать dll статической сериализации; например, в отдельной консоли exe (просто как инструмент; мне действительно нужно обернуть это в отдельную утилиту!)

Итак, если вы создаете исполняемый файл консоли, который ссылается на вашу необфусцированную библиотеку и protobuf-net.dll:

var model = RuntimeTypeModel.Create();
model.Add(typeof(DMailer), true); // true means "use the attributes etc"
// and other types needed, etc
model.Compile("MailSerializer", "MailSerializer.dll");

здесь должно быть написано MailSerializer.dll, на которое вы затем можете ссылаться из своего основного кода (в дополнение к protobuf-net) и использовать:

var ser = new MailSerializer(); // our pre-genereated serializer
ser.Serialize(...); // etc

Затем включите MailSerializer.dll в полезные данные обфускации.

(это все зависит от версии 2, кстати)

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

person Marc Gravell    schedule 29.11.2011
comment
Спасибо. Я определенно постараюсь разработать упрощенный способ воспроизведения, а сейчас я хочу попробовать другое ваше предложение. Для тех, кто играет в домашнюю игру, вот версия создания модели на VB: _1 _... хорошо, я не знаю, как работают теги кода в быстрых ответах - person Ňɏssa Pøngjǣrdenlarp; 29.11.2011
comment
@Plutonix Я использовал C # в своем примере исключительно для моей простоты; если бы я попытался написать это на VB, я, вероятно, допустил бы тонкую, но трудно обнаруживаемую ошибку, где, как я уверен, вы можете прочитать C # и легко перевести на VB. Библиотека явно не заботится о языках; p - person Marc Gravell; 29.11.2011
comment
Статическая DLL на самом деле не работает: для того, чтобы она могла сделать DLL, вам нужно сделать все задействованные типы общедоступными, чтобы она могла получить к ним доступ. Но затем во время выполнения он задыхается, если вы не освободите все эти типы от обфускации, иначе вы получите `` Не удалось загрузить тип xxx из сборки '' для любого задействованного класса, перечисления и т. Д. Я предполагаю из сообщения, что они должны оставаться общедоступными И не запутанный (не только для создания статической DLL), что делает нас хуже, чем раньше. хотя спасибо за идею! - person Ňɏssa Pøngjǣrdenlarp; 30.11.2011
comment
@Plutonix Тогда мне нужно будет взглянуть на основную проблему. - person Marc Gravell; 30.11.2011