__libc_start_main由入口点代码调用(通常在名为crt0.S或类似的文件中)并且该代码通常设置初始EBP值(通常为 0,以表示调试器的调用堆栈结束)。这是来自随机 ELF 二进制文件的示例入口点代码:
_start:
xor ebp, ebp
pop esi
mov ecx, esp
and esp, 0FFFFFFF0h
push eax
push esp ; stack_end
push edx ; rtld_fini
push offset __libc_csu_fini ; fini
push offset __libc_csu_init ; init
push ecx ; ubp_av
push esi ; argc
push offset main ; main
call ___libc_start_main
hlt
虽然__libc_start_main它本身可以初始化EBP为 0,但在查看调用堆栈时,这会使它看起来好像是二进制文件中的第一个代码,这是不正确的(执行从_start入口点开始)。
此外,__libc_start_main 可以(并且经常是)用 C 语言而不是汇编语言编写,并且编译器更容易为它生成标准的 prolog 代码,而不是产生某种特殊情况的异常。
至于覆盖该值,您不会崩溃,因为:
ebp___libc_start_main(入口点代码)的调用者实际上并未使用
___libc_start_main实际上并没有返回,因为它调用exit()返回值main()to 直接退出到操作系统,所以你的损坏ebp没有关系
在不太可能___libc_start_main返回的情况下(例如,由于 libc 中的错误),入口点代码将执行hlt特权指令,因此该进程将被操作系统杀死。