Сериализация протобуфа с обфускацией - PullRequest
3 голосов
/ 29 ноября 2011

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

В этот момент P-BN завершается неудачно, не вызывая исключения, возвращая по-разному байтовый массив длиной 0 или ракурс в зависимости от того, с чем я возился. Класс довольно прост (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 переименовывает каждый из них в ноль, по-видимому, так как все они Friend, и это, кажется, душит прото-бафф. Если я освобождаю класс от переименования (только имя класса, а не реквизиты / члены), он снова работает. Имеет смысл, что P-BN сможет работать только с объектами с правильным именем, хотя при запросе сериализации объекта с нулевым именем кажется, что исключение может быть в порядке.

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

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

а) ... Я в основном правильно предположил проблему

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

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

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

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

(много) ТИА

Ответы [ 2 ]

4 голосов
/ 29 ноября 2011

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

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

Однако!возможно, здесь есть обходной путь, который должен работать сейчас ;вы можете предварительно сгенерировать статическую сериализацию dll;например, в отдельном консольном исполняемом файле (просто как инструмент; мне действительно нужно обернуть его в отдельную утилиту!)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 в полезную нагрузку обфускации.

(это относится только к v2, кстати)

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

2 голосов
/ 10 января 2012

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

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 и bingo, все готово.

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

HTH

...