启用aslr需-fpie -pie,启用dep/nx需-z noexecstack;二者须配合-z relro/-z now及内核randomize_va_space=2生效。

Linux 下用 gcc 或 g++ 启用 ASLR 和 DEP/NX 的编译选项
ASLR 和 DEP(Windows 叫 NX)在 Linux 上主要靠链接器和内核协同实现,编译器本身不“开启”它们,但能通过标记让生成的二进制具备被内核启用这些保护的能力。关键不是加什么编译 flag,而是确保链接阶段生成符合要求的 ELF 属性。
必须启用的两个核心选项是:
-
-z relro(部分 RELRO)或更严格的-z relro -z now(完全 RELRO),用于加固 GOT 表,配合 ASLR 有效防止 GOT 覆盖攻击 -
-z noexecstack,标记栈段为不可执行,这是启用 DEP/NX 的前提;若代码中显式申请可执行栈(如mmap(..., PROT_EXEC)),该标记不会阻止,但会拒绝默认栈执行
补充建议:
- 加上
-pie(Position Independent Executable),让整个程序可被 ASLR 随机加载——这是现代 Linux 发行版(如 Ubuntu/Debian 默认)启用全局 ASLR 的硬性要求 -
-fPIE必须与-pie配合使用,否则链接失败;它让编译器生成位置无关的机器码 - 不要依赖
-fstack-protector来实现 DEP:它是栈金丝雀(stack canary),和 NX/DEP 完全无关
验证是否生效:用 readelf 和 checksec
光加参数不等于生效,得看 ELF 头和段属性是否真被写入。最直接的方式是检查:
- 是否有
PT_INTERP+PT_GNU_RELRO段 → 对应-z relro - 是否含
GNU_STACK程序头,且标志不含PF_X(即没有可执行权限)→ 对应-z noexecstack - 是否为 DYNAMIC 类型、有
DF_1_PIE标志 → 对应-pie
快速验证命令:
readelf -l ./a.out | grep -A1 GNU_STACK readelf -d ./a.out | grep -E "(RELRO|BIND_NOW)" file ./a.out # 应显示 "PIE executable"
更省事可用 checksec --file=./a.out(需安装 checksec 工具),它会明确告诉你 NX、PIC/PIE、RELRO 是否启用。
Windows MSVC 下的等效操作(cl.exe)
Windows 不叫 ASLR/DEP,但对应机制是:/DYNAMICBASE(启用 ASLR)和 /NXCOMPAT(声明兼容 DEP/NX)。这两个是链接器开关,必须传给 link.exe,而非编译器。
典型用法:
-
cl /c /EHsc main.cpp(只编译,不链接) link main.obj /DYNAMICBASE /NXCOMPAT /OUT:main.exe
注意:
- MSVC 2015+ 默认开启
/DYNAMICBASE和/NXCOMPAT,但显式写出更可靠,尤其跨版本构建时 - 若项目含内联汇编或手动修改页属性(如
VirtualProtect(..., PAGE_EXECUTE_READWRITE)),/NXCOMPAT不会报错,但系统可能拒绝加载(取决于策略) -
/SAFESEH是另一层保护(异常处理完整性),和 DEP/ASLR 无直接关系,别混淆
常见失效场景与坑
即使写了所有 flag,也可能白忙一场:
- 忘记
-fPIE却用了-pie→ 链接时报错relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object - 用
g++ main.cpp -z noexecstack -z relro -pie,但没加-fPIE→ 编译通过,链接失败 - 在容器或旧内核(如
kernel.yama.ptrace_scope > 0)中测试,ASLR 被系统级禁用 →cat /proc/sys/kernel/randomize_va_space必须为2 - 用
strip去符号后破坏了.dynamic段结构 → 某些情况下导致RELRO失效(尤其完全 RELRO) - 静态链接(
-static)下-pie无效 → GCC 明确报错,但容易忽略
真正起作用的是「编译器生成位置无关代码 + 链接器打上安全标记 + 内核运行时按标记启用」三者缺一不可。少一个环节,就只是看起来开了。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











