Last active
February 20, 2020 13:32
Program that demonstrates issues with branch ofsets
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; | |
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