- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
有什么办法可以改变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
这表明我已经成功修改了从Main
→ A
→ B
→ C
的调用堆栈到 Main
→ A
→ A
→ C
。
但是当在 Release 模式下运行时,当使用 F5 运行时,或者当我将局部变量添加到 B
或 C
时,它会停止工作,显示这是多么脆弱。
所以,这是可以做到的,但是永远不要这样做(教育目的除外)。
关于c# - OpCodes.Ret 使用的地址存储在哪里?可以改变吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25778356/
我有一个递归函数 emit : Map -> exp -> unit哪里il : ILGenerator对函数来说是全局的,并且 exp是一个判别联合,表示带有大小写 InstanceCall of
我正在使用 ASM 框架进行 java 字节码操作。 ASM中出现两次的一些操作码助记符,它们以“H_”为前缀: Opcodes.H_GETFIELD vs. Opcodes.GETF
谁能告诉我以下段错误究竟意味着什么? Unhandled dwarf expression opcode 0x93 它在solaris 10 i386上。 任何建议表示赞赏。 最佳答案 如果您的 GD
在构建芯片 8 仿真器时,我遇到了芯片 8 信息的 2 个主要来源似乎不同的问题,这对整个芯片 8 解释器有影响。 一方面,我们有 wikipedia , 在操作码 FX65 下告诉我们 “用从地址
在intel software developers manual volumen 2A chapter 2.1.2说 Two-byte opcode formats for general-purp
.NET Framework 4.0 向 Reflection API 引入了多项内容,这些内容对我的工作从极其有用到至关重要。其中包括 Assembly、Module、MethodBody 和 Lo
我正在使用 Kony Studio 开发应用程序。我已经使用 Eclipse 完成了登录验证,以编写用于创建 Web 服务以连接到 oracle10g 数据库的代码。但是在前端,当我尝试将前端连接到
当您在堆栈顶部引用 (B) 的实例时,是否有必要发出 OpCode.CastClass(typeof(A)),其中 B 是派生自 A 的类,当准备调用方法时类型 A 的参数? 添加: interfac
如果我有一个 lua 脚本,比如 print("Hello, world!") 我如何获得与之等效的指令或操作码? (用于 luaV_execute) 最佳答案 您几乎不需要对 Lua 的解释器做一个
我们的计算机体系结构教授给了我们一个示例程序,要求输入密码。任务是在比较输入的密码并决定是否正确后更改跳转操作码。我编写了一个程序,可以更改给定二进制文件中特定位置的任何字节。 这是密码程序的代码:
我有一个包含以下代码的汇编程序。 这段代码对于英特尔处理器来说编译得很好。但是,当我使用 PPC(交叉)编译器时,我收到一个错误,提示无法识别操作码。我试图找出是否有 PPC 架构的等效操作码。 .f
这可能是一个非常奇怪的问题,但我一直在小人电脑上做一些工作,这让我有点恼火,不仅没有操作代码 4,而且互联网上也绝对没有关于为什么。 操作码从 0 到 9 但跳过 4。从来没有任何以 4 开头的三位数
我正在阅读Go源代码,就像读过一样,当我阅读fastrand()函数时(对于我的机器,该函数位于asm_amd64.s文件中),我遇到了以下片段: XORL $0x88888eef, D
我设置了一个简单的 Geth (v1.10.2-stable-97d11b01) 专用网络(下面的 genesis.json 配置)。我编译并部署了这个简单的测试合约(solidity版本:0.8.4
我对此很陌生。我试图以清晰的方式理解上述术语之间的区别,但是,我仍然感到困惑。这是我发现的: 在计算机汇编语言中,助记符是操作的缩写。它被输入到每个汇编程序指令的操作码字段中。例如 AND AC,37
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我正在尝试为属性生成动态代理。 生成的代理源 self 们要代理的类型。当代理需要访问其派生类型的(虚拟)属性时,不能使用 OpCodes.Callvirt - 它会导致无限递归。因此我们需要调用Op
有什么办法可以改变OpCodes.Ret跳转到的地址吗? IL 中的方法可以更改 C# 使用的调用堆栈吗? 据我所知,在 C++ 中,您可以访问堆栈上的值并更改返回地址等。在 IL 中,除了“Inva
我已经在我的 linuxbox 上安装了 Zend OpCache。我使用以下命令安装扩展: sudo pecl install zendopcache-7.0.2 现在,无需修改我的 php.ini
许多框架利用 spl_autoload_register() 来动态加载类(即 Controller 和模型)。有几篇关于自动加载和操作码缓存问题的帖子。特别是一篇帖子有@cletus 的回复,其中引
我是一名优秀的程序员,十分优秀!