《coredump问题原理探究》Windows版 笔记
Debug
原文链接:
侵删
一、环境搭建
1、Win7捕获程序dump
注册表HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/Windows Error Reporting/LocalDumps中新建几个key
抓dump注册表配置
2、Windbg符号表设置(Symbols Search Path)
自动下载
D:\Debug\Symbols;SRV\*D:\Debug\Symbols\*;D:\Debug\Dump
手动下载
https://developer.microsoft.com/en-us/windows/hardware/download-symbols
二、WinDbg命令 命令 含义 实例
x 显示所有上下文中符合某种模式的符号 x Test!m*
bp 设置一个或多个软件断点;可通过
组合、地址、条件、选项来设置多种类型的断点 bp Test!main
u 显示出内存里某段程序的汇编 u Test!main
g 开始执行指令的进程或线程;当出现下列情况,执行停止:
1、进程结束;2、执行到断点;3、某个时间导致调试器终止
dd 显示指定范围内存单位的内容(双字dword) dd esp L 8
da 显示指定内存开始的字符串 da 004020dc
db 单字节显示内存 db esp
t 执行一条指令或一行代码,并显示出所有寄存器和状态的值 Trace
p 执行一条指令或一行代码,并显示出所有寄存器和状态的值
当函数调用或中断发生时,也只是作为一条指令执行 Step
kbn 显示指定线程的栈帧,并显示相关信息
.frame n 切换到栈帧n
ln 查找就近的符号 ln 004010e0
dt -v 结构体名 地址 打印结构体 dt -v _HEAP_ENTRY 00730000
!heap -a 查看堆信息
!heap -x 地址 查看地址所属的堆块信息 !heap -x 00730000
!heap -hf 地址 查看堆上所有的堆块 !heap -hf 00730000
三、函数栈帧
1、栈内存布局
返回地址ret
上一栈帧地址fp
局部变量
从右往左压入参数
返回地址ret
......
2、栈溢出
往局部变量中写数据越界,导致淹没了fp和ret,函数返回时ebp、eip就会被写入非法值
此时fp/ret对的链表关系被破坏,调试器无法显示正确的函数栈
3、栈的规律
esp的值不会被覆盖,永远指向栈顶
fp/ret对的链表没有被完全破坏,往高地址的一些地方还是保持这种关系
从栈顶到栈底,内存地址由低到高。如果帧指针fp1的内容是fp2,fp2的内容是fp3,那么存在:esp<fp1<fp2<fp3
如果两对(fp1,ret2)、(fp2,ret2)符合条件:fp1的内容刚好是fp2,那么它们除了满足第3点外,还满足:ln ret1和ln ret2都能列出函数符号,ret2的上一条指令一定是调用ret1所在的函数
4、定位栈溢出问题的经验方法
dd esp查看由esp开始的内存
找到某个内容比esp的值稍大、数值相差不是太远的内存单元,称为FP1。下一个单元称为RET1
ln查看RET1的内容。如果没有显示函数符号,跳过FP1,回到第2步
dd *FP1 L 2得到两个内存单元(FP2,RET2)。如果FP2的内容小于FP1的内容,跳过FP1,回到第2步
ln查看RET2的内容。如果没有显示函数符号,跳过FP1,回到第2步;如果OK,跳到FP2,回到第4步
四、函数逆向
汇编代码中跳转和循环为函数的骨架,要优先寻找
五、C内存布局
1、基本类型 类型 特征
char byte ptr 挤在一起
short word ptr 占用四字节空间
int dword ptr
long dword ptr win64采用LLP64标准,Windows系统中long和int是相同的
float dword ptr 单精度占四字节,要配合浮点计算指令确认
double qword ptr 双精度占八字节,要配合浮点计算指令确认
指针 lea