为何通过环境变量注入的shellcode在现代操作系统中无法执行
问题原因及解决方法
你遇到的是现代Linux系统在Ubuntu 7.04之后新增的几类栈布局、内核硬ening机制导致的,即使你关闭了ASLR、栈保护、栈不可执行、PIE,仍有以下默认机制会影响漏洞利用:
- 首先是栈初始布局偏移调整:新版glibc和内核调整了进程启动时的栈底偏移、环境变量与argv参数的存储位置,哪怕完全关闭ASLR,环境变量
SHELLCODE的存储地址也和旧版Ubuntu 7.04的0xbffff217完全不同,书中的硬编码地址不能直接复用。 - 其次是vdso/vsyscall映射挤占地址空间:现代Linux默认会在栈地址空间上方映射vdso动态系统调用页,导致栈的可用地址范围整体下移,旧系统中0xbfff开头的栈地址区间在新版系统中已经被其他内容占用。
- 第三是内核栈随机化残留:部分发行版默认开启了内核层面的栈固定偏移配置,即使将
/proc/sys/kernel/randomize_va_space设为0关闭用户态ASLR,仍可能存在几十字节的固定偏移,导致你计算的NOP雪橇中间地址出现偏差。 - 第四是命令行参数长度限制:新版shell对传入的命令行参数长度有更严格的校验,你构造的40次重复地址可能被截断,导致没有完整覆盖目标函数的返回地址。
排查步骤
- 先获取当前系统中
SHELLCODE环境变量的真实地址,编译运行以下C程序即可:
#include <stdio.h> #include <stdlib.h> int main() { printf("SHELLCODE 存储地址:%p\n", getenv("SHELLCODE")); return 0; }
将输出的地址按小端序转换后,替换书中的\x17\xf2\xff\xbf即可。
2. 用gdb在notesearch程序的溢出函数返回位置下断点,确认返回地址已经被你构造的内容完整覆盖,且目标地址确实属于SHELLCODE前的NOP雪橇区间。
3. 确认内核参数完全关闭所有随机化配置,若仍有问题可在内核启动参数中添加randomize_va_space=0后重启系统。
内容的提问来源于stack exchange,提问作者Duderus Smith
相关产品推荐
相关产品推荐

