合理限制内存分配是防范堆栈缓冲区溢出的关键措施,包括限制栈大小、禁用栈执行(nx/dep)、启用aslr及控制堆行为,需结合系统配置与程序编译选项协同实施。

限制单个进程的栈大小
操作系统允许为每个进程设定最大栈空间(如Linux中通过ulimit -s)。过大的默认栈(如8MB)给攻击者留出充足空间构造恶意载荷;适当收紧(例如1MB或更低)可使多数溢出攻击因空间不足而失败。
- 在启动关键服务前,用
ulimit -s 1024限制栈为1MB(单位KB) - 在systemd服务文件中添加
LimitSTACK=1048576实现持久化配置 - 注意:过小可能影响合法递归或大型局部数组,需结合实际负载测试
禁用栈上执行代码(NX/DEP)
即使攻击者成功覆盖返回地址,若栈内存被标记为“不可执行”,注入的shellcode就无法运行。这是硬件级防护,现代CPU和OS默认启用。
- Linux检查:
cat /proc/cpuinfo | grep nx(应有输出) - 确认内核启用:
cat /proc/sys/kernel/exec-shield(值为1表示开启) - 编译程序时加
-z noexecstack确保链接器不请求可执行栈
启用地址空间布局随机化(ASLR)
ASLR让栈、堆、库等内存区域每次加载地址都不同,攻击者无法精准预测跳转目标地址——哪怕溢出成功,也很难命中shellcode位置。
- Linux启用等级:/proc/sys/kernel/randomize_va_space设为2(完全随机化)
- 验证是否生效:
cat /proc/self/maps | head -n3,多次执行观察地址变化 - 注意:部分调试或嵌入式环境会关闭ASLR,生产环境务必保持开启
控制堆内存分配行为
堆溢出虽与栈不同,但常与栈溢出协同利用(如覆盖堆管理元数据或伪造vtable)。限制堆行为可削弱链式利用能力。
- 使用
malloc_trim(0)及时归还空闲内存,减少堆碎片和可控布局机会 - 避免频繁
malloc/free交替,防止攻击者操控堆块布局 - 启用glibc的
MALLOC_CHECK_环境变量(如设为1),在检测到堆破坏时终止进程











