首页 时政热点 科技头条 智能AI 安全攻防 数码硬件 开发者生态 汽车 游戏 社会热点 开源推荐 医疗健康 归档 标签 关于

没有可执行堆栈的 GCC 上嵌套函数的间接调用

2026-08-30 1 阅读 约6分钟阅读 uecker
分享:
字号:
在没有可执行堆栈的情况下在 GCC 上间接调用嵌套函数 Martin Uecker,2026-08-29 简介 上次我们讨论了如何在需要可执行堆栈的情况下在 GCC 17 和 Clang 上使用嵌套函数进行回调。但是如果需要支持旧版本的 GCC 该怎么办?当然,我们可以简单地接受一个可执行堆栈(它并不像某些人声称的那么可怕),但也可以通过 hack 来避免这种情况。 GCC:嵌套函数和 Trampolines 让我们首先讨论 GCC 如何支持获取嵌套函数的地址。我们的玩具示例(未使用新宏)如下所示(Godbolt 示例)。 typedef int cb_f(int y); int baz(cb_f p, int x) { 返回 p(x); } int foo(int k) { int bar(int x) { return k + x;返回 baz(bar, 2 * k);在 x86_64 上,生成的程序集如下。 bar.0: movl %edi, %eax addl (%r10), %eax ret foo: subq $56, %rsp leaq 64(%rsp), %rax movq %rax, 32(%rsp) movl %edi, (%rsp) leaq 4(%rsp), %rax movw $-17591, 4(%rsp) movabsq $bar.0, %rcx movq %rcx, 6(%rsp) movw $-17847, 14(%rsp) movq %rsp, 16(%rsp) movl $-1864106167, 24(%rsp) addl %edi, %edi 调用 *%rax addq $56, %rsp ret 此代码将一个蹦床放置在堆栈上,并立即通过内联的 baz 函数调用它。蹦床是一个短代码序列,它将静态帧寄存器加载到堆栈上的结构中,该结构包含从父函数捕获的变量,然后跳转到本地函数。如果将常量 -17591、-17847 和 -1864106167 转换回汇编指令,则会获得以下 x86_64 代码。 movq $bar.0, %r11 movq $frame, %r10 Jump *%r11 静态链和代码地址都是蹦床代码中移动指令使用的立即常量。我们可以不使用trampoline的地址来调用函数,而是可以从trampoline中提取代码地址和静态链,并将它们与__builtin_call_with_static_chain内置函数一起使用,直接调用本地函数。例如,使用 noplate 的 peek 和 array_slice 宏,对于 x64_64(和大内存模型)可以通过以下方式完成。无符号 char (*tramp)[24] = (void*)bar; void *code = peek(uint64_t, &array_slice(tramp, 2, 10)); void *chain = peek(uint64_t, &array_slice(tramp, 12, 20));这些指针与在尚未发布的 GCC 17 上通过新内置函数 __builtin_call_static_chain 和 __builtin_call_code_adress 获得的信息完全相同,并且可用于调用本地函数,如前所述。 __builtin_call_with_static_chain(((typeof(bar)*)code)(arg), chain);因此,我们可以使用从蹦床读取这两个指针值作为旧版本 GCC 中的后备机制。缺点是仍然会创建蹦床,编译器仍然无法对间接调用进行去虚拟化,并且堆栈仍然会被标记为可执行。那么收获了什么?由于我们从未真正调用过蹦床,因此我们可以使用以下命令再次使堆栈不可执行,这至少解决了此功能的安全问题。 patchelf --clear-execstack 程序 这个想法在我的实验库 noplate 中实现,其中从代码地址和静态链构造了一个宽指针。蹦床作为函数描述符 我发现还有另一个值得探索的想法:人们也可以使用蹦床本身作为函数描述符。我们没有提取创建蹦床的静态链和代码指针,而是像平常一样传递蹦床的地址。但是在任何可能调用蹦床的地方,我们首先检查指针是否指向蹦床,然后提取代码地址和静态链以使用 __builtin_call_with_static_chain 直接调用嵌套函数。从某种意义上说,我们可以说,我们不是调用蹦床,而是使用一个超级简单的解释器在调用站点解释蹦床的代码,该解释器只能解释这个特定的代码序列,而且非常简单,可以内联(Godbolt 示例)。文学
这篇文章对您有帮助吗?

订阅66必读

每日精选科技资讯,直达你的邮箱