How to generate C# code from IL Instructions

793 views Asked by At

I'm trying to generate c# code from IL instructions using the dnlib library.

The code I'm trying to generate is this one:

private string GetIp()
{
    return new WebClient().DownloadString("https://api.myip.com/");
}

My code:

Type webclientType = typeof(System.Net.WebClient);

ConstructorInfo constructor = webclientType.GetConstructors()[0];

MethodInfo methodInfo = webclientType.GetMethod("DownloadString", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance, null, System.Reflection.CallingConventions.Any, new Type[] { typeof(string) }, null);

MethodDefUser m = new MethodDefUser("GetIp", MethodSig.CreateInstance(module.CorLibTypes.String), MethodImplAttributes.IL, MethodAttributes.Static | MethodAttributes.HideBySig)
{
    Body = new CilBody()
};

m.Body.Instructions.Add(new Instruction(OpCodes.Newobj, constructor));
m.Body.Instructions.Add(new Instruction(OpCodes.Ldstr, "https://api.myip.com/"));
m.Body.Instructions.Add(new Instruction(OpCodes.Callvirt, methodInfo));
m.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));

I get an error (Invalid instruction operand) when trying to save the module to disk.

Right now my code is generating these instructions:

newobj - Void .ctor()
ldstr - https://api.myip.com/
callvirt - System.String DownloadString(System.String)
ret - 

When they should be this:

newobj - System.Void System.Net.WebClient::.ctor()
ldstr - https://api.myip.com/
callvirt - System.String System.Net.WebClient::DownloadString(System.String)
ret -

I've tried to replace the constructor for the webclientType variable but with no luck, also no luck finding any information online.

1

There are 1 answers

0
Milton Cardoso On BEST ANSWER

while trying some stuff, I saw that I needed to be using the main object (from dnlib) that has the .NET module loaded (ModuleDefMD).

So I did it this way:

m.Body.Instructions.Add(new Instruction(OpCodes.Newobj, module.Import(typeof(System.Net.WebClient).GetConstructors()[0])));
m.Body.Instructions.Add(new Instruction(OpCodes.Ldstr, "https://api.myip.com/"));
m.Body.Instructions.Add(new Instruction(OpCodes.Callvirt, module.Import(typeof(System.Net.WebClient).GetMethod("DownloadString", new Type[] { typeof(string) }))));
m.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));

module being the main object where I load the .NET File:

ModuleDefMD module = ModuleDefMD.Load(TxtFilepath.Text);

This now generates this C# code:

static string GetIp()
{
    return new WebClient().DownloadString("https://api.myip.com/");
}