删除堆栈框架设置/初始化

时间:2019-12-03 16:49:22

标签: c gcc assembly clang

我有以下程序:

void main1() {
    ((void(*)(void)) (0xabcdefabcdef)) ();
}

我用以下命令创建它:

clang -fno-stack-protector -c -static -nostdlib -fpic  -fpie -O0 -fno-asynchronous-unwind-tables main.c -o shellcode.o
ld shellcode.o -o shellcode -S -static -dylib -e main1 -order_file order.txt
gobjcopy -O binary --only-section=.text shellcode shellcode.output

程序集如下所示:

                             //
                             // ram 
                             // ram: 00000000-00000011
                             //
                             **************************************************************
                             *                          FUNCTION                          *
                             **************************************************************
                             undefined FUN_00000000()
             undefined         AL:1           <RETURN>
                             FUN_00000000
        00000000 55              PUSH       RBP
        00000001 48 89 e5        MOV        RBP,RSP
        00000004 48 b8 ef        MOV        RAX,0xabcdefabcdef
                 cd ab ef 
                 cd ab 00 00
        0000000e ff d0           CALL       RAX
        00000010 5d              POP        RBP
        00000011 c3              RET

由于不需要{@ {1}},PUSH RBPMOV RBP,RSP指令,我该如何对其进行删除?

如果我用以下代码行汇编程序,就可以做到这一点:

POP RBP

以及以下构建命令:

.globl start
start:
    movq $0xabcdefabcdef, %rax
    call *%rax
    ret

和生成的程序集:

clang  -static -nostdlib main.S -o crashme.o
gobjcopy -O binary --only-section=.text crashme.o crashme.output

但是我更愿意编写C代码而不是汇编代码。

1 个答案:

答案 0 :(得分:3)

您忘记启用优化。任何优化级别(例如-O3都会启用-fomit-frame-pointer

尽管如此,它也会将尾调用最优化为jmp而不是call / ret。如果出于某种原因需要避免这种情况,也许可以在默认的-fomit-frame-pointer上使用-O0

对于shellcode,您可能希望-Os针对代码大小进行优化。甚至c的-Oz;这样做的副作用是,通过使用0 / push imm8而不是pop reg在寄存器中放置较小的常量,可以避免机器代码中的某些mov reg, imm32字节。