Customization and extension through code

16 views
Skip to first unread message

obiwanjacobi

unread,
May 15, 2007, 1:40:08 AM5/15/07
to obfuscar
Hi,

I'm not sure how obfuscar works internally but I had an idea.

Suppose you have a Type enumerator that iterates over all types in an
assembly and a member enumerator that iterates over all members in a
type. The main loop will iterate all modules (from the settings file)
all types and all members. I guess you have similar code in obfuscar
now.

Then a framework (very small) would allow 'providers' to work with the
assemblies,types and members an each provider decides what has to be
done. So obfuscation would be implemented as a provider. I can also
see providers that check if a type/member is unused and if so remove
it from the target assembly.

I cannot oversee all the details but it appears to be a viable
solution in which a developer can add its own logic that is executed
during an 'assembly-transform'.

What do you think? Would it be a big step from your current code base
to go in this direction?

Grtx,
--Marc

Ryan Williams

unread,
May 15, 2007, 8:54:43 AM5/15/07
to obfu...@googlegroups.com
It probably wouldn't be a small task, but it wouldn't be impossible.
Something like that would have a lot of advantages, like being able to
plug in string encryption 'providers', dead code elimination
providers, control flow obfuscation providers, etc.

Right now, it's pretty special purpose...built around several loops
that go through the types, renaming bits on each pass. If an option
is added to switch on using unique names instead of the current
smallest-set, this may be a good direction to go when getting it done.

(btw, I've added an issue, re: the unique naming. see
http://code.google.com/p/obfuscar/issues/detail?id=5 )

obiwanjacobi

unread,
May 17, 2007, 7:11:17 AM5/17/07
to obfuscar
Sounds great! How much are you planning to get done when implementing
the unique-name feature?

Anyway, if you need sparring on the architecture.... ;-)

Ryan Williams

unread,
May 17, 2007, 11:08:22 AM5/17/07
to obfu...@googlegroups.com
The two schemes, unique names vs. massive overloading are pretty
different. Implementing support for both would be a decent start
towards a more flexible architecture.

The basic algorithm is currently as follows:

1. Load everything.
2. Group methods.
3. Rename stuff.
4. Save everything.
5. Save the mapping.

The real meat of the current system is the InheritMap and the assembly
handling by the Project class (in steps 1 and 2), which would continue
to be shared by both engines...the part that needs to change is the
series of RenameXXX calls (step 3, currently, made from Program.Main).

The first step I'd like to take is refactoring the current RenameXXX
calls into a behavior, possibly called OverloadingObfuscator or
something similar, that accepts a Project object, and does its
renaming work via a single (or minimal) entry point.

The next step would be implementing a UniqueObfuscator behavior that
implements the same interface and does the same kind of work, but uses
the unique name scheme.

Other project processors could also be created, and there wouldn't be
any reason that multiple project processors couldn't be chained, e.g.,
first the project is handed to DeadCodeEliminator, then to
OverloadingObfuscator, then to StringScrambler, etc.

Obiwan Jacobi

unread,
May 18, 2007, 1:55:57 PM5/18/07
to obfu...@googlegroups.com
I wouldn't have realized that the two schemes would be such a world apart...
 
We need to factor out the common 'services' of the two scenarios and provide some way to reuse them. My favorite way of providing services is using a service container. Each provider could have access to a service container that contains common service interfaces. By publishing the service interfaces (and not the implementation) the providers can reuse common framework service or publish new sevices that they implement. A service is accessed by querying the service container for a service interface (refer to System.ComponentModel.IServiceProvider).
 
So, for instance both methods of obfuscation need a mapping. Perhaps you can implement it as a service and both obfucator provider implementations can access the same service. Perhaps the Cecil object model of an assembly can also be provided by a service.
 
I also think that perhaps you need a bit more fine grained stages. Each stage would be a method on the provider interface. Perhaps you could work with a list of source assemblies and a list of target assemblies -it's important for a provider to know all assemblies to work out what members aren't used for instance- but the calls to the provider are 'per assembly'. There should also be a stage that allows providers to vote for the types and members they would like to copy (and to which assembly? so you can make a merger?).
 
so far, my 2 cents...
 
Grtx
Marc



> Date: Thu, 17 May 2007 11:08:22 -0400
> From: drcf...@gmail.com
> To: obfu...@googlegroups.com
> Subject: Re: Customization and extension through code

obiwanjacobi

unread,
May 18, 2007, 2:31:33 PM5/18/07
to obfuscar
I just ran into an 'issue' with Xml serialization (its not a bug in
obfuscar ;-).

You need to skip all the types and members that are involved in Xml
Serialization. You have to do this by hand now. Wouldn't it be great I
you could have a provider search for the Xml code attributes and mark
those for the obfuscator provider automatically? There are other areas
of the .NET framework that might also need some attention, like
configuration...

It would require that all provders work on a central "data model" (of
some kind), though....

Ryan Williams

unread,
May 18, 2007, 5:59:33 PM5/18/07
to obfu...@googlegroups.com
There is a bit of functionality in there to exclude types that have an
associated attribute. It wouldn't be hard to extend it to handle
other attributes, or to make the exclusion by reflection more
flexible.

The only trouble is figuring out which attributes are important and
how to take advantage of them. For example, if a property has the
XmlElement attribute on it, it should be skipped...unless the
XmlElement's ElementName is set, in which case changing the name of
the property is fine.

To make it more complicated, .net has at least 3 different ways to
serialize / annotate your classes to be exposed via xml (including
attributes in System.Xml.Serialization, System.Web.Services, and
System.Runtime.Remoting.Metadata).

obiwanjacobi

unread,
May 19, 2007, 9:32:50 AM5/19/07
to obfuscar
On May 18, 11:59 pm, "Ryan Williams" <drcfor...@gmail.com> wrote:
> The only trouble is figuring out which attributes are important and
> how to take advantage of them. For example, if a property has the
> XmlElement attribute on it, it should be skipped...unless the
> XmlElement's ElementName is set, in which case changing the name of
> the property is fine.
>
> To make it more complicated, .net has at least 3 different ways to
> serialize / annotate your classes to be exposed via xml (including
> attributes in System.Xml.Serialization, System.Web.Services, and
> System.Runtime.Remoting.Metadata).

I would just make a 'skip-provider' for each category of code
attributes. Make one specifically for Xml-atributes. Then one that
works for web service attributes. If you need to, you just combine
these providers in your obfuscar project settings.

Reply all
Reply to author
Forward
0 new messages