C# : modificare un campo readonly ? Si può con la Reflection !

Tutti sappiamo che definendo il campo di una classe con la keyword readonly, quest’ultimo assumerà un valore a runtime che potrà essere assegnato solo ed esclusivamente nel costruttore della classe ma non potrà più essere modificato successivamente.

Ad esempio, consideriamo la definizione della seguente classe :

public class MyClass
{
    private readonly int rField;

    public MyClass(int field)
    {
        this.rField = field;
    }

    public int RField
    {
        get
        {
            return this.rField;
        }
        set
        {
            this.rField = value;
        }
    }
}

Se proviamo a compilare tale classe, il compilatore restituirà il seguente errore :

A readonly field cannot be assigned to (except in a constructor or a variable initializer)

Attraverso la Reflection è invece possibile modificare un campo definito readonly in un qualsiasi momento dell’esecuzione.

Per fare questo, bisogna modificare il set della property RField nel modo seguente :

set
{
    this.GetType()
        .GetField("rField", BindingFlags.NonPublic | BindingFlags.Instance)
        .SetValue(this, value);
}

Utilizzando la Reflection, si accede al campo readonly rField e se ne modifica il valore.

In questo modo, non otteniamo alcun errore di compilazione ed eseguendo il seguente programma di test :

static void Main(string[] args)
{
    MyClass myClass = new MyClass(10);
    Console.WriteLine("MyClass.RField = {0} after ctor", myClass.RField);
    myClass.RField = 5;
    Console.WriteLine("MyClass.RField = {0} after setting property", myClass.RField);
}

otteniamo il seguente output :

2626.readonly_field_2DC466D6

dal quale si evince che il campo readonly è stato modificato !

Hacking su un campo private e readonly

Andando oltre il semplice esempio didattico suddetto, questa tecnica si potrebbe utilizzare per eseguire un hacking su un campo privato readonly di una classe. Supponiamo che la classe suddetta sia di questo tipo :

public class MyClass
{
    private readonly int rField;

    public MyClass(int field)
    {
        this.rField = field;
    }

    public int RField
    {
        get
        {
            return this.rField;
        }
    }
}

Il campo rField non è accessibile dall’esterno (private), non è modificabile a runtime (readonly) e la relativa property RField ne permette esclusivamente la lettura (get). Sfruttando però la Reflection con la tecnica vista prima, possiamo comunque modificare il campo nel modo seguente :

static void Main(string[] args)
{

    MyClass myClass = new MyClass(10);
    Console.WriteLine("MyClass.RField = {0} after ctor", myClass.RField);
    myClass.GetType()
           .GetField("rField", BindingFlags.NonPublic | BindingFlags.Instance)
           .SetValue(myClass, 5);
    Console.WriteLine("MyClass.RField = {0} after setting property", myClass.RField);

}

che in esecuzione darà il seguente output :

5148.readonly_field_5D5A6701

A tutti gli effetti abbiamo eseguito un hacking su un campo che era stato previsto non accessibile in scrittura e non modificabile dallo sviluppatore !

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s