【问题标题】:Modify next Instruction in memory with gcc使用 gcc 修改内存中的下一条指令
【发布时间】:2014-12-15 13:17:54
【问题描述】:

我想在获取之前修改下一条指令,在 foo 函数中 This post 的最佳答案中,*p 指向 main 函数中的下一条指令。我想修改*p 指向的内容。例如,我想将下一条指令更改为跳转指令。我该怎么做?

void foo()
{
    void** p = search((void**)&p, __builtin_return_address(0));
    // modify content of where *p points at.
}

int main()
{
    
    foo();
    //next instruction. *p points here
    return 0;
}

我想在 intel Core-i7 3632QM 处理器上使用 gcc 编译器。

【问题讨论】:

    标签: c assembly gcc instructions self-modifying


    【解决方案1】:

    例如我想将下一条指令更改为跳转指令。我该怎么做?

    在具有现代操作系统的桌面系统上,您不能,除非正在执行的程序注意将代码保存在read-write memory pages 中。默认情况下,代码加载在只读内存页面中。

    【讨论】:

    • 如果将其设为可读写,我会感到惊讶。 Intel 内核在 MMU 中有一个 XD/XN 位,用于安全目的,防止病毒运行数据。这有效地将代码与 MMU 中的数据隔离开来,防止更新可执行区域。如果有任何类型的操作系统正在运行,这样做会引发异常(并且很可能会将您的代码发送给制作病毒扫描程序的人)。
    • @MikeofSST 我从未尝试过它,但我相信按照stackoverflow.com/a/4169440/139746 中的步骤操作就足以允许修改代码。
    • 很棒的链接 - 这就像特洛伊木马的秘诀! :-) 我也想在调用修改后的代码之前刷新我的 i-cache,以防万一。
    • 这个关于i-cache的问题也很有趣。
    • @MikeofSST 关于特洛伊木马:在大多数情况下,系统会保护自己(无论如何,防止新代码——参见“面向返回的编程”):如果攻击者可以执行mprotect,那么他们可以执行更多轻松执行他们选择的代码,但他们无法执行mprotect。关于指令案例,有一段时间,确保新代码加载的指令随着每一代处理器而改变,但现在应该已经稳定了,我猜。
    【解决方案2】:

    只是一个想法。正如 cmets 中已经提到的那样,writeexecute [通常] 不能设置在相同的内存范围内。但是任何 POSIX 系统都应该有动态链接器的接口(@98​​7654321@,dlclose(),...)。所以有一种方法可以在运行时修改进程内存布局,供动态链接器使用。

    如果修改动态链接器或使用与它使用的相同的接口是可接受的选项,则可以转储内存段(或将其复制到另一个范围)、修改、释放原始段并将修改后的段加载到同一范围内.

    【讨论】:

    • 许多操作系统确实允许页面同时具有写入和执行权限。默认情况下,它们不会在普通可执行文件中以这种方式映射许多(或现在任何)页面。您可以mprotect 进行设置。但是,在某些操作系统(如 OpenBSD)上,有严格的 W^X 策略,mprotect(PROT_WRITE|PROT_EXEC) 会返回错误。
    猜你喜欢
    • 2013-06-04
    • 1970-01-01
    • 2013-11-19
    • 1970-01-01
    • 2015-05-20
    • 2013-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多