Last active
April 10, 2018 10:08
-
-
Save PathogenDavid/28c52c6a90fcc4c28a9d66981c92ba5d to your computer and use it in GitHub Desktop.
Evil Fody weaver for force writing readonly fields with test program to be weaved by it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Fody; | |
using Mono.Cecil; | |
using Mono.Cecil.Cil; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace Evil.Fody | |
{ | |
public class ModuleWeaver : BaseModuleWeaver | |
{ | |
public override void Execute() | |
{ | |
TypeDefinition programType = ModuleDefinition.Types.First(t => t.Name == "Program"); | |
FieldDefinition lolField = programType.Fields.First(f => f.Name == "<Lol>k__BackingField"); | |
FieldDefinition lelField = programType.Fields.First(f => f.Name == "Lel"); | |
MethodDefinition evilConstructor = programType.Methods.First(m => m.Name == ".ctor" && m.Parameters.Count == 0); | |
MethodDefinition evilMethod = programType.Methods.First(m => m.Name == "Evil"); | |
evilMethod.Body.Instructions.Clear(); | |
ILProcessor processor = evilMethod.Body.GetILProcessor(); | |
processor.Emit(OpCodes.Nop); | |
#if true | |
// This produces verification error 0x80131884 | |
// [IL]: Error: [... : ForceWriteReadonly.Program::Evil][offset 0x0000000A] | |
// Cannot change initonly field outside its .ctor.(Error: 0x80131884) | |
processor.Emit(OpCodes.Ldarg_0); | |
processor.Emit(OpCodes.Ldarg_0); | |
processor.Emit(OpCodes.Ldfld, lelField); | |
processor.Emit(OpCodes.Ldc_I4_1); | |
processor.Emit(OpCodes.Add); | |
processor.Emit(OpCodes.Stfld, lelField); | |
processor.Emit(OpCodes.Ldarg_0); | |
processor.Emit(OpCodes.Ldarg_0); | |
processor.Emit(OpCodes.Ldfld, lolField); | |
processor.Emit(OpCodes.Ldc_I4_1); | |
processor.Emit(OpCodes.Add); | |
processor.Emit(OpCodes.Stfld, lolField); | |
#else | |
// This produces verification error 0x801318BF | |
// [IL]: Error: [... : ForceWriteReadonly.Program::Evil][offset 0x00000002][found ref ('this' ptr) 'ForceWriteReadonly.Program'] | |
// Call to .ctor only allowed to initialize this pointer from within a .ctor. Try newobj.(Error: 0x801318BF) | |
processor.Emit(OpCodes.Ldarg_0); | |
processor.Emit(OpCodes.Call, evilConstructor); | |
#endif | |
processor.Emit(OpCodes.Ret); | |
} | |
public override IEnumerable<string> GetAssembliesForScanning() | |
{ | |
yield break; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace ForceWriteReadonly | |
{ | |
class Program | |
{ | |
public int Lol { get; } | |
public readonly int Lel; | |
public Program(int x, int y) | |
{ | |
Lol = x; | |
Lel = y; | |
} | |
// Evil constructor for alternate method | |
private Program() | |
{ | |
Lol++; | |
Lel++; | |
} | |
public void Evil() | |
{ | |
//Lol++; | |
//Lel++; | |
} | |
public override string ToString() | |
=> $"{Lol}, {Lel}"; | |
static void Main(string[] args) | |
{ | |
Program p = new Program(100, 200); | |
Console.WriteLine(p); | |
p.Evil(); | |
Console.WriteLine(p); | |
p.Evil(); | |
Console.WriteLine(p); | |
p.Evil(); | |
Console.WriteLine(p); | |
Console.WriteLine("Done."); | |
Console.ReadLine(); | |
} | |
} | |
} |
Also maybe worth pointing out that I've tested this in .NET Framework as well as .NET Core using Fody 3.0.3.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here's the output of the weaved program: