这是由于程序中的 pop rdi ;ret 它大概的位置在 <__libc_csu_init+99>: pop rdi也就是说它存在于 __libc_csu_init 这个函数中
我们观察它的汇编代码其实不难发现,它其中并未含有 pop rdi ; ret 这个gadget
其实它来自于 pop r15; 的一部分 对比下面字节码我们就可以知道,pop rdi; ret 的字节码和 pop r15; ret 后半部分相同,所以把 pop r15; ret 截下来一半就是 pop rdi;ret 而在glibc 2.34 中 pop rdi; ret 消失的根本原因是一个补丁移除了 __libc_csu_init 的二进制生成。
该补丁旨在删除 ret2csu 的有用 ROP 小工具,并具有删除针对 glibc 2.34+ 编译的二进制文件中的 pop rdi ; ret 的效果。 这将导致一些问题,例如 __libc_start_main,它将 __libc_csu_init 作为参数。现在它不存在,它仍然接受参数,但对它没有任何作用,所以它在 2.34 中被版本优化了,因为它现在有不同的行为。这意味着我们不能够在较旧的 glibc 版本上运行为 2.34+ 编译的二进制文件,否则你会得到非常烦人的错误, 如下 现在我们知道在程序中由于 __libc_csu_init 函数被优化了,所以我们已经没办法在编译后的程序中找到 pop rdi;ret 了
但是没有关系,__libc_csu_init 并非是 pop rdi;ret 的唯一来源,显然按照我们上面的解释,哪里有 pop r15 那么哪里就会有 pop rdi 虽然程序中没有 pop rdi但是glibc自身含大量使用r15的函数,必存pop r15; ret,泄露libc基址后,即可定位libc中的pop rdi; ret偏移 所以我们最大的问题还是需要溢出