You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含__attribute__((constructor))与函数指针的漏洞代码技术问询

漏洞代码分析与疑问解答

先贴出完整代码:

#include <stdio.h>
#include <string.h>
//Ignore this thing
__attribute__((constructor))
void setup(){
  setvbuf(stdout,NULL,2,0);
  setvbuf(stderr,NULL,2,0);
  setvbuf(stdin,NULL,2,0);
}

int main()
{
  printf("What's you name?\n");
  char name[100];
  fgets(name,100,stdin);
  void(*Kekpointer)() = (void(*)())&name;
  Kekpointer();
  return 0;
}

核心疑问解析

1. void(*Kekpointer)() 是什么类型的指针?

这是指向「无参数、返回值为void的函数」的指针,也就是标准的函数指针。

拆解语法逻辑:

  • C语言中()的优先级高于*,必须用括号把*Kekpointer括起来——如果写成void* Kekpointer(),会被解释成「返回void指针的函数」,和函数指针完全是两回事。
  • 完整结构void (*指针变量名)()的含义是:该指针存储的地址指向一个函数,这个函数不需要输入参数,执行后也不返回任何值。
  • 正常情况下这类指针用来存储合法函数的地址,通过指针调用函数;但这段代码把栈数组的地址塞进去,强行当成函数地址来用。

2. (void(*)())&name 是类型转换吗?

是的,这是强制类型转换,目的是把数组指针转换成函数指针。

  • &name取的是栈数组name的首地址,它的原生类型是char (*)[100](指向包含100个char元素的数组的指针)。
  • (void(*)())是强制转换的目标类型,也就是前面说的「无参数、返回void的函数指针」。
  • C语言不允许不同类型的指针直接赋值,所以必须通过强制转换绕过类型检查,才能把&name的值赋值给Kekpointer。

3. __attribute__((constructor)) 修饰的setup函数影响漏洞吗?

完全不影响漏洞的核心逻辑,它只是个辅助调试的工具。

  • __attribute__((constructor))是GCC的扩展属性,作用是让被修饰的函数在main()执行之前自动运行。
  • 这里的setup函数调用setvbuf把标准输入、输出、错误流都设置为无缓冲模式(参数2对应_IONBF),目的是让printf的提示信息立刻显示在终端,不会因为缓冲区缓存导致调试时看不到输出。
  • 它既不会改变栈的执行权限,也不会影响输入存储或函数指针的调用逻辑,对漏洞利用没有直接作用。

漏洞原理与利用思路

这段代码的致命漏洞在于直接将栈上数组的地址当作函数指针调用:

  • 数组name存放在栈中,当用户输入的内容是可执行的机器指令(即shellcode)时,调用Kekpointer()就会跳转到栈上执行这段指令。
  • 利用的前提是程序运行环境允许栈执行代码:现代操作系统默认开启DEP(数据执行保护)禁止栈执行,所以需要编译时加-z execstack选项关闭栈保护,或者目标系统本身未开启DEP。
  • 实际利用时,只需输入对应架构的shellcode(比如x86架构的\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80),就能触发远程shell。

内容的提问来源于stack exchange,提问作者Haaziq Jamal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 05:30:46