Skip to content

Instantly share code, notes, and snippets.

@adrianoc
Last active February 20, 2020 13:32
Program that demonstrates issues with branch ofsets
using System;
using System.IO;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
namespace CecilSandbox
{
class Program
{
static void Main(string[] args)
{
if (args.Length == 0)
{
var programName = Path.GetFileName(Environment.GetCommandLineArgs()[0]);
Console.WriteLine($"run: '{programName} modify <num>' to save a modified version of the assembly where <num> is the number of NOP instructions to inject and then\n");
Console.WriteLine($"run: '{programName} run' to execute the method with the modified body.");
return;
}
var nopCount = 0;
if (args.Length == 2 && args[0] == "modify" && !int.TryParse(args[1], out nopCount))
{
Console.WriteLine($"'{args[1]}' is not a valid # of nops to inject.");
return;
}
else if(args.Length == 1 && args[0] == "run")
{
Console.WriteLine("Trying to run the modified method...");
Foo(1);
return;
}
else if (nopCount == 0)
{
Console.WriteLine("Invalid command line args");
return;
}
using (var a = AssemblyDefinition.ReadAssembly(typeof(Program).Assembly.Location))
{
var t = a.MainModule.Types.Single(tc => tc.Name == "Program");
var m = t.Methods.Single(mc => mc.Name == "Foo");
foreach (var i in m.Body.Instructions)
{
Console.WriteLine(i);
}
if (nopCount == -1)
return;
m.Body.SimplifyMacros();
var branch = m.Body.Instructions.First(i => i.OpCode.OperandType == OperandType.ShortInlineBrTarget || i.OpCode.OperandType == OperandType.InlineBrTarget);
var il = m.Body.GetILProcessor();
for(int i = 0; i < nopCount; i++)
il.InsertAfter(branch, Instruction.Create(OpCodes.Nop));
m.Body.OptimizeMacros();
var targetAssemblyPath = Path.Combine(Path.GetTempPath(), "Output.exe");
a.Write(targetAssemblyPath);
Console.WriteLine($"Modified assembly saved to '{targetAssemblyPath}'. Run it with '{targetAssemblyPath} run'");
}
}
static void Foo(int i)
{
if (i > 0)
{
Console.WriteLine("" + i);
Console.WriteLine("" + i++);
Console.WriteLine("" + i++);
Console.WriteLine("" + i++);
}
Console.WriteLine("The End");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment