51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

请描述缓冲区溢出(栈溢出)漏洞的利用过程,包括如何构造payload、绕过ASLR(地址空间布局随机化)和DEP(数据执行保护)等安全机制,并举例说明。

360助理安全研究员(漏洞挖掘与利用)难度:困难

答案

1) 【一句话结论】

栈溢出漏洞利用的核心是通过构造精心设计的payload覆盖函数返回地址,绕过地址空间布局随机化(ASLR)和数据执行保护(DEP),最终控制程序执行流程,实现提权或执行任意代码。

2) 【原理/概念讲解】

老师口吻:栈溢出利用的本质是“覆盖函数返回地址,劫持程序执行流程”。函数调用时,栈从高地址向低地址增长,保存返回地址(函数返回后跳转的地址)、参数、局部变量。当缓冲区(如局部变量buffer)溢出时,输入数据会覆盖返回地址,导致函数返回时跳转到恶意地址。

利用步骤可拆解为三步:

  • 确定偏移量:通过fuzzing(输入不同长度的数据,观察程序崩溃或跳转位置)或分析栈布局(如用gdb调试,查看栈上返回地址的位置),找到缓冲区数据到返回地址的偏移量(例如,局部变量buffer占8字节,返回地址在栈上偏移24字节,偏移量为24)。
  • 构造payload:
    • 前部分:NOP滑板(连续的0x90指令,跳过验证时自动跳转);
    • 中间:shellcode(执行系统调用或加载/bin/sh的代码,长度需适配);
    • 后部分:偏移量调整后的返回地址(指向shellcode或系统调用地址,需考虑偏移量)。
  • 绕过安全机制:
    • 绕过ASLR:通过信息泄露(如格式化字符串漏洞,用%8$n等获取可执行区域地址),计算绝对地址(如libc基址+system函数偏移);
    • 绕过DEP:用shellcode替换返回地址(shellcode在非执行内存,或利用系统调用(如execve)绕过,或通过返回到已加载的库函数(如printf)跳过DEP)。

类比:把栈想象成“堆叠的盘子”,函数调用时放返回地址(盘子1)、参数(盘子2)、局部变量(盘子3)。缓冲区溢出就像把盘子3的菜(数据)堆到盘子1上,导致盘子1的位置被覆盖,下次函数返回时跳到错误地址。

3) 【对比与适用场景】

比较项栈溢出利用堆溢出利用
栈布局固定偏移(函数内局部变量位置固定)堆偏移不固定(由malloc分配,位置随机)
返回地址位置固定(函数内偏移量固定)需分析堆布局(更复杂)
绕过ASLR需信息泄露找地址,计算绝对地址需堆布局分析,难度更高
绕过DEP用shellcode或系统调用同样需要shellcode,但堆布局分析更复杂

4) 【示例】

以一个存在缓冲区溢出的C函数为例:

void vulnerable_function(char *input) {
    char buffer[8];
    strcpy(buffer, input); // 溢出点
    printf("Input processed\n");
}

int main() {
    vulnerable_function("A" * 24); // 输入24字节,覆盖返回地址
    return 0;
}

利用步骤:

  1. 确定偏移量:通过调试发现,返回地址在栈上偏移24字节(假设buffer占8字节,返回地址在栈上偏移24)。
  2. 构造payload:
    • NOP滑板:4字节(0x90*4);
    • shellcode:system("/bin/sh")的shellcode(约31字节);
    • 返回地址:偏移量调整后的地址(指向shellcode)。
  3. 绕过ASLR:通过格式化字符串漏洞获取libc基址(如%8$n泄露),计算system函数绝对地址(libc基址 + system偏移);
  4. 绕过DEP:用shellcode替换返回地址,程序跳转到shellcode执行,最终执行/bin/sh。

5) 【面试口播版答案】

“栈溢出利用的核心是通过构造payload覆盖函数返回地址,绕过ASLR和DEP。首先,确定缓冲区大小和返回地址偏移,比如函数中局部变量buffer大小为8字节,返回地址在栈上偏移24字节,所以偏移量是24。然后构造payload:前4字节NOP滑板(跳过验证),中间是system("/bin/sh")的shellcode(约31字节),后8字节是偏移量调整后的返回地址(指向shellcode)。绕过ASLR时,通过格式化字符串漏洞获取libc基址,计算system函数的绝对地址;绕过DEP时,用shellcode替换返回地址,因为shellcode在非执行内存(通过信息泄露或漏洞),或者利用系统调用(如execve)绕过。比如,假设通过漏洞获取libc基址为0x7f000000,system地址是0x7f000100,那么返回地址设置为0x7f000100,程序就会跳转到system函数执行,最终执行/bin/sh。这样就能利用栈溢出漏洞获取shell。”

6) 【追问清单】

  1. 如何确定返回地址的偏移量?
    回答:通过fuzzing测试不同长度的输入,观察程序崩溃或跳转位置,或用gdb调试分析栈布局(查看栈上返回地址的位置)。
  2. 如何处理栈保护(如栈canary)?
    回答:栈canary是放在返回地址前的一个随机值,需先覆盖canary,再覆盖返回地址,或用特定payload绕过canary(如用canary的值构造)。
  3. 绕过ASLR时,如果信息泄露失败怎么办?
    回答:尝试其他信息泄露方法(如堆溢出泄露),或利用其他漏洞(如格式化字符串)获取地址。
  4. 如何处理不同的编译器优化(如优化后变量位置变化)?
    回答:分析编译后的汇编代码,确定变量在栈上的偏移,或用静态分析工具(如IDA)反编译。
  5. 堆溢出和栈溢出的区别?
    回答:栈溢出利用偏移量固定,堆溢出偏移量不固定,需分析堆布局,栈溢出更常见于函数调用。

7) 【常见坑/雷区】

  1. 偏移量计算错误:未考虑栈保护(如canary)或编译器优化,导致payload覆盖位置不对。
  2. 忽略栈保护(如NX位):直接用shellcode,DEP保护下无法执行,需绕过。
  3. payload构造错误:NOP滑板长度不够,跳过验证失败;shellcode长度或地址错误,跳转失败。
  4. 绕过ASLR时信息泄露不准确:获取的地址是相对地址,未转换为绝对地址,导致跳转错误。
  5. 忽略操作系统差异:Windows和Linux的栈布局不同,返回地址位置不同,需调整偏移量。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1