首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么C代码会使用"JMP EDI“或"PUSH EDI RET"?

什么C代码会使用"JMP EDI“或"PUSH EDI RET"?
EN

Stack Overflow用户
提问于 2020-02-27 15:57:44
回答 1查看 168关注 0票数 0

两者之间有什么区别吗?

代码语言:javascript
复制
JMP EDI 

代码语言:javascript
复制
PUSH EDI
RET

什么样的c代码会以这种方式反汇编?动态解析的函数指针,然后被调用?

EN

回答 1

Stack Overflow用户

发布于 2020-02-27 23:35:39

如果您正在寻找ROP小工具,volatile int tmp = 0xffe7ffe4将编译为mov,其立即数包含JMP EDI和JMP ESP的机器代码字节。但当然,当正常执行时,它只是mov dword [esp], 0xffe7ffe4或编译器发出的任何东西。该0xffe7常量的任何其他用法都可以编译为包含它的立即数的机器码。

编译器永远不会发出推送/返回。它破坏了返回地址预测器堆栈,导致在随后的调用堆栈向上返回时发生错误预测。即使是retpoline通常也只使用调用/修改堆栈/ret。(GCC将使用-mindirect-branch=thunk自动发出retpolines )。当然,您也可以将这个3字节的序列作为立即数。

jmp edi可能会作为编译器输出的普通部分出现(而不仅仅是作为另一条指令的一部分)。但这不太可能。在32位调用约定中,edi是调用保留的,因此您不会发现jmp edi实现了尾部调用;在返回或尾部调用之前必须恢复寄存器。如果你让GCC在寄存器中保存一个函数指针,它会在尾调用之前用mov eax, edi / pop edi / jmp eax来恢复它的调用者的值。(Godbolt)。

如果你使用了足够多的其他局部变量,以至于编译器的寄存器分配器选择了call edi,那么使用局部函数指针就不难获得EDI。但不是jmp

在x86-64system V中,RDI是一个arg传递寄存器和调用阻塞寄存器,但是当然指针是64位的,所以你总是会得到jmp rdi。在ILP32变体( x32 ABI)中,调用约定显然仍然需要将指针args从零扩展到64位,因为是GCC -mx32 still emits jmp rdi,而不是jmp edi。(使用mov eax,edi /jmp rax,Clang将截断为32位)。禁用优化是没有用的;编译器随后只会存储到堆栈中并重新加载到EAX中。

gcc9.2的工作示例

一个不错的选择是GNU C computed-goto to the address of a local label

代码语言:javascript
复制
// function arg and target both need call-preserved registers to survive across ext()
int use_local_label(int *p)
{
    void *volatile target_launder = &&label1;
    void *target = target_launder;       // defeat constant-propagation

 label1:
    ext();  // non-inline function call forces using call-preserved registers
    if (++*p == 0) target = &&label2;
    goto *target;

    return 0;

 label2:
    return 1;
}

-O2 -m32 -fcall-used-esi (而不是使用第三个本地变量,我只是告诉编译器ESI是被调用的,以阻止它在EDI之前选择它。ptarget最终分别进入了EBX和EDI。)

代码语言:javascript
复制
use_local_label:
        push    edi                                # save call-preserved regs
        push    ebx
        sub     esp, 20
        mov     DWORD PTR [esp+12], OFFSET FLAT:.L4   # volatile init
        mov     ebx, DWORD PTR [esp+32]               # p = function arg
        mov     edi, DWORD PTR [esp+12]               # target = volatile reload
.L4:
        call    ext
        add     DWORD PTR [ebx], 1
        je      .L5                # if = conditional jump over the goto
        jmp     edi                # goto *target, normally to .L4
.L5:
        add     esp, 20
        mov     eax, 1
        pop     ebx
        pop     edi
        ret
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60428627

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档