Giter Site home page Giter Site logo

methodredirect's People

Contributors

spinico avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

methodredirect's Issues

Does it work for newer version?

I tried https://stackoverflow.com/questions/7299097/dynamically-replace-the-contents-of-a-c-sharp-method but it seems not work. I'm using FX4.7.2 or .NET6

using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

class C
{
    public static int F() => 123;
    public static int F2() => 456;
}

internal class Program
{
    static void Main(string[] args)
    {
        Type c = typeof(C);
        c.GetMethod("F").RedirectTo(c.GetMethod("F2"));
        Console.WriteLine(C.F());
        Console.ReadKey();
    }
}

static class Extensions
{
    public static void RedirectTo(this MethodInfo origin, MethodInfo target)
    {
        IntPtr ori = GetMethodAddress(origin);
        IntPtr tar = GetMethodAddress(target);

        Marshal.Copy(new IntPtr[] { Marshal.ReadIntPtr(tar) }, 0, ori, 1);
    }

    private static IntPtr GetMethodAddress(MethodInfo mi)
    {
        const ushort SLOT_NUMBER_MASK = 0xfff; // 3 bytes
        const int MT_OFFSET_32BIT = 0x28;      // 40 bytes
        const int MT_OFFSET_64BIT = 0x40;      // 64 bytes

        IntPtr address;

        // JIT compilation of the method
        RuntimeHelpers.PrepareMethod(mi.MethodHandle);

        IntPtr md = mi.MethodHandle.Value;             // MethodDescriptor address
        IntPtr mt = mi.DeclaringType.TypeHandle.Value; // MethodTable address

        if (mi.IsVirtual)
        {
            // The fixed-size portion of the MethodTable structure depends on the process type
            int offset = IntPtr.Size == 4 ? MT_OFFSET_32BIT : MT_OFFSET_64BIT;

            // First method slot = MethodTable address + fixed-size offset
            // This is the address of the first method of any type (i.e. ToString)
            IntPtr ms = Marshal.ReadIntPtr(mt + offset);

            // Get the slot number of the virtual method entry from the MethodDesc data structure
            // Remark: the slot number is represented on 3 bytes
            long shift = Marshal.ReadInt64(md) >> 32;
            int slot = (int)(shift & SLOT_NUMBER_MASK);

            // Get the virtual method address relative to the first method slot
            address = ms + (slot * IntPtr.Size);
        }
        else
        {
            // Bypass default MethodDescriptor padding (8 bytes) 
            // Reach the CodeOrIL field which contains the address of the JIT-compiled code
            address = md + 8;
        }

        return address;
    }
}

Redirecting methods in System libraries

Hi!

I'm trying to redirect System.IO.File.ReadAllText to my own method.
I tried using the examples but getting a System.MissingMethodException: 'Cannot create an abstract class.' while trying to initiate the dynamic variable on:

    var scenario = (System.IO.File)Activator.CreateInstance(Scenario_Type);

How can this be done?
Thanks

2 bytes, which correspond to a maximum of 255 per type -> 2 bytes (16 bits) corresponds to a maximum number of 65536 slots per type

Unfortunately your code does not work for me.
I have now debugged around and come to the conclusion that something is wrong with the slot.

For fun I have now simply searched for the address after the ms address and come to a much larger slot number (288 instead of 152).
An with these values correct method gets called afterwards, but the code ist dangerous :-(

                // Get the virtual method address relative to the first method slot
                address = ms + (slot2 * IntPtr.Size);  // slot is 152 here
                int slot = 0;
                while (true)
                {
                    
                    address = ms + (slot * IntPtr.Size); 
                    if (Marshal.ReadIntPtr(address) == solution)
                    {
                        break; //slot ist 288 here
                    }
                    slot += 1;
                }

Any hints?

PS:
2 bytes, which correspond to a maximum of 255 per type -> 2 bytes (16 bits) corresponds to a maximum number of 65536 slots per type

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.