gpt4 book ai didi

c# - OpCodes.Ret 使用的地址存储在哪里?可以改变吗?

转载 作者:太空宇宙 更新时间:2023-11-03 10:39:56 25 4
gpt4 key购买 nike

有什么办法可以改变OpCodes.Ret跳转到的地址吗? IL 中的方法可以更改 C# 使用的调用堆栈吗?

据我所知,在 C++ 中,您可以访问堆栈上的值并更改返回地址等。在 IL 中,除了“InvalidProgramException”之外,我尝试访问当前方法之外的堆栈的所有内容都失败了。

我的示例代码:

    public static void Test2()
{
var ma = typeof(Program).GetMethod("Test2");
DynamicMethod meth = new DynamicMethod("", null, null, ma.Module, true);
ILGenerator il = meth.GetILGenerator();



il.EmitWriteLine("Start to run the IL method");

var t = il.DeclareLocal(typeof(int));



//take the top of the stack (from the caller method) and put it into the variable t
//this seems to be not possible?
il.Emit(OpCodes.Stloc, t);

//print the value from the stack
il.EmitWriteLine(t);

//load the value back from the field onto the stack to allow everything to preceed normally
il.Emit(OpCodes.Ldloc, t);

//return
il.Emit(OpCodes.Ret);

Action a = (Action)meth.CreateDelegate(typeof(Action));

a();
}

最佳答案

好吧,OpCodes.Ret IL 指令实际上并没有进行任何跳跃。相反,IL 代码由 CLR 编译为 native 机器代码并执行。为某些 IL 代码生成什么机器代码取决于您的体系结构(x86、ARM 等),它是 CLR 的实现细节。

假设在 x86 上,ret IL 指令被编译为 ret x86 指令是有意义的,但它可能不是,例如,因为整个方法可能是内联的。

为此,您可以尝试使用指针修改堆栈,因为那是存储 x86 ret 跳转到的地址的地方,但这样做非常危险(您很容易修改错误的内存)并且非常脆弱(因为它依赖于堆栈的布局,很容易改变)。

例如,看下面的代码:

using System;

static class Program
{
static void Main()
{
A();
}

static void A()
{
Console.WriteLine("A before");
B();
Console.WriteLine("A after");
}

static void B()
{
Console.WriteLine("B before");
C();
Console.WriteLine("B after");
}

static unsafe void C()
{
int local;

int* localPointer = &local;

localPointer[2] = localPointer[4];
}
}

如果我在我的计算机上运行这个,在 Debug模式下使用 Ctrl+F5,它打印:

A before
B before
A after
A after

这表明我已经成功修改了从MainABC 的调用堆栈到 MainAAC

但是当在 Release 模式下运行时,当使用 F5 运行时,或者当我将局部变量添加到 BC 时,它会停止工作,显示这是多么脆弱。

所以,这是可以做到的,但是永远不要这样做(教育目的除外)。

关于c# - OpCodes.Ret 使用的地址存储在哪里?可以改变吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25778356/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com