从.NET中的混淆中排除构造函数

时间:2015-02-26 04:59:05

标签: c# .net obfuscation

.NET中有ObfuscationAttibute。但我不明白,如何从混淆中排除构造函数中的代码。

// Obfuscated class
class MyClass {
    [Obfuscation(Exclude = true)] // "Attribute 'Obfuscation' is not valid on this declaration type"
    public MyClass() {
        //some code, I need to exclude this code from obfuscation
    }
    // Obfuscated method
    public void Method1() {
        //some code
    |
    // Obfuscated method
    public void Method2() {
        //some code
    |
}

UPD:问题不在于重命名构造函数。它的名字显然变成了“.ctor”。我需要防止代码本身的混淆。是的,一些混淆器不仅重命名符号,还改变代码。是的,我知道我不能用这个属性来做。编译器也这么说。我已经知道我不能做什么。我问我能做什么,最好只使用标准的.net工具。

4 个答案:

答案 0 :(得分:5)

您可以仅使用ObfuscationAttribute执行您想要的操作,但这很乏味:将[Obfuscation(ApplyToMembers=false)]应用于课程,将[Obfuscation]应用于每个成员,但构造

或者,使用混淆器的配置来排除构造函数。由于ObfuscationAttribute仅提供非常有限的控制(基本上只打开和关闭功能),因此大多数都具有单独的配置以进行细粒度控制。

最后,考虑使构造函数如此简单和无趣,以至于流是否被混淆无关紧要。无论如何理想情况应该是这样 - 如果你的构造函数只执行成员初始化,那么首先就没有太多的混淆。您可以为更多涉及的内容调用成员函数,并且可以控制使用该属性的那些人的模糊处理。

答案 1 :(得分:4)

构造函数始终在内部重命名为.ctor,您不能使用混淆的名称(但您也不能使用原始名称)。反编译器将使用模糊的类名称命名构造函数。

我想你的意思是对函数内的代码进行模糊处理,而不是成员名称?据推测,支持代码重新排列的更先进的混淆器而不仅仅是名称混淆将具有自己的属性来控制...因为System.Reflection.ObfuscationAttribute不适合控制更强大的混淆技术。

特别是,AttributeUsageAttribute类的ObfuscationAttribute不包含AttributeTargets.Constructor作为允许的使用。

答案 2 :(得分:2)

我非常同意这样的评论,即混淆不仅仅涉及重命名,而且似乎确实疏忽了构造函数未被视为[Obfuscation]的有效目标。我遇到了死代码删除的问题,其中混淆器可以删除无法访问的代码(我正在简化)。有时有必要重写此行为,例如对于反射/序列化方案,它可以与其他任何代码元素一样多地应用于构造函数。请注意,[AttributeUsage]仅是建议性的,并由C#(或VB)编译器强制实施。它不是由CLR强制执行的。因此,如果您的混淆器旨在在构造函数中寻找[Obfuscation](由于某些混淆器逻辑可能平等对待所有方法,这很可能是偶然的情况),并且您可以使用某种后期编译IL处理框架(例如PostSharp),则可以将[Obfuscation]放入构造函数中。对于PostSharp用户,以下是ObfuscationAttribute的多播版本,它将愉快地将[Obfuscation]应用于构造函数:

using System;
using PostSharp.Aspects;
using PostSharp.Extensibility;
using PostSharp.Reflection;
using System.Collections.Generic;
using System.Reflection;

/// <summary>
/// A multicast adapter for <see cref="ObfuscationAttribute"/>. Instructs obfuscation tools to take the specified actions for the target assembly, type, or member.
/// </summary>
[AttributeUsage( AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.Delegate | AttributeTargets.Constructor, AllowMultiple = true, Inherited = false )]
[MulticastAttributeUsage( 
    MulticastTargets.Assembly | MulticastTargets.Class | MulticastTargets.Struct | MulticastTargets.Enum | MulticastTargets.Method | MulticastTargets.Property | MulticastTargets.Field | MulticastTargets.Event | MulticastTargets.Interface | MulticastTargets.Parameter | MulticastTargets.Delegate | MulticastTargets.InstanceConstructor | MulticastTargets.InstanceConstructor,
    AllowMultiple = true,
    PersistMetaData = false)]
public sealed class MulticastObfuscationAttribute : MulticastAttribute, IAspectProvider
{
    bool _stripAfterObfuscation = true;
    bool _exclude = true;
    bool _applyToMembers = true;
    string _feature = "all";

    bool _stripAfterObfuscationIsSpecified;
    bool _excludeIsSpecified;
    bool _applyToMembersIsSpecified;
    bool _featureIsSpecified;

    static readonly ConstructorInfo ObfuscationAttributeCtor = typeof( ObfuscationAttribute ).GetConstructor( Type.EmptyTypes );

    IEnumerable<AspectInstance> IAspectProvider.ProvideAspects( object targetElement )
    {
        var oc = new ObjectConstruction( ObfuscationAttributeCtor );

        if ( _applyToMembersIsSpecified )
            oc.NamedArguments[ nameof( ObfuscationAttribute.ApplyToMembers ) ] = _applyToMembers;

        if ( _excludeIsSpecified )
            oc.NamedArguments[ nameof( ObfuscationAttribute.Exclude ) ] = _exclude;

        if ( _featureIsSpecified )
            oc.NamedArguments[ nameof( ObfuscationAttribute.Feature ) ] = _feature;

        if ( _stripAfterObfuscationIsSpecified )
            oc.NamedArguments[ nameof( ObfuscationAttribute.StripAfterObfuscation ) ] = _stripAfterObfuscation;

        return new[] { new AspectInstance( targetElement, new CustomAttributeIntroductionAspect( oc ) ) };
    }

    /// <summary>
    /// Gets or sets a <see cref="T:System.Boolean" /> value indicating whether the obfuscation tool should remove this attribute after processing.
    /// </summary>
    /// <returns>
    /// <see langword="true" /> if an obfuscation tool should remove the attribute after processing; otherwise, <see langword="false" />. The default is <see langword="true" />.
    /// </returns>
    public bool StripAfterObfuscation
    {
        get => _stripAfterObfuscation;
        set
        {
            _stripAfterObfuscationIsSpecified = true;
            _stripAfterObfuscation = value;
        }
    }

    /// <summary>
    /// Gets or sets a <see cref="T:System.Boolean" /> value indicating whether the obfuscation tool should exclude the type or member from obfuscation.
    /// </summary>
    /// <returns>
    /// <see langword="true" /> if the type or member to which this attribute is applied should be excluded from obfuscation; otherwise, <see langword="false" />. The default is <see langword="true" />.
    /// </returns>
    public bool Exclude
    {
        get => _exclude;
        set
        {
            _excludeIsSpecified = true;
            _exclude = value;
        }
    }

    /// <summary>
    /// Gets or sets a <see cref="T:System.Boolean" /> value indicating whether the attribute of a type is to apply to the members of the type.
    /// </summary>
    /// <returns>
    /// <see langword="true" /> if the attribute is to apply to the members of the type; otherwise, <see langword="false" />. The default is <see langword="true" />.
    /// </returns>
    public bool ApplyToMembers
    {
        get => _applyToMembers;
        set
        {
            _applyToMembersIsSpecified = true;
            _applyToMembers = value;
        }
    }

    /// <summary>
    /// Gets or sets a string value that is recognized by the obfuscation tool, and which specifies processing options.
    /// </summary>
    /// <returns>
    /// A string value that is recognized by the obfuscation tool, and which specifies processing options. The default is "all".
    /// </returns>
    public string Feature
    {
        get => _feature;
        set
        {
            _featureIsSpecified = true;
            _feature = value;
        }
    }
}

答案 3 :(得分:0)

为什么构造函数

上不允许[ObfuscationAttribute]

您无法将[Obfuscation(Exclude = true)]置于构造函数上,因为混淆重命名符号,而不是方法内容(通常 - 更高级)混淆器可以改变代码流,修改常量等,使逆向工程变得更加困难)

例如,请考虑以下事项:

// obfuscated class
public class MyClass
{
    public MyClass()
    {
    }

    public void MyMethod()
    {
    }
}

// unobfuscated class
public class CallingClass
{
    public static void TestMyClass()
    {
        MyClass class = new MyClass();
        class.MyMethod();
    }
}

混淆器会将MyClass重命名为其他内容(例如qfghjigffvvb),将MyMethod()重命名为其他内容(例如ghjbvxdghh())并更改所有引用,以便代码仍可正常工作同样的,即

public class qfghjigffvvb
{
    public qfghjigffvvb()
    {
    }

    public void ghjbvxdghh()
    {
    }
}

// unobfuscated class
public class CallingClass
{
    public static void TestMyClass()
    {
        qfghjigffvvb class = new qfghjigffvvb();
        class.ghjbvxdghh();
    }
}

如果您将[Obfuscation(Exclude = true)]属性放在MyClass的构造函数上,那么CallingClass.TestMyClass()将如下所示:

public class CallingClass
{
    public static void TestMyClass()
    {
        qfghjigffvvb class = new MyClass(); // ?
        class.ghjbvxdghh();
    }
}

如果您需要MyClass构造函数的内容不被混淆,您需要将[Obfuscation(Exclude = true)]属性放到它调用的所有内容上,以便这些符号不会被重命名。


思想实验:排除构造函数的内容

假设您有一个[ContentObfuscation]属性,可用于阻止方法(或构造函数或属性)的内容被混淆。你想在这里做什么?

public class MyClass
{
    [ContentObfuscation(Exclude = true)]
    public MyClass()
    {
        // SecurityCriticalClass is obfuscated
        var securityCriticalClass = new SecurityCriticalClass();
        securityCriticalClass.DoSomeTopSecretStuff();
    }
}

如果构造函数的内容未进行模糊处理,则SecurityCriticalClass也必须不进行模糊处理,可能会产生安全问题。