• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2025-03-17 00:16 Aet 隐藏边栏 |   抢沙发  8 
文章评分 1 次,平均分 5.0

示例dump分析:重复释放同一堆内存

代码

分析步骤

  1. windbg打开Dump 文件并加载符号
    1. ctrl + s
    2. ctrl + p
    3. ctrl + i
  2. 自动分析崩溃原因

  1. 看到了相关异常信息如下

  1. 异常上下文解析:

    1. 可以看出,异常触发位置是:aet_breakpad_test!_free_dbg+0x2e
      说明崩溃发生在 _free_dbg(调试版堆释放函数)内部
    2. 异常代码
      c0000005 (Access violation)
      非法内存访问
    3. 奔溃发生的地址
      000000000000810f(这个就是无效地址)
      总结来说就是在读取[rax+1Ch]的时候发生了奔溃,80f3 + 1C = 810f
    4. 结论:RAX 存储了一个无效的堆块地址,可能是由于:
      堆块已被释放(双重释放)
      堆块头信息被破坏(堆溢出或野指针写入)
  2. 查看调用栈

    1. 可以看到和我们自己的模块相关的代码是main这一行

  1. 检查变量和寄存器(储存制作p的值)

  1. 反汇编

验证观察

  1. 附加到exe后,进行单步调试观察堆内存
    1. 这一行代码执行后,用!heap -p -a 0x00000000 0042bdd0去观察,如下
    2. 状态是busy

  1. 第一次delete之后,再次观察
    1. 发现状态是free

  1. 继续往下走,观察第二次执行delete的变化
    1. 发现崩溃了
    2. 再观察堆信息

总结

  1. 结合前面的异常代码和这里的空指针,可以认为是访问了未映射的地址

示例dump分析:死锁

代码

分析步骤

  1. 由于这个是死锁,所以不是奔溃,所以要附加到进程来调试
  2. 自动分析崩溃原因

  1. 看到了相关异常信息如下
    1. 80000003调试断点指令

  1. 列出所有线程~*k
    1. 线程0,正在等待多个对象
    2. 线程1,是breakpad的异常处理线程,处理等待单个对象的状态
    3. 线程23,执行了ThreadAThreadB,并且都调用了RtlEnterCriticalSection,但随后进入了等待状态

  1. !locks查看

  1. 在调用栈中显示,线程 258cThreadA,当前正 等待获取 cs2

  1. 在调用栈中显示,线程 5a74ThreadB,当前正 等待获取 cs1

验证观察

  1. 查看cs1的相关信息

字段 值/含义
Critical section 0x00007ff7ae27f8d0(临界区 cs1 的地址)
LockCount 0x1(有 1 个线程 在等待此临界区)
OwningThread 0x258c(持有此临界区的线程 ID 是 258c,对应线程 2)
RecursionCount 0x1(持有线程已 重入锁 1 次,即首次获取后未释放)
WaiterWoken No(无等待线程被唤醒)
SpinCount 0x20007d0(自旋计数,用于优化多核环境下的锁竞争)
StackTraceDataBase NULL(堆栈跟踪未启用,需配置符号或启用调试选项)
  1. 查看cs2的相关信息

总结

  1. ThreadA 持有 cs1 → 等待 cs2
  2. ThreadB 持有 cs2 → 等待 cs1

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享