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

在Linux系统中,一个应用程序存在堆溢出漏洞(缓冲区溢出导致堆块被篡改),请详细说明从漏洞复现到成功利用(执行任意代码)的完整步骤,包括内存布局分析(使用gdb调试查看堆块)、漏洞触发的具体操作、以及如何构造payload来控制EIP寄存器。

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

答案

1) 【一句话结论】在Linux系统中,堆溢出漏洞利用需通过gdb分析堆块结构(memptr、size、fd、bk偏移),构造覆盖EIP的payload,同时处理size字段覆盖导致的错误回收、tcache链表指针问题及ASLR,最终控制程序跳转到任意代码执行。

2) 【原理/概念讲解】老师讲解:堆溢出是程序向堆分配的缓冲区写入超长数据,覆盖堆块的控制信息(如指针、返回地址)。堆块由memptr(偏移0,指向数据)、size(偏移8,块大小)、fd(偏移16,前向指针)、bk(偏移24,后向指针)组成。覆盖size字段会导致系统错误管理堆块(如提前回收),利用失败。类比:堆块像储物柜,size是柜子标签,标明大小,溢出数据覆盖标签,系统误判柜子大小,导致回收错误。

3) 【对比与适用场景】

特性栈溢出堆溢出
溢出对象栈缓冲区(函数参数/局部变量)堆缓冲区(动态分配的内存)
覆盖内容返回地址(栈帧中)堆块指针(memptr、fd、bk)或返回地址
利用难度低(直接覆盖返回地址)高(需分析堆布局,处理碎片化)
关键工具gdb查看栈帧gdb查看堆块,分析tcache/fastbin
堆保护应对栈保护(canary)、NXASLR(地址随机化)、tcache回收机制

4) 【示例】
伪代码(漏洞程序):

#include <stdio.h>
#include <stdlib.h>

void vulnerable_function() {
    char *buffer = malloc(64);
    if (!buffer) return;
    printf("Enter a string: ");
    fgets(buffer, 64, stdin);
    printf("You entered: %s", buffer);
    free(buffer); // 假设free后可能触发tcache回收
}

int main() {
    vulnerable_function();
    return 0;
}

调试步骤:

  • 编译:gcc -g -o vuln vuln.c
  • 用gdb启动:gdb ./vuln
  • 设置断点:b vulnerable_function
  • 运行:r
  • 查看堆块:在函数内,用info heap查看堆块结构,确定偏移:size在偏移8(0x8),fd在偏移16(0x10),bk在偏移24(0x14)。
  • 触发漏洞:输入超过64字节(如A*100),覆盖返回地址(假设返回地址在堆块后0x10偏移处)。
  • 构造payload:前64字节填充A,接着是覆盖EIP的地址(如0xdeadbeef),最后是shellcode。注意:payload长度需考虑size字段,若覆盖size,需调整长度(比如跳过size字段,或构造时让size字段为0x100,避免覆盖)。

5) 【面试口播版答案】(约90秒)
“面试官您好,针对Linux系统下的堆溢出漏洞利用,步骤如下:首先,用gdb分析内存布局,通过info heap或x/16xw heap_block查看堆块结构,确定memptr(0偏移)、size(8偏移)、fd(16偏移)、bk(24偏移)的位置,以及返回地址在堆块后的偏移(比如0x10)。然后,触发漏洞,输入超过缓冲区长度的数据(如100个A),覆盖返回地址。接着,构造payload:前64字节填充,接着是覆盖EIP的地址(比如0xdeadbeef),最后是shellcode。关键是要处理size字段,若覆盖size会导致堆块被系统错误回收,需调整payload长度(比如跳过size字段,或构造时让size字段为0x100,避免覆盖)。还要考虑tcache回收机制,确保覆盖的fd和bk指针为NULL(0x0),避免被系统回收。如果系统开启ASLR,可通过多次触发漏洞获取偏移信息(记录不同输入下返回地址的偏移变化),或利用tcache链表固定位置(如链表头地址已知)来构造payload。”

6) 【追问清单】

  • 问:如何确定堆块中fd和bk指针的偏移量?
    回答要点:通过gdb命令info heap查看堆块结构,偏移量在glibc中固定(如fd在偏移16,bk在偏移24),或用x/16xw heap_block逐字节查看。
  • 问:系统开启ASLR后,如何应对?
    回答要点:利用tcache链表固定位置(如链表头地址已知),构造payload时包含偏移量;或通过多次触发漏洞,记录不同输入下返回地址的偏移变化,计算偏移量。
  • 问:为什么覆盖size字段会导致利用失败?
    回答要点:覆盖size字段会改变堆块大小,系统在回收时误判堆块大小,导致提前回收或错误链接,利用时程序崩溃。
  • 问:如何验证payload是否成功覆盖EIP?
    回答要点:在gdb中设置断点在返回地址位置,输入payload后,用x/x $eip检查是否为构造的地址(如0xdeadbeef),若成功则覆盖正确。
  • 问:tcache回收机制下,如何避免覆盖的指针被回收?
    回答要点:构造payload时,使覆盖的fd和bk指针为NULL(0x0),或指向无效地址,避免被tcache链表回收。

7) 【常见坑/雷区】

  • 忽略堆块size字段:覆盖size会导致堆块被错误管理,利用失败。
  • 未处理tcache回收:覆盖的fd/bk指针若有效,会被系统回收,导致利用失败。
  • ASLR应对不足:未通过多次触发漏洞获取偏移信息,或未利用tcache链表固定位置,导致payload失效。
  • payload长度计算错误:未考虑堆块偏移量,导致覆盖位置偏移,无法控制EIP。
  • 忽略堆碎片化:堆块位置变化后,偏移量失效,需重新分析。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1