3

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.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Milton Cardoso
  • 358
  • 3
  • 14
  • What is `MethodDefUser`? What is `MethodSig`? What is `module`? Please post a [mcve] so that we can properly help you. – Lasse V. Karlsen Oct 30 '21 at 21:38
  • Also, what exactly do you mean by "generating csharp code"? Please explain what this means, as your question seem to be about getting som IL emitting to work properly, not about generating C# code. – Lasse V. Karlsen Oct 30 '21 at 21:40
  • @LasseV.Karlsen `MethodDefUser` is used to define a method that then you can add functionality using CIL instruction, and in the end write it to a .net file – Milton Cardoso Oct 30 '21 at 21:45

1 Answers1

2

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/");
}
Milton Cardoso
  • 358
  • 3
  • 14